├── docs ├── undocumented.txt ├── docsets │ ├── Marklight.docset │ │ └── Contents │ │ │ ├── Resources │ │ │ ├── Documents │ │ │ │ ├── undocumented.txt │ │ │ │ ├── img │ │ │ │ │ ├── gh.png │ │ │ │ │ ├── carat.png │ │ │ │ │ └── dash.png │ │ │ │ ├── js │ │ │ │ │ └── jazzy.js │ │ │ │ ├── Structs.html │ │ │ │ ├── css │ │ │ │ │ ├── highlight.css │ │ │ │ │ └── jazzy.css │ │ │ │ └── Classes.html │ │ │ └── docSet.dsidx │ │ │ └── Info.plist │ └── Marklight.tgz ├── img │ ├── gh.png │ ├── carat.png │ └── dash.png ├── js │ └── jazzy.js ├── Structs.html ├── css │ ├── highlight.css │ └── jazzy.css └── Classes.html ├── Assets ├── marklight.gif └── screenshot-0.png ├── Sample ├── Pods │ ├── Target Support Files │ │ ├── Marklight-OSX │ │ │ ├── Marklight-OSX.modulemap │ │ │ ├── Marklight-OSX-dummy.m │ │ │ ├── Marklight-OSX-prefix.pch │ │ │ ├── Marklight-OSX-umbrella.h │ │ │ ├── Marklight-OSX.xcconfig │ │ │ └── Info.plist │ │ ├── Marklight-iOS │ │ │ ├── Marklight-iOS.modulemap │ │ │ ├── Marklight-iOS-dummy.m │ │ │ ├── Marklight-iOS-prefix.pch │ │ │ ├── Marklight-iOS-umbrella.h │ │ │ ├── Marklight-iOS.xcconfig │ │ │ └── Info.plist │ │ ├── Marklight-macOS │ │ │ ├── Marklight-macOS.modulemap │ │ │ ├── Marklight-macOS-dummy.m │ │ │ ├── Marklight-macOS-prefix.pch │ │ │ ├── Marklight-macOS-umbrella.h │ │ │ ├── Marklight-macOS.xcconfig │ │ │ └── Info.plist │ │ ├── Pods-Marklight-Marklight Sample │ │ │ ├── Pods-Marklight-Marklight Sample.modulemap │ │ │ ├── Pods-Marklight-Marklight Sample-dummy.m │ │ │ ├── Pods-Marklight-Marklight Sample-umbrella.h │ │ │ ├── Pods-Marklight-Marklight Sample.debug.xcconfig │ │ │ ├── Pods-Marklight-Marklight Sample.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-Marklight-Marklight Sample-frameworks.sh │ │ │ ├── Pods-Marklight-Marklight Sample-resources.sh │ │ │ ├── Pods-Marklight-Marklight Sample-acknowledgements.markdown │ │ │ └── Pods-Marklight-Marklight Sample-acknowledgements.plist │ │ └── Pods-Marklight-Marklight Sample macOS │ │ │ ├── Pods-Marklight-Marklight Sample macOS.modulemap │ │ │ ├── Pods-Marklight-Marklight Sample macOS-dummy.m │ │ │ ├── Pods-Marklight-Marklight Sample macOS-umbrella.h │ │ │ ├── Pods-Marklight-Marklight Sample macOS.debug.xcconfig │ │ │ ├── Pods-Marklight-Marklight Sample macOS.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-Marklight-Marklight Sample macOS-frameworks.sh │ │ │ ├── Pods-Marklight-Marklight Sample macOS-resources.sh │ │ │ ├── Pods-Marklight-Marklight Sample macOS-acknowledgements.markdown │ │ │ └── Pods-Marklight-Marklight Sample macOS-acknowledgements.plist │ ├── Manifest.lock │ └── Local Podspecs │ │ └── Marklight.podspec.json ├── Marklight Sample.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ ├── Marklight Sample iOS.xcscheme │ │ └── Marklight Sample macOS.xcscheme ├── Podfile ├── Marklight Sample.xcworkspace │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── contents.xcworkspacedata ├── Podfile.lock ├── Marklight Sample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── ViewController.swift ├── Marklight Sample macOS │ ├── AppDelegate.swift │ ├── Info.plist │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ └── ViewController.swift └── Sample.md ├── Marklight.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── Marklight macOS.xcscheme │ └── Marklight iOS.xcscheme ├── .travis.yml ├── Marklight ├── Array+appending.swift ├── NSString+paragraphRangeAt.swift ├── Marklight.h ├── MarklightStyleApplier.swift ├── UniversalTypes.swift ├── Info.plist ├── MarklightTextProcessingResult.swift ├── MarklightRegex.swift ├── MarklightTextProcessor.swift └── MarklightTextStorage.swift ├── CHANGELOG ├── .gitignore ├── Marklight macOSTests └── Info.plist ├── MarklightTests ├── Info.plist └── MarklightTextProcessorTests.swift ├── Marklight macOS └── Info.plist ├── Marklight.podspec ├── LICENSE └── README.md /docs/undocumented.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/undocumented.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/img/gh.png -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/img/dash.png -------------------------------------------------------------------------------- /Assets/marklight.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/Assets/marklight.gif -------------------------------------------------------------------------------- /Assets/screenshot-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/Assets/screenshot-0.png -------------------------------------------------------------------------------- /docs/docsets/Marklight.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/docsets/Marklight.tgz -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/docsets/Marklight.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/docsets/Marklight.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/docsets/Marklight.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macteo/Marklight/HEAD/docs/docsets/Marklight.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Marklight-OSX.modulemap: -------------------------------------------------------------------------------- 1 | framework module Marklight { 2 | umbrella header "Marklight-OSX-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Marklight-iOS.modulemap: -------------------------------------------------------------------------------- 1 | framework module Marklight { 2 | umbrella header "Marklight-iOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Marklight-macOS.modulemap: -------------------------------------------------------------------------------- 1 | framework module Marklight { 2 | umbrella header "Marklight-macOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Marklight-OSX-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Marklight_OSX : NSObject 3 | @end 4 | @implementation PodsDummy_Marklight_OSX 5 | @end 6 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Marklight-iOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Marklight_iOS : NSObject 3 | @end 4 | @implementation PodsDummy_Marklight_iOS 5 | @end 6 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Marklight-macOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Marklight_macOS : NSObject 3 | @end 4 | @implementation PodsDummy_Marklight_macOS 5 | @end 6 | -------------------------------------------------------------------------------- /Marklight.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample/Marklight Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Marklight_Marklight_Sample { 2 | umbrella header "Pods-Marklight-Marklight Sample-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Marklight_Marklight_Sample : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Marklight_Marklight_Sample 5 | @end 6 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Marklight_Marklight_Sample_macOS { 2 | umbrella header "Pods-Marklight-Marklight Sample macOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Marklight_Marklight_Sample_macOS : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Marklight_Marklight_Sample_macOS 5 | @end 6 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Marklight-OSX-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Marklight-iOS-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Marklight-macOS-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Sample/Podfile: -------------------------------------------------------------------------------- 1 | project 'Marklight Sample' 2 | use_frameworks! 3 | 4 | abstract_target 'Marklight' do 5 | pod 'Marklight', :path => '..' 6 | 7 | target 'Marklight Sample' do 8 | platform :ios, '8.0' 9 | end 10 | 11 | target 'Marklight Sample macOS' do 12 | platform :osx, '10.11' 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode10.1 3 | script: xcodebuild -project Marklight.xcodeproj -scheme 'Marklight iOS' -destination 'platform=iOS Simulator,OS=12.1,id=B40F7090-26EE-4D2E-A7A2-C13E10EDA669' -enableCodeCoverage YES clean build test 4 | after_success: 5 | - bash <(curl -s https://codecov.io/bash) 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample/Marklight Sample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Marklight.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/Marklight Sample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Sample/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Marklight (1.4.0) 3 | 4 | DEPENDENCIES: 5 | - Marklight (from `..`) 6 | 7 | EXTERNAL SOURCES: 8 | Marklight: 9 | :path: .. 10 | 11 | SPEC CHECKSUMS: 12 | Marklight: c175962a8d5a6f07b3e244ec6a2986404153cff4 13 | 14 | PODFILE CHECKSUM: 611f98c4d26093f40dc84dc73cf7a4453a5d8b00 15 | 16 | COCOAPODS: 1.3.1 17 | -------------------------------------------------------------------------------- /Sample/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Marklight (1.4.0) 3 | 4 | DEPENDENCIES: 5 | - Marklight (from `..`) 6 | 7 | EXTERNAL SOURCES: 8 | Marklight: 9 | :path: .. 10 | 11 | SPEC CHECKSUMS: 12 | Marklight: c175962a8d5a6f07b3e244ec6a2986404153cff4 13 | 14 | PODFILE CHECKSUM: 611f98c4d26093f40dc84dc73cf7a4453a5d8b00 15 | 16 | COCOAPODS: 1.3.1 17 | -------------------------------------------------------------------------------- /Marklight/Array+appending.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array+appending 3 | // 4 | // Created by Christian Tietze on 2017-07-19. 5 | // Copyright © 2016 MacTeo. LICENSE for details. 6 | // 7 | 8 | extension Array { 9 | func appending(contentsOf other: [Element]) -> [Element] { 10 | var result = self 11 | result.append(contentsOf: other) 12 | return result 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Marklight/NSString+paragraphRangeAt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+paragraphRangeAt.swift 3 | // Marklight 4 | // 5 | // Created by Christian Tietze on 20.07.17. 6 | // Copyright © 2017 MacTeo. See LICENSE for details. 7 | // 8 | 9 | import Foundation 10 | 11 | extension NSString { 12 | func paragraphRange(at location: Int) -> NSRange { 13 | return paragraphRange(for: NSRange(location: location, length: 0)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Marklight-OSX-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double MarklightVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char MarklightVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Marklight-iOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double MarklightVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char MarklightVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Marklight-macOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double MarklightVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char MarklightVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Marklight_Marklight_SampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Marklight_Marklight_SampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Marklight_Marklight_Sample_macOSVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Marklight_Marklight_Sample_macOSVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Marklight/Marklight.h: -------------------------------------------------------------------------------- 1 | // 2 | // Marklight 3 | // 4 | // Created by Matteo Gavagnin on 01/01/16. 5 | // Copyright © 2016 MacTeo. LICENSE for details. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for Marklight. 11 | FOUNDATION_EXPORT double MarklightVersionNumber; 12 | 13 | //! Project version string for Marklight. 14 | FOUNDATION_EXPORT const unsigned char MarklightVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /Sample/Marklight Sample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Marklight Sample 4 | // 5 | // Created by Matteo Gavagnin on 01/01/16. 6 | // Copyright © 2016 MacTeo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | fileprivate func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any]?) -> Bool { 17 | // Override point for customisation after application launch. 18 | return true 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Marklight-iOS.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Marklight-iOS 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | ## 1.3.x (2018-08-27) 2 | * Add initializer to `MarklightTextProcessor`. 3 | 4 | ## 1.3.0 (2017-08-11) 5 | * Marklight becomes pluggable [#8](https://github.com/macteo/Marklight/issues/8) 6 | * Support for bold-italic [#6](https://github.com/macteo/Marklight/issues/6) 7 | 8 | ## 1.2.0 (2017-07-20) 9 | * macOS support [#5](https://github.com/macteo/Marklight/issues/5) 10 | 11 | ## 1.0.0 (2017-02-09) 12 | * Converted to Swift 3 13 | 14 | ## 0.1.4 (2016-05-20) 15 | * Added some tests 16 | 17 | ## 0.1.3 (2016-01-02) 18 | 19 | * Added few tests. 20 | * Updated readme. 21 | 22 | ## 0.1.2 (2016-01-01) 23 | 24 | * Initial release. 25 | -------------------------------------------------------------------------------- /Marklight/MarklightStyleApplier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarklightStyleApplier 3 | // Marklight 4 | // 5 | // Created by Christian Tietze on 2017-07-20. 6 | // Copyright © 2017 MacTeo. See LICENSE for details. 7 | // 8 | 9 | import Foundation 10 | import CoreGraphics 11 | 12 | public protocol MarklightStyleApplier { 13 | func addAttribute(_ name: NSAttributedString.Key, value: Any, range: NSRange) 14 | func addAttributes(_ attrs: [NSAttributedString.Key : Any], range: NSRange) 15 | func removeAttribute(_ name: NSAttributedString.Key, range: NSRange) 16 | func resetMarklightTextAttributes(textSize: CGFloat, range: NSRange) 17 | } 18 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Marklight-OSX.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Marklight-OSX 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Marklight-macOS.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Marklight-macOS 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | -------------------------------------------------------------------------------- /Sample/Marklight Sample macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Marklight Sample macOS 4 | // 5 | // Created by Christian Tietze on 19.07.17. 6 | // Copyright © 2017 Dolomate. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | // Insert code here to initialize your application 18 | } 19 | 20 | func applicationWillTerminate(_ aNotification: Notification) { 21 | // Insert code here to tear down your application 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy.marklight 7 | CFBundleName 8 | Marklight 9 | DocSetPlatformFamily 10 | jazzy 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | .DS_Store 35 | -------------------------------------------------------------------------------- /Marklight macOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.2.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Marklight-iOS" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Marklight-iOS/Marklight.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Marklight" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Marklight-iOS" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Marklight-iOS/Marklight.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Marklight" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Marklight/UniversalTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UniversalTypes.swift 3 | // Marklight 4 | // 5 | // Created by Christian Tietze on 20.07.17. 6 | // Copyright © 2017 MacTeo. See LICENSE for details. 7 | // 8 | 9 | #if os(iOS) 10 | import UIKit 11 | 12 | typealias MarklightColor = UIColor 13 | typealias MarklightFont = UIFont 14 | typealias MarklightFontDescriptor = UIFontDescriptor 15 | #elseif os(macOS) 16 | import AppKit 17 | 18 | 19 | typealias MarklightColor = NSColor 20 | typealias MarklightFont = NSFont 21 | typealias MarklightFontDescriptor = NSFontDescriptor 22 | 23 | extension NSFont { 24 | static func italicSystemFont(ofSize size: CGFloat) -> NSFont { 25 | return NSFontManager().convert(NSFont.systemFont(ofSize: size), toHaveTrait: .italicFontMask) 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /MarklightTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sample/Pods/Local Podspecs/Marklight.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Marklight", 3 | "version": "1.4.0", 4 | "summary": "Markdown syntax highlighter for iOS and macOS.", 5 | "description": "Marklight is a drop in component to easily add realtime markdown syntax highlight on any user editable text view on iOS applications.", 6 | "homepage": "https://github.com/macteo/Marklight", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "Matteo Gavagnin": "m@macteo.it" 13 | }, 14 | "social_media_url": "https://twitter.com/macteo", 15 | "platforms": { 16 | "ios": "8.0", 17 | "osx": "10.11" 18 | }, 19 | "source": { 20 | "git": "https://github.com/macteo/Marklight.git", 21 | "tag": "v1.4.0" 22 | }, 23 | "source_files": "Marklight/**/*.{swift}", 24 | "requires_arc": true 25 | } 26 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CODE_SIGN_IDENTITY = 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Marklight-macOS" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 6 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Marklight-macOS/Marklight.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Marklight" 8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 9 | PODS_BUILD_DIR = $BUILD_DIR 10 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 12 | PODS_ROOT = ${SRCROOT}/Pods 13 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CODE_SIGN_IDENTITY = 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Marklight-macOS" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 6 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Marklight-macOS/Marklight.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Marklight" 8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 9 | PODS_BUILD_DIR = $BUILD_DIR 10 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 12 | PODS_ROOT = ${SRCROOT}/Pods 13 | -------------------------------------------------------------------------------- /Marklight/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.5.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Marklight macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.5.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2017 Dolomate. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-OSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.4.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Marklight-macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.4.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Marklight.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "Marklight" 3 | s.version = "1.5.0" 4 | s.summary = "Markdown syntax highlighter for iOS and macOS." 5 | s.description = <<-DESC 6 | Marklight is a drop in component to easily add realtime markdown syntax highlight on any user editable text view on iOS applications. 7 | DESC 8 | s.homepage = "https://github.com/macteo/Marklight" 9 | s.license = { :type => "MIT", :file => "LICENSE" } 10 | s.author = { "Matteo Gavagnin" => "m@macteo.it" } 11 | s.social_media_url = "https://twitter.com/macteo" 12 | 13 | s.ios.deployment_target = "8.0" 14 | s.osx.deployment_target = "10.11" 15 | 16 | s.source = { :git => "https://github.com/macteo/Marklight.git", :tag => "v#{s.version}" } 17 | s.source_files = "Marklight/**/*.{swift}" 18 | s.requires_arc = true 19 | 20 | s.swift_version = '4.2' 21 | end 22 | -------------------------------------------------------------------------------- /Sample/Marklight Sample macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.5.0 21 | CFBundleVersion 22 | 8 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2017 Dolomate. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Sample/Marklight Sample macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | -------------------------------------------------------------------------------- /Marklight/MarklightTextProcessingResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarklightTextProcessingResult 3 | // Marklight 4 | // 5 | // Created by Christian Tietze on 2017-07-20. 6 | // Copyright © 2017 MacTeo. See LICENSE for details. 7 | // 8 | 9 | #if os(iOS) 10 | import UIKit 11 | #elseif os(macOS) 12 | import Foundation 13 | import AppKit 14 | #endif 15 | 16 | public struct MarklightProcessingResult { 17 | public let editedRange: NSRange 18 | public let affectedRange: NSRange 19 | 20 | public init(editedRange: NSRange, affectedRange: NSRange) { 21 | 22 | self.editedRange = editedRange 23 | self.affectedRange = affectedRange 24 | } 25 | 26 | public func updateLayoutManagers(for textStorage: NSTextStorage) { 27 | 28 | textStorage.layoutManagers.forEach { 29 | $0.processEditing( 30 | for: textStorage, 31 | processingResult: self) 32 | } 33 | } 34 | } 35 | 36 | extension NSLayoutManager { 37 | func processEditing(for textStorage: NSTextStorage, processingResult: MarklightProcessingResult) { 38 | 39 | self.processEditing( 40 | for: textStorage, 41 | edited: .editedAttributes, 42 | range: processingResult.editedRange, 43 | changeInLength: 0, 44 | invalidatedRange: processingResult.affectedRange) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | -------------------------------------------------------------------------------- /Sample/Sample.md: -------------------------------------------------------------------------------- 1 | _Paragraphs_ are separated by a blank line. 2 | 3 | # H1 header 4 | 5 | 2nd paragraph: you can write `monospace`, single word *italic* or *an entire phrase in italic*. **Bold** is also supported, even on **multiple words**. 6 | 7 | Itemized lists look like: 8 | 9 | * this one 10 | * that one 11 | * the other one 12 | 13 | > Block quotes are written like so. 14 | > 15 | > They can span multiple paragraphs, if you like. 16 | 17 | 18 | ## H2 header 19 | 20 | Here's a numbered list: 21 | 22 | 1. first item 23 | 2. second item 24 | 3. third item 25 | 26 | # Let me re-iterate ... 27 | for i in 1 .. 10 { do-something(i) } 28 | 29 | As you probably guessed, indented 4 spaces. By the way, instead of 30 | indenting the block, you can use delimited blocks, if you like: 31 | 32 | ``` 33 | define foobar() { 34 | print "Welcome to flavor country!"; 35 | } 36 | ``` 37 | 38 | https://example.com 39 | 40 | mailto:m@example.com 41 | 42 | ### An h3 header ### 43 | 44 | Now a nested list: 45 | 46 | 1. First, get these ingredients: 47 | 48 | * carrots 49 | * celery 50 | * lentils 51 | 52 | 2. Boil some water. 53 | 54 | 3. Dump everything in the pot. 55 | 56 | Here's a link to [a website](http://example.com), to a [local doc](local-doc.html), and to a [section heading in the current doc](#an-h2-header). Here's a reference link [1]. 57 | 58 | [1]: Footnote text goes here. 59 | 60 | ![example image](example-image.jpg) 61 | -------------------------------------------------------------------------------- /Sample/Marklight Sample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /Sample/Marklight Sample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Marklight 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.5.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 8 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationPortraitUpsideDown 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Sample/Marklight Sample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Sample/Marklight Sample macOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Marklight Sample macOS 4 | // 5 | // Created by Christian Tietze on 2017-07-19. 6 | // Copyright © 2017 MacTeo. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import Marklight 11 | 12 | class ViewController: NSViewController { 13 | 14 | @IBOutlet var textView: NSTextView! 15 | let textStorage = MarklightTextStorage() 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | textStorage.marklightTextProcessor.codeColor = NSColor.orange 21 | textStorage.marklightTextProcessor.quoteColor = NSColor.darkGray 22 | textStorage.marklightTextProcessor.syntaxColor = NSColor.blue 23 | textStorage.marklightTextProcessor.codeFontName = "Courier" 24 | textStorage.marklightTextProcessor.textSize = 18.0 25 | textStorage.marklightTextProcessor.hideSyntax = false 26 | 27 | textView.layoutManager?.replaceTextStorage(textStorage) 28 | 29 | textView.textContainerInset = NSSize(width: 10, height: 8) 30 | textView.isAutomaticQuoteSubstitutionEnabled = false 31 | textView.isAutomaticDashSubstitutionEnabled = false 32 | 33 | if let samplePath = Bundle.main.path(forResource: "Sample", ofType: "md"), 34 | let string = try? String(contentsOfFile: samplePath) { 35 | let attributedString = NSAttributedString(string: string) 36 | textStorage.append(attributedString) 37 | } 38 | } 39 | 40 | func isDarkMode(view: NSView?) -> Bool { 41 | if #available(OSX 10.14, *) { 42 | let appearance = view?.effectiveAppearance ?? NSAppearance.current! 43 | return (appearance.name == .darkAqua) 44 | } 45 | return false 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Marklight/MarklightRegex.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarklightRegex.swift 3 | // Marklight 4 | // 5 | // Created by Matteo Gavagnin on 30/08/2017. 6 | // 7 | 8 | import Foundation 9 | 10 | public struct MarklightRegex { 11 | public let regularExpression: NSRegularExpression! 12 | 13 | public init(pattern: String, options: NSRegularExpression.Options = NSRegularExpression.Options(rawValue: 0)) { 14 | var error: NSError? 15 | let re: NSRegularExpression? 16 | do { 17 | re = try NSRegularExpression(pattern: pattern, 18 | options: options) 19 | } catch let error1 as NSError { 20 | error = error1 21 | re = nil 22 | } 23 | 24 | // If re is nil, it means NSRegularExpression didn't like 25 | // the pattern we gave it. All regex patterns used by Markdown 26 | // should be valid, so this probably means that a pattern 27 | // valid for .NET Regex is not valid for NSRegularExpression. 28 | if re == nil { 29 | if let error = error { 30 | print("Regular expression error: \(error.userInfo)") 31 | } 32 | assert(re != nil) 33 | } 34 | 35 | self.regularExpression = re 36 | } 37 | 38 | public func matches(_ input: String, range: NSRange, 39 | completion: @escaping (_ result: NSTextCheckingResult?) -> Void) { 40 | let s = input as NSString 41 | let options = NSRegularExpression.MatchingOptions(rawValue: 0) 42 | regularExpression.enumerateMatches(in: s as String, 43 | options: options, 44 | range: range, 45 | using: { (result, flags, stop) -> Void in 46 | completion(result) 47 | }) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sample/Marklight Sample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sample/Marklight Sample.xcodeproj/xcshareddata/xcschemes/Marklight Sample iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Sample/Marklight Sample.xcodeproj/xcshareddata/xcschemes/Marklight Sample macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Marklight.xcodeproj/xcshareddata/xcschemes/Marklight macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Marklight.xcodeproj/xcshareddata/xcschemes/Marklight iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

Marklight Docs (100% documented)

16 |

View on GitHub

17 |
18 |
19 |
20 | 25 |
26 |
27 | 47 |
48 |
49 |
50 |

Structs

51 |

The following structs are available globally.

52 | 53 |
54 |
55 |
56 |
    57 |
  • 58 |
    59 | 60 | 61 | 62 | Marklight 63 | 64 |
    65 |
    66 |
    67 |
    68 |
    69 |
    70 |

    Marklight struct that parses a String inside a NSTextStorage 71 | subclass, looking for markdown syntax to be highlighted. Internally many 72 | regular expressions are used to detect the syntax. The highlights will be 73 | applied as attributes to the NSTextStorage’s NSAttributedString. You should 74 | create your our NSTextStorage subclass or use the readily available 75 | MarklightTextStorage class.

    76 | 77 |
    78 |

    See

    79 | MarklightTextStorage 80 | 81 |
    82 | 83 | See more 84 |
    85 |
    86 |

    Declaration

    87 |
    88 |

    Swift

    89 |
    public struct Marklight
    90 | 91 |
    92 |
    93 |
    94 | Show on GitHub 95 |
    96 |
    97 |
    98 |
  • 99 |
100 |
101 |
102 |
103 | 107 |
108 |
109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

Marklight Docs (100% documented)

16 |

View on GitHub

17 |
18 |
19 |
20 | 25 |
26 |
27 | 47 |
48 |
49 |
50 |

Structs

51 |

The following structs are available globally.

52 | 53 |
54 |
55 |
56 |
    57 |
  • 58 |
    59 | 60 | 61 | 62 | Marklight 63 | 64 |
    65 |
    66 |
    67 |
    68 |
    69 |
    70 |

    Marklight struct that parses a String inside a NSTextStorage 71 | subclass, looking for markdown syntax to be highlighted. Internally many 72 | regular expressions are used to detect the syntax. The highlights will be 73 | applied as attributes to the NSTextStorage’s NSAttributedString. You should 74 | create your our NSTextStorage subclass or use the readily available 75 | MarklightTextStorage class.

    76 | 77 |
    78 |

    See

    79 | MarklightTextStorage 80 | 81 |
    82 | 83 | See more 84 |
    85 |
    86 |

    Declaration

    87 |
    88 |

    Swift

    89 |
    public struct Marklight
    90 | 91 |
    92 |
    93 |
    94 | Show on GitHub 95 |
    96 |
    97 |
    98 |
  • 99 |
100 |
101 |
102 |
103 | 107 |
108 |
109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 12 | 13 | install_framework() 14 | { 15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 16 | local source="${BUILT_PRODUCTS_DIR}/$1" 17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 19 | elif [ -r "$1" ]; then 20 | local source="$1" 21 | fi 22 | 23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | 25 | if [ -L "${source}" ]; then 26 | echo "Symlinked..." 27 | source="$(readlink "${source}")" 28 | fi 29 | 30 | # Use filter instead of exclude so missing patterns don't throw errors. 31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 33 | 34 | local basename 35 | basename="$(basename -s .framework "$1")" 36 | binary="${destination}/${basename}.framework/${basename}" 37 | if ! [ -r "$binary" ]; then 38 | binary="${destination}/${basename}" 39 | fi 40 | 41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 43 | strip_invalid_archs "$binary" 44 | fi 45 | 46 | # Resign the code if required by the build settings to avoid unstable apps 47 | code_sign_if_enabled "${destination}/$(basename "$1")" 48 | 49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 51 | local swift_runtime_libs 52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 53 | for lib in $swift_runtime_libs; do 54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 56 | code_sign_if_enabled "${destination}/${lib}" 57 | done 58 | fi 59 | } 60 | 61 | # Copies the dSYM of a vendored framework 62 | install_dsym() { 63 | local source="$1" 64 | if [ -r "$source" ]; then 65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" 66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" 67 | fi 68 | } 69 | 70 | # Signs a framework with the provided identity 71 | code_sign_if_enabled() { 72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 73 | # Use the current code_sign_identitiy 74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 76 | 77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 78 | code_sign_cmd="$code_sign_cmd &" 79 | fi 80 | echo "$code_sign_cmd" 81 | eval "$code_sign_cmd" 82 | fi 83 | } 84 | 85 | # Strip invalid architectures 86 | strip_invalid_archs() { 87 | binary="$1" 88 | # Get architectures for current file 89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 90 | stripped="" 91 | for arch in $archs; do 92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 93 | # Strip non-valid architectures in-place 94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 95 | stripped="$stripped $arch" 96 | fi 97 | done 98 | if [[ "$stripped" ]]; then 99 | echo "Stripped $binary of architectures:$stripped" 100 | fi 101 | } 102 | 103 | 104 | if [[ "$CONFIGURATION" == "Debug" ]]; then 105 | install_framework "${BUILT_PRODUCTS_DIR}/Marklight-iOS/Marklight.framework" 106 | fi 107 | if [[ "$CONFIGURATION" == "Release" ]]; then 108 | install_framework "${BUILT_PRODUCTS_DIR}/Marklight-iOS/Marklight.framework" 109 | fi 110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 111 | wait 112 | fi 113 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 12 | 13 | install_framework() 14 | { 15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 16 | local source="${BUILT_PRODUCTS_DIR}/$1" 17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 19 | elif [ -r "$1" ]; then 20 | local source="$1" 21 | fi 22 | 23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | 25 | if [ -L "${source}" ]; then 26 | echo "Symlinked..." 27 | source="$(readlink "${source}")" 28 | fi 29 | 30 | # Use filter instead of exclude so missing patterns don't throw errors. 31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 33 | 34 | local basename 35 | basename="$(basename -s .framework "$1")" 36 | binary="${destination}/${basename}.framework/${basename}" 37 | if ! [ -r "$binary" ]; then 38 | binary="${destination}/${basename}" 39 | fi 40 | 41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 43 | strip_invalid_archs "$binary" 44 | fi 45 | 46 | # Resign the code if required by the build settings to avoid unstable apps 47 | code_sign_if_enabled "${destination}/$(basename "$1")" 48 | 49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 51 | local swift_runtime_libs 52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 53 | for lib in $swift_runtime_libs; do 54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 56 | code_sign_if_enabled "${destination}/${lib}" 57 | done 58 | fi 59 | } 60 | 61 | # Copies the dSYM of a vendored framework 62 | install_dsym() { 63 | local source="$1" 64 | if [ -r "$source" ]; then 65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" 66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" 67 | fi 68 | } 69 | 70 | # Signs a framework with the provided identity 71 | code_sign_if_enabled() { 72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 73 | # Use the current code_sign_identitiy 74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 76 | 77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 78 | code_sign_cmd="$code_sign_cmd &" 79 | fi 80 | echo "$code_sign_cmd" 81 | eval "$code_sign_cmd" 82 | fi 83 | } 84 | 85 | # Strip invalid architectures 86 | strip_invalid_archs() { 87 | binary="$1" 88 | # Get architectures for current file 89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 90 | stripped="" 91 | for arch in $archs; do 92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 93 | # Strip non-valid architectures in-place 94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 95 | stripped="$stripped $arch" 96 | fi 97 | done 98 | if [[ "$stripped" ]]; then 99 | echo "Stripped $binary of architectures:$stripped" 100 | fi 101 | } 102 | 103 | 104 | if [[ "$CONFIGURATION" == "Debug" ]]; then 105 | install_framework "${BUILT_PRODUCTS_DIR}/Marklight-macOS/Marklight.framework" 106 | fi 107 | if [[ "$CONFIGURATION" == "Release" ]]; then 108 | install_framework "${BUILT_PRODUCTS_DIR}/Marklight-macOS/Marklight.framework" 109 | fi 110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 111 | wait 112 | fi 113 | -------------------------------------------------------------------------------- /MarklightTests/MarklightTextProcessorTests.swift: -------------------------------------------------------------------------------- 1 | // Created by Christian Tietze on 2017-07-20. 2 | // Copyright © 2017 MacTeo. See LICENSE for details. 3 | 4 | import XCTest 5 | @testable import Marklight 6 | 7 | extension NSRange { 8 | public static func ==(lhs: NSRange, rhs: NSRange) -> Bool { 9 | return lhs.location == rhs.location && lhs.length == rhs.length 10 | } 11 | 12 | public var description: String { 13 | return "NSRange(\(location), \(length))" 14 | } 15 | } 16 | 17 | class MarklightTextProcessorTests: XCTestCase { 18 | 19 | class StyleApplierDouble: MarklightStyleApplier { 20 | 21 | var didAddAttributes: (attributes: [NSAttributedString.Key : Any], range: NSRange)? 22 | func addAttributes(_ attrs: [NSAttributedString.Key : Any], range: NSRange) { 23 | didAddAttributes = (attrs, range) 24 | } 25 | 26 | var didAddAttribute: (name: NSAttributedString.Key, value: Any, range: NSRange)? 27 | func addAttribute(_ name: NSAttributedString.Key, value: Any, range: NSRange) { 28 | didAddAttribute = (name, value, range) 29 | } 30 | 31 | var didRemoveAttribute: (name: NSAttributedString.Key, range: NSRange)? 32 | func removeAttribute(_ name: NSAttributedString.Key, range: NSRange) { 33 | didRemoveAttribute = (name, range) 34 | } 35 | 36 | var didResetMarklightTextAttributes: (textSize: CGFloat, range: NSRange)? 37 | func resetMarklightTextAttributes(textSize: CGFloat, range: NSRange) { 38 | didResetMarklightTextAttributes = (textSize, range) 39 | } 40 | } 41 | 42 | var styleApplierDouble: StyleApplierDouble! 43 | 44 | override func setUp() { 45 | super.setUp() 46 | styleApplierDouble = StyleApplierDouble() 47 | } 48 | 49 | override func tearDown() { 50 | styleApplierDouble = nil 51 | super.tearDown() 52 | } 53 | 54 | 55 | func testProcess_EditedSingleLine_ResetsAttributesForWholeLine() { 56 | 57 | let string = "single" 58 | let editedRange = NSRange(location: 0, length: 0) 59 | 60 | let result = MarklightTextProcessor().processEditing(styleApplier: styleApplierDouble, string: string, editedRange: editedRange) 61 | 62 | let expectedAffectedRange = NSRange(location: 0, length: 6) 63 | XCTAssertNotNil(styleApplierDouble.didResetMarklightTextAttributes) 64 | if let values = styleApplierDouble.didResetMarklightTextAttributes { 65 | XCTAssertEqual(values.range, expectedAffectedRange) 66 | } 67 | 68 | XCTAssertEqual(result.editedRange, editedRange) 69 | XCTAssertEqual(result.affectedRange, expectedAffectedRange) 70 | } 71 | 72 | 73 | func testProcess_EditedFirstLine_ResetsAttributesForFirstAndSecondLine() { 74 | 75 | let string = "1\n2\n3\n" 76 | let editedRange = NSRange(location: 0, length: 0) 77 | 78 | let result = MarklightTextProcessor().processEditing(styleApplier: styleApplierDouble, string: string, editedRange: editedRange) 79 | 80 | let expectedAffectedRange = NSRange(location: 0, length: 4) 81 | XCTAssertNotNil(styleApplierDouble.didResetMarklightTextAttributes) 82 | if let values = styleApplierDouble.didResetMarklightTextAttributes { 83 | XCTAssertEqual(values.range, expectedAffectedRange) 84 | } 85 | 86 | XCTAssertEqual(result.editedRange, editedRange) 87 | XCTAssertEqual(result.affectedRange, expectedAffectedRange) 88 | } 89 | 90 | func testProcess_EditedLineWithEmptyLinesAround_ResetsAttributesForEmptyLines() { 91 | 92 | let string = "_\n\nxx\n\n_\n" 93 | // ^ ^^^ ^ 94 | let editedRange = NSRange(location: 4, length: 0) 95 | 96 | let result = MarklightTextProcessor().processEditing(styleApplier: styleApplierDouble, string: string, editedRange: editedRange) 97 | 98 | let expectedAffectedRange = NSRange(location: 2, length: 5) 99 | XCTAssertNotNil(styleApplierDouble.didResetMarklightTextAttributes) 100 | if let values = styleApplierDouble.didResetMarklightTextAttributes { 101 | XCTAssertEqual(values.range, expectedAffectedRange) 102 | } 103 | 104 | XCTAssertEqual(result.editedRange, editedRange) 105 | XCTAssertEqual(result.affectedRange, expectedAffectedRange) 106 | } 107 | 108 | func testProcess_EditedAtMiddleOfMiddleLine_ResetsAttributesForSurroundingLines() { 109 | 110 | let string = "1\n2\n3333\n4\n5\n" 111 | // ^^ ^^^^^ ^^ 112 | let editedRange = NSRange(location: 6, length: 0) 113 | 114 | let result = MarklightTextProcessor().processEditing(styleApplier: styleApplierDouble, string: string, editedRange: editedRange) 115 | 116 | let expectedAffectedRange = NSRange(location: 2, length: 9) 117 | XCTAssertNotNil(styleApplierDouble.didResetMarklightTextAttributes) 118 | if let values = styleApplierDouble.didResetMarklightTextAttributes { 119 | XCTAssertEqual(values.range, expectedAffectedRange) 120 | } 121 | 122 | XCTAssertEqual(result.editedRange, editedRange) 123 | XCTAssertEqual(result.affectedRange, expectedAffectedRange) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Marklight 2 | Copyright (c) 2016 Matteo Gavagnin 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | ------------------------------------------------------------------------------ 24 | 25 | Markdown.swift 26 | Copyright (c) 2014 Kristopher Johnson 27 | 28 | Permission is hereby granted, free of charge, to any person obtaining 29 | a copy of this software and associated documentation files (the 30 | "Software"), to deal in the Software without restriction, including 31 | without limitation the rights to use, copy, modify, merge, publish, 32 | distribute, sublicense, and/or sell copies of the Software, and to 33 | permit persons to whom the Software is furnished to do so, subject to 34 | the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be 37 | included in all copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 42 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 43 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 44 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 45 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 46 | 47 | Markdown.swift is based on MarkdownSharp, whose licenses and history are 48 | enumerated in the following sections. 49 | 50 | ------------------------------------------------------------------------------ 51 | 52 | MarkdownSharp 53 | ------------- 54 | a C# Markdown processor 55 | 56 | Markdown is a text-to-HTML conversion tool for web writers 57 | Copyright (c) 2004 John Gruber 58 | http://daringfireball.net/projects/markdown/ 59 | 60 | Markdown.NET 61 | Copyright (c) 2004-2009 Milan Negovan 62 | http://www.aspnetresources.com 63 | http://aspnetresources.com/blog/markdown_announced.aspx 64 | 65 | MarkdownSharp 66 | Copyright (c) 2009-2011 Jeff Atwood 67 | http://stackoverflow.com 68 | http://www.codinghorror.com/blog/ 69 | http://code.google.com/p/markdownsharp/ 70 | 71 | History: Milan ported the Markdown processor to C#. He granted license to me so I can open source it 72 | and let the community contribute to and improve MarkdownSharp. 73 | 74 | ------------------------------------------------------------------------------ 75 | 76 | Copyright (c) 2009 - 2010 Jeff Atwood 77 | 78 | http://www.opensource.org/licenses/mit-license.php 79 | 80 | Permission is hereby granted, free of charge, to any person obtaining a copy 81 | of this software and associated documentation files (the "Software"), to deal 82 | in the Software without restriction, including without limitation the rights 83 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 84 | copies of the Software, and to permit persons to whom the Software is 85 | furnished to do so, subject to the following conditions: 86 | 87 | The above copyright notice and this permission notice shall be included in 88 | all copies or substantial portions of the Software. 89 | 90 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 91 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 92 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 93 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 94 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 95 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 96 | THE SOFTWARE. 97 | 98 | ------------------------------------------------------------------------------ 99 | 100 | Copyright (c) 2003-2004 John Gruber 101 | 102 | All rights reserved. 103 | 104 | Redistribution and use in source and binary forms, with or without 105 | modification, are permitted provided that the following conditions are 106 | met: 107 | 108 | Redistributions of source code must retain the above copyright notice, 109 | this list of conditions and the following disclaimer. 110 | 111 | Redistributions in binary form must reproduce the above copyright 112 | notice, this list of conditions and the following disclaimer in the 113 | documentation and/or other materials provided with the distribution. 114 | 115 | Neither the name "Markdown" nor the names of its contributors may 116 | be used to endorse or promote products derived from this software 117 | without specific prior written permission. 118 | 119 | This software is provided by the copyright holders and contributors "as 120 | is" and any express or implied warranties, including, but not limited 121 | to, the implied warranties of merchantability and fitness for a 122 | particular purpose are disclaimed. In no event shall the copyright owner 123 | or contributors be liable for any direct, indirect, incidental, special, 124 | exemplary, or consequential damages (including, but not limited to, 125 | procurement of substitute goods or services; loss of use, data, or 126 | profits; or business interruption) however caused and on any theory of 127 | liability, whether in contract, strict liability, or tort (including 128 | negligence or otherwise) arising in any way out of the use of this 129 | software, even if advised of the possibility of such damage. 130 | -------------------------------------------------------------------------------- /Marklight/MarklightTextProcessor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarklightTextProcessor 3 | // Marklight 4 | // 5 | // Created by Christian Tietze on 2017-07-20. 6 | // Copyright © 2017 MacTeo. LICENSE for details. 7 | // 8 | 9 | #if os(iOS) 10 | import UIKit 11 | #elseif os(macOS) 12 | import AppKit 13 | #endif 14 | 15 | 16 | open class MarklightTextProcessor { 17 | 18 | // MARK: Syntax highlight customisation 19 | 20 | /** 21 | Color used to highlight markdown syntax. Default value is light grey. 22 | */ 23 | open var syntaxColor = MarklightColor.lightGray 24 | 25 | /** 26 | Font used for blocks and inline code. Default value is *Menlo*. 27 | */ 28 | open var codeFontName = "Menlo" 29 | 30 | /** 31 | `MarklightColor` used for blocks and inline code. Default value is dark grey. 32 | */ 33 | open var codeColor = MarklightColor.darkGray 34 | 35 | /** 36 | Font used for quote blocks. Default value is *Menlo*. 37 | */ 38 | open var quoteFontName = "Menlo" 39 | 40 | /** 41 | `MarklightColor` used for quote blocks. Default value is dark grey. 42 | */ 43 | open var quoteColor = MarklightColor.darkGray 44 | 45 | /** 46 | Quote indentation in points. Default 20. 47 | */ 48 | open var quoteIndendation : CGFloat = 20 49 | 50 | /** 51 | If the markdown syntax should be hidden or visible 52 | */ 53 | open var hideSyntax = false 54 | 55 | // MARK: Initializers 56 | 57 | public init() {} 58 | 59 | // MARK: Syntax highlighting 60 | 61 | open func processEditing( 62 | styleApplier: MarklightStyleApplier, 63 | string: String, 64 | editedRange: NSRange 65 | ) -> MarklightProcessingResult { 66 | 67 | let editedAndAdjacentParagraphRange = self.editedAndAdjacentParagraphRange(in: string, editedRange: editedRange) 68 | 69 | Marklight.syntaxColor = syntaxColor 70 | Marklight.codeFontName = codeFontName 71 | Marklight.codeColor = codeColor 72 | Marklight.quoteFontName = quoteFontName 73 | Marklight.quoteColor = quoteColor 74 | Marklight.quoteIndendation = quoteIndendation 75 | Marklight.textSize = textSize 76 | Marklight.hideSyntax = hideSyntax 77 | 78 | resetMarklightAttributes( 79 | styleApplier: styleApplier, 80 | range: editedAndAdjacentParagraphRange) 81 | Marklight.applyMarkdownStyle( 82 | styleApplier, 83 | string: string, 84 | affectedRange: editedAndAdjacentParagraphRange) 85 | 86 | return MarklightProcessingResult( 87 | editedRange: editedRange, 88 | affectedRange: editedAndAdjacentParagraphRange) 89 | } 90 | 91 | fileprivate func editedAndAdjacentParagraphRange(in string: String, editedRange: NSRange) -> NSRange { 92 | let nsString = string as NSString 93 | let editedParagraphRange = nsString.paragraphRange(for: editedRange) 94 | 95 | let previousParagraphRange: NSRange 96 | if editedParagraphRange.location > 0 { 97 | previousParagraphRange = nsString.paragraphRange(at: editedParagraphRange.location - 1) 98 | } else { 99 | previousParagraphRange = NSRange(location: editedParagraphRange.location, length: 0) 100 | } 101 | 102 | let nextParagraphRange: NSRange 103 | let locationAfterEditedParagraph = editedParagraphRange.location + editedParagraphRange.length 104 | if locationAfterEditedParagraph < nsString.length { 105 | nextParagraphRange = nsString.paragraphRange(at: locationAfterEditedParagraph) 106 | } else { 107 | nextParagraphRange = NSRange.init(location: 0, length: 0) 108 | } 109 | 110 | return NSRange( 111 | location: previousParagraphRange.location, 112 | length: [previousParagraphRange, editedParagraphRange, nextParagraphRange].map { $0.length }.reduce(0, +)) 113 | } 114 | 115 | fileprivate func resetMarklightAttributes(styleApplier: MarklightStyleApplier, range: NSRange) { 116 | 117 | styleApplier.resetMarklightTextAttributes( 118 | textSize: self.textSize, 119 | range: range) 120 | } 121 | 122 | #if os(iOS) 123 | 124 | // MARK: Font Style Settings 125 | 126 | /** 127 | Dynamic type font text style, default `UIFontTextStyleBody`. 128 | 129 | - see: [Text Styles](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/UIFontDescriptor_Class/index.html#//apple_ref/doc/constant_group/Text_Styles) 130 | */ 131 | open var fontTextStyle : String = UIFont.TextStyle.body.rawValue 132 | 133 | /// Text size measured in points. 134 | fileprivate var textSize: CGFloat { 135 | return MarklightFontDescriptor 136 | .preferredFontDescriptor(withTextStyle: UIFont.TextStyle(rawValue: self.fontTextStyleValidated)) 137 | .pointSize 138 | } 139 | 140 | // We are validating the user provided fontTextStyle `String` to match the 141 | // system supported ones. 142 | fileprivate var fontTextStyleValidated : String { 143 | 144 | let supportedTextStyles: [String] = { 145 | 146 | let baseStyles = [ 147 | UIFont.TextStyle.headline.rawValue, 148 | UIFont.TextStyle.subheadline.rawValue, 149 | UIFont.TextStyle.body.rawValue, 150 | UIFont.TextStyle.footnote.rawValue, 151 | UIFont.TextStyle.caption1.rawValue, 152 | UIFont.TextStyle.caption2.rawValue 153 | ] 154 | 155 | guard #available(iOS 9.0, *) else { return baseStyles } 156 | 157 | return baseStyles.appending(contentsOf: [ 158 | UIFont.TextStyle.title1.rawValue, 159 | UIFont.TextStyle.title2.rawValue, 160 | UIFont.TextStyle.title3.rawValue, 161 | UIFont.TextStyle.callout.rawValue 162 | ]) 163 | }() 164 | 165 | guard supportedTextStyles.contains(self.fontTextStyle) else { 166 | return UIFont.TextStyle.body.rawValue 167 | } 168 | 169 | return self.fontTextStyle 170 | } 171 | 172 | #elseif os(macOS) 173 | 174 | open var textSize: CGFloat = NSFont.systemFontSize 175 | 176 | #endif 177 | } 178 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Marklight 5 | 6 | Marklight 7 | Copyright (c) 2016 Matteo Gavagnin 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | ------------------------------------------------------------------------------ 29 | 30 | Markdown.swift 31 | Copyright (c) 2014 Kristopher Johnson 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining 34 | a copy of this software and associated documentation files (the 35 | "Software"), to deal in the Software without restriction, including 36 | without limitation the rights to use, copy, modify, merge, publish, 37 | distribute, sublicense, and/or sell copies of the Software, and to 38 | permit persons to whom the Software is furnished to do so, subject to 39 | the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be 42 | included in all copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 45 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 46 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 47 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 48 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 49 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 50 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | 52 | Markdown.swift is based on MarkdownSharp, whose licenses and history are 53 | enumerated in the following sections. 54 | 55 | ------------------------------------------------------------------------------ 56 | 57 | MarkdownSharp 58 | ------------- 59 | a C# Markdown processor 60 | 61 | Markdown is a text-to-HTML conversion tool for web writers 62 | Copyright (c) 2004 John Gruber 63 | http://daringfireball.net/projects/markdown/ 64 | 65 | Markdown.NET 66 | Copyright (c) 2004-2009 Milan Negovan 67 | http://www.aspnetresources.com 68 | http://aspnetresources.com/blog/markdown_announced.aspx 69 | 70 | MarkdownSharp 71 | Copyright (c) 2009-2011 Jeff Atwood 72 | http://stackoverflow.com 73 | http://www.codinghorror.com/blog/ 74 | http://code.google.com/p/markdownsharp/ 75 | 76 | History: Milan ported the Markdown processor to C#. He granted license to me so I can open source it 77 | and let the community contribute to and improve MarkdownSharp. 78 | 79 | ------------------------------------------------------------------------------ 80 | 81 | Copyright (c) 2009 - 2010 Jeff Atwood 82 | 83 | http://www.opensource.org/licenses/mit-license.php 84 | 85 | Permission is hereby granted, free of charge, to any person obtaining a copy 86 | of this software and associated documentation files (the "Software"), to deal 87 | in the Software without restriction, including without limitation the rights 88 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 89 | copies of the Software, and to permit persons to whom the Software is 90 | furnished to do so, subject to the following conditions: 91 | 92 | The above copyright notice and this permission notice shall be included in 93 | all copies or substantial portions of the Software. 94 | 95 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 96 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 97 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 98 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 99 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 100 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 101 | THE SOFTWARE. 102 | 103 | ------------------------------------------------------------------------------ 104 | 105 | Copyright (c) 2003-2004 John Gruber 106 | 107 | All rights reserved. 108 | 109 | Redistribution and use in source and binary forms, with or without 110 | modification, are permitted provided that the following conditions are 111 | met: 112 | 113 | Redistributions of source code must retain the above copyright notice, 114 | this list of conditions and the following disclaimer. 115 | 116 | Redistributions in binary form must reproduce the above copyright 117 | notice, this list of conditions and the following disclaimer in the 118 | documentation and/or other materials provided with the distribution. 119 | 120 | Neither the name "Markdown" nor the names of its contributors may 121 | be used to endorse or promote products derived from this software 122 | without specific prior written permission. 123 | 124 | This software is provided by the copyright holders and contributors "as 125 | is" and any express or implied warranties, including, but not limited 126 | to, the implied warranties of merchantability and fitness for a 127 | particular purpose are disclaimed. In no event shall the copyright owner 128 | or contributors be liable for any direct, indirect, incidental, special, 129 | exemplary, or consequential damages (including, but not limited to, 130 | procurement of substitute goods or services; loss of use, data, or 131 | profits; or business interruption) however caused and on any theory of 132 | liability, whether in contract, strict liability, or tort (including 133 | negligence or otherwise) arising in any way out of the use of this 134 | software, even if advised of the possibility of such damage. 135 | 136 | Generated by CocoaPods - https://cocoapods.org 137 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Marklight 5 | 6 | Marklight 7 | Copyright (c) 2016 Matteo Gavagnin 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | ------------------------------------------------------------------------------ 29 | 30 | Markdown.swift 31 | Copyright (c) 2014 Kristopher Johnson 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining 34 | a copy of this software and associated documentation files (the 35 | "Software"), to deal in the Software without restriction, including 36 | without limitation the rights to use, copy, modify, merge, publish, 37 | distribute, sublicense, and/or sell copies of the Software, and to 38 | permit persons to whom the Software is furnished to do so, subject to 39 | the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be 42 | included in all copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 45 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 46 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 47 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 48 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 49 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 50 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | 52 | Markdown.swift is based on MarkdownSharp, whose licenses and history are 53 | enumerated in the following sections. 54 | 55 | ------------------------------------------------------------------------------ 56 | 57 | MarkdownSharp 58 | ------------- 59 | a C# Markdown processor 60 | 61 | Markdown is a text-to-HTML conversion tool for web writers 62 | Copyright (c) 2004 John Gruber 63 | http://daringfireball.net/projects/markdown/ 64 | 65 | Markdown.NET 66 | Copyright (c) 2004-2009 Milan Negovan 67 | http://www.aspnetresources.com 68 | http://aspnetresources.com/blog/markdown_announced.aspx 69 | 70 | MarkdownSharp 71 | Copyright (c) 2009-2011 Jeff Atwood 72 | http://stackoverflow.com 73 | http://www.codinghorror.com/blog/ 74 | http://code.google.com/p/markdownsharp/ 75 | 76 | History: Milan ported the Markdown processor to C#. He granted license to me so I can open source it 77 | and let the community contribute to and improve MarkdownSharp. 78 | 79 | ------------------------------------------------------------------------------ 80 | 81 | Copyright (c) 2009 - 2010 Jeff Atwood 82 | 83 | http://www.opensource.org/licenses/mit-license.php 84 | 85 | Permission is hereby granted, free of charge, to any person obtaining a copy 86 | of this software and associated documentation files (the "Software"), to deal 87 | in the Software without restriction, including without limitation the rights 88 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 89 | copies of the Software, and to permit persons to whom the Software is 90 | furnished to do so, subject to the following conditions: 91 | 92 | The above copyright notice and this permission notice shall be included in 93 | all copies or substantial portions of the Software. 94 | 95 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 96 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 97 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 98 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 99 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 100 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 101 | THE SOFTWARE. 102 | 103 | ------------------------------------------------------------------------------ 104 | 105 | Copyright (c) 2003-2004 John Gruber 106 | 107 | All rights reserved. 108 | 109 | Redistribution and use in source and binary forms, with or without 110 | modification, are permitted provided that the following conditions are 111 | met: 112 | 113 | Redistributions of source code must retain the above copyright notice, 114 | this list of conditions and the following disclaimer. 115 | 116 | Redistributions in binary form must reproduce the above copyright 117 | notice, this list of conditions and the following disclaimer in the 118 | documentation and/or other materials provided with the distribution. 119 | 120 | Neither the name "Markdown" nor the names of its contributors may 121 | be used to endorse or promote products derived from this software 122 | without specific prior written permission. 123 | 124 | This software is provided by the copyright holders and contributors "as 125 | is" and any express or implied warranties, including, but not limited 126 | to, the implied warranties of merchantability and fitness for a 127 | particular purpose are disclaimed. In no event shall the copyright owner 128 | or contributors be liable for any direct, indirect, incidental, special, 129 | exemplary, or consequential damages (including, but not limited to, 130 | procurement of substitute goods or services; loss of use, data, or 131 | profits; or business interruption) however caused and on any theory of 132 | liability, whether in contract, strict liability, or tort (including 133 | negligence or otherwise) arising in any way out of the use of this 134 | software, even if advised of the possibility of such damage. 135 | 136 | Generated by CocoaPods - https://cocoapods.org 137 | -------------------------------------------------------------------------------- /Sample/Marklight Sample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Marklight Sample 4 | // 5 | // Created by Matteo Gavagnin on 01/01/16. 6 | // Copyright © 2016 MacTeo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // Import the Marklight framework 12 | import Marklight 13 | 14 | class ViewController: UIViewController, UITextViewDelegate { 15 | 16 | // Keep strong instance of the `NSTextStorage` subclass 17 | let textStorage = MarklightTextStorage() 18 | 19 | var textView : UITextView? 20 | 21 | // Connect the `textView`'s bottom layout constraint to react to keyboard movements 22 | var bottomTextViewConstraint: NSLayoutConstraint? 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | 27 | textStorage.marklightTextProcessor.codeColor = UIColor.orange 28 | textStorage.marklightTextProcessor.quoteColor = UIColor.darkGray 29 | textStorage.marklightTextProcessor.syntaxColor = UIColor.blue 30 | textStorage.marklightTextProcessor.codeFontName = "Courier" 31 | textStorage.marklightTextProcessor.fontTextStyle = UIFontTextStyle.subheadline.rawValue 32 | textStorage.marklightTextProcessor.hideSyntax = false 33 | 34 | let layoutManager = NSLayoutManager() 35 | 36 | // Assign the `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass 37 | textStorage.addLayoutManager(layoutManager) 38 | 39 | let textContainer = NSTextContainer() 40 | layoutManager.addTextContainer(textContainer) 41 | 42 | textView = UITextView(frame: view.bounds, textContainer: textContainer) 43 | guard let textView = textView else { return } 44 | 45 | textView.frame = view.bounds 46 | textView.translatesAutoresizingMaskIntoConstraints = false 47 | 48 | if #available(iOS 11.0, *) { 49 | textView.smartDashesType = .no 50 | textView.smartQuotesType = .no 51 | } 52 | 53 | view.addSubview(textView) 54 | 55 | view.addConstraint(NSLayoutConstraint(item: textView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0)) 56 | view.addConstraint(NSLayoutConstraint(item: textView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0)) 57 | view.addConstraint(NSLayoutConstraint(item: textView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)) 58 | bottomTextViewConstraint = NSLayoutConstraint(item: textView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0) 59 | guard let bottomTextViewConstraint = bottomTextViewConstraint else { return } 60 | view.addConstraint(bottomTextViewConstraint) 61 | 62 | // Add a beautiful padding to the `UITextView` content 63 | textView.textContainerInset = UIEdgeInsetsMake(4, 4, 4, 4) 64 | textView.delegate = self 65 | textView.isEditable = true 66 | 67 | // Load a sample markdown content from a file inside the app bundle 68 | if let samplePath = Bundle.main.path(forResource: "Sample", ofType: "md"){ 69 | do { 70 | let string = try String(contentsOfFile: samplePath) 71 | // Convert string to an `NSAttributedString` 72 | let attributedString = NSAttributedString(string: string) 73 | 74 | // Set the loaded string to the `UITextView` 75 | textStorage.append(attributedString) 76 | } catch _ { 77 | print("Cannot read Sample.md file") 78 | } 79 | } 80 | 81 | // We do some magic to resize the `UITextView` to react the the keyboard size change (appearance, disappearance, ecc) 82 | NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: OperationQueue.main) { (notification) -> Void in 83 | 84 | let initialRect = ((notification as NSNotification).userInfo![UIKeyboardFrameBeginUserInfoKey] as AnyObject).cgRectValue 85 | let _ = self.view.frame.size.height - self.view.convert(initialRect!, from: nil).origin.y 86 | let keyboardRect = ((notification as NSNotification).userInfo![UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue 87 | let newHeight = self.view.frame.size.height - self.view.convert(keyboardRect!, from: nil).origin.y 88 | 89 | guard let bottomTextViewConstraint = self.bottomTextViewConstraint else { return } 90 | bottomTextViewConstraint.constant = newHeight 91 | 92 | textView.setNeedsUpdateConstraints() 93 | 94 | let duration = ((notification as NSNotification).userInfo![UIKeyboardAnimationDurationUserInfoKey] as AnyObject).doubleValue 95 | let curve = ((notification as NSNotification).userInfo![UIKeyboardAnimationCurveUserInfoKey] as AnyObject).uintValue 96 | 97 | UIView.animate(withDuration: duration!, delay: 0, options: [UIViewAnimationOptions(rawValue: curve!), .beginFromCurrentState], animations: { () -> Void in 98 | textView.layoutIfNeeded() 99 | }, completion: { (finished) -> Void in 100 | 101 | }) 102 | } 103 | 104 | // Partial fixes to a long standing bug, to keep the caret inside the `UITextView` always visible 105 | NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextViewTextDidChange, object: textView, queue: OperationQueue.main) { (notification) -> Void in 106 | if textView.textStorage.string.hasSuffix("\n") { 107 | CATransaction.setCompletionBlock({ () -> Void in 108 | self.scrollToCaret(textView, animated: false) 109 | }) 110 | } else { 111 | self.scrollToCaret(textView, animated: false) 112 | } 113 | } 114 | } 115 | 116 | func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool { 117 | print("Should interact with: \(URL)") 118 | return true 119 | } 120 | 121 | func scrollToCaret(_ textView: UITextView, animated: Bool) { 122 | var rect = textView.caretRect(for: textView.selectedTextRange!.end) 123 | rect.size.height = rect.size.height + textView.textContainerInset.bottom 124 | textView.scrollRectToVisible(rect, animated: animated) 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marklight 2 | 3 | Markdown syntax highlighter for iOS and macOS. 4 | 5 | [![License MIT](https://img.shields.io/cocoapods/l/Marklight.svg)](https://raw.githubusercontent.com/macteo/marklight/master/LICENSE) [![Version](https://img.shields.io/cocoapods/v/Marklight.svg)](https://cocoapods.org/?q=marklight) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![travis-ci](https://travis-ci.org/macteo/Marklight.svg?branch=master)](https://travis-ci.org/macteo/Marklight) 6 | [![codecov.io](https://codecov.io/github/macteo/Marklight/coverage.svg?branch=feature/swift4)](https://codecov.io/github/macteo/Marklight?branch=master) 7 | ![Swift 4.1](https://img.shields.io/badge/language-Swift%204.1-EB7943.svg) ![iOS 8+](https://img.shields.io/badge/iOS-8+-EB7943.svg) 8 | 9 | ## Description 10 | 11 | Marklight is a drop in component to easily add realtime Markdown syntax highlight on any user editable text view in iOS and macOS applications. 12 | Marklight doesn't include HTML generation from Markdown, but you can use one of the many other components available like [Markingbird](https://github.com/kristopherjohnson/Markingbird). 13 | 14 | Regular expressions are taken from [Markingbird](https://github.com/kristopherjohnson/Markingbird), a Markdown parser and html generator. 15 | 16 | ![Marklight Gif](https://raw.githubusercontent.com/macteo/Marklight/master/Assets/marklight.gif)![Screenshot 0](https://raw.githubusercontent.com/macteo/Marklight/master/Assets/screenshot-0.png) 17 | 18 | ## Features 19 | 20 | - [x] Applicable to any `UITextView`. 21 | - [x] `NSTextStorage` subclass ready to use. 22 | - [x] Struct optimized for performances. 23 | - [x] Swift 4.1 compatible. 24 | - [x] Dynamic text style supported. 25 | - [x] Choose markdown syntax color. 26 | - [x] Choose font and color for code blocks. 27 | - [x] Choose font and color for quotes. 28 | - [x] Choose dynamic type font text style. 29 | - [x] Quote indentation. 30 | - [x] Documented. 31 | - [x] macOS compatibility. 32 | - [ ] Parsing tests. 33 | - [ ] Performance tests. 34 | 35 | ## Requirements 36 | 37 | - iOS 8.0+ 38 | - Xcode 9.3+ 39 | - macOS 10.11+ 40 | 41 | ## Installation 42 | 43 | ### CocoaPods 44 | 45 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: 46 | 47 | ```bash 48 | $ gem install cocoapods 49 | ``` 50 | 51 | > CocoaPods 1.0.0+ is required to build Marklight. 52 | 53 | To integrate Marklight into your Xcode project using CocoaPods, specify it in your `Podfile`: 54 | 55 | ```ruby 56 | source 'https://github.com/CocoaPods/Specs.git' 57 | platform :ios, '8.0' 58 | use_frameworks! 59 | 60 | pod 'Marklight' 61 | ``` 62 | 63 | Then, run the following command: 64 | 65 | ```bash 66 | $ pod install 67 | ``` 68 | 69 | ### Carthage 70 | 71 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. 72 | 73 | You can install [Carthage](https://github.com/Carthage/Carthage) with [Homebrew](http://brew.sh/) using the following command: 74 | 75 | ```bash 76 | $ brew update 77 | $ brew install carthage 78 | ``` 79 | 80 | To integrate Marklight into your Xcode project using [Carthage](https://github.com/Carthage/Carthage), specify it in your `Cartfile`: 81 | 82 | ```ogdl 83 | github "macteo/Marklight" 84 | ``` 85 | 86 | Run `carthage update --platform iOS` to build the framework and drag the built `Marklight.framework` into your Xcode project. 87 | 88 | ### Manually 89 | 90 | Add the *Marklight* Xcode project to your own. Then add the `Marklight` framework as desired to the embedded binaries of your app's target. 91 | 92 | ## Usage 93 | 94 | In this repository you can find a sample project with few lines of code in the `ViewController` class for a jumpstart. 95 | 96 | *Sample code is written in Swift but Objective-C should be supported too, if you find an incompatibility please open an issue.* 97 | 98 | ### Integration 99 | 100 | The easiest way to crete a user editable `UITextView` with markdown syntax highlight is to use the provided `MarklightTextStorage` class as `NSTextStorage` and add the `UITextView`'s `textLayout` to the `MarklightTextStorage` text storage. 101 | 102 | Import *Marklight* modules into your Swift class 103 | 104 | ```swift 105 | import Marklight 106 | ``` 107 | 108 | or if you are writing in Objective-C 109 | 110 | ```objc 111 | #import 112 | ``` 113 | 114 | > Keep in mind the you have to let the project generate the Bridging Header otherwise the integration may fail. 115 | 116 | In your `UIViewController` subclass keep a strong instance of the this `MarklightTextStorage` class. 117 | 118 | ```swift 119 | let textStorage = MarklightTextStorage() 120 | ``` 121 | 122 | Customize the appearance as desired: 123 | 124 | * Dynamic text style. 125 | * Markdown syntax color. 126 | * Code's font and color. 127 | * Quotes' font and color. 128 | 129 | As per Apple's documentation it should be enough to assign the `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass, in our case `MarklightTextStorage`. 130 | 131 | ```swift 132 | textStorage.addLayoutManager(textView.layoutManager) 133 | ``` 134 | However I'm experiencing some crashes if I want to preload some text instead of letting the user start from scratch with a new text. A workaround is proposed below. 135 | 136 | For simplicity we assume you have a `String` to be highlighted inside an editable `UITextView` loaded from a storyboard. 137 | 138 | ```swift 139 | let string = "# My awesome markdown string" 140 | ``` 141 | 142 | Convert `string` to an `NSAttributedString` 143 | 144 | ```swift 145 | let attributedString = NSAttributedString(string: string) 146 | ``` 147 | 148 | Set the loaded string to the `UITextView` 149 | 150 | ```swift 151 | textView.attributedText = attributedString 152 | ``` 153 | 154 | Append the loaded string to the `NSTextStorage` 155 | 156 | ```swift 157 | textStorage.appendAttributedString(attributedString) 158 | ``` 159 | 160 | Enjoy. 161 | 162 | ## Acknowledgements 163 | 164 | * Matteo Gavagnin – [@macteo](https://twitter.com/macteo) 165 | * Christian Tietze (macOS Port) - [@ctietze](https://twitter.com/ctietze), [GitHub](http://github.com/DivineDominion) 166 | 167 | --- 168 | 169 | Marklight is heavily based on [Markingbird](https://github.com/kristopherjohnson/Markingbird), so many thanks to [Kristopher Johnson](http://undefinedvalue.com) and every previous contribution on which [Markingbird](https://github.com/kristopherjohnson/Markingbird) is based upon. 170 | 171 | ## License 172 | 173 | Marklight is released under the MIT license. See [LICENSE](https://raw.githubusercontent.com/macteo/Marklight/master/LICENSE) for details. 174 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample/Pods-Marklight-Marklight Sample-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Marklight 18 | Copyright (c) 2016 Matteo Gavagnin 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining 21 | a copy of this software and associated documentation files (the 22 | "Software"), to deal in the Software without restriction, including 23 | without limitation the rights to use, copy, modify, merge, publish, 24 | distribute, sublicense, and/or sell copies of the Software, and to 25 | permit persons to whom the Software is furnished to do so, subject to 26 | the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be 29 | included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 35 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 36 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 37 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38 | 39 | ------------------------------------------------------------------------------ 40 | 41 | Markdown.swift 42 | Copyright (c) 2014 Kristopher Johnson 43 | 44 | Permission is hereby granted, free of charge, to any person obtaining 45 | a copy of this software and associated documentation files (the 46 | "Software"), to deal in the Software without restriction, including 47 | without limitation the rights to use, copy, modify, merge, publish, 48 | distribute, sublicense, and/or sell copies of the Software, and to 49 | permit persons to whom the Software is furnished to do so, subject to 50 | the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be 53 | included in all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 56 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 58 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 59 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 60 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 61 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | 63 | Markdown.swift is based on MarkdownSharp, whose licenses and history are 64 | enumerated in the following sections. 65 | 66 | ------------------------------------------------------------------------------ 67 | 68 | MarkdownSharp 69 | ------------- 70 | a C# Markdown processor 71 | 72 | Markdown is a text-to-HTML conversion tool for web writers 73 | Copyright (c) 2004 John Gruber 74 | http://daringfireball.net/projects/markdown/ 75 | 76 | Markdown.NET 77 | Copyright (c) 2004-2009 Milan Negovan 78 | http://www.aspnetresources.com 79 | http://aspnetresources.com/blog/markdown_announced.aspx 80 | 81 | MarkdownSharp 82 | Copyright (c) 2009-2011 Jeff Atwood 83 | http://stackoverflow.com 84 | http://www.codinghorror.com/blog/ 85 | http://code.google.com/p/markdownsharp/ 86 | 87 | History: Milan ported the Markdown processor to C#. He granted license to me so I can open source it 88 | and let the community contribute to and improve MarkdownSharp. 89 | 90 | ------------------------------------------------------------------------------ 91 | 92 | Copyright (c) 2009 - 2010 Jeff Atwood 93 | 94 | http://www.opensource.org/licenses/mit-license.php 95 | 96 | Permission is hereby granted, free of charge, to any person obtaining a copy 97 | of this software and associated documentation files (the "Software"), to deal 98 | in the Software without restriction, including without limitation the rights 99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100 | copies of the Software, and to permit persons to whom the Software is 101 | furnished to do so, subject to the following conditions: 102 | 103 | The above copyright notice and this permission notice shall be included in 104 | all copies or substantial portions of the Software. 105 | 106 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 107 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 108 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 109 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 110 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 111 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 112 | THE SOFTWARE. 113 | 114 | ------------------------------------------------------------------------------ 115 | 116 | Copyright (c) 2003-2004 John Gruber 117 | <http://daringfireball.net/> 118 | All rights reserved. 119 | 120 | Redistribution and use in source and binary forms, with or without 121 | modification, are permitted provided that the following conditions are 122 | met: 123 | 124 | Redistributions of source code must retain the above copyright notice, 125 | this list of conditions and the following disclaimer. 126 | 127 | Redistributions in binary form must reproduce the above copyright 128 | notice, this list of conditions and the following disclaimer in the 129 | documentation and/or other materials provided with the distribution. 130 | 131 | Neither the name "Markdown" nor the names of its contributors may 132 | be used to endorse or promote products derived from this software 133 | without specific prior written permission. 134 | 135 | This software is provided by the copyright holders and contributors "as 136 | is" and any express or implied warranties, including, but not limited 137 | to, the implied warranties of merchantability and fitness for a 138 | particular purpose are disclaimed. In no event shall the copyright owner 139 | or contributors be liable for any direct, indirect, incidental, special, 140 | exemplary, or consequential damages (including, but not limited to, 141 | procurement of substitute goods or services; loss of use, data, or 142 | profits; or business interruption) however caused and on any theory of 143 | liability, whether in contract, strict liability, or tort (including 144 | negligence or otherwise) arising in any way out of the use of this 145 | software, even if advised of the possibility of such damage. 146 | 147 | License 148 | MIT 149 | Title 150 | Marklight 151 | Type 152 | PSGroupSpecifier 153 | 154 | 155 | FooterText 156 | Generated by CocoaPods - https://cocoapods.org 157 | Title 158 | 159 | Type 160 | PSGroupSpecifier 161 | 162 | 163 | StringsTable 164 | Acknowledgements 165 | Title 166 | Acknowledgements 167 | 168 | 169 | -------------------------------------------------------------------------------- /Sample/Pods/Target Support Files/Pods-Marklight-Marklight Sample macOS/Pods-Marklight-Marklight Sample macOS-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Marklight 18 | Copyright (c) 2016 Matteo Gavagnin 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining 21 | a copy of this software and associated documentation files (the 22 | "Software"), to deal in the Software without restriction, including 23 | without limitation the rights to use, copy, modify, merge, publish, 24 | distribute, sublicense, and/or sell copies of the Software, and to 25 | permit persons to whom the Software is furnished to do so, subject to 26 | the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be 29 | included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 35 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 36 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 37 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38 | 39 | ------------------------------------------------------------------------------ 40 | 41 | Markdown.swift 42 | Copyright (c) 2014 Kristopher Johnson 43 | 44 | Permission is hereby granted, free of charge, to any person obtaining 45 | a copy of this software and associated documentation files (the 46 | "Software"), to deal in the Software without restriction, including 47 | without limitation the rights to use, copy, modify, merge, publish, 48 | distribute, sublicense, and/or sell copies of the Software, and to 49 | permit persons to whom the Software is furnished to do so, subject to 50 | the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be 53 | included in all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 56 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 58 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 59 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 60 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 61 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | 63 | Markdown.swift is based on MarkdownSharp, whose licenses and history are 64 | enumerated in the following sections. 65 | 66 | ------------------------------------------------------------------------------ 67 | 68 | MarkdownSharp 69 | ------------- 70 | a C# Markdown processor 71 | 72 | Markdown is a text-to-HTML conversion tool for web writers 73 | Copyright (c) 2004 John Gruber 74 | http://daringfireball.net/projects/markdown/ 75 | 76 | Markdown.NET 77 | Copyright (c) 2004-2009 Milan Negovan 78 | http://www.aspnetresources.com 79 | http://aspnetresources.com/blog/markdown_announced.aspx 80 | 81 | MarkdownSharp 82 | Copyright (c) 2009-2011 Jeff Atwood 83 | http://stackoverflow.com 84 | http://www.codinghorror.com/blog/ 85 | http://code.google.com/p/markdownsharp/ 86 | 87 | History: Milan ported the Markdown processor to C#. He granted license to me so I can open source it 88 | and let the community contribute to and improve MarkdownSharp. 89 | 90 | ------------------------------------------------------------------------------ 91 | 92 | Copyright (c) 2009 - 2010 Jeff Atwood 93 | 94 | http://www.opensource.org/licenses/mit-license.php 95 | 96 | Permission is hereby granted, free of charge, to any person obtaining a copy 97 | of this software and associated documentation files (the "Software"), to deal 98 | in the Software without restriction, including without limitation the rights 99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100 | copies of the Software, and to permit persons to whom the Software is 101 | furnished to do so, subject to the following conditions: 102 | 103 | The above copyright notice and this permission notice shall be included in 104 | all copies or substantial portions of the Software. 105 | 106 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 107 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 108 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 109 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 110 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 111 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 112 | THE SOFTWARE. 113 | 114 | ------------------------------------------------------------------------------ 115 | 116 | Copyright (c) 2003-2004 John Gruber 117 | <http://daringfireball.net/> 118 | All rights reserved. 119 | 120 | Redistribution and use in source and binary forms, with or without 121 | modification, are permitted provided that the following conditions are 122 | met: 123 | 124 | Redistributions of source code must retain the above copyright notice, 125 | this list of conditions and the following disclaimer. 126 | 127 | Redistributions in binary form must reproduce the above copyright 128 | notice, this list of conditions and the following disclaimer in the 129 | documentation and/or other materials provided with the distribution. 130 | 131 | Neither the name "Markdown" nor the names of its contributors may 132 | be used to endorse or promote products derived from this software 133 | without specific prior written permission. 134 | 135 | This software is provided by the copyright holders and contributors "as 136 | is" and any express or implied warranties, including, but not limited 137 | to, the implied warranties of merchantability and fitness for a 138 | particular purpose are disclaimed. In no event shall the copyright owner 139 | or contributors be liable for any direct, indirect, incidental, special, 140 | exemplary, or consequential damages (including, but not limited to, 141 | procurement of substitute goods or services; loss of use, data, or 142 | profits; or business interruption) however caused and on any theory of 143 | liability, whether in contract, strict liability, or tort (including 144 | negligence or otherwise) arising in any way out of the use of this 145 | software, even if advised of the possibility of such damage. 146 | 147 | License 148 | MIT 149 | Title 150 | Marklight 151 | Type 152 | PSGroupSpecifier 153 | 154 | 155 | FooterText 156 | Generated by CocoaPods - https://cocoapods.org 157 | Title 158 | 159 | Type 160 | PSGroupSpecifier 161 | 162 | 163 | StringsTable 164 | Acknowledgements 165 | Title 166 | Acknowledgements 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

Marklight Docs (100% documented)

16 |

View on GitHub

17 |
18 |
19 |
20 | 25 |
26 |
27 | 47 |
48 |
49 |
50 |

Classes

51 |

The following classes are available globally.

52 | 53 |
54 |
55 |
56 |
    57 |
  • 58 |
    59 | 60 | 61 | 62 | MarklightTextStorage 63 | 64 |
    65 |
    66 |
    67 |
    68 |
    69 |
    70 |

    NSTextStorage subclass that uses Marklight to highlight markdown syntax 71 | on a UITextView. 72 | In your UIViewController subclass keep a strong instance of the this 73 | MarklightTextStorage class. 74 | swift 75 | let textStorage = MarklightTextStorage() 76 |

    77 | 78 |

    Customise the appearance as desired:

    79 | 80 |
      81 |
    • Dynamic text style.
    • 82 |
    • Markdown syntax color.
    • 83 |
    • Code’s font and color.
    • 84 |
    • Quotes’ font and color.
    • 85 |
    86 | 87 |

    As per Apple’s documentation it should be enough to assign the 88 | UITextView’s NSLayoutManager to the NSTextStorage subclass, in our 89 | case MarklightTextStorage.

    90 | 91 |
     textStorage.addLayoutManager(textView.layoutManager)
     92 | 
    93 | 94 |

    However I’m experiencing some crashes if I want to preload some text instead 95 | of letting the user start from scratch with a new text. A workaround is 96 | proposed below.

    97 | 98 |

    For simplicity we assume you have a String to be highlighted inside an 99 | editable UITextView loaded from a storyboard.

    100 | 101 |
    let string = "# My awesome markdown string"
    102 | 
    103 | 104 |

    Convert string to an NSAttributedString

    105 | 106 |
    let attributedString = NSAttributedString(string: string)
    107 | 
    108 | 109 |

    Set the loaded string to the UITextView

    110 | 111 |
    textView.attributedText = attributedString
    112 | 
    113 | 114 |

    Append the loaded string to the NSTextStorage

    115 | 116 |
    textStorage.appendAttributedString(attributedString)
    117 | 
    118 | 119 |

    For more informations on how to implement your own NSTextStorage subclass, 120 | follow Apple’s official documentation.

    121 | 122 |
    123 |

    See

    124 | NSTextStorage 125 | 126 |
    127 |

    See

    128 | Marklight 129 | 130 |
    131 | 132 | See more 133 |
    134 |
    135 |

    Declaration

    136 |
    137 |

    Swift

    138 |
    public class MarklightTextStorage: NSTextStorage
    139 | 140 |
    141 |
    142 |
    143 | Show on GitHub 144 |
    145 |
    146 |
    147 |
  • 148 |
149 |
150 |
151 |
152 | 156 |
157 |
158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

Marklight Docs (100% documented)

16 |

View on GitHub

17 |
18 |
19 |
20 | 25 |
26 |
27 | 47 |
48 |
49 |
50 |

Classes

51 |

The following classes are available globally.

52 | 53 |
54 |
55 |
56 |
    57 |
  • 58 |
    59 | 60 | 61 | 62 | MarklightTextStorage 63 | 64 |
    65 |
    66 |
    67 |
    68 |
    69 |
    70 |

    NSTextStorage subclass that uses Marklight to highlight markdown syntax 71 | on a UITextView. 72 | In your UIViewController subclass keep a strong instance of the this 73 | MarklightTextStorage class. 74 | swift 75 | let textStorage = MarklightTextStorage() 76 |

    77 | 78 |

    Customise the appearance as desired:

    79 | 80 |
      81 |
    • Dynamic text style.
    • 82 |
    • Markdown syntax color.
    • 83 |
    • Code’s font and color.
    • 84 |
    • Quotes’ font and color.
    • 85 |
    86 | 87 |

    As per Apple’s documentation it should be enough to assign the 88 | UITextView’s NSLayoutManager to the NSTextStorage subclass, in our 89 | case MarklightTextStorage.

    90 | 91 |
     textStorage.addLayoutManager(textView.layoutManager)
     92 | 
    93 | 94 |

    However I’m experiencing some crashes if I want to preload some text instead 95 | of letting the user start from scratch with a new text. A workaround is 96 | proposed below.

    97 | 98 |

    For simplicity we assume you have a String to be highlighted inside an 99 | editable UITextView loaded from a storyboard.

    100 | 101 |
    let string = "# My awesome markdown string"
    102 | 
    103 | 104 |

    Convert string to an NSAttributedString

    105 | 106 |
    let attributedString = NSAttributedString(string: string)
    107 | 
    108 | 109 |

    Set the loaded string to the UITextView

    110 | 111 |
    textView.attributedText = attributedString
    112 | 
    113 | 114 |

    Append the loaded string to the NSTextStorage

    115 | 116 |
    textStorage.appendAttributedString(attributedString)
    117 | 
    118 | 119 |

    For more informations on how to implement your own NSTextStorage subclass, 120 | follow Apple’s official documentation.

    121 | 122 |
    123 |

    See

    124 | NSTextStorage 125 | 126 |
    127 |

    See

    128 | Marklight 129 | 130 |
    131 | 132 | See more 133 |
    134 |
    135 |

    Declaration

    136 |
    137 |

    Swift

    138 |
    public class MarklightTextStorage: NSTextStorage
    139 | 140 |
    141 |
    142 |
    143 | Show on GitHub 144 |
    145 |
    146 |
    147 |
  • 148 |
149 |
150 |
151 |
152 | 156 |
157 |
158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; } 143 | .nav-group-task a { 144 | color: #888; } 145 | 146 | .main-content { 147 | background-color: #fff; 148 | border: 1px solid #e2e2e2; 149 | margin-left: 246px; 150 | position: absolute; 151 | overflow: hidden; 152 | padding-bottom: 60px; 153 | top: 70px; 154 | width: 734px; } 155 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 156 | margin-bottom: 1em; } 157 | .main-content p { 158 | line-height: 1.8em; } 159 | .main-content section .section:first-child { 160 | margin-top: 0; 161 | padding-top: 0; } 162 | .main-content section .task-group-section .task-group:first-of-type { 163 | padding-top: 10px; } 164 | .main-content section .task-group-section .task-group:first-of-type .section-name { 165 | padding-top: 15px; } 166 | 167 | .section { 168 | padding: 0 25px; } 169 | 170 | .highlight { 171 | background-color: #eee; 172 | padding: 10px 12px; 173 | border: 1px solid #e2e2e2; 174 | border-radius: 4px; 175 | overflow-x: auto; } 176 | 177 | .declaration .highlight { 178 | overflow-x: initial; 179 | padding: 0 40px 40px 0; 180 | margin-bottom: -25px; 181 | background-color: transparent; 182 | border: none; } 183 | 184 | .section-name { 185 | margin: 0; 186 | margin-left: 18px; } 187 | 188 | .task-group-section { 189 | padding-left: 6px; 190 | border-top: 1px solid #e2e2e2; } 191 | 192 | .task-group { 193 | padding-top: 0px; } 194 | 195 | .task-name-container a[name]:before { 196 | content: ""; 197 | display: block; 198 | padding-top: 70px; 199 | margin: -70px 0 0; } 200 | 201 | .item { 202 | padding-top: 8px; 203 | width: 100%; 204 | list-style-type: none; } 205 | .item a[name]:before { 206 | content: ""; 207 | display: block; 208 | padding-top: 70px; 209 | margin: -70px 0 0; } 210 | .item code { 211 | background-color: transparent; 212 | padding: 0; } 213 | .item .token { 214 | padding-left: 3px; 215 | margin-left: 15px; 216 | font-size: 11.9px; } 217 | .item .declaration-note { 218 | font-size: .85em; 219 | color: gray; 220 | font-style: italic; } 221 | 222 | .pointer-container { 223 | border-bottom: 1px solid #e2e2e2; 224 | left: -23px; 225 | padding-bottom: 13px; 226 | position: relative; 227 | width: 110%; } 228 | 229 | .pointer { 230 | background: #f9f9f9; 231 | border-left: 1px solid #e2e2e2; 232 | border-top: 1px solid #e2e2e2; 233 | height: 12px; 234 | left: 21px; 235 | top: -7px; 236 | -webkit-transform: rotate(45deg); 237 | -moz-transform: rotate(45deg); 238 | -o-transform: rotate(45deg); 239 | transform: rotate(45deg); 240 | position: absolute; 241 | width: 12px; } 242 | 243 | .height-container { 244 | display: none; 245 | left: -25px; 246 | padding: 0 25px; 247 | position: relative; 248 | width: 100%; 249 | overflow: hidden; } 250 | .height-container .section { 251 | background: #f9f9f9; 252 | border-bottom: 1px solid #e2e2e2; 253 | left: -25px; 254 | position: relative; 255 | width: 100%; 256 | padding-top: 10px; 257 | padding-bottom: 5px; } 258 | 259 | .aside, .language { 260 | padding: 6px 12px; 261 | margin: 12px 0; 262 | border-left: 5px solid #dddddd; 263 | overflow-y: hidden; } 264 | .aside .aside-title, .language .aside-title { 265 | font-size: 9px; 266 | letter-spacing: 2px; 267 | text-transform: uppercase; 268 | padding-bottom: 0; 269 | margin: 0; 270 | color: #aaa; 271 | -webkit-user-select: none; } 272 | .aside p:last-child, .language p:last-child { 273 | margin-bottom: 0; } 274 | 275 | .language { 276 | border-left: 5px solid #cde9f4; } 277 | .language .aside-title { 278 | color: #4b8afb; } 279 | 280 | .aside-warning { 281 | border-left: 5px solid #ff6666; } 282 | .aside-warning .aside-title { 283 | color: #ff0000; } 284 | 285 | .graybox { 286 | border-collapse: collapse; 287 | width: 100%; } 288 | .graybox p { 289 | margin: 0; 290 | word-break: break-word; 291 | min-width: 50px; } 292 | .graybox td { 293 | border: 1px solid #e2e2e2; 294 | padding: 5px 25px 5px 10px; 295 | vertical-align: middle; } 296 | .graybox tr td:first-of-type { 297 | text-align: right; 298 | padding: 7px; 299 | vertical-align: top; 300 | word-break: normal; 301 | width: 40px; } 302 | 303 | .slightly-smaller { 304 | font-size: 0.9em; } 305 | 306 | #footer { 307 | position: absolute; 308 | bottom: 10px; 309 | margin-left: 25px; } 310 | #footer p { 311 | margin: 0; 312 | color: #aaa; 313 | font-size: 0.8em; } 314 | 315 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 316 | display: none; } 317 | html.dash .main-content { 318 | width: 980px; 319 | margin-left: 0; 320 | border: none; 321 | width: 100%; 322 | top: 0; 323 | padding-bottom: 0; } 324 | html.dash .height-container { 325 | display: block; } 326 | html.dash .item .token { 327 | margin-left: 0; } 328 | html.dash .content-wrapper { 329 | width: auto; } 330 | html.dash #footer { 331 | position: static; } 332 | -------------------------------------------------------------------------------- /docs/docsets/Marklight.docset/Contents/Resources/Documents/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; } 143 | .nav-group-task a { 144 | color: #888; } 145 | 146 | .main-content { 147 | background-color: #fff; 148 | border: 1px solid #e2e2e2; 149 | margin-left: 246px; 150 | position: absolute; 151 | overflow: hidden; 152 | padding-bottom: 60px; 153 | top: 70px; 154 | width: 734px; } 155 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 156 | margin-bottom: 1em; } 157 | .main-content p { 158 | line-height: 1.8em; } 159 | .main-content section .section:first-child { 160 | margin-top: 0; 161 | padding-top: 0; } 162 | .main-content section .task-group-section .task-group:first-of-type { 163 | padding-top: 10px; } 164 | .main-content section .task-group-section .task-group:first-of-type .section-name { 165 | padding-top: 15px; } 166 | 167 | .section { 168 | padding: 0 25px; } 169 | 170 | .highlight { 171 | background-color: #eee; 172 | padding: 10px 12px; 173 | border: 1px solid #e2e2e2; 174 | border-radius: 4px; 175 | overflow-x: auto; } 176 | 177 | .declaration .highlight { 178 | overflow-x: initial; 179 | padding: 0 40px 40px 0; 180 | margin-bottom: -25px; 181 | background-color: transparent; 182 | border: none; } 183 | 184 | .section-name { 185 | margin: 0; 186 | margin-left: 18px; } 187 | 188 | .task-group-section { 189 | padding-left: 6px; 190 | border-top: 1px solid #e2e2e2; } 191 | 192 | .task-group { 193 | padding-top: 0px; } 194 | 195 | .task-name-container a[name]:before { 196 | content: ""; 197 | display: block; 198 | padding-top: 70px; 199 | margin: -70px 0 0; } 200 | 201 | .item { 202 | padding-top: 8px; 203 | width: 100%; 204 | list-style-type: none; } 205 | .item a[name]:before { 206 | content: ""; 207 | display: block; 208 | padding-top: 70px; 209 | margin: -70px 0 0; } 210 | .item code { 211 | background-color: transparent; 212 | padding: 0; } 213 | .item .token { 214 | padding-left: 3px; 215 | margin-left: 15px; 216 | font-size: 11.9px; } 217 | .item .declaration-note { 218 | font-size: .85em; 219 | color: gray; 220 | font-style: italic; } 221 | 222 | .pointer-container { 223 | border-bottom: 1px solid #e2e2e2; 224 | left: -23px; 225 | padding-bottom: 13px; 226 | position: relative; 227 | width: 110%; } 228 | 229 | .pointer { 230 | background: #f9f9f9; 231 | border-left: 1px solid #e2e2e2; 232 | border-top: 1px solid #e2e2e2; 233 | height: 12px; 234 | left: 21px; 235 | top: -7px; 236 | -webkit-transform: rotate(45deg); 237 | -moz-transform: rotate(45deg); 238 | -o-transform: rotate(45deg); 239 | transform: rotate(45deg); 240 | position: absolute; 241 | width: 12px; } 242 | 243 | .height-container { 244 | display: none; 245 | left: -25px; 246 | padding: 0 25px; 247 | position: relative; 248 | width: 100%; 249 | overflow: hidden; } 250 | .height-container .section { 251 | background: #f9f9f9; 252 | border-bottom: 1px solid #e2e2e2; 253 | left: -25px; 254 | position: relative; 255 | width: 100%; 256 | padding-top: 10px; 257 | padding-bottom: 5px; } 258 | 259 | .aside, .language { 260 | padding: 6px 12px; 261 | margin: 12px 0; 262 | border-left: 5px solid #dddddd; 263 | overflow-y: hidden; } 264 | .aside .aside-title, .language .aside-title { 265 | font-size: 9px; 266 | letter-spacing: 2px; 267 | text-transform: uppercase; 268 | padding-bottom: 0; 269 | margin: 0; 270 | color: #aaa; 271 | -webkit-user-select: none; } 272 | .aside p:last-child, .language p:last-child { 273 | margin-bottom: 0; } 274 | 275 | .language { 276 | border-left: 5px solid #cde9f4; } 277 | .language .aside-title { 278 | color: #4b8afb; } 279 | 280 | .aside-warning { 281 | border-left: 5px solid #ff6666; } 282 | .aside-warning .aside-title { 283 | color: #ff0000; } 284 | 285 | .graybox { 286 | border-collapse: collapse; 287 | width: 100%; } 288 | .graybox p { 289 | margin: 0; 290 | word-break: break-word; 291 | min-width: 50px; } 292 | .graybox td { 293 | border: 1px solid #e2e2e2; 294 | padding: 5px 25px 5px 10px; 295 | vertical-align: middle; } 296 | .graybox tr td:first-of-type { 297 | text-align: right; 298 | padding: 7px; 299 | vertical-align: top; 300 | word-break: normal; 301 | width: 40px; } 302 | 303 | .slightly-smaller { 304 | font-size: 0.9em; } 305 | 306 | #footer { 307 | position: absolute; 308 | bottom: 10px; 309 | margin-left: 25px; } 310 | #footer p { 311 | margin: 0; 312 | color: #aaa; 313 | font-size: 0.8em; } 314 | 315 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 316 | display: none; } 317 | html.dash .main-content { 318 | width: 980px; 319 | margin-left: 0; 320 | border: none; 321 | width: 100%; 322 | top: 0; 323 | padding-bottom: 0; } 324 | html.dash .height-container { 325 | display: block; } 326 | html.dash .item .token { 327 | margin-left: 0; } 328 | html.dash .content-wrapper { 329 | width: auto; } 330 | html.dash #footer { 331 | position: static; } 332 | -------------------------------------------------------------------------------- /Marklight/MarklightTextStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarklightTextStorage 3 | // 4 | // Created by Matteo Gavagnin on 01/01/16. 5 | // Copyright © 2016 MacTeo. LICENSE for details. 6 | // 7 | 8 | #if os(iOS) 9 | import UIKit 10 | #elseif os(macOS) 11 | import AppKit 12 | #endif 13 | 14 | /** 15 | `NSTextStorage` subclass that uses `Marklight` to highlight markdown syntax 16 | on a `UITextView`. 17 | In your `UIViewController` subclass keep a strong instance of the this 18 | `MarklightTextStorage` class. 19 | ```swift 20 | let textStorage = MarklightTextStorage() 21 | ``` 22 | 23 | Customise the appearance as desired: 24 | 25 | * Dynamic text style. 26 | * Markdown syntax color. 27 | * Code's font and color. 28 | * Quotes' font and color. 29 | 30 | As per Apple's documentation it should be enough to assign the 31 | `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass, in our 32 | case `MarklightTextStorage`. 33 | 34 | ```swift 35 | textStorage.addLayoutManager(textView.layoutManager) 36 | ``` 37 | However I'm experiencing some crashes if I want to preload some text instead 38 | of letting the user start from scratch with a new text. A workaround is 39 | proposed below. 40 | 41 | For simplicity we assume you have a `String` to be highlighted inside an 42 | editable `UITextView` loaded from a storyboard. 43 | 44 | ```swift 45 | let string = "# My awesome markdown string" 46 | ``` 47 | 48 | Convert `string` to an `NSAttributedString` 49 | 50 | ```swift 51 | let attributedString = NSAttributedString(string: string) 52 | ``` 53 | 54 | Set the loaded string to the `UITextView` 55 | 56 | ```swift 57 | textView.attributedText = attributedString 58 | ``` 59 | 60 | Append the loaded string to the `NSTextStorage` 61 | 62 | ```swift 63 | textStorage.appendAttributedString(attributedString) 64 | ``` 65 | 66 | For more informations on how to implement your own `NSTextStorage` subclass, 67 | follow Apple's official documentation. 68 | 69 | - see: [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorageDelegate_Protocol_TextKit/index.html#//apple_ref/swift/intf/c:objc(pl)NSTextStorage) 70 | - see: `Marklight` 71 | */ 72 | 73 | open class MarklightTextStorage: NSTextStorage, MarklightStyleApplier { 74 | 75 | open lazy var marklightTextProcessor: MarklightTextProcessor = MarklightTextProcessor() 76 | 77 | /// Delegate from this class cluster to a regular `NSTextStorage` instance 78 | /// because it does some additional performance optimizations 79 | /// over `NSMutableAttributedString`. 80 | fileprivate let imp = NSTextStorage() 81 | 82 | 83 | // MARK: Syntax highlighting 84 | 85 | /// Switch used to prevent `processEditing` callbacks from 86 | /// within `processEditing`. 87 | fileprivate var isBusyProcessing = false 88 | 89 | /** 90 | To customise the appearance of the markdown syntax highlights you should 91 | subclass `MarklightTextProcessor`. Sends out 92 | `-textStorage:willProcessEditing`, fixes the attributes, sends out 93 | `-textStorage:didProcessEditing`, and notifies the layout managers of 94 | change with the 95 | `-processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:` 96 | method. Invoked from `-edited:range:changeInLength:` or `-endEditing`. 97 | 98 | - see: 99 | [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorage_Class_TextKit/index.html#//apple_ref/doc/uid/TP40013282) 100 | */ 101 | override open func processEditing() { 102 | 103 | self.isBusyProcessing = true 104 | defer { self.isBusyProcessing = false } 105 | 106 | let processingResult = marklightTextProcessor.processEditing( 107 | styleApplier: self, 108 | string: self.string, 109 | editedRange: editedRange) 110 | 111 | defer { 112 | // Include surrounding paragraphs in layout manager's styling pass 113 | // after finishing the real edit. Mostly needed for Setex headings. 114 | processingResult.updateLayoutManagers(for: self) 115 | } 116 | 117 | super.processEditing() 118 | } 119 | 120 | public func resetMarklightTextAttributes(textSize: CGFloat, range: NSRange) { 121 | // Use `imp` directly instead of `self` to avoid changing the edited range 122 | // after attribute fixing, affecting the insertion point on macOS. 123 | imp.removeAttribute(NSAttributedString.Key.foregroundColor, range: range) 124 | imp.addAttribute(NSAttributedString.Key.font, value: MarklightFont.systemFont(ofSize: textSize), range: range) 125 | imp.addAttribute(NSAttributedString.Key.paragraphStyle, value: NSParagraphStyle(), range: range) 126 | } 127 | 128 | 129 | // MARK: Reading Text 130 | 131 | /** 132 | Use this method to extract the text from the `UITextView` as plain text. 133 | 134 | - returns: The `String` containing the text inside the `UITextView`. 135 | 136 | - see: 137 | [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorage_Class_TextKit/index.html#//apple_ref/doc/uid/TP40013282) 138 | */ 139 | override open var string : String { 140 | return imp.string 141 | } 142 | 143 | /** 144 | Returns the attributes for the character at a given index. 145 | The attributes for the character at index. 146 | 147 | - parameter index: The index for which to return attributes. This value must 148 | lie within the bounds of the receiver. 149 | - parameter aRange: Upon return, the range over which the attributes and 150 | values are the same as those at index. This range isn’t necessarily the 151 | maximum range covered, and its extent is implementation-dependent. If you 152 | need the maximum range, use 153 | attributesAtIndex:longestEffectiveRange:inRange:. If you don't need this 154 | value, pass NULL. 155 | - returns: The attributes for the character at index. - see: 156 | [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorage_Class_TextKit/index.html#//apple_ref/doc/uid/TP40013282) 157 | */ 158 | 159 | open override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key : Any] { 160 | return imp.attributes(at: location, effectiveRange: range) 161 | } 162 | 163 | // MARK: Text Editing 164 | 165 | /** 166 | Replaces the characters in the given range with the characters of the given 167 | string. The new characters inherit the attributes of the first replaced 168 | character from aRange. Where the length of aRange is 0, the new characters 169 | inherit the attributes of the character preceding aRange if it has any, 170 | otherwise of the character following aRange. Raises an NSRangeException if 171 | any part of aRange lies beyond the end of the receiver’s characters. 172 | - parameter aRange: A range specifying the characters to replace. 173 | - parameter aString: A string specifying the characters to replace those in 174 | aRange. 175 | - see: 176 | [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorage_Class_TextKit/index.html#//apple_ref/doc/uid/TP40013282) 177 | */ 178 | override open func replaceCharacters(in range: NSRange, with str: String) { 179 | beginEditing() 180 | imp.replaceCharacters(in: range, with: str) 181 | edited([.editedCharacters], range: range, changeInLength: (str as NSString).length - range.length) 182 | endEditing() 183 | } 184 | 185 | /** 186 | Sets the attributes for the characters in the specified range to the 187 | specified attributes. These new attributes replace any attributes previously 188 | associated with the characters in aRange. Raises an NSRangeException if any 189 | part of aRange lies beyond the end of the receiver’s characters. To set 190 | attributes for a zero-length NSMutableAttributedString displayed in a text 191 | view, use the NSTextView method setTypingAttributes:. 192 | - parameter attributes: A dictionary containing the attributes to set. 193 | Attribute keys can be supplied by another framework or can be custom ones 194 | you define. For information about where to find the system-supplied 195 | attribute keys, see the overview section in NSAttributedString Class 196 | Reference. 197 | - parameter aRange: The range of characters whose attributes are set. 198 | - see: 199 | [`NSMutableAttributedString`](xcdoc://?url=developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/index.html#//apple_ref/swift/cl/c:objc(cs)NSMutableAttributedString 200 | ) 201 | - see: 202 | [`NSTextStorage`](xcdoc://?url=developer.apple.com/library/ios/documentation/UIKit/Reference/NSTextStorage_Class_TextKit/index.html#//apple_ref/doc/uid/TP40013282) 203 | */ 204 | 205 | override open func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange) { 206 | // When we are processing, using the regular callback triggers will 207 | // result in the caret jumping to the end of the document. 208 | guard !isBusyProcessing else { 209 | imp.setAttributes(attrs, range: range) 210 | return 211 | } 212 | 213 | beginEditing() 214 | imp.setAttributes(attrs, range: range) 215 | edited([.editedAttributes], range: range, changeInLength: 0) 216 | endEditing() 217 | } 218 | 219 | #if os(iOS) 220 | 221 | // MARK: - Dynamic text sizing 222 | 223 | required override public init() { 224 | super.init() 225 | observeTextSize() 226 | } 227 | 228 | required public init?(coder aDecoder: NSCoder) { 229 | super.init(coder: aDecoder) 230 | observeTextSize() 231 | } 232 | 233 | /** 234 | Internal method to register to notifications determined by dynamic type size 235 | changes and redraw the attributed text with the appropriate text size. 236 | 237 | - note: Currently it works only after the user adds or removes some chars inside the 238 | `UITextView`. 239 | */ 240 | // TODO: Make this work without needing to type in the text view. 241 | func observeTextSize() { 242 | NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: OperationQueue.main) { [weak self] (notification) -> Void in 243 | self?.invalidateTextSizeForWholeRange() 244 | } 245 | } 246 | 247 | deinit { 248 | NotificationCenter.default.removeObserver(self) 249 | } 250 | 251 | fileprivate func invalidateTextSizeForWholeRange() { 252 | let wholeRange = NSMakeRange(0, (self.string as NSString).length) 253 | self.invalidateAttributes(in: wholeRange) 254 | for layoutManager in self.layoutManagers { 255 | layoutManager.invalidateDisplay(forCharacterRange: wholeRange) 256 | } 257 | } 258 | #endif 259 | } 260 | --------------------------------------------------------------------------------