├── .gitignore ├── .ruby-version ├── Markr.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── WorkspaceSettings.xcsettings ├── Markr.xcworkspace ├── xcshareddata │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── Luka.xcuserdatad │ └── WorkspaceSettings.xcsettings ├── Markr ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── markr-1024.png │ │ ├── markr-128.png │ │ ├── markr-16.png │ │ ├── markr-256.png │ │ ├── markr-32.png │ │ ├── markr-512.png │ │ └── markr-64.png │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── EditorViewController.swift ├── Info.plist ├── MarkdownFormatter.swift ├── MarkdownViewController.swift ├── PreferencesViewController.swift └── PreferencesWindowController.swift ├── Podfile ├── Podfile.lock ├── Pods ├── Down │ ├── LICENSE │ ├── README.md │ ├── Resources │ │ └── DownView.bundle │ │ │ ├── css │ │ │ └── down.min.css │ │ │ ├── index.html │ │ │ └── js │ │ │ ├── down.js │ │ │ └── highlight.min.js │ └── Source │ │ ├── Down.h │ │ ├── Down.swift │ │ ├── Enums & Options │ │ ├── DownErrors.swift │ │ └── DownOptions.swift │ │ ├── Extensions │ │ ├── NSAttributedString+HTML.swift │ │ └── String+ToHTML.swift │ │ ├── Renderers │ │ ├── DownASTRenderable.swift │ │ ├── DownAttributedStringRenderable.swift │ │ ├── DownCommonMarkRenderable.swift │ │ ├── DownGroffRenderable.swift │ │ ├── DownHTMLRenderable.swift │ │ ├── DownLaTeXRenderable.swift │ │ ├── DownRenderable.swift │ │ └── DownXMLRenderable.swift │ │ ├── Views │ │ └── DownView.swift │ │ └── cmark │ │ ├── COPYING │ │ ├── blocks.c │ │ ├── buffer.c │ │ ├── buffer.h │ │ ├── case_fold_switch.inc │ │ ├── chunk.h │ │ ├── cmark.c │ │ ├── cmark.h │ │ ├── cmark_ctype.c │ │ ├── cmark_ctype.h │ │ ├── cmark_export.h │ │ ├── cmark_version.h │ │ ├── commonmark.c │ │ ├── config.h │ │ ├── debug.h │ │ ├── entities.inc │ │ ├── houdini.h │ │ ├── houdini_href_e.c │ │ ├── houdini_html_e.c │ │ ├── houdini_html_u.c │ │ ├── html.c │ │ ├── html_unescape.h │ │ ├── inlines.c │ │ ├── inlines.h │ │ ├── iterator.c │ │ ├── iterator.h │ │ ├── latex.c │ │ ├── man.c │ │ ├── module.modulemap │ │ ├── node.c │ │ ├── node.h │ │ ├── parser.h │ │ ├── references.c │ │ ├── references.h │ │ ├── render.c │ │ ├── render.h │ │ ├── scanners.c │ │ ├── scanners.h │ │ ├── utf8.c │ │ ├── utf8.h │ │ └── xml.c ├── Manifest.lock ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── Luka.xcuserdatad │ │ └── xcschemes │ │ ├── Down.xcscheme │ │ ├── Pods-markr.xcscheme │ │ └── xcschememanagement.plist └── Target Support Files │ ├── Down │ ├── Down-dummy.m │ ├── Down-prefix.pch │ ├── Down-umbrella.h │ ├── Down.modulemap │ ├── Down.xcconfig │ └── Info.plist │ ├── Pods-Markr │ ├── Pods-Markr.debug.xcconfig │ └── Pods-Markr.release.xcconfig │ └── Pods-markr │ ├── Info.plist │ ├── Pods-markr-acknowledgements.markdown │ ├── Pods-markr-acknowledgements.plist │ ├── Pods-markr-dummy.m │ ├── Pods-markr-frameworks.sh │ ├── Pods-markr-resources.sh │ ├── Pods-markr-umbrella.h │ └── Pods-markr.modulemap ├── README.md └── markr.xcworkspace ├── contents.xcworkspacedata └── xcuserdata └── Luka.xcuserdatad └── UserInterfaceState.xcuserstate /.gitignore: -------------------------------------------------------------------------------- 1 | markr.xcodeproj/xcuserdata 2 | markr.xcodeproj/project.xcworkspace/xcuserdata -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.4.2 2 | -------------------------------------------------------------------------------- /Markr.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Markr.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Latest 7 | 8 | 9 | -------------------------------------------------------------------------------- /Markr.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Latest 7 | 8 | 9 | -------------------------------------------------------------------------------- /Markr.xcworkspace/xcuserdata/Luka.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Markr/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 9/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | let defaults = UserDefaults.standard 12 | 13 | @NSApplicationMain 14 | class AppDelegate: NSObject, NSApplicationDelegate { 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | // Main window 18 | if let window = NSApplication.shared.windows.first { 19 | window.appearance = NSAppearance(named: NSAppearance.Name.vibrantLight) 20 | 21 | // Title bar properties 22 | window.styleMask.insert(.fullSizeContentView) 23 | window.isOpaque = false 24 | window.invalidateShadow() 25 | } 26 | } 27 | 28 | func applicationWillTerminate(_ aNotification: Notification) { 29 | } 30 | 31 | // Close the application when there are no windows left 32 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 33 | return true 34 | } 35 | 36 | // When a file is dragged onto the application's icon 37 | func application(_ sender: NSApplication, openFile filename: String) -> Bool { 38 | let window = NSApplication.shared.windows.first! 39 | if let editorViewController = window.contentViewController?.childViewControllers[0] as? EditorViewController { 40 | editorViewController.loadFile(filename) 41 | return true 42 | } 43 | return false 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "markr-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "markr-32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "markr-32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "markr-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "markr-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "markr-256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "markr-256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "markr-512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "markr-512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "markr-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-1024.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-128.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-16.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-256.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-32.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-512.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/AppIcon.appiconset/markr-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/Markr/Assets.xcassets/AppIcon.appiconset/markr-64.png -------------------------------------------------------------------------------- /Markr/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Markr/EditorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EditorViewController.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 9/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import Down 11 | 12 | let DEFAULT_THEME = "Light" 13 | let DEFAULT_FONT = "Monaco" 14 | let DEFAULT_FONT_SIZE = "14" 15 | 16 | class EditorViewController: NSViewController { 17 | 18 | @IBOutlet var editor: NSTextView! 19 | @IBOutlet weak var editorBackground: NSVisualEffectView! 20 | @IBOutlet weak var fileLabel: NSTextField! 21 | 22 | var editingFile = false 23 | var editingFilePath : URL? 24 | var fileChanged = false 25 | var editingNewFile = false 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | 30 | // Register for theme change notification 31 | NotificationCenter.default.addObserver( 32 | self, 33 | selector: #selector(self.setTheme), 34 | name: NSNotification.Name(rawValue: "themeChangedNotification"), 35 | object: nil 36 | ) 37 | 38 | editor.insertionPointColor = NSColor(red:0.75, green:0.75, blue:0.75, alpha:1.00) 39 | 40 | let defaultFont = defaults.string(forKey: "font") ?? DEFAULT_FONT 41 | let defaultFontSize = defaults.string(forKey: "fontSize") ?? DEFAULT_FONT_SIZE 42 | editor.font = NSFont(name: defaultFont, size: CGFloat(Int(defaultFontSize)!)) 43 | 44 | setTheme(nil) 45 | } 46 | 47 | @objc dynamic var editorText: String = "" { 48 | didSet { 49 | loadMarkdown() 50 | 51 | if editingFile { 52 | fileChanged = true 53 | if let path = editingFilePath { 54 | setFileLabel(path.lastPathComponent, fileChanged: fileChanged) 55 | } 56 | } 57 | 58 | if editingFilePath == nil && !editingFile { 59 | editingNewFile = true 60 | if (editor.string == "") { 61 | setFileLabel("", fileChanged: false) 62 | } else { 63 | setFileLabel("Untitled", fileChanged: editingNewFile) 64 | } 65 | } 66 | } 67 | } 68 | 69 | @objc private static let keyPathsForValuesAffectingAttributedTextInput: Set = [ 70 | #keyPath(editorText) 71 | ] 72 | 73 | @objc private var attributedTextInput: NSAttributedString { 74 | get { return NSAttributedString(string: self.editorText) } 75 | set { self.editorText = newValue.string } 76 | } 77 | 78 | @objc func setTheme(_ notification: Notification?) { 79 | var theme = notification?.object as? String ?? defaults.string(forKey: "theme") 80 | if theme == nil { 81 | theme = DEFAULT_THEME 82 | } 83 | if let theme = theme { 84 | if (theme == "Light") { 85 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantLight) 86 | editorBackground.material = .light 87 | editor.textColor = NSColor.black 88 | } else { 89 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark) 90 | editorBackground.material = .dark 91 | editor.textColor = NSColor.white 92 | } 93 | } 94 | } 95 | 96 | func setFont(font: NSFont) { 97 | let defaultFont = defaults.string(forKey: "font") ?? DEFAULT_FONT 98 | let defaultFontSize = defaults.string(forKey: "fontSize") ?? DEFAULT_FONT_SIZE 99 | 100 | if font.fontName != defaultFont { 101 | defaults.setValue(font.fontName, forKey: "font") 102 | } 103 | 104 | if font.pointSize != CGFloat(Int(defaultFontSize)!) { 105 | defaults.setValue(font.pointSize, forKey: "fontSize") 106 | } 107 | } 108 | 109 | @IBAction func saveFile(_ sender: AnyObject?) { 110 | let contents = editor.string 111 | 112 | if editingFile && editingFilePath != nil { 113 | if let path = editingFilePath { 114 | // May want to remove all text so dont check if editorText is empty 115 | do { 116 | try contents.write(to: path, atomically: true, encoding: .utf8) 117 | fileChanged = false 118 | setFileLabel(path.lastPathComponent, fileChanged: fileChanged) 119 | return 120 | } catch { 121 | popup(message: "There was an error saving the file.") 122 | } 123 | } 124 | } 125 | 126 | saveDialog(nil, contents: contents) 127 | } 128 | 129 | @IBAction func saveDocumentAs(_ sender: AnyObject?) { 130 | let contents = editor.string 131 | if let path = editingFilePath { 132 | saveDialog(path, contents: contents) 133 | } 134 | } 135 | 136 | func saveDialog(_ path: URL?, contents: String) { 137 | let dialog = NSSavePanel() 138 | 139 | dialog.title = "Save a markdown file" 140 | dialog.allowedFileTypes = ["md"] 141 | dialog.canCreateDirectories = false 142 | 143 | if let path = editingFilePath { 144 | dialog.nameFieldStringValue = path.lastPathComponent 145 | } 146 | 147 | if dialog.runModal() == NSApplication.ModalResponse.OK { 148 | if let result = dialog.url { 149 | do { 150 | try contents.write(to: result, atomically: true, encoding: .utf8) 151 | editingFile = true 152 | editingFilePath = result 153 | fileChanged = false 154 | setFileLabel(result.lastPathComponent, fileChanged: fileChanged) 155 | } catch { 156 | self.popup(message: "There was an error saving the file.") 157 | } 158 | } 159 | } 160 | } 161 | 162 | @IBAction func openFile(_ sender: AnyObject?) { 163 | let dialog = NSOpenPanel() 164 | 165 | dialog.title = "Open a markdown file" 166 | dialog.allowedFileTypes = ["md"] 167 | dialog.allowsMultipleSelection = false 168 | dialog.canChooseDirectories = false 169 | 170 | if dialog.runModal() == NSApplication.ModalResponse.OK { 171 | if let result = dialog.url, 172 | let contents = try? String(contentsOf: result, encoding: .utf8) { 173 | editor.string = contents 174 | editingFile = true 175 | editingFilePath = result 176 | setFileLabel(result.lastPathComponent, fileChanged: fileChanged) 177 | } 178 | } 179 | loadMarkdown() 180 | } 181 | 182 | func loadFile(_ filePath: String) { 183 | if let content = try? String(contentsOfFile: filePath, encoding: .utf8) { 184 | editor.string = content 185 | editingFile = true 186 | 187 | let urlPath = NSURL.fileURL(withPath: filePath) 188 | editingFilePath = urlPath 189 | setFileLabel(urlPath.lastPathComponent, fileChanged: fileChanged) 190 | } 191 | loadMarkdown() 192 | MarkdownViewController().setWordCountLabel() 193 | } 194 | 195 | func loadMarkdown() { 196 | let down = Down(markdownString: editor.string) 197 | 198 | if let font = editor.font { 199 | setFont(font: font) 200 | } 201 | 202 | if let attrMarkdown = try? down.toAttributedString(), 203 | let splitViewController = self.parent as? NSSplitViewController, 204 | let markdownSplitView = splitViewController.splitViewItems.last { 205 | let markdownVC = markdownSplitView.viewController as? MarkdownViewController 206 | markdownVC?.setMarkdown(attrMarkdown) 207 | } 208 | } 209 | 210 | func setFileLabel(_ fileName: String, fileChanged: Bool) { 211 | if fileChanged { 212 | fileLabel.stringValue = fileName + " (edited)" 213 | return 214 | } 215 | fileLabel.stringValue = fileName 216 | } 217 | 218 | func popup(message: String) { 219 | let alert = NSAlert() 220 | alert.informativeText = message 221 | alert.alertStyle = .warning 222 | alert.addButton(withTitle: "OK") 223 | alert.runModal() 224 | } 225 | 226 | @IBAction func expandSidebar(_ sender: NSButton) { 227 | if let splitViewController = self.parent as? NSSplitViewController, 228 | let markdownSplitView = splitViewController.splitViewItems.last { 229 | markdownSplitView.collapseBehavior = .preferResizingSplitViewWithFixedSiblings 230 | markdownSplitView.animator().isCollapsed = !markdownSplitView.isCollapsed 231 | } 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /Markr/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | md 13 | 14 | CFBundleTypeName 15 | Markdown Files 16 | CFBundleTypeRole 17 | Editor 18 | NSDocumentClass 19 | NSDocument 20 | 21 | 22 | CFBundleExecutable 23 | $(EXECUTABLE_NAME) 24 | CFBundleIconFile 25 | 26 | CFBundleIdentifier 27 | $(PRODUCT_BUNDLE_IDENTIFIER) 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | $(PRODUCT_NAME) 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.0 36 | CFBundleVersion 37 | 1 38 | LSApplicationCategoryType 39 | public.app-category.developer-tools 40 | LSMinimumSystemVersion 41 | $(MACOSX_DEPLOYMENT_TARGET) 42 | NSHumanReadableCopyright 43 | Copyright © 2017 Luka Kerr. All rights reserved. 44 | NSMainStoryboardFile 45 | Main 46 | NSPrincipalClass 47 | NSApplication 48 | 49 | 50 | -------------------------------------------------------------------------------- /Markr/MarkdownFormatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarkdownFormatter.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 14/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class MarkdownFormatter { 12 | 13 | func format(_ markdownString: NSAttributedString) -> NSAttributedString { 14 | let attrStr = NSMutableAttributedString(attributedString: markdownString) 15 | return changeFont(attrStr) 16 | } 17 | 18 | func changeFont(_ attrStr: NSMutableAttributedString) -> NSMutableAttributedString { 19 | // Enumerate through all the font ranges 20 | attrStr.enumerateAttribute(NSAttributedStringKey.font, in: NSMakeRange(0, attrStr.length), options: []) { value, range, stop in 21 | guard var currentFont = value as? NSFont else { 22 | return 23 | } 24 | 25 | let theme = defaults.string(forKey: "theme") ?? DEFAULT_THEME 26 | 27 | let fontName: String = currentFont.fontName.lowercased() 28 | var destinationFont: NSFont = NSFont(name: "Helvetica Light", size: currentFont.pointSize)! 29 | 30 | let boldFont = fontName.range(of: "bold") 31 | let italicFont = fontName.range(of: "italic") 32 | let codeFont = fontName.range(of: "courier") 33 | 34 | if boldFont != nil { 35 | if let font = NSFont(name: "Helvetica Bold", size: currentFont.pointSize) { 36 | destinationFont = font 37 | } 38 | } else if italicFont != nil { 39 | if let font = NSFont(name: "Helvetica Oblique", size: currentFont.pointSize) { 40 | destinationFont = font 41 | } 42 | } else if codeFont != nil { 43 | if let font = NSFont(name: "Monaco", size: currentFont.pointSize), 44 | let newCurrentFont = NSFont(name: currentFont.fontName, size: currentFont.pointSize * 0.85) { 45 | destinationFont = font 46 | currentFont = newCurrentFont 47 | } 48 | } 49 | 50 | let fontDescriptor = destinationFont.fontDescriptor 51 | 52 | // Ask the system for an actual font that most closely matches the description above 53 | if let newFontDescriptor = fontDescriptor.matchingFontDescriptors(withMandatoryKeys: [NSFontDescriptor.AttributeName.name]).first, 54 | let newFont = NSFont(descriptor: newFontDescriptor, size: currentFont.pointSize * 1.25) { 55 | attrStr.addAttributes([NSAttributedStringKey.font: newFont], range: range) 56 | 57 | if theme == "Light" && codeFont == nil { 58 | attrStr.addAttribute( 59 | NSAttributedStringKey.foregroundColor, 60 | value: NSColor.black, 61 | range: range 62 | ) 63 | } else if codeFont == nil { 64 | attrStr.addAttribute( 65 | NSAttributedStringKey.foregroundColor, 66 | value: NSColor.white, 67 | range: range 68 | ) 69 | } 70 | 71 | if codeFont != nil { 72 | if (theme == "Light") { 73 | attrStr.addAttribute( 74 | NSAttributedStringKey.foregroundColor, 75 | value: NSColor(red:0, green:0, blue:0, alpha:0.5), 76 | range: range 77 | ) 78 | } else { 79 | attrStr.addAttribute( 80 | NSAttributedStringKey.foregroundColor, 81 | value: NSColor(red:1, green:1, blue:1, alpha:0.75), 82 | range: range 83 | ) 84 | } 85 | } 86 | 87 | let paragraphStyle: NSMutableParagraphStyle = NSMutableParagraphStyle() 88 | paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: 15, options: NSDictionary() as! [NSTextTab.OptionKey : Any])] 89 | paragraphStyle.defaultTabInterval = 15 90 | paragraphStyle.firstLineHeadIndent = 0 91 | paragraphStyle.headIndent = 0 92 | if codeFont == nil { 93 | paragraphStyle.paragraphSpacing = 15 94 | } else { 95 | paragraphStyle.paragraphSpacing = 7.5 96 | } 97 | 98 | attrStr.addAttribute( 99 | NSAttributedStringKey.paragraphStyle, 100 | value: paragraphStyle, 101 | range: range 102 | ) 103 | } 104 | } 105 | return attrStr 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /Markr/MarkdownViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MarkdownViewController.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 9/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class MarkdownViewController: NSViewController { 12 | 13 | @IBOutlet weak var markdownBackground: NSVisualEffectView! 14 | @IBOutlet weak var wordCountLabel: NSTextField! 15 | @IBOutlet var markdown: NSTextView! { 16 | didSet { 17 | markdown.layoutManager?.defaultAttachmentScaling = NSImageScaling.scaleProportionallyDown 18 | } 19 | } 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | // Register for theme change notification 25 | NotificationCenter.default.addObserver( 26 | self, 27 | selector: #selector(self.setTheme), 28 | name: NSNotification.Name(rawValue: "themeChangedNotification"), 29 | object: nil 30 | ) 31 | 32 | setTheme(nil) 33 | } 34 | 35 | @objc func setTheme(_ notification: Notification?) { 36 | var theme = notification?.object as? String ?? defaults.string(forKey: "theme") 37 | if theme == nil { 38 | theme = DEFAULT_THEME 39 | } 40 | 41 | if (theme == "Light") { 42 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantLight) 43 | markdownBackground.material = .light 44 | markdown.textColor = NSColor.black 45 | } else { 46 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark) 47 | markdownBackground.material = .dark 48 | markdown.textColor = NSColor.white 49 | } 50 | } 51 | 52 | func setMarkdown(_ markdownString: NSAttributedString) { 53 | let formattedMarkdown = MarkdownFormatter().format(markdownString) 54 | markdown.textStorage?.mutableString.setString("") 55 | markdown.textStorage?.append(formattedMarkdown) 56 | setWordCountLabel() 57 | } 58 | 59 | func setWordCountLabel() { 60 | if let splitViewController = self.parent as? NSSplitViewController, 61 | let editorSplitView = splitViewController.splitViewItems.first { 62 | let editorViewController = editorSplitView.viewController as? EditorViewController 63 | if let charCount = editorViewController?.editor.textStorage?.words.count { 64 | if charCount == 1 { 65 | wordCountLabel.stringValue = String(charCount) + " word" 66 | } else if charCount > 0 { 67 | wordCountLabel.stringValue = String(charCount) + " words" 68 | } else { 69 | wordCountLabel.stringValue = "" 70 | } 71 | } 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Markr/PreferencesViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesViewController.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 11/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class PreferencesViewController: NSViewController { 12 | 13 | var theme = defaults.string(forKey: "theme") ?? DEFAULT_THEME { 14 | didSet { 15 | defaults.setValue(theme, forKey: "theme") 16 | } 17 | } 18 | 19 | @IBOutlet weak var themeButton: NSSegmentedControl! { 20 | didSet { 21 | switch theme { 22 | case "Light": 23 | themeButton.selectedSegment = 0 24 | default: 25 | themeButton.selectedSegment = 1 26 | } 27 | } 28 | } 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | } 33 | 34 | @IBAction func themeChanged(_ sender: NSSegmentedControl) { 35 | if (sender.selectedSegment == 0) { 36 | theme = "Light" 37 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantLight) 38 | } else { 39 | theme = "Dark" 40 | self.view.window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark) 41 | } 42 | 43 | NotificationCenter.default.post( 44 | name: NSNotification.Name(rawValue: "themeChangedNotification"), 45 | object: theme 46 | ) 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Markr/PreferencesWindowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesWindowController.swift 3 | // Markr 4 | // 5 | // Created by Luka Kerr on 11/10/17. 6 | // Copyright © 2017 Luka Kerr. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class PreferencesWindowController: NSWindowController { 12 | 13 | let theme = defaults.string(forKey: "theme") ?? DEFAULT_THEME 14 | 15 | override func windowDidLoad() { 16 | super.windowDidLoad() 17 | 18 | // Window properties 19 | window?.titleVisibility = NSWindow.TitleVisibility.hidden; 20 | window?.titlebarAppearsTransparent = true; 21 | window?.styleMask.insert(.fullSizeContentView) 22 | window?.isOpaque = false 23 | window?.invalidateShadow() 24 | 25 | switch theme { 26 | case "Light": 27 | window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantLight) 28 | default: 29 | window?.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark) 30 | } 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.13' 2 | 3 | target 'Markr' do 4 | use_frameworks! 5 | 6 | pod 'Down' 7 | end 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Down (0.3.4) 3 | 4 | DEPENDENCIES: 5 | - Down 6 | 7 | SPEC CHECKSUMS: 8 | Down: 3f35b61e51a603df3e9e7e0289b15752e72f82e6 9 | 10 | PODFILE CHECKSUM: 390b72be4a2772d690fda4f93f87102e224636f9 11 | 12 | COCOAPODS: 1.3.1 13 | -------------------------------------------------------------------------------- /Pods/Down/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Rob Phillips. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Pods/Down/README.md: -------------------------------------------------------------------------------- 1 | ## Down 2 | [![Build Status](https://travis-ci.org/iwasrobbed/Down.svg?branch=master)](https://travis-ci.org/iwasrobbed/Down) 3 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/iwasrobbed/Down/blob/master/LICENSE) 4 | [![CocoaPods](https://img.shields.io/cocoapods/v/Down.svg?maxAge=2592000)]() 5 | [![Swift](https://img.shields.io/badge/language-Swift-blue.svg)](https://swift.org) 6 | [![macOS](https://img.shields.io/badge/OS-macOS-orange.svg)](https://developer.apple.com/macos/) 7 | [![iOS](https://img.shields.io/badge/OS-iOS-orange.svg)](https://developer.apple.com/ios/) 8 | [![tvOS](https://img.shields.io/badge/OS-tvOS-orange.svg)](https://developer.apple.com/tvos/) 9 | [![Coverage Status](https://coveralls.io/repos/github/iwasrobbed/Down/badge.svg?branch=master)](https://coveralls.io/github/iwasrobbed/Down?branch=master) 10 | 11 | Blazing fast Markdown rendering in Swift, built upon [cmark](https://github.com/jgm/cmark). 12 | 13 | Is your app using it? [Let me know!](mailto:rob@desideratalabs.co) 14 | 15 | ### Installation 16 | 17 | Quickly install using [CocoaPods](https://cocoapods.org): 18 | 19 | ```ruby 20 | pod 'Down' 21 | ``` 22 | 23 | Or [Carthage](https://github.com/Carthage/Carthage): 24 | 25 | ``` 26 | github "iwasrobbed/Down" 27 | ``` 28 | 29 | Or manually install: 30 | 31 | 1. Clone this repository 32 | 2. Build the Down project 33 | 3. Add the resulting framework file to your project 34 | 4. ? 35 | 5. Profit 36 | 37 | ### Robust Performance 38 | 39 | >[cmark](https://github.com/jgm/cmark) can render a Markdown version of War and Peace in the blink of an eye (127 milliseconds on a ten year old laptop, vs. 100-400 milliseconds for an eye blink). In our [benchmarks](https://github.com/jgm/cmark/blob/master/benchmarks.md), cmark is 10,000 times faster than the original Markdown.pl, and on par with the very fastest available Markdown processors. 40 | 41 | > The library has been extensively fuzz-tested using [american fuzzy lop](http://lcamtuf.coredump.cx/afl). The test suite includes pathological cases that bring many other Markdown parsers to a crawl (for example, thousands-deep nested bracketed text or block quotes). 42 | 43 | ### Output Formats 44 | * Web View (see DownView class) 45 | * HTML 46 | * XML 47 | * LaTeX 48 | * groff man 49 | * CommonMark Markdown 50 | * NSAttributedString 51 | * AST (abstract syntax tree) 52 | 53 | ### View Rendering 54 | 55 | The `DownView` class offers a very simple way to parse a UTF-8 encoded string with Markdown and convert it to a web view that can be added to any view: 56 | 57 | ```swift 58 | let downView = try? DownView(frame: self.view.bounds, markdownString: "**Oh Hai**") { 59 | // Optional callback for loading finished 60 | } 61 | // Now add to view or constrain w/ Autolayout 62 | // Or you could optionally update the contents at some point: 63 | try? downView?.update(markdownString: "## [Google](https://google.com)") { 64 | // Optional callback for loading finished 65 | } 66 | ``` 67 | 68 | Meta example of rendering this README: 69 | 70 | ![Example gif](Images/ohhai.gif) 71 | 72 | ### Parsing API 73 | 74 | The `Down` struct has everything you need if you just want out-of-the-box setup for parsing and conversion. 75 | 76 | ```swift 77 | let down = Down(markdownString: "## [Down](https://github.com/iwasrobbed/Down)") 78 | 79 | // Convert to HTML 80 | let html = try? down.toHTML() 81 | // "

Down

\n" 82 | 83 | // Convert to XML 84 | let xml = try? down.toXML() 85 | // "\n\n\n \n \n Down\n \n \n\n" 86 | 87 | // Convert to groff man 88 | let man = try? down.toGroff() 89 | // ".SS\nDown (https://github.com/iwasrobbed/Down)\n" 90 | 91 | // Convert to LaTeX 92 | let latex = try? down.toLaTeX() 93 | // "\\subsection{\\href{https://github.com/iwasrobbed/Down}{Down}}\n" 94 | 95 | // Convert to CommonMark Markdown 96 | let commonMark = try? down.toCommonMark() 97 | // "## [Down](https://github.com/iwasrobbed/Down)\n" 98 | 99 | // Convert to an attributed string 100 | let attributedString = try? down.toAttributedString() 101 | // NSAttributedString representation of the rendered HTML 102 | 103 | // Convert to abstract syntax tree 104 | let ast = try? down.toAST() 105 | // Returns pointer to AST that you can manipulate 106 | 107 | ``` 108 | 109 | ### Rendering Granularity 110 | 111 | If you'd like more granularity for the output types you want to support, you can create your own struct conforming to at least one of the renderable protocols: 112 | 113 | * DownHTMLRenderable 114 | * DownXMLRenderable 115 | * DownLaTeXRenderable 116 | * DownGroffRenderable 117 | * DownCommonMarkRenderable 118 | * DownASTRenderable 119 | * DownAttributedStringRenderable 120 | 121 | Example: 122 | 123 | ```swift 124 | public struct MarkdownToHTML: DownHTMLRenderable { 125 | /** 126 | A string containing CommonMark Markdown 127 | */ 128 | public var markdownString: String 129 | 130 | /** 131 | Initializes the container with a CommonMark Markdown string which can then be rendered as HTML using `toHTML()` 132 | 133 | - parameter markdownString: A string containing CommonMark Markdown 134 | 135 | - returns: An instance of Self 136 | */ 137 | @warn_unused_result 138 | public init(markdownString: String) { 139 | self.markdownString = markdownString 140 | } 141 | } 142 | ``` 143 | 144 | ### Options 145 | 146 | Each protocol has options that will influence either rendering or parsing: 147 | 148 | ```swift 149 | /** 150 | Default options 151 | */ 152 | public static let Default = DownOptions(rawValue: 0) 153 | 154 | // MARK: - Rendering Options 155 | 156 | /** 157 | Include a `data-sourcepos` attribute on all block elements 158 | */ 159 | public static let SourcePos = DownOptions(rawValue: 1 << 1) 160 | 161 | /** 162 | Render `softbreak` elements as hard line breaks. 163 | */ 164 | public static let HardBreaks = DownOptions(rawValue: 1 << 2) 165 | 166 | /** 167 | Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`, 168 | `file:`, and `data:`, except for `image/png`, `image/gif`, 169 | `image/jpeg`, or `image/webp` mime types). Raw HTML is replaced 170 | by a placeholder HTML comment. Unsafe links are replaced by 171 | empty strings. 172 | */ 173 | public static let Safe = DownOptions(rawValue: 1 << 3) 174 | 175 | // MARK: - Parsing Options 176 | 177 | /** 178 | Normalize tree by consolidating adjacent text nodes. 179 | */ 180 | public static let Normalize = DownOptions(rawValue: 1 << 4) 181 | 182 | /** 183 | Validate UTF-8 in the input before parsing, replacing illegal 184 | sequences with the replacement character U+FFFD. 185 | */ 186 | public static let ValidateUTF8 = DownOptions(rawValue: 1 << 5) 187 | 188 | /** 189 | Convert straight quotes to curly, --- to em dashes, -- to en dashes. 190 | */ 191 | public static let Smart = DownOptions(rawValue: 1 << 6) 192 | ``` 193 | 194 | ### Supports 195 | Swift, ARC & iOS 8+ 196 | 197 | ### Markdown Specification 198 | 199 | Down is built upon the [CommonMark](http://commonmark.org) specification. 200 | 201 | ### A little help from my friends 202 | Please feel free to fork and create a pull request for bug fixes or improvements, being sure to maintain the general coding style, adding tests, and adding comments as necessary. 203 | 204 | ### Credit 205 | This library is a wrapper around [cmark](https://github.com/jgm/cmark), which is built upon the [CommonMark](http://commonmark.org) Markdown specification. 206 | 207 | [cmark](https://github.com/jgm/cmark) is Copyright (c) 2014, John MacFarlane. View [full license](https://github.com/jgm/cmark/blob/master/COPYING). 208 | -------------------------------------------------------------------------------- /Pods/Down/Resources/DownView.bundle/css/down.min.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */progress,sub,sup{vertical-align:baseline}button,hr,input{overflow:visible}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} 2 | 3 | /* Modified version of github.com/sindresorhus/github-markdown-css | MIT License */ 4 | /* Unminify it @ unminify.com */ 5 | hr,img{box-sizing:content-box}body:after,body:before,hr::after,hr::before{display:table;content:""}a,a:not([href]){text-decoration:none}blockquote,h6{color:#777}hr,svg:not(:root){overflow:hidden}dl,dl dt,hr,td,th{padding:0}img,table tr{background-color:#fff}pre,pre code{word-wrap:normal}body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#333;font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1.5em;line-height:1.6;word-wrap:break-word;padding:2rem}a{background-color:transparent;-webkit-text-decoration-skip:objects;color:#4078c0}a:active,a:hover{outline-width:0;text-decoration:underline}strong{font-weight:bolder}h1{margin:.67em 0}img{border-style:none;max-width:100%}h1,h2{padding-bottom:.3em;border-bottom:1px solid #eee}input{margin:0;overflow:visible;font:13px/1.4 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}[type=checkbox]{box-sizing:border-box;padding:0}table{border-spacing:0;border-collapse:collapse;display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}*{box-sizing:border-box}body:after,hr::after{clear:both}blockquote{margin:0;padding:0 15px;border-left:4px solid #ddd}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}dd{margin-left:0}code,pre{font:.9em Consolas,"Liberation Mono",Menlo,Courier,monospace}dl dt,table th{font-weight:700}body>:first-child{margin-top:0!important}dl dt,li>p{margin-top:16px}body>:last-child{margin-bottom:0!important}a:not([href]){color:inherit}h1,h2,h3,h4,h5,h6{margin-top:1em;margin-bottom:16px;font-weight:700;line-height:1.4}h1{font-size:2.25em;line-height:1.2}h2{font-size:1.75em;line-height:1.225}h3{font-size:1.5em;line-height:1.43}h4{font-size:1.25em}dl dt,h5,h6{font-size:1em}blockquote,dl,ol,p,pre,table,ul{margin-top:0;margin-bottom:16px}hr{background:#e7e7e7;height:4px;margin:16px 0;border:0}ol,ul{padding-left:2em}ol ol,ol ul,ul ol,ul ul{margin-top:0;margin-bottom:0}dl dt{font-style:italic}dl dd{padding:0 16px;margin-bottom:16px}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table td,table th{padding:6px 13px;border:1px solid #ddd}table tr{border-top:1px solid #ccc}table tr:nth-child(2n){background-color:#f8f8f8}code{padding:.2em 0;margin:0;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px}pre code,pre>code{padding:0;margin:0;border:0}code:after,code:before{letter-spacing:-.2em;content:"\00a0"}pre>code{font-size:100%;word-break:normal;white-space:pre;background:0 0}pre code{display:inline;max-width:initial;overflow:initial;line-height:inherit;background-color:transparent}pre code:after,pre code:before{content:normal}kbd{display:inline-block;padding:3px 5px;font:11px Consolas,"Liberation Mono",Menlo,Courier,monospace;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:1px solid #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}:checked+.radio-label{position:relative;z-index:1;border-color:#4078c0}hr{border-bottom-color:#eee} 6 | 7 | /*! highlightjs */ 8 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#1d1f21;color:#c5c8c6}.hljs span::selection,.hljs::selection{background:#373b41}.hljs span::-moz-selection,.hljs::-moz-selection{background:#373b41}.hljs-name,.hljs-title{color:#f0c674}.hljs-comment,.hljs-meta,.hljs-meta .hljs-keyword{color:#707880}.hljs-deletion,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol{color:#c66}.hljs-addition,.hljs-doctag,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-string{color:#b5bd68}.hljs-attribute,.hljs-code,.hljs-selector-id{color:#b294bb}.hljs-bullet,.hljs-keyword,.hljs-selector-tag,.hljs-tag{color:#81a2be}.hljs-subst,.hljs-template-tag,.hljs-template-variable,.hljs-variable{color:#8abeb7}.hljs-built_in,.hljs-builtin-name,.hljs-quote,.hljs-section,.hljs-selector-class,.hljs-type{color:#de935f}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} -------------------------------------------------------------------------------- /Pods/Down/Resources/DownView.bundle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | DOWN_HTML 13 | 14 | -------------------------------------------------------------------------------- /Pods/Down/Resources/DownView.bundle/js/down.js: -------------------------------------------------------------------------------- 1 | hljs.initHighlightingOnLoad(); -------------------------------------------------------------------------------- /Pods/Down/Source/Down.h: -------------------------------------------------------------------------------- 1 | // 2 | // Down.h 3 | // Down 4 | // 5 | // Created by Rob Phillips on 6/1/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for Down. 12 | FOUNDATION_EXPORT double DownVersionNumber; 13 | 14 | //! Project version string for Down. 15 | FOUNDATION_EXPORT const unsigned char DownVersionString[]; 16 | -------------------------------------------------------------------------------- /Pods/Down/Source/Down.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Down.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/28/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Down: DownASTRenderable, DownHTMLRenderable, DownXMLRenderable, 12 | DownLaTeXRenderable, DownGroffRenderable, DownCommonMarkRenderable, 13 | DownAttributedStringRenderable { 14 | /** 15 | A string containing CommonMark Markdown 16 | */ 17 | public var markdownString: String 18 | 19 | /** 20 | Initializes the container with a CommonMark Markdown string which can then be rendered depending on protocol conformance 21 | 22 | - parameter markdownString: A string containing CommonMark Markdown 23 | 24 | - returns: An instance of Self 25 | */ 26 | 27 | public init(markdownString: String) { 28 | self.markdownString = markdownString 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Pods/Down/Source/Enums & Options/DownErrors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownErrors.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/28/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum DownErrors: Error { 12 | /** 13 | Thrown when there was an issue converting the Markdown into an abstract syntax tree 14 | */ 15 | case markdownToASTError 16 | 17 | /** 18 | Thrown when the abstract syntax tree could not be rendered into another format 19 | */ 20 | case astRenderingError 21 | 22 | /** 23 | Thrown when an HTML string cannot be converted into an `NSData` representation 24 | */ 25 | case htmlDataConversionError 26 | } 27 | -------------------------------------------------------------------------------- /Pods/Down/Source/Enums & Options/DownOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownOptions.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/28/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public struct DownOptions: OptionSet { 13 | public let rawValue: Int32 14 | public init(rawValue: Int32) { self.rawValue = rawValue } 15 | 16 | /** 17 | Default options 18 | */ 19 | public static let Default = DownOptions(rawValue: CMARK_OPT_DEFAULT) 20 | 21 | // MARK: - Rendering Options 22 | 23 | /** 24 | Include a `data-sourcepos` attribute on all block elements 25 | */ 26 | public static let SourcePos = DownOptions(rawValue: CMARK_OPT_SOURCEPOS) 27 | 28 | /** 29 | Render `softbreak` elements as hard line breaks. 30 | */ 31 | public static let HardBreaks = DownOptions(rawValue: CMARK_OPT_HARDBREAKS) 32 | 33 | /** 34 | Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`, 35 | `file:`, and `data:`, except for `image/png`, `image/gif`, 36 | `image/jpeg`, or `image/webp` mime types). Raw HTML is replaced 37 | by a placeholder HTML comment. Unsafe links are replaced by 38 | empty strings. 39 | */ 40 | public static let Safe = DownOptions(rawValue: CMARK_OPT_SAFE) 41 | 42 | // MARK: - Parsing Options 43 | 44 | /** 45 | Normalize tree by consolidating adjacent text nodes. 46 | */ 47 | public static let Normalize = DownOptions(rawValue: CMARK_OPT_NORMALIZE) 48 | 49 | /** 50 | Validate UTF-8 in the input before parsing, replacing illegal 51 | sequences with the replacement character U+FFFD. 52 | */ 53 | public static let ValidateUTF8 = DownOptions(rawValue: CMARK_OPT_VALIDATE_UTF8) 54 | 55 | /** 56 | Convert straight quotes to curly, --- to em dashes, -- to en dashes. 57 | */ 58 | public static let Smart = DownOptions(rawValue: CMARK_OPT_SMART) 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Pods/Down/Source/Extensions/NSAttributedString+HTML.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+HTML.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 6/1/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | #if os(OSX) 10 | import AppKit 11 | #else 12 | import UIKit 13 | #endif 14 | 15 | 16 | extension NSAttributedString { 17 | 18 | /** 19 | Instantiates an attributed string with the given HTML string 20 | 21 | - parameter htmlString: An HTML string 22 | 23 | - throws: `HTMLDataConversionError` or an instantiation error 24 | 25 | - returns: An attributed string 26 | */ 27 | convenience init(htmlString: String) throws { 28 | guard let data = htmlString.data(using: String.Encoding.utf8) else { 29 | throw DownErrors.htmlDataConversionError 30 | } 31 | 32 | 33 | let options: [NSAttributedString.DocumentReadingOptionKey : Any] = [ 34 | NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.documentType.rawValue): NSAttributedString.DocumentType.html, 35 | NSAttributedString.DocumentReadingOptionKey(rawValue: NSAttributedString.DocumentAttributeKey.characterEncoding.rawValue): NSNumber(value: String.Encoding.utf8.rawValue) 36 | ] 37 | try self.init(data: data, options: options, documentAttributes: nil) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Pods/Down/Source/Extensions/String+ToHTML.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+ToHTML.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 6/1/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | extension String { 13 | 14 | /** 15 | Generates an HTML string from the contents of the string (self), which should contain CommonMark Markdown 16 | 17 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 18 | 19 | - throws: `DownErrors` depending on the scenario 20 | 21 | - returns: HTML string 22 | */ 23 | public func toHTML(_ options: DownOptions = .Default) throws -> String { 24 | let ast = try DownASTRenderer.stringToAST(self, options: options) 25 | let html = try DownHTMLRenderer.astToHTML(ast, options: options) 26 | cmark_node_free(ast) 27 | return html 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownASTRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownASTRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/31/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownASTRenderable: DownRenderable { 13 | /** 14 | Generates an abstract syntax tree from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | 18 | - throws: `MarkdownToASTError` if conversion fails 19 | 20 | - returns: An abstract syntax tree representation of the Markdown input 21 | */ 22 | 23 | func toAST(_ options: DownOptions) throws -> UnsafeMutablePointer 24 | } 25 | 26 | public extension DownASTRenderable { 27 | /** 28 | Generates an abstract syntax tree from the `markdownString` property 29 | 30 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 31 | 32 | - throws: `MarkdownToASTError` if conversion fails 33 | 34 | - returns: An abstract syntax tree representation of the Markdown input 35 | */ 36 | 37 | public func toAST(_ options: DownOptions = .Default) throws -> UnsafeMutablePointer { 38 | return try DownASTRenderer.stringToAST(markdownString, options: options) 39 | } 40 | } 41 | 42 | public struct DownASTRenderer { 43 | /** 44 | Generates an abstract syntax tree from the given CommonMark Markdown string 45 | 46 | **Important:** It is the caller's responsibility to call `cmark_node_free(ast)` on the returned value 47 | 48 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 49 | 50 | - throws: `MarkdownToASTError` if conversion fails 51 | 52 | - returns: An abstract syntax tree representation of the Markdown input 53 | */ 54 | 55 | public static func stringToAST(_ string: String, options: DownOptions = .Default) throws -> UnsafeMutablePointer { 56 | var tree: UnsafeMutablePointer? 57 | string.withCString { 58 | let stringLength = Int(strlen($0)) 59 | tree = cmark_parse_document($0, stringLength, options.rawValue) 60 | } 61 | 62 | guard let ast = tree else { 63 | throw DownErrors.markdownToASTError 64 | } 65 | return ast 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownAttributedStringRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownAttributedStringRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 6/1/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownAttributedStringRenderable: DownHTMLRenderable { 13 | /** 14 | Generates an `NSAttributedString` from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | 18 | - throws: `DownErrors` depending on the scenario 19 | 20 | - returns: An `NSAttributedString` 21 | */ 22 | 23 | func toAttributedString(_ options: DownOptions) throws -> NSAttributedString 24 | } 25 | 26 | public extension DownAttributedStringRenderable { 27 | /** 28 | Generates an `NSAttributedString` from the `markdownString` property 29 | 30 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 31 | 32 | - throws: `DownErrors` depending on the scenario 33 | 34 | - returns: An `NSAttributedString` 35 | */ 36 | 37 | public func toAttributedString(_ options: DownOptions = .Default) throws -> NSAttributedString { 38 | let html = try self.toHTML(options) 39 | return try NSAttributedString(htmlString: html) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownCommonMarkRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownCommonMarkRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/31/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownCommonMarkRenderable: DownRenderable { 13 | /** 14 | Generates a CommonMark Markdown string from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | - parameter width: The width to break on 18 | 19 | - throws: `DownErrors` depending on the scenario 20 | 21 | - returns: CommonMark Markdown string 22 | */ 23 | 24 | func toCommonMark(_ options: DownOptions, width: Int32) throws -> String 25 | } 26 | 27 | public extension DownCommonMarkRenderable { 28 | /** 29 | Generates a CommonMark Markdown string from the `markdownString` property 30 | 31 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 32 | - parameter width: The width to break on, defaulting to 0 33 | 34 | - throws: `DownErrors` depending on the scenario 35 | 36 | - returns: CommonMark Markdown string 37 | */ 38 | 39 | public func toCommonMark(_ options: DownOptions = .Default, width: Int32 = 0) throws -> String { 40 | let ast = try DownASTRenderer.stringToAST(markdownString, options: options) 41 | let commonMark = try DownCommonMarkRenderer.astToCommonMark(ast, options: options, width: width) 42 | cmark_node_free(ast) 43 | return commonMark 44 | } 45 | } 46 | 47 | public struct DownCommonMarkRenderer { 48 | /** 49 | Generates a CommonMark Markdown string from the given abstract syntax tree 50 | 51 | **Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns 52 | 53 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 54 | - parameter width: The width to break on, defaulting to 0 55 | 56 | - throws: `ASTRenderingError` if the AST could not be converted 57 | 58 | - returns: CommonMark Markdown string 59 | */ 60 | 61 | public static func astToCommonMark(_ ast: UnsafeMutablePointer, 62 | options: DownOptions = .Default, 63 | width: Int32 = 0) throws -> String { 64 | guard let cCommonMarkString = cmark_render_commonmark(ast, options.rawValue, width) else { 65 | throw DownErrors.astRenderingError 66 | } 67 | defer { free(cCommonMarkString) } 68 | 69 | guard let commonMarkString = String(cString: cCommonMarkString, encoding: String.Encoding.utf8) else { 70 | throw DownErrors.astRenderingError 71 | } 72 | 73 | return commonMarkString 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownGroffRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownGroffRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/31/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownGroffRenderable: DownRenderable { 13 | /** 14 | Generates a groff man string from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | - parameter width: The width to break on 18 | 19 | - throws: `DownErrors` depending on the scenario 20 | 21 | - returns: groff man string 22 | */ 23 | 24 | func toGroff(_ options: DownOptions, width: Int32) throws -> String 25 | } 26 | 27 | public extension DownGroffRenderable { 28 | /** 29 | Generates a groff man string from the `markdownString` property 30 | 31 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 32 | - parameter width: The width to break on, defaulting to 0 33 | 34 | - throws: `DownErrors` depending on the scenario 35 | 36 | - returns: groff man string 37 | */ 38 | 39 | public func toGroff(_ options: DownOptions = .Default, width: Int32 = 0) throws -> String { 40 | let ast = try DownASTRenderer.stringToAST(markdownString, options: options) 41 | let groff = try DownGroffRenderer.astToGroff(ast, options: options, width: width) 42 | cmark_node_free(ast) 43 | return groff 44 | } 45 | } 46 | 47 | public struct DownGroffRenderer { 48 | /** 49 | Generates a groff man string from the given abstract syntax tree 50 | 51 | **Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns 52 | 53 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 54 | - parameter width: The width to break on, defaulting to 0 55 | 56 | - throws: `ASTRenderingError` if the AST could not be converted 57 | 58 | - returns: groff man string 59 | */ 60 | 61 | public static func astToGroff(_ ast: UnsafeMutablePointer, 62 | options: DownOptions = .Default, 63 | width: Int32 = 0) throws -> String { 64 | guard let cGroffString = cmark_render_man(ast, options.rawValue, width) else { 65 | throw DownErrors.astRenderingError 66 | } 67 | defer { free(cGroffString) } 68 | 69 | guard let groffString = String(cString: cGroffString, encoding: String.Encoding.utf8) else { 70 | throw DownErrors.astRenderingError 71 | } 72 | 73 | return groffString 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownHTMLRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownHTMLRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/28/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownHTMLRenderable: DownRenderable { 13 | /** 14 | Generates an HTML string from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | 18 | - throws: `DownErrors` depending on the scenario 19 | 20 | - returns: HTML string 21 | */ 22 | 23 | func toHTML(_ options: DownOptions) throws -> String 24 | } 25 | 26 | public extension DownHTMLRenderable { 27 | /** 28 | Generates an HTML string from the `markdownString` property 29 | 30 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 31 | 32 | - throws: `DownErrors` depending on the scenario 33 | 34 | - returns: HTML string 35 | */ 36 | 37 | public func toHTML(_ options: DownOptions = .Default) throws -> String { 38 | return try markdownString.toHTML(options) 39 | } 40 | } 41 | 42 | public struct DownHTMLRenderer { 43 | /** 44 | Generates an HTML string from the given abstract syntax tree 45 | 46 | **Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns 47 | 48 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 49 | 50 | - throws: `ASTRenderingError` if the AST could not be converted 51 | 52 | - returns: HTML string 53 | */ 54 | 55 | public static func astToHTML(_ ast: UnsafeMutablePointer, options: DownOptions = .Default) throws -> String { 56 | guard let cHTMLString = cmark_render_html(ast, options.rawValue) else { 57 | throw DownErrors.astRenderingError 58 | } 59 | defer { free(cHTMLString) } 60 | 61 | guard let htmlString = String(cString: cHTMLString, encoding: String.Encoding.utf8) else { 62 | throw DownErrors.astRenderingError 63 | } 64 | 65 | return htmlString 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownLaTeXRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownLaTeXRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/31/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownLaTeXRenderable: DownRenderable { 13 | /** 14 | Generates a LaTeX string from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | - parameter width: The width to break on 18 | 19 | - throws: `DownErrors` depending on the scenario 20 | 21 | - returns: LaTeX string 22 | */ 23 | 24 | func toLaTeX(_ options: DownOptions, width: Int32) throws -> String 25 | } 26 | 27 | public extension DownLaTeXRenderable { 28 | /** 29 | Generates a LaTeX string from the `markdownString` property 30 | 31 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 32 | - parameter width: The width to break on, defaulting to 0 33 | 34 | - throws: `DownErrors` depending on the scenario 35 | 36 | - returns: LaTeX string 37 | */ 38 | 39 | public func toLaTeX(_ options: DownOptions = .Default, width: Int32 = 0) throws -> String { 40 | let ast = try DownASTRenderer.stringToAST(markdownString, options: options) 41 | let latex = try DownLaTeXRenderer.astToLaTeX(ast, options: options, width: width) 42 | cmark_node_free(ast) 43 | return latex 44 | } 45 | } 46 | 47 | public struct DownLaTeXRenderer { 48 | /** 49 | Generates a LaTeX string from the given abstract syntax tree 50 | 51 | **Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns 52 | 53 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 54 | - parameter width: The width to break on, defaulting to 0 55 | 56 | - throws: `ASTRenderingError` if the AST could not be converted 57 | 58 | - returns: LaTeX string 59 | */ 60 | 61 | public static func astToLaTeX(_ ast: UnsafeMutablePointer, 62 | options: DownOptions = .Default, 63 | width: Int32 = 0) throws -> String { 64 | guard let cLatexString = cmark_render_latex(ast, options.rawValue, width) else { 65 | throw DownErrors.astRenderingError 66 | } 67 | defer { free(cLatexString) } 68 | 69 | guard let latexString = String(cString: cLatexString, encoding: String.Encoding.utf8) else { 70 | throw DownErrors.astRenderingError 71 | } 72 | 73 | return latexString 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/28/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol DownRenderable { 12 | /** 13 | A string containing CommonMark Markdown 14 | */ 15 | var markdownString: String { get set } 16 | } -------------------------------------------------------------------------------- /Pods/Down/Source/Renderers/DownXMLRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownXMLRenderable.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 5/31/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import libcmark 11 | 12 | public protocol DownXMLRenderable: DownRenderable { 13 | /** 14 | Generates an XML string from the `markdownString` property 15 | 16 | - parameter options: `DownOptions` to modify parsing or rendering 17 | 18 | - throws: `DownErrors` depending on the scenario 19 | 20 | - returns: XML string 21 | */ 22 | 23 | func toXML(_ options: DownOptions) throws -> String 24 | } 25 | 26 | public extension DownXMLRenderable { 27 | /** 28 | Generates an XML string from the `markdownString` property 29 | 30 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 31 | 32 | - throws: `DownErrors` depending on the scenario 33 | 34 | - returns: XML string 35 | */ 36 | 37 | public func toXML(_ options: DownOptions = .Default) throws -> String { 38 | let ast = try DownASTRenderer.stringToAST(markdownString, options: options) 39 | let xml = try DownXMLRenderer.astToXML(ast, options: options) 40 | cmark_node_free(ast) 41 | return xml 42 | } 43 | } 44 | 45 | public struct DownXMLRenderer { 46 | /** 47 | Generates an XML string from the given abstract syntax tree 48 | 49 | **Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns 50 | 51 | - parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default` 52 | 53 | - throws: `ASTRenderingError` if the AST could not be converted 54 | 55 | - returns: XML string 56 | */ 57 | 58 | public static func astToXML(_ ast: UnsafeMutablePointer, options: DownOptions = .Default) throws -> String { 59 | guard let cXMLString = cmark_render_xml(ast, options.rawValue) else { 60 | throw DownErrors.astRenderingError 61 | } 62 | defer { free(cXMLString) } 63 | 64 | guard let xmlString = String(cString: cXMLString, encoding: String.Encoding.utf8) else { 65 | throw DownErrors.astRenderingError 66 | } 67 | 68 | return xmlString 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Pods/Down/Source/Views/DownView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownView.swift 3 | // Down 4 | // 5 | // Created by Rob Phillips on 6/1/16. 6 | // Copyright © 2016 Glazed Donut, LLC. All rights reserved. 7 | // 8 | 9 | import WebKit 10 | 11 | // MARK: - Public API 12 | 13 | public typealias DownViewClosure = () -> () 14 | 15 | open class DownView: WKWebView { 16 | 17 | /** 18 | Initializes a web view with the results of rendering a CommonMark Markdown string 19 | 20 | - parameter frame: The frame size of the web view 21 | - parameter markdownString: A string containing CommonMark Markdown 22 | - parameter openLinksInBrowser: Whether or not to open links using an external browser 23 | - parameter templateBundle: Optional custom template bundle. Leaving this as `nil` will use the bundle included with Down. 24 | - parameter didLoadSuccessfully: Optional callback for when the web content has loaded successfully 25 | 26 | - returns: An instance of Self 27 | */ 28 | public init(frame: CGRect, markdownString: String, openLinksInBrowser: Bool = true, templateBundle: Bundle? = nil, didLoadSuccessfully: DownViewClosure? = nil) throws { 29 | self.didLoadSuccessfully = didLoadSuccessfully 30 | 31 | if let templateBundle = templateBundle { 32 | self.bundle = templateBundle 33 | } else { 34 | let classBundle = Bundle(for: DownView.self) 35 | let url = classBundle.url(forResource: "DownView", withExtension: "bundle")! 36 | self.bundle = Bundle(url: url)! 37 | } 38 | 39 | super.init(frame: frame, configuration: WKWebViewConfiguration()) 40 | 41 | if openLinksInBrowser || didLoadSuccessfully != nil { navigationDelegate = self } 42 | try loadHTMLView(markdownString) 43 | } 44 | 45 | required public init?(coder: NSCoder) { 46 | fatalError("init(coder:) has not been implemented") 47 | } 48 | 49 | // MARK: - API 50 | 51 | /** 52 | Renders the given CommonMark Markdown string into HTML and updates the DownView while keeping the style intact 53 | 54 | - parameter markdownString: A string containing CommonMark Markdown 55 | - parameter didLoadSuccessfully: Optional callback for when the web content has loaded successfully 56 | 57 | - throws: `DownErrors` depending on the scenario 58 | */ 59 | public func update(markdownString: String, didLoadSuccessfully: DownViewClosure? = nil) throws { 60 | // Note: As the init method takes this callback already, we only overwrite it here if 61 | // a non-nil value is passed in 62 | if let didLoadSuccessfully = didLoadSuccessfully { 63 | self.didLoadSuccessfully = didLoadSuccessfully 64 | } 65 | 66 | try loadHTMLView(markdownString) 67 | } 68 | 69 | // MARK: - Private Properties 70 | 71 | let bundle: Bundle 72 | 73 | fileprivate lazy var baseURL: URL = { 74 | return self.bundle.url(forResource: "index", withExtension: "html")! 75 | }() 76 | 77 | fileprivate var didLoadSuccessfully: DownViewClosure? 78 | } 79 | 80 | // MARK: - Private API 81 | 82 | private extension DownView { 83 | 84 | func loadHTMLView(_ markdownString: String) throws { 85 | let htmlString = try markdownString.toHTML() 86 | let pageHTMLString = try htmlFromTemplate(htmlString) 87 | loadHTMLString(pageHTMLString, baseURL: baseURL) 88 | } 89 | 90 | func htmlFromTemplate(_ htmlString: String) throws -> String { 91 | let template = try NSString(contentsOf: baseURL, encoding: String.Encoding.utf8.rawValue) 92 | return template.replacingOccurrences(of: "DOWN_HTML", with: htmlString) 93 | } 94 | 95 | } 96 | 97 | // MARK: - WKNavigationDelegate 98 | 99 | extension DownView: WKNavigationDelegate { 100 | 101 | public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 102 | guard let url = navigationAction.request.url else { return } 103 | 104 | switch navigationAction.navigationType { 105 | case .linkActivated: 106 | decisionHandler(.cancel) 107 | #if os(iOS) 108 | UIApplication.shared.openURL(url) 109 | #elseif os(OSX) 110 | NSWorkspace.shared.open(url) 111 | #endif 112 | default: 113 | decisionHandler(.allow) 114 | } 115 | } 116 | 117 | public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 118 | didLoadSuccessfully?() 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, John MacFarlane 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | ----- 29 | 30 | houdini.h, houdini_href_e.c, houdini_html_e.c, houdini_html_u.c, 31 | html_unescape.gperf, html_unescape.h 32 | 33 | derive from https://github.com/vmg/houdini (with some modifications) 34 | 35 | Copyright (C) 2012 Vicent Martí 36 | 37 | Permission is hereby granted, free of charge, to any person obtaining a copy of 38 | this software and associated documentation files (the "Software"), to deal in 39 | the Software without restriction, including without limitation the rights to 40 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 41 | of the Software, and to permit persons to whom the Software is furnished to do 42 | so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be included in all 45 | copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 51 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 52 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 53 | SOFTWARE. 54 | 55 | ----- 56 | 57 | buffer.h, buffer.c, chunk.h 58 | 59 | are derived from code (C) 2012 Github, Inc. 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy of 62 | this software and associated documentation files (the "Software"), to deal in 63 | the Software without restriction, including without limitation the rights to 64 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 65 | of the Software, and to permit persons to whom the Software is furnished to do 66 | so, subject to the following conditions: 67 | 68 | The above copyright notice and this permission notice shall be included in all 69 | copies or substantial portions of the Software. 70 | 71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 72 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 73 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 74 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 75 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 76 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 77 | SOFTWARE. 78 | 79 | ----- 80 | 81 | utf8.c and utf8.c 82 | 83 | are derived from utf8proc 84 | (), 85 | (C) 2009 Public Software Group e. V., Berlin, Germany. 86 | 87 | Permission is hereby granted, free of charge, to any person obtaining a 88 | copy of this software and associated documentation files (the "Software"), 89 | to deal in the Software without restriction, including without limitation 90 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 91 | and/or sell copies of the Software, and to permit persons to whom the 92 | Software is furnished to do so, subject to the following conditions: 93 | 94 | The above copyright notice and this permission notice shall be included in 95 | all copies or substantial portions of the Software. 96 | 97 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 98 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 99 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 100 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 101 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 102 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 103 | DEALINGS IN THE SOFTWARE. 104 | 105 | ----- 106 | 107 | The normalization code in runtests.py was derived from the 108 | markdowntest project, Copyright 2013 Karl Dubost: 109 | 110 | The MIT License (MIT) 111 | 112 | Copyright (c) 2013 Karl Dubost 113 | 114 | Permission is hereby granted, free of charge, to any person obtaining 115 | a copy of this software and associated documentation files (the 116 | "Software"), to deal in the Software without restriction, including 117 | without limitation the rights to use, copy, modify, merge, publish, 118 | distribute, sublicense, and/or sell copies of the Software, and to 119 | permit persons to whom the Software is furnished to do so, subject to 120 | the following conditions: 121 | 122 | The above copyright notice and this permission notice shall be 123 | included in all copies or substantial portions of the Software. 124 | 125 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 126 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 127 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 128 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 129 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 130 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 131 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 132 | 133 | ----- 134 | 135 | The CommonMark spec (test/spec.txt) is 136 | 137 | Copyright (C) 2014-15 John MacFarlane 138 | 139 | Released under the Creative Commons CC-BY-SA 4.0 license: 140 | . 141 | 142 | ----- 143 | 144 | The test software in test/ is 145 | 146 | Copyright (c) 2014, John MacFarlane 147 | 148 | All rights reserved. 149 | 150 | Redistribution and use in source and binary forms, with or without 151 | modification, are permitted provided that the following conditions are met: 152 | 153 | * Redistributions of source code must retain the above copyright 154 | notice, this list of conditions and the following disclaimer. 155 | 156 | * Redistributions in binary form must reproduce the above 157 | copyright notice, this list of conditions and the following 158 | disclaimer in the documentation and/or other materials provided 159 | with the distribution. 160 | 161 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 162 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 163 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 164 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 165 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 166 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 167 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 168 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 169 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 170 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 171 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 172 | 173 | ----- 174 | 175 | The normalization code in runtests.py was derived from the 176 | markdowntest project, Copyright 2013 Karl Dubost: 177 | 178 | The MIT License (MIT) 179 | 180 | Copyright (c) 2013 Karl Dubost 181 | 182 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 183 | 184 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 185 | 186 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 187 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 188 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 189 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 190 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 191 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 192 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "config.h" 10 | #include "cmark_ctype.h" 11 | #include "buffer.h" 12 | 13 | /* Used as default value for cmark_strbuf->ptr so that people can always 14 | * assume ptr is non-NULL and zero terminated even for new cmark_strbufs. 15 | */ 16 | unsigned char cmark_strbuf__initbuf[1]; 17 | 18 | #ifndef MIN 19 | #define MIN(x, y) ((x < y) ? x : y) 20 | #endif 21 | 22 | void cmark_strbuf_init(cmark_strbuf *buf, bufsize_t initial_size) { 23 | buf->asize = 0; 24 | buf->size = 0; 25 | buf->ptr = cmark_strbuf__initbuf; 26 | 27 | if (initial_size > 0) 28 | cmark_strbuf_grow(buf, initial_size); 29 | } 30 | 31 | void cmark_strbuf_overflow_err() { 32 | fprintf(stderr, "String buffer overflow"); 33 | abort(); 34 | } 35 | 36 | static CMARK_INLINE void S_strbuf_grow_by(cmark_strbuf *buf, size_t add) { 37 | size_t target_size = (size_t)buf->size + add; 38 | 39 | if (target_size < add /* Integer overflow. */ 40 | || target_size > BUFSIZE_MAX /* Truncation overflow. */ 41 | ) { 42 | cmark_strbuf_overflow_err(); 43 | return; /* unreachable */ 44 | } 45 | 46 | if ((bufsize_t)target_size >= buf->asize) 47 | cmark_strbuf_grow(buf, (bufsize_t)target_size); 48 | } 49 | 50 | void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { 51 | unsigned char *new_ptr; 52 | 53 | if (target_size < buf->asize) 54 | return; 55 | 56 | if (buf->asize == 0) { 57 | new_ptr = NULL; 58 | } else { 59 | new_ptr = buf->ptr; 60 | } 61 | 62 | /* Oversize the buffer by 50% to guarantee amortized linear time 63 | * complexity on append operations. */ 64 | size_t new_size = (size_t)target_size + (size_t)target_size / 2; 65 | 66 | /* Account for terminating null byte. */ 67 | new_size += 1; 68 | 69 | /* round allocation up to multiple of 8 */ 70 | new_size = (new_size + 7) & ~7; 71 | 72 | if (new_size < (size_t)target_size /* Integer overflow. */ 73 | || new_size > BUFSIZE_MAX /* Truncation overflow. */ 74 | ) { 75 | if (target_size >= BUFSIZE_MAX) { 76 | /* No space for terminating null byte. */ 77 | cmark_strbuf_overflow_err(); 78 | return; /* unreachable */ 79 | } 80 | /* Oversize by the maximum possible amount. */ 81 | new_size = BUFSIZE_MAX; 82 | } 83 | 84 | new_ptr = (unsigned char *)realloc(new_ptr, new_size); 85 | 86 | if (!new_ptr) { 87 | perror("realloc in cmark_strbuf_grow"); 88 | abort(); 89 | } 90 | 91 | buf->asize = (bufsize_t)new_size; 92 | buf->ptr = new_ptr; 93 | } 94 | 95 | bufsize_t cmark_strbuf_len(const cmark_strbuf *buf) { return buf->size; } 96 | 97 | void cmark_strbuf_free(cmark_strbuf *buf) { 98 | if (!buf) 99 | return; 100 | 101 | if (buf->ptr != cmark_strbuf__initbuf) 102 | free(buf->ptr); 103 | 104 | cmark_strbuf_init(buf, 0); 105 | } 106 | 107 | void cmark_strbuf_clear(cmark_strbuf *buf) { 108 | buf->size = 0; 109 | 110 | if (buf->asize > 0) 111 | buf->ptr[0] = '\0'; 112 | } 113 | 114 | void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, 115 | bufsize_t len) { 116 | if (len <= 0 || data == NULL) { 117 | cmark_strbuf_clear(buf); 118 | } else { 119 | if (data != buf->ptr) { 120 | if (len >= buf->asize) 121 | cmark_strbuf_grow(buf, len); 122 | memmove(buf->ptr, data, len); 123 | } 124 | buf->size = len; 125 | buf->ptr[buf->size] = '\0'; 126 | } 127 | } 128 | 129 | void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) { 130 | cmark_strbuf_set(buf, (const unsigned char *)string, 131 | string ? cmark_strbuf_safe_strlen(string) : 0); 132 | } 133 | 134 | void cmark_strbuf_putc(cmark_strbuf *buf, int c) { 135 | S_strbuf_grow_by(buf, 1); 136 | buf->ptr[buf->size++] = (unsigned char)(c & 0xFF); 137 | buf->ptr[buf->size] = '\0'; 138 | } 139 | 140 | void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, 141 | bufsize_t len) { 142 | if (len <= 0) 143 | return; 144 | 145 | S_strbuf_grow_by(buf, len); 146 | memmove(buf->ptr + buf->size, data, len); 147 | buf->size += len; 148 | buf->ptr[buf->size] = '\0'; 149 | } 150 | 151 | void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) { 152 | cmark_strbuf_put(buf, (const unsigned char *)string, 153 | cmark_strbuf_safe_strlen(string)); 154 | } 155 | 156 | void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, 157 | const cmark_strbuf *buf) { 158 | bufsize_t copylen; 159 | 160 | assert(buf); 161 | if (!data || datasize <= 0) 162 | return; 163 | 164 | data[0] = '\0'; 165 | 166 | if (buf->size == 0 || buf->asize <= 0) 167 | return; 168 | 169 | copylen = buf->size; 170 | if (copylen > datasize - 1) 171 | copylen = datasize - 1; 172 | memmove(data, buf->ptr, copylen); 173 | data[copylen] = '\0'; 174 | } 175 | 176 | void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b) { 177 | cmark_strbuf t = *buf_a; 178 | *buf_a = *buf_b; 179 | *buf_b = t; 180 | } 181 | 182 | unsigned char *cmark_strbuf_detach(cmark_strbuf *buf) { 183 | unsigned char *data = buf->ptr; 184 | 185 | if (buf->asize == 0) { 186 | /* return an empty string */ 187 | return (unsigned char *)calloc(1, 1); 188 | } 189 | 190 | cmark_strbuf_init(buf, 0); 191 | return data; 192 | } 193 | 194 | int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) { 195 | int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); 196 | return (result != 0) ? result 197 | : (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; 198 | } 199 | 200 | bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) { 201 | if (pos >= buf->size) 202 | return -1; 203 | if (pos < 0) 204 | pos = 0; 205 | 206 | const unsigned char *p = 207 | (unsigned char *)memchr(buf->ptr + pos, c, buf->size - pos); 208 | if (!p) 209 | return -1; 210 | 211 | return (bufsize_t)(p - (const unsigned char *)buf->ptr); 212 | } 213 | 214 | bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) { 215 | if (pos < 0 || buf->size == 0) 216 | return -1; 217 | if (pos >= buf->size) 218 | pos = buf->size - 1; 219 | 220 | bufsize_t i; 221 | for (i = pos; i >= 0; i--) { 222 | if (buf->ptr[i] == (unsigned char)c) 223 | return i; 224 | } 225 | 226 | return -1; 227 | } 228 | 229 | void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) { 230 | if (len < 0) 231 | len = 0; 232 | 233 | if (len < buf->size) { 234 | buf->size = len; 235 | buf->ptr[buf->size] = '\0'; 236 | } 237 | } 238 | 239 | void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n) { 240 | if (n > 0) { 241 | if (n > buf->size) 242 | n = buf->size; 243 | buf->size = buf->size - n; 244 | if (buf->size) 245 | memmove(buf->ptr, buf->ptr + n, buf->size); 246 | 247 | buf->ptr[buf->size] = '\0'; 248 | } 249 | } 250 | 251 | void cmark_strbuf_rtrim(cmark_strbuf *buf) { 252 | if (!buf->size) 253 | return; 254 | 255 | while (buf->size > 0) { 256 | if (!cmark_isspace(buf->ptr[buf->size - 1])) 257 | break; 258 | 259 | buf->size--; 260 | } 261 | 262 | buf->ptr[buf->size] = '\0'; 263 | } 264 | 265 | void cmark_strbuf_trim(cmark_strbuf *buf) { 266 | bufsize_t i = 0; 267 | 268 | if (!buf->size) 269 | return; 270 | 271 | while (i < buf->size && cmark_isspace(buf->ptr[i])) 272 | i++; 273 | 274 | cmark_strbuf_drop(buf, i); 275 | 276 | cmark_strbuf_rtrim(buf); 277 | } 278 | 279 | // Destructively modify string, collapsing consecutive 280 | // space and newline characters into a single space. 281 | void cmark_strbuf_normalize_whitespace(cmark_strbuf *s) { 282 | bool last_char_was_space = false; 283 | bufsize_t r, w; 284 | 285 | for (r = 0, w = 0; r < s->size; ++r) { 286 | if (cmark_isspace(s->ptr[r])) { 287 | if (!last_char_was_space) { 288 | s->ptr[w++] = ' '; 289 | last_char_was_space = true; 290 | } 291 | } else { 292 | s->ptr[w++] = s->ptr[r]; 293 | last_char_was_space = false; 294 | } 295 | } 296 | 297 | cmark_strbuf_truncate(s, w); 298 | } 299 | 300 | // Destructively unescape a string: remove backslashes before punctuation chars. 301 | extern void cmark_strbuf_unescape(cmark_strbuf *buf) { 302 | bufsize_t r, w; 303 | 304 | for (r = 0, w = 0; r < buf->size; ++r) { 305 | if (buf->ptr[r] == '\\' && cmark_ispunct(buf->ptr[r + 1])) 306 | r++; 307 | 308 | buf->ptr[w++] = buf->ptr[r]; 309 | } 310 | 311 | cmark_strbuf_truncate(buf, w); 312 | } 313 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_BUFFER_H 2 | #define CMARK_BUFFER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef int bufsize_t; 15 | 16 | typedef struct { 17 | unsigned char *ptr; 18 | bufsize_t asize, size; 19 | } cmark_strbuf; 20 | 21 | extern unsigned char cmark_strbuf__initbuf[]; 22 | 23 | #define GH_BUF_INIT \ 24 | { cmark_strbuf__initbuf, 0, 0 } 25 | #define BUFSIZE_MAX INT_MAX 26 | 27 | /** 28 | * Initialize a cmark_strbuf structure. 29 | * 30 | * For the cases where GH_BUF_INIT cannot be used to do static 31 | * initialization. 32 | */ 33 | void cmark_strbuf_init(cmark_strbuf *buf, bufsize_t initial_size); 34 | 35 | /** 36 | * Grow the buffer to hold at least `target_size` bytes. 37 | */ 38 | void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size); 39 | 40 | void cmark_strbuf_free(cmark_strbuf *buf); 41 | void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b); 42 | 43 | bufsize_t cmark_strbuf_len(const cmark_strbuf *buf); 44 | 45 | int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b); 46 | 47 | unsigned char *cmark_strbuf_detach(cmark_strbuf *buf); 48 | void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, 49 | const cmark_strbuf *buf); 50 | 51 | static CMARK_INLINE const char *cmark_strbuf_cstr(const cmark_strbuf *buf) { 52 | return (char *)buf->ptr; 53 | } 54 | 55 | #define cmark_strbuf_at(buf, n) ((buf)->ptr[n]) 56 | 57 | void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, 58 | bufsize_t len); 59 | void cmark_strbuf_sets(cmark_strbuf *buf, const char *string); 60 | void cmark_strbuf_putc(cmark_strbuf *buf, int c); 61 | void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, 62 | bufsize_t len); 63 | void cmark_strbuf_puts(cmark_strbuf *buf, const char *string); 64 | void cmark_strbuf_clear(cmark_strbuf *buf); 65 | 66 | bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos); 67 | bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos); 68 | void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n); 69 | void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len); 70 | void cmark_strbuf_rtrim(cmark_strbuf *buf); 71 | void cmark_strbuf_trim(cmark_strbuf *buf); 72 | void cmark_strbuf_normalize_whitespace(cmark_strbuf *s); 73 | void cmark_strbuf_unescape(cmark_strbuf *s); 74 | 75 | /* Print error and abort. */ 76 | void cmark_strbuf_overflow_err(void); 77 | 78 | static CMARK_INLINE bufsize_t cmark_strbuf_check_bufsize(size_t size) { 79 | if (size > BUFSIZE_MAX) { 80 | cmark_strbuf_overflow_err(); 81 | } 82 | return (bufsize_t)size; 83 | } 84 | 85 | static CMARK_INLINE bufsize_t cmark_strbuf_safe_strlen(const char *str) { 86 | return cmark_strbuf_check_bufsize(strlen(str)); 87 | } 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/chunk.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_CHUNK_H 2 | #define CMARK_CHUNK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "cmark_ctype.h" 8 | #include "buffer.h" 9 | 10 | #define CMARK_CHUNK_EMPTY \ 11 | { NULL, 0, 0 } 12 | 13 | typedef struct { 14 | unsigned char *data; 15 | bufsize_t len; 16 | bufsize_t alloc; // also implies a NULL-terminated string 17 | } cmark_chunk; 18 | 19 | static CMARK_INLINE void cmark_chunk_free(cmark_chunk *c) { 20 | if (c->alloc) 21 | free(c->data); 22 | 23 | c->data = NULL; 24 | c->alloc = 0; 25 | c->len = 0; 26 | } 27 | 28 | static CMARK_INLINE void cmark_chunk_ltrim(cmark_chunk *c) { 29 | assert(!c->alloc); 30 | 31 | while (c->len && cmark_isspace(c->data[0])) { 32 | c->data++; 33 | c->len--; 34 | } 35 | } 36 | 37 | static CMARK_INLINE void cmark_chunk_rtrim(cmark_chunk *c) { 38 | while (c->len > 0) { 39 | if (!cmark_isspace(c->data[c->len - 1])) 40 | break; 41 | 42 | c->len--; 43 | } 44 | } 45 | 46 | static CMARK_INLINE void cmark_chunk_trim(cmark_chunk *c) { 47 | cmark_chunk_ltrim(c); 48 | cmark_chunk_rtrim(c); 49 | } 50 | 51 | static CMARK_INLINE bufsize_t cmark_chunk_strchr(cmark_chunk *ch, int c, 52 | bufsize_t offset) { 53 | const unsigned char *p = 54 | (unsigned char *)memchr(ch->data + offset, c, ch->len - offset); 55 | return p ? (bufsize_t)(p - ch->data) : ch->len; 56 | } 57 | 58 | static CMARK_INLINE const char *cmark_chunk_to_cstr(cmark_chunk *c) { 59 | unsigned char *str; 60 | 61 | if (c->alloc) { 62 | return (char *)c->data; 63 | } 64 | str = (unsigned char *)malloc(c->len + 1); 65 | if (str != NULL) { 66 | if (c->len > 0) { 67 | memcpy(str, c->data, c->len); 68 | } 69 | str[c->len] = 0; 70 | } 71 | c->data = str; 72 | c->alloc = 1; 73 | 74 | return (char *)str; 75 | } 76 | 77 | static CMARK_INLINE void cmark_chunk_set_cstr(cmark_chunk *c, const char *str) { 78 | if (c->alloc) { 79 | free(c->data); 80 | } 81 | if (str == NULL) { 82 | c->len = 0; 83 | c->data = NULL; 84 | c->alloc = 0; 85 | } else { 86 | c->len = cmark_strbuf_safe_strlen(str); 87 | c->data = (unsigned char *)malloc(c->len + 1); 88 | c->alloc = 1; 89 | memcpy(c->data, str, c->len + 1); 90 | } 91 | } 92 | 93 | static CMARK_INLINE cmark_chunk cmark_chunk_literal(const char *data) { 94 | bufsize_t len = data ? cmark_strbuf_safe_strlen(data) : 0; 95 | cmark_chunk c = {(unsigned char *)data, len, 0}; 96 | return c; 97 | } 98 | 99 | static CMARK_INLINE cmark_chunk cmark_chunk_dup(const cmark_chunk *ch, 100 | bufsize_t pos, bufsize_t len) { 101 | cmark_chunk c = {ch->data + pos, len, 0}; 102 | return c; 103 | } 104 | 105 | static CMARK_INLINE cmark_chunk cmark_chunk_buf_detach(cmark_strbuf *buf) { 106 | cmark_chunk c; 107 | 108 | c.len = buf->size; 109 | c.data = cmark_strbuf_detach(buf); 110 | c.alloc = 1; 111 | 112 | return c; 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/cmark.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "node.h" 5 | #include "houdini.h" 6 | #include "cmark.h" 7 | #include "buffer.h" 8 | 9 | int cmark_version() { return CMARK_VERSION; } 10 | 11 | const char *cmark_version_string() { return CMARK_VERSION_STRING; } 12 | 13 | char *cmark_markdown_to_html(const char *text, size_t len, int options) { 14 | cmark_node *doc; 15 | char *result; 16 | 17 | doc = cmark_parse_document(text, len, options); 18 | 19 | result = cmark_render_html(doc, options); 20 | cmark_node_free(doc); 21 | 22 | return result; 23 | } 24 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/cmark_ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cmark_ctype.h" 4 | 5 | /** 1 = space, 2 = punct, 3 = digit, 4 = alpha, 0 = other 6 | */ 7 | static const uint8_t cmark_ctype_class[256] = { 8 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 9 | /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 10 | /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11 | /* 2 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12 | /* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 13 | /* 4 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 14 | /* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 15 | /* 6 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16 | /* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0, 17 | /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 | /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 | /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21 | /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 | /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 | /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 25 | 26 | /** 27 | * Returns 1 if c is a "whitespace" character as defined by the spec. 28 | */ 29 | int cmark_isspace(char c) { return cmark_ctype_class[(uint8_t)c] == 1; } 30 | 31 | /** 32 | * Returns 1 if c is an ascii punctuation character. 33 | */ 34 | int cmark_ispunct(char c) { return cmark_ctype_class[(uint8_t)c] == 2; } 35 | 36 | int cmark_isalnum(char c) { 37 | uint8_t result; 38 | result = cmark_ctype_class[(uint8_t)c]; 39 | return (result == 3 || result == 4); 40 | } 41 | 42 | int cmark_isdigit(char c) { return cmark_ctype_class[(uint8_t)c] == 3; } 43 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/cmark_ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_CMARK_CTYPE_H 2 | #define CMARK_CMARK_CTYPE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /** Locale-independent versions of functions from ctype.h. 9 | * We want cmark to behave the same no matter what the system locale. 10 | */ 11 | 12 | int cmark_isspace(char c); 13 | 14 | int cmark_ispunct(char c); 15 | 16 | int cmark_isalnum(char c); 17 | 18 | int cmark_isdigit(char c); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/cmark_export.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef CMARK_EXPORT_H 3 | #define CMARK_EXPORT_H 4 | 5 | #ifdef CMARK_STATIC_DEFINE 6 | # define CMARK_EXPORT 7 | # define CMARK_NO_EXPORT 8 | #else 9 | # ifndef CMARK_EXPORT 10 | # ifdef libcmark_EXPORTS 11 | /* We are building this library */ 12 | # define CMARK_EXPORT __attribute__((visibility("default"))) 13 | # else 14 | /* We are using this library */ 15 | # define CMARK_EXPORT __attribute__((visibility("default"))) 16 | # endif 17 | # endif 18 | 19 | # ifndef CMARK_NO_EXPORT 20 | # define CMARK_NO_EXPORT __attribute__((visibility("hidden"))) 21 | # endif 22 | #endif 23 | 24 | #ifndef CMARK_DEPRECATED 25 | # define CMARK_DEPRECATED __attribute__ ((__deprecated__)) 26 | #endif 27 | 28 | #ifndef CMARK_DEPRECATED_EXPORT 29 | # define CMARK_DEPRECATED_EXPORT CMARK_EXPORT CMARK_DEPRECATED 30 | #endif 31 | 32 | #ifndef CMARK_DEPRECATED_NO_EXPORT 33 | # define CMARK_DEPRECATED_NO_EXPORT CMARK_NO_EXPORT CMARK_DEPRECATED 34 | #endif 35 | 36 | #define DEFINE_NO_DEPRECATED 0 37 | #if DEFINE_NO_DEPRECATED 38 | # define CMARK_NO_DEPRECATED 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/cmark_version.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_VERSION_H 2 | #define CMARK_VERSION_H 3 | 4 | #define CMARK_VERSION ((0 << 16) | (25 << 8) | 2) 5 | #define CMARK_VERSION_STRING "0.25.2" 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_CONFIG_H 2 | #define CMARK_CONFIG_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define HAVE_STDBOOL_H 9 | 10 | #ifdef HAVE_STDBOOL_H 11 | #include 12 | #elif !defined(__cplusplus) 13 | typedef char bool; 14 | #endif 15 | 16 | #define HAVE___BUILTIN_EXPECT 17 | 18 | #define HAVE___ATTRIBUTE__ 19 | 20 | #ifdef HAVE___ATTRIBUTE__ 21 | #define CMARK_ATTRIBUTE(list) __attribute__ (list) 22 | #else 23 | #define CMARK_ATTRIBUTE(list) 24 | #endif 25 | 26 | #ifndef CMARK_INLINE 27 | #if defined(_MSC_VER) && !defined(__cplusplus) 28 | #define CMARK_INLINE __inline 29 | #else 30 | #define CMARK_INLINE inline 31 | #endif 32 | #endif 33 | 34 | /* snprintf and vsnprintf fallbacks for MSVC before 2015, 35 | due to Valentin Milea http://stackoverflow.com/questions/2915672/ 36 | */ 37 | 38 | #if defined(_MSC_VER) && _MSC_VER < 1900 39 | 40 | #include 41 | #include 42 | 43 | #define snprintf c99_snprintf 44 | #define vsnprintf c99_vsnprintf 45 | 46 | CMARK_INLINE int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) 47 | { 48 | int count = -1; 49 | 50 | if (size != 0) 51 | count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); 52 | if (count == -1) 53 | count = _vscprintf(format, ap); 54 | 55 | return count; 56 | } 57 | 58 | CMARK_INLINE int c99_snprintf(char *outBuf, size_t size, const char *format, ...) 59 | { 60 | int count; 61 | va_list ap; 62 | 63 | va_start(ap, format); 64 | count = c99_vsnprintf(outBuf, size, format, ap); 65 | va_end(ap); 66 | 67 | return count; 68 | } 69 | 70 | #endif 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_DEBUG_H 2 | #define CMARK_DEBUG_H 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef NDEBUG 8 | #define debug(M, ...) 9 | #else 10 | #define debug(M, ...) \ 11 | fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) \ 17 | fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, \ 18 | clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_warn(M, ...) \ 21 | fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, \ 22 | clean_errno(), ##__VA_ARGS__) 23 | 24 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, \ 25 | __LINE__, ##__VA_ARGS__) 26 | 27 | #define check(A, M, ...) \ 28 | if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #define sentinel(M, ...) \ 31 | { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 32 | 33 | #define check_debug(A, M, ...) \ 34 | if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/houdini.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_HOUDINI_H 2 | #define CMARK_HOUDINI_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "config.h" 10 | #include "buffer.h" 11 | 12 | #ifdef HAVE___BUILTIN_EXPECT 13 | #define likely(x) __builtin_expect((x), 1) 14 | #define unlikely(x) __builtin_expect((x), 0) 15 | #else 16 | #define likely(x) (x) 17 | #define unlikely(x) (x) 18 | #endif 19 | 20 | #ifdef HOUDINI_USE_LOCALE 21 | #define _isxdigit(c) isxdigit(c) 22 | #define _isdigit(c) isdigit(c) 23 | #else 24 | /* 25 | * Helper _isdigit methods -- do not trust the current locale 26 | * */ 27 | #define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL) 28 | #define _isdigit(c) ((c) >= '0' && (c) <= '9') 29 | #endif 30 | 31 | #define HOUDINI_ESCAPED_SIZE(x) (((x)*12) / 10) 32 | #define HOUDINI_UNESCAPED_SIZE(x) (x) 33 | 34 | extern bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, 35 | bufsize_t size); 36 | extern int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, 37 | bufsize_t size); 38 | extern int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, 39 | bufsize_t size, int secure); 40 | extern int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, 41 | bufsize_t size); 42 | extern void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, 43 | bufsize_t size); 44 | extern int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, 45 | bufsize_t size); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/houdini_href_e.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "houdini.h" 6 | 7 | /* 8 | * The following characters will not be escaped: 9 | * 10 | * -_.+!*'(),%#@?=;:/,+&$ alphanum 11 | * 12 | * Note that this character set is the addition of: 13 | * 14 | * - The characters which are safe to be in an URL 15 | * - The characters which are *not* safe to be in 16 | * an URL because they are RESERVED characters. 17 | * 18 | * We asume (lazily) that any RESERVED char that 19 | * appears inside an URL is actually meant to 20 | * have its native function (i.e. as an URL 21 | * component/separator) and hence needs no escaping. 22 | * 23 | * There are two exceptions: the chacters & (amp) 24 | * and ' (single quote) do not appear in the table. 25 | * They are meant to appear in the URL as components, 26 | * yet they require special HTML-entity escaping 27 | * to generate valid HTML markup. 28 | * 29 | * All other characters will be escaped to %XX. 30 | * 31 | */ 32 | static const char HREF_SAFE[] = { 33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 35 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 37 | 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 38 | 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44 | }; 45 | 46 | int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { 47 | static const uint8_t hex_chars[] = "0123456789ABCDEF"; 48 | bufsize_t i = 0, org; 49 | uint8_t hex_str[3]; 50 | 51 | hex_str[0] = '%'; 52 | 53 | while (i < size) { 54 | org = i; 55 | while (i < size && HREF_SAFE[src[i]] != 0) 56 | i++; 57 | 58 | if (likely(i > org)) 59 | cmark_strbuf_put(ob, src + org, i - org); 60 | 61 | /* escaping */ 62 | if (i >= size) 63 | break; 64 | 65 | switch (src[i]) { 66 | /* amp appears all the time in URLs, but needs 67 | * HTML-entity escaping to be inside an href */ 68 | case '&': 69 | cmark_strbuf_puts(ob, "&"); 70 | break; 71 | 72 | /* the single quote is a valid URL character 73 | * according to the standard; it needs HTML 74 | * entity escaping too */ 75 | case '\'': 76 | cmark_strbuf_puts(ob, "'"); 77 | break; 78 | 79 | /* the space can be escaped to %20 or a plus 80 | * sign. we're going with the generic escape 81 | * for now. the plus thing is more commonly seen 82 | * when building GET strings */ 83 | #if 0 84 | case ' ': 85 | cmark_strbuf_putc(ob, '+'); 86 | break; 87 | #endif 88 | 89 | /* every other character goes with a %XX escaping */ 90 | default: 91 | hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; 92 | hex_str[2] = hex_chars[src[i] & 0xF]; 93 | cmark_strbuf_put(ob, hex_str, 3); 94 | } 95 | 96 | i++; 97 | } 98 | 99 | return 1; 100 | } 101 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/houdini_html_e.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "houdini.h" 6 | 7 | /** 8 | * According to the OWASP rules: 9 | * 10 | * & --> & 11 | * < --> < 12 | * > --> > 13 | * " --> " 14 | * ' --> ' ' is not recommended 15 | * / --> / forward slash is included as it helps end an HTML entity 16 | * 17 | */ 18 | static const char HTML_ESCAPE_TABLE[] = { 19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, 21 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | }; 31 | 32 | static const char *HTML_ESCAPES[] = {"", """, "&", "'", 33 | "/", "<", ">"}; 34 | 35 | int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size, 36 | int secure) { 37 | bufsize_t i = 0, org, esc = 0; 38 | 39 | while (i < size) { 40 | org = i; 41 | while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) 42 | i++; 43 | 44 | if (i > org) 45 | cmark_strbuf_put(ob, src + org, i - org); 46 | 47 | /* escaping */ 48 | if (unlikely(i >= size)) 49 | break; 50 | 51 | /* The forward slash is only escaped in secure mode */ 52 | if ((src[i] == '/' || src[i] == '\'') && !secure) { 53 | cmark_strbuf_putc(ob, src[i]); 54 | } else { 55 | cmark_strbuf_puts(ob, HTML_ESCAPES[esc]); 56 | } 57 | 58 | i++; 59 | } 60 | 61 | return 1; 62 | } 63 | 64 | int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { 65 | return houdini_escape_html0(ob, src, size, 1); 66 | } 67 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/houdini_html_u.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "buffer.h" 6 | #include "houdini.h" 7 | #include "utf8.h" 8 | #include "entities.inc" 9 | 10 | /* Binary tree lookup code for entities added by JGM */ 11 | 12 | static const unsigned char *S_lookup(int i, int low, int hi, 13 | const unsigned char *s, int len) { 14 | int j; 15 | int cmp = 16 | strncmp((const char *)s, (const char *)cmark_entities[i].entity, len); 17 | if (cmp == 0 && cmark_entities[i].entity[len] == 0) { 18 | return (const unsigned char *)cmark_entities[i].bytes; 19 | } else if (cmp < 0 && i > low) { 20 | j = i - ((i - low) / 2); 21 | if (j == i) 22 | j -= 1; 23 | return S_lookup(j, low, i - 1, s, len); 24 | } else if (cmp > 0 && i < hi) { 25 | j = i + ((hi - i) / 2); 26 | if (j == i) 27 | j += 1; 28 | return S_lookup(j, i + 1, hi, s, len); 29 | } else { 30 | return NULL; 31 | } 32 | } 33 | 34 | static const unsigned char *S_lookup_entity(const unsigned char *s, int len) { 35 | return S_lookup(CMARK_NUM_ENTITIES / 2, 0, CMARK_NUM_ENTITIES - 1, s, len); 36 | } 37 | 38 | bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, 39 | bufsize_t size) { 40 | bufsize_t i = 0; 41 | 42 | if (size >= 3 && src[0] == '#') { 43 | int codepoint = 0; 44 | int num_digits = 0; 45 | 46 | if (_isdigit(src[1])) { 47 | for (i = 1; i < size && _isdigit(src[i]); ++i) { 48 | codepoint = (codepoint * 10) + (src[i] - '0'); 49 | 50 | if (codepoint >= 0x110000) { 51 | // Keep counting digits but 52 | // avoid integer overflow. 53 | codepoint = 0x110000; 54 | } 55 | } 56 | 57 | num_digits = i - 1; 58 | } 59 | 60 | else if (src[1] == 'x' || src[1] == 'X') { 61 | for (i = 2; i < size && _isxdigit(src[i]); ++i) { 62 | codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9); 63 | 64 | if (codepoint >= 0x110000) { 65 | // Keep counting digits but 66 | // avoid integer overflow. 67 | codepoint = 0x110000; 68 | } 69 | } 70 | 71 | num_digits = i - 2; 72 | } 73 | 74 | if (num_digits >= 1 && num_digits <= 8 && i < size && src[i] == ';') { 75 | if (codepoint == 0 || (codepoint >= 0xD800 && codepoint < 0xE000) || 76 | codepoint >= 0x110000) { 77 | codepoint = 0xFFFD; 78 | } 79 | cmark_utf8proc_encode_char(codepoint, ob); 80 | return i + 1; 81 | } 82 | } 83 | 84 | else { 85 | if (size > CMARK_ENTITY_MAX_LENGTH) 86 | size = CMARK_ENTITY_MAX_LENGTH; 87 | 88 | for (i = CMARK_ENTITY_MIN_LENGTH; i < size; ++i) { 89 | if (src[i] == ' ') 90 | break; 91 | 92 | if (src[i] == ';') { 93 | const unsigned char *entity = S_lookup_entity(src, i); 94 | 95 | if (entity != NULL) { 96 | cmark_strbuf_puts(ob, (const char *)entity); 97 | return i + 1; 98 | } 99 | 100 | break; 101 | } 102 | } 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, 109 | bufsize_t size) { 110 | bufsize_t i = 0, org, ent; 111 | 112 | while (i < size) { 113 | org = i; 114 | while (i < size && src[i] != '&') 115 | i++; 116 | 117 | if (likely(i > org)) { 118 | if (unlikely(org == 0)) { 119 | if (i >= size) 120 | return 0; 121 | 122 | cmark_strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size)); 123 | } 124 | 125 | cmark_strbuf_put(ob, src + org, i - org); 126 | } 127 | 128 | /* escaping */ 129 | if (i >= size) 130 | break; 131 | 132 | i++; 133 | 134 | ent = houdini_unescape_ent(ob, src + i, size - i); 135 | i += ent; 136 | 137 | /* not really an entity */ 138 | if (ent == 0) 139 | cmark_strbuf_putc(ob, '&'); 140 | } 141 | 142 | return 1; 143 | } 144 | 145 | void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, 146 | bufsize_t size) { 147 | if (!houdini_unescape_html(ob, src, size)) 148 | cmark_strbuf_put(ob, src, size); 149 | } 150 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/html.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "cmark_ctype.h" 6 | #include "config.h" 7 | #include "cmark.h" 8 | #include "node.h" 9 | #include "buffer.h" 10 | #include "houdini.h" 11 | #include "scanners.h" 12 | 13 | #define BUFFER_SIZE 100 14 | 15 | // Functions to convert cmark_nodes to HTML strings. 16 | 17 | static void escape_html(cmark_strbuf *dest, const unsigned char *source, 18 | bufsize_t length) { 19 | houdini_escape_html0(dest, source, length, 0); 20 | } 21 | 22 | static CMARK_INLINE void cr(cmark_strbuf *html) { 23 | if (html->size && html->ptr[html->size - 1] != '\n') 24 | cmark_strbuf_putc(html, '\n'); 25 | } 26 | 27 | struct render_state { 28 | cmark_strbuf *html; 29 | cmark_node *plain; 30 | }; 31 | 32 | static void S_render_sourcepos(cmark_node *node, cmark_strbuf *html, 33 | int options) { 34 | char buffer[BUFFER_SIZE]; 35 | if (CMARK_OPT_SOURCEPOS & options) { 36 | snprintf(buffer, BUFFER_SIZE, " data-sourcepos=\"%d:%d-%d:%d\"", 37 | cmark_node_get_start_line(node), cmark_node_get_start_column(node), 38 | cmark_node_get_end_line(node), cmark_node_get_end_column(node)); 39 | cmark_strbuf_puts(html, buffer); 40 | } 41 | } 42 | 43 | static int S_render_node(cmark_node *node, cmark_event_type ev_type, 44 | struct render_state *state, int options) { 45 | cmark_node *parent; 46 | cmark_node *grandparent; 47 | cmark_strbuf *html = state->html; 48 | char start_heading[] = "plain == node) { // back at original node 56 | state->plain = NULL; 57 | } 58 | 59 | if (state->plain != NULL) { 60 | switch (node->type) { 61 | case CMARK_NODE_TEXT: 62 | case CMARK_NODE_CODE: 63 | case CMARK_NODE_HTML_INLINE: 64 | escape_html(html, node->as.literal.data, node->as.literal.len); 65 | break; 66 | 67 | case CMARK_NODE_LINEBREAK: 68 | case CMARK_NODE_SOFTBREAK: 69 | cmark_strbuf_putc(html, ' '); 70 | break; 71 | 72 | default: 73 | break; 74 | } 75 | return 1; 76 | } 77 | 78 | switch (node->type) { 79 | case CMARK_NODE_DOCUMENT: 80 | break; 81 | 82 | case CMARK_NODE_BLOCK_QUOTE: 83 | if (entering) { 84 | cr(html); 85 | cmark_strbuf_puts(html, "\n"); 88 | } else { 89 | cr(html); 90 | cmark_strbuf_puts(html, "\n"); 91 | } 92 | break; 93 | 94 | case CMARK_NODE_LIST: { 95 | cmark_list_type list_type = node->as.list.list_type; 96 | int start = node->as.list.start; 97 | 98 | if (entering) { 99 | cr(html); 100 | if (list_type == CMARK_BULLET_LIST) { 101 | cmark_strbuf_puts(html, "\n"); 104 | } else if (start == 1) { 105 | cmark_strbuf_puts(html, "\n"); 108 | } else { 109 | snprintf(buffer, BUFFER_SIZE, "
    \n"); 113 | } 114 | } else { 115 | cmark_strbuf_puts(html, 116 | list_type == CMARK_BULLET_LIST ? "\n" : "
\n"); 117 | } 118 | break; 119 | } 120 | 121 | case CMARK_NODE_ITEM: 122 | if (entering) { 123 | cr(html); 124 | cmark_strbuf_puts(html, "'); 127 | } else { 128 | cmark_strbuf_puts(html, "\n"); 129 | } 130 | break; 131 | 132 | case CMARK_NODE_HEADING: 133 | if (entering) { 134 | cr(html); 135 | start_heading[2] = (char)('0' + node->as.heading.level); 136 | cmark_strbuf_puts(html, start_heading); 137 | S_render_sourcepos(node, html, options); 138 | cmark_strbuf_putc(html, '>'); 139 | } else { 140 | end_heading[3] = (char)('0' + node->as.heading.level); 141 | cmark_strbuf_puts(html, end_heading); 142 | cmark_strbuf_puts(html, ">\n"); 143 | } 144 | break; 145 | 146 | case CMARK_NODE_CODE_BLOCK: 147 | cr(html); 148 | 149 | if (node->as.code.info.len == 0) { 150 | cmark_strbuf_puts(html, ""); 153 | } else { 154 | bufsize_t first_tag = 0; 155 | while (first_tag < node->as.code.info.len && 156 | !cmark_isspace(node->as.code.info.data[first_tag])) { 157 | first_tag += 1; 158 | } 159 | 160 | cmark_strbuf_puts(html, "as.code.info.data, first_tag); 164 | cmark_strbuf_puts(html, "\">"); 165 | } 166 | 167 | escape_html(html, node->as.code.literal.data, node->as.code.literal.len); 168 | cmark_strbuf_puts(html, "\n"); 169 | break; 170 | 171 | case CMARK_NODE_HTML_BLOCK: 172 | cr(html); 173 | if (options & CMARK_OPT_SAFE) { 174 | cmark_strbuf_puts(html, ""); 175 | } else { 176 | cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); 177 | } 178 | cr(html); 179 | break; 180 | 181 | case CMARK_NODE_CUSTOM_BLOCK: 182 | cr(html); 183 | if (entering) { 184 | cmark_strbuf_put(html, node->as.custom.on_enter.data, 185 | node->as.custom.on_enter.len); 186 | } else { 187 | cmark_strbuf_put(html, node->as.custom.on_exit.data, 188 | node->as.custom.on_exit.len); 189 | } 190 | cr(html); 191 | break; 192 | 193 | case CMARK_NODE_THEMATIC_BREAK: 194 | cr(html); 195 | cmark_strbuf_puts(html, "\n"); 198 | break; 199 | 200 | case CMARK_NODE_PARAGRAPH: 201 | parent = cmark_node_parent(node); 202 | grandparent = cmark_node_parent(parent); 203 | if (grandparent != NULL && grandparent->type == CMARK_NODE_LIST) { 204 | tight = grandparent->as.list.tight; 205 | } else { 206 | tight = false; 207 | } 208 | if (!tight) { 209 | if (entering) { 210 | cr(html); 211 | cmark_strbuf_puts(html, "'); 214 | } else { 215 | cmark_strbuf_puts(html, "

\n"); 216 | } 217 | } 218 | break; 219 | 220 | case CMARK_NODE_TEXT: 221 | escape_html(html, node->as.literal.data, node->as.literal.len); 222 | break; 223 | 224 | case CMARK_NODE_LINEBREAK: 225 | cmark_strbuf_puts(html, "
\n"); 226 | break; 227 | 228 | case CMARK_NODE_SOFTBREAK: 229 | if (options & CMARK_OPT_HARDBREAKS) { 230 | cmark_strbuf_puts(html, "
\n"); 231 | } else { 232 | cmark_strbuf_putc(html, '\n'); 233 | } 234 | break; 235 | 236 | case CMARK_NODE_CODE: 237 | cmark_strbuf_puts(html, ""); 238 | escape_html(html, node->as.literal.data, node->as.literal.len); 239 | cmark_strbuf_puts(html, ""); 240 | break; 241 | 242 | case CMARK_NODE_HTML_INLINE: 243 | if (options & CMARK_OPT_SAFE) { 244 | cmark_strbuf_puts(html, ""); 245 | } else { 246 | cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); 247 | } 248 | break; 249 | 250 | case CMARK_NODE_CUSTOM_INLINE: 251 | if (entering) { 252 | cmark_strbuf_put(html, node->as.custom.on_enter.data, 253 | node->as.custom.on_enter.len); 254 | } else { 255 | cmark_strbuf_put(html, node->as.custom.on_exit.data, 256 | node->as.custom.on_exit.len); 257 | } 258 | break; 259 | 260 | case CMARK_NODE_STRONG: 261 | if (entering) { 262 | cmark_strbuf_puts(html, ""); 263 | } else { 264 | cmark_strbuf_puts(html, ""); 265 | } 266 | break; 267 | 268 | case CMARK_NODE_EMPH: 269 | if (entering) { 270 | cmark_strbuf_puts(html, ""); 271 | } else { 272 | cmark_strbuf_puts(html, ""); 273 | } 274 | break; 275 | 276 | case CMARK_NODE_LINK: 277 | if (entering) { 278 | cmark_strbuf_puts(html, "as.link.url, 0))) { 281 | houdini_escape_href(html, node->as.link.url.data, 282 | node->as.link.url.len); 283 | } 284 | if (node->as.link.title.len) { 285 | cmark_strbuf_puts(html, "\" title=\""); 286 | escape_html(html, node->as.link.title.data, node->as.link.title.len); 287 | } 288 | cmark_strbuf_puts(html, "\">"); 289 | } else { 290 | cmark_strbuf_puts(html, ""); 291 | } 292 | break; 293 | 294 | case CMARK_NODE_IMAGE: 295 | if (entering) { 296 | cmark_strbuf_puts(html, "as.link.url, 0))) { 299 | houdini_escape_href(html, node->as.link.url.data, 300 | node->as.link.url.len); 301 | } 302 | cmark_strbuf_puts(html, "\" alt=\""); 303 | state->plain = node; 304 | } else { 305 | if (node->as.link.title.len) { 306 | cmark_strbuf_puts(html, "\" title=\""); 307 | escape_html(html, node->as.link.title.data, node->as.link.title.len); 308 | } 309 | 310 | cmark_strbuf_puts(html, "\" />"); 311 | } 312 | break; 313 | 314 | default: 315 | assert(false); 316 | break; 317 | } 318 | 319 | // cmark_strbuf_putc(html, 'x'); 320 | return 1; 321 | } 322 | 323 | char *cmark_render_html(cmark_node *root, int options) { 324 | char *result; 325 | cmark_strbuf html = GH_BUF_INIT; 326 | cmark_event_type ev_type; 327 | cmark_node *cur; 328 | struct render_state state = {&html, NULL}; 329 | cmark_iter *iter = cmark_iter_new(root); 330 | 331 | while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { 332 | cur = cmark_iter_get_node(iter); 333 | S_render_node(cur, ev_type, &state, options); 334 | } 335 | result = (char *)cmark_strbuf_detach(&html); 336 | 337 | cmark_iter_free(iter); 338 | return result; 339 | } 340 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/inlines.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_INLINES_H 2 | #define CMARK_INLINES_H 3 | 4 | #import "references.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | cmark_chunk cmark_clean_url(cmark_chunk *url); 11 | cmark_chunk cmark_clean_title(cmark_chunk *title); 12 | 13 | void cmark_parse_inlines(cmark_node *parent, cmark_reference_map *refmap, 14 | int options); 15 | 16 | bufsize_t cmark_parse_reference_inline(cmark_strbuf *input, 17 | cmark_reference_map *refmap); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/iterator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "config.h" 5 | #include "node.h" 6 | #include "cmark.h" 7 | #include "iterator.h" 8 | 9 | static const int S_leaf_mask = 10 | (1 << CMARK_NODE_HTML_BLOCK) | (1 << CMARK_NODE_THEMATIC_BREAK) | 11 | (1 << CMARK_NODE_CODE_BLOCK) | (1 << CMARK_NODE_TEXT) | 12 | (1 << CMARK_NODE_SOFTBREAK) | (1 << CMARK_NODE_LINEBREAK) | 13 | (1 << CMARK_NODE_CODE) | (1 << CMARK_NODE_HTML_INLINE); 14 | 15 | cmark_iter *cmark_iter_new(cmark_node *root) { 16 | if (root == NULL) { 17 | return NULL; 18 | } 19 | cmark_iter *iter = (cmark_iter *)malloc(sizeof(cmark_iter)); 20 | if (iter == NULL) { 21 | return NULL; 22 | } 23 | iter->root = root; 24 | iter->cur.ev_type = CMARK_EVENT_NONE; 25 | iter->cur.node = NULL; 26 | iter->next.ev_type = CMARK_EVENT_ENTER; 27 | iter->next.node = root; 28 | return iter; 29 | } 30 | 31 | void cmark_iter_free(cmark_iter *iter) { free(iter); } 32 | 33 | static bool S_is_leaf(cmark_node *node) { 34 | return ((1 << node->type) & S_leaf_mask) != 0; 35 | } 36 | 37 | cmark_event_type cmark_iter_next(cmark_iter *iter) { 38 | cmark_event_type ev_type = iter->next.ev_type; 39 | cmark_node *node = iter->next.node; 40 | 41 | iter->cur.ev_type = ev_type; 42 | iter->cur.node = node; 43 | 44 | if (ev_type == CMARK_EVENT_DONE) { 45 | return ev_type; 46 | } 47 | 48 | /* roll forward to next item, setting both fields */ 49 | if (ev_type == CMARK_EVENT_ENTER && !S_is_leaf(node)) { 50 | if (node->first_child == NULL) { 51 | /* stay on this node but exit */ 52 | iter->next.ev_type = CMARK_EVENT_EXIT; 53 | } else { 54 | iter->next.ev_type = CMARK_EVENT_ENTER; 55 | iter->next.node = node->first_child; 56 | } 57 | } else if (node == iter->root) { 58 | /* don't move past root */ 59 | iter->next.ev_type = CMARK_EVENT_DONE; 60 | iter->next.node = NULL; 61 | } else if (node->next) { 62 | iter->next.ev_type = CMARK_EVENT_ENTER; 63 | iter->next.node = node->next; 64 | } else if (node->parent) { 65 | iter->next.ev_type = CMARK_EVENT_EXIT; 66 | iter->next.node = node->parent; 67 | } else { 68 | assert(false); 69 | iter->next.ev_type = CMARK_EVENT_DONE; 70 | iter->next.node = NULL; 71 | } 72 | 73 | return ev_type; 74 | } 75 | 76 | void cmark_iter_reset(cmark_iter *iter, cmark_node *current, 77 | cmark_event_type event_type) { 78 | iter->next.ev_type = event_type; 79 | iter->next.node = current; 80 | cmark_iter_next(iter); 81 | } 82 | 83 | cmark_node *cmark_iter_get_node(cmark_iter *iter) { return iter->cur.node; } 84 | 85 | cmark_event_type cmark_iter_get_event_type(cmark_iter *iter) { 86 | return iter->cur.ev_type; 87 | } 88 | 89 | cmark_node *cmark_iter_get_root(cmark_iter *iter) { return iter->root; } 90 | 91 | void cmark_consolidate_text_nodes(cmark_node *root) { 92 | if (root == NULL) { 93 | return; 94 | } 95 | cmark_iter *iter = cmark_iter_new(root); 96 | cmark_strbuf buf = GH_BUF_INIT; 97 | cmark_event_type ev_type; 98 | cmark_node *cur, *tmp, *next; 99 | 100 | while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { 101 | cur = cmark_iter_get_node(iter); 102 | if (ev_type == CMARK_EVENT_ENTER && cur->type == CMARK_NODE_TEXT && 103 | cur->next && cur->next->type == CMARK_NODE_TEXT) { 104 | cmark_strbuf_clear(&buf); 105 | cmark_strbuf_put(&buf, cur->as.literal.data, cur->as.literal.len); 106 | tmp = cur->next; 107 | while (tmp && tmp->type == CMARK_NODE_TEXT) { 108 | cmark_iter_next(iter); // advance pointer 109 | cmark_strbuf_put(&buf, tmp->as.literal.data, tmp->as.literal.len); 110 | next = tmp->next; 111 | cmark_node_free(tmp); 112 | tmp = next; 113 | } 114 | cmark_chunk_free(&cur->as.literal); 115 | cur->as.literal = cmark_chunk_buf_detach(&buf); 116 | } 117 | } 118 | 119 | cmark_strbuf_free(&buf); 120 | cmark_iter_free(iter); 121 | } 122 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_ITERATOR_H 2 | #define CMARK_ITERATOR_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "cmark.h" 9 | 10 | typedef struct { 11 | cmark_event_type ev_type; 12 | cmark_node *node; 13 | } cmark_iter_state; 14 | 15 | struct cmark_iter { 16 | cmark_node *root; 17 | cmark_iter_state cur; 18 | cmark_iter_state next; 19 | }; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/latex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "config.h" 8 | #include "cmark.h" 9 | #include "node.h" 10 | #include "buffer.h" 11 | #include "utf8.h" 12 | #include "scanners.h" 13 | #include "render.h" 14 | 15 | #define safe_strlen(s) cmark_strbuf_safe_strlen(s) 16 | #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) 17 | #define LIT(s) renderer->out(renderer, s, false, LITERAL) 18 | #define CR() renderer->cr(renderer) 19 | #define BLANKLINE() renderer->blankline(renderer) 20 | #define LIST_NUMBER_STRING_SIZE 20 21 | 22 | static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape, 23 | int32_t c, unsigned char nextc) { 24 | if (escape == LITERAL) { 25 | cmark_render_code_point(renderer, c); 26 | return; 27 | } 28 | 29 | switch (c) { 30 | case 123: // '{' 31 | case 125: // '}' 32 | case 35: // '#' 33 | case 37: // '%' 34 | case 38: // '&' 35 | cmark_render_ascii(renderer, "\\"); 36 | cmark_render_code_point(renderer, c); 37 | break; 38 | case 36: // '$' 39 | case 95: // '_' 40 | if (escape == NORMAL) { 41 | cmark_render_ascii(renderer, "\\"); 42 | } 43 | cmark_render_code_point(renderer, c); 44 | break; 45 | case 45: // '-' 46 | if (nextc == 45) { // prevent ligature 47 | cmark_render_ascii(renderer, "\\-"); 48 | } else { 49 | cmark_render_ascii(renderer, "-"); 50 | } 51 | break; 52 | case 126: // '~' 53 | if (escape == NORMAL) { 54 | cmark_render_ascii(renderer, "\\textasciitilde{}"); 55 | } else { 56 | cmark_render_code_point(renderer, c); 57 | } 58 | break; 59 | case 94: // '^' 60 | cmark_render_ascii(renderer, "\\^{}"); 61 | break; 62 | case 92: // '\\' 63 | if (escape == URL) { 64 | // / acts as path sep even on windows: 65 | cmark_render_ascii(renderer, "/"); 66 | } else { 67 | cmark_render_ascii(renderer, "\\textbackslash{}"); 68 | } 69 | break; 70 | case 124: // '|' 71 | cmark_render_ascii(renderer, "\\textbar{}"); 72 | break; 73 | case 60: // '<' 74 | cmark_render_ascii(renderer, "\\textless{}"); 75 | break; 76 | case 62: // '>' 77 | cmark_render_ascii(renderer, "\\textgreater{}"); 78 | break; 79 | case 91: // '[' 80 | case 93: // ']' 81 | cmark_render_ascii(renderer, "{"); 82 | cmark_render_code_point(renderer, c); 83 | cmark_render_ascii(renderer, "}"); 84 | break; 85 | case 34: // '"' 86 | cmark_render_ascii(renderer, "\\textquotedbl{}"); 87 | // requires \usepackage[T1]{fontenc} 88 | break; 89 | case 39: // '\'' 90 | cmark_render_ascii(renderer, "\\textquotesingle{}"); 91 | // requires \usepackage{textcomp} 92 | break; 93 | case 160: // nbsp 94 | cmark_render_ascii(renderer, "~"); 95 | break; 96 | case 8230: // hellip 97 | cmark_render_ascii(renderer, "\\ldots{}"); 98 | break; 99 | case 8216: // lsquo 100 | if (escape == NORMAL) { 101 | cmark_render_ascii(renderer, "`"); 102 | } else { 103 | cmark_render_code_point(renderer, c); 104 | } 105 | break; 106 | case 8217: // rsquo 107 | if (escape == NORMAL) { 108 | cmark_render_ascii(renderer, "\'"); 109 | } else { 110 | cmark_render_code_point(renderer, c); 111 | } 112 | break; 113 | case 8220: // ldquo 114 | if (escape == NORMAL) { 115 | cmark_render_ascii(renderer, "``"); 116 | } else { 117 | cmark_render_code_point(renderer, c); 118 | } 119 | break; 120 | case 8221: // rdquo 121 | if (escape == NORMAL) { 122 | cmark_render_ascii(renderer, "''"); 123 | } else { 124 | cmark_render_code_point(renderer, c); 125 | } 126 | break; 127 | case 8212: // emdash 128 | if (escape == NORMAL) { 129 | cmark_render_ascii(renderer, "---"); 130 | } else { 131 | cmark_render_code_point(renderer, c); 132 | } 133 | break; 134 | case 8211: // endash 135 | if (escape == NORMAL) { 136 | cmark_render_ascii(renderer, "--"); 137 | } else { 138 | cmark_render_code_point(renderer, c); 139 | } 140 | break; 141 | default: 142 | cmark_render_code_point(renderer, c); 143 | } 144 | } 145 | 146 | typedef enum { 147 | NO_LINK, 148 | URL_AUTOLINK, 149 | EMAIL_AUTOLINK, 150 | NORMAL_LINK, 151 | INTERNAL_LINK 152 | } link_type; 153 | 154 | static link_type get_link_type(cmark_node *node) { 155 | size_t title_len, url_len; 156 | cmark_node *link_text; 157 | char *realurl; 158 | int realurllen; 159 | bool isemail = false; 160 | 161 | if (node->type != CMARK_NODE_LINK) { 162 | return NO_LINK; 163 | } 164 | 165 | const char *url = cmark_node_get_url(node); 166 | cmark_chunk url_chunk = cmark_chunk_literal(url); 167 | 168 | if (url && *url == '#') { 169 | return INTERNAL_LINK; 170 | } 171 | 172 | url_len = safe_strlen(url); 173 | if (url_len == 0 || scan_scheme(&url_chunk, 0) == 0) { 174 | return NO_LINK; 175 | } 176 | 177 | const char *title = cmark_node_get_title(node); 178 | title_len = safe_strlen(title); 179 | // if it has a title, we can't treat it as an autolink: 180 | if (title_len == 0) { 181 | 182 | link_text = node->first_child; 183 | cmark_consolidate_text_nodes(link_text); 184 | realurl = (char *)url; 185 | realurllen = url_len; 186 | if (strncmp(realurl, "mailto:", 7) == 0) { 187 | realurl += 7; 188 | realurllen -= 7; 189 | isemail = true; 190 | } 191 | if (realurllen == link_text->as.literal.len && 192 | strncmp(realurl, (char *)link_text->as.literal.data, 193 | link_text->as.literal.len) == 0) { 194 | if (isemail) { 195 | return EMAIL_AUTOLINK; 196 | } else { 197 | return URL_AUTOLINK; 198 | } 199 | } 200 | } 201 | 202 | return NORMAL_LINK; 203 | } 204 | 205 | static int S_get_enumlevel(cmark_node *node) { 206 | int enumlevel = 0; 207 | cmark_node *tmp = node; 208 | while (tmp) { 209 | if (tmp->type == CMARK_NODE_LIST && 210 | cmark_node_get_list_type(node) == CMARK_ORDERED_LIST) { 211 | enumlevel++; 212 | } 213 | tmp = tmp->parent; 214 | } 215 | return enumlevel; 216 | } 217 | 218 | static int S_render_node(cmark_renderer *renderer, cmark_node *node, 219 | cmark_event_type ev_type, int options) { 220 | int list_number; 221 | char list_number_string[LIST_NUMBER_STRING_SIZE]; 222 | bool entering = (ev_type == CMARK_EVENT_ENTER); 223 | cmark_list_type list_type; 224 | const char *roman_numerals[] = {"", "i", "ii", "iii", "iv", "v", 225 | "vi", "vii", "viii", "ix", "x"}; 226 | 227 | // avoid warning about unused parameter: 228 | (void)(options); 229 | 230 | switch (node->type) { 231 | case CMARK_NODE_DOCUMENT: 232 | break; 233 | 234 | case CMARK_NODE_BLOCK_QUOTE: 235 | if (entering) { 236 | LIT("\\begin{quote}"); 237 | CR(); 238 | } else { 239 | LIT("\\end{quote}"); 240 | BLANKLINE(); 241 | } 242 | break; 243 | 244 | case CMARK_NODE_LIST: 245 | list_type = cmark_node_get_list_type(node); 246 | if (entering) { 247 | LIT("\\begin{"); 248 | LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); 249 | LIT("}"); 250 | CR(); 251 | list_number = cmark_node_get_list_start(node); 252 | if (list_number > 1) { 253 | snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d", 254 | list_number); 255 | LIT("\\setcounter{enum"); 256 | LIT((char *)roman_numerals[S_get_enumlevel(node)]); 257 | LIT("}{"); 258 | OUT(list_number_string, false, NORMAL); 259 | LIT("}"); 260 | CR(); 261 | } 262 | } else { 263 | LIT("\\end{"); 264 | LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); 265 | LIT("}"); 266 | BLANKLINE(); 267 | } 268 | break; 269 | 270 | case CMARK_NODE_ITEM: 271 | if (entering) { 272 | LIT("\\item "); 273 | } else { 274 | CR(); 275 | } 276 | break; 277 | 278 | case CMARK_NODE_HEADING: 279 | if (entering) { 280 | switch (cmark_node_get_heading_level(node)) { 281 | case 1: 282 | LIT("\\section"); 283 | break; 284 | case 2: 285 | LIT("\\subsection"); 286 | break; 287 | case 3: 288 | LIT("\\subsubsection"); 289 | break; 290 | case 4: 291 | LIT("\\paragraph"); 292 | break; 293 | case 5: 294 | LIT("\\subparagraph"); 295 | break; 296 | } 297 | LIT("{"); 298 | } else { 299 | LIT("}"); 300 | BLANKLINE(); 301 | } 302 | break; 303 | 304 | case CMARK_NODE_CODE_BLOCK: 305 | CR(); 306 | LIT("\\begin{verbatim}"); 307 | CR(); 308 | OUT(cmark_node_get_literal(node), false, LITERAL); 309 | CR(); 310 | LIT("\\end{verbatim}"); 311 | BLANKLINE(); 312 | break; 313 | 314 | case CMARK_NODE_HTML_BLOCK: 315 | break; 316 | 317 | case CMARK_NODE_CUSTOM_BLOCK: 318 | CR(); 319 | OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), 320 | false, LITERAL); 321 | CR(); 322 | break; 323 | 324 | case CMARK_NODE_THEMATIC_BREAK: 325 | BLANKLINE(); 326 | LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}"); 327 | BLANKLINE(); 328 | break; 329 | 330 | case CMARK_NODE_PARAGRAPH: 331 | if (!entering) { 332 | BLANKLINE(); 333 | } 334 | break; 335 | 336 | case CMARK_NODE_TEXT: 337 | OUT(cmark_node_get_literal(node), true, NORMAL); 338 | break; 339 | 340 | case CMARK_NODE_LINEBREAK: 341 | LIT("\\\\"); 342 | CR(); 343 | break; 344 | 345 | case CMARK_NODE_SOFTBREAK: 346 | if (renderer->width == 0) { 347 | CR(); 348 | } else { 349 | OUT(" ", true, NORMAL); 350 | } 351 | break; 352 | 353 | case CMARK_NODE_CODE: 354 | LIT("\\texttt{"); 355 | OUT(cmark_node_get_literal(node), false, NORMAL); 356 | LIT("}"); 357 | break; 358 | 359 | case CMARK_NODE_HTML_INLINE: 360 | break; 361 | 362 | case CMARK_NODE_CUSTOM_INLINE: 363 | OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), 364 | false, LITERAL); 365 | break; 366 | 367 | case CMARK_NODE_STRONG: 368 | if (entering) { 369 | LIT("\\textbf{"); 370 | } else { 371 | LIT("}"); 372 | } 373 | break; 374 | 375 | case CMARK_NODE_EMPH: 376 | if (entering) { 377 | LIT("\\emph{"); 378 | } else { 379 | LIT("}"); 380 | } 381 | break; 382 | 383 | case CMARK_NODE_LINK: 384 | if (entering) { 385 | const char *url = cmark_node_get_url(node); 386 | // requires \usepackage{hyperref} 387 | switch (get_link_type(node)) { 388 | case URL_AUTOLINK: 389 | LIT("\\url{"); 390 | OUT(url, false, URL); 391 | break; 392 | case EMAIL_AUTOLINK: 393 | LIT("\\href{"); 394 | OUT(url, false, URL); 395 | LIT("}\\nolinkurl{"); 396 | break; 397 | case NORMAL_LINK: 398 | LIT("\\href{"); 399 | OUT(url, false, URL); 400 | LIT("}{"); 401 | break; 402 | case INTERNAL_LINK: 403 | LIT("\\protect\\hyperlink{"); 404 | OUT(url + 1, false, URL); 405 | LIT("}{"); 406 | break; 407 | case NO_LINK: 408 | LIT("{"); // error? 409 | } 410 | } else { 411 | LIT("}"); 412 | } 413 | 414 | break; 415 | 416 | case CMARK_NODE_IMAGE: 417 | if (entering) { 418 | LIT("\\protect\\includegraphics{"); 419 | // requires \include{graphicx} 420 | OUT(cmark_node_get_url(node), false, URL); 421 | LIT("}"); 422 | return 0; 423 | } 424 | break; 425 | 426 | default: 427 | assert(false); 428 | break; 429 | } 430 | 431 | return 1; 432 | } 433 | 434 | char *cmark_render_latex(cmark_node *root, int options, int width) { 435 | return cmark_render(root, options, width, outc, S_render_node); 436 | } 437 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/man.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "config.h" 7 | #include "cmark.h" 8 | #include "node.h" 9 | #include "buffer.h" 10 | #include "utf8.h" 11 | #include "render.h" 12 | 13 | #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) 14 | #define LIT(s) renderer->out(renderer, s, false, LITERAL) 15 | #define CR() renderer->cr(renderer) 16 | #define BLANKLINE() renderer->blankline(renderer) 17 | #define LIST_NUMBER_SIZE 20 18 | 19 | // Functions to convert cmark_nodes to groff man strings. 20 | static void S_outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, 21 | unsigned char nextc) { 22 | (void)(nextc); 23 | 24 | if (escape == LITERAL) { 25 | cmark_render_code_point(renderer, c); 26 | return; 27 | } 28 | 29 | switch (c) { 30 | case 46: 31 | if (renderer->begin_line) { 32 | cmark_render_ascii(renderer, "\\&."); 33 | } else { 34 | cmark_render_code_point(renderer, c); 35 | } 36 | break; 37 | case 39: 38 | if (renderer->begin_line) { 39 | cmark_render_ascii(renderer, "\\&'"); 40 | } else { 41 | cmark_render_code_point(renderer, c); 42 | } 43 | break; 44 | case 45: 45 | cmark_render_ascii(renderer, "\\-"); 46 | break; 47 | case 92: 48 | cmark_render_ascii(renderer, "\\e"); 49 | break; 50 | case 8216: // left single quote 51 | cmark_render_ascii(renderer, "\\[oq]"); 52 | break; 53 | case 8217: // right single quote 54 | cmark_render_ascii(renderer, "\\[cq]"); 55 | break; 56 | case 8220: // left double quote 57 | cmark_render_ascii(renderer, "\\[lq]"); 58 | break; 59 | case 8221: // right double quote 60 | cmark_render_ascii(renderer, "\\[rq]"); 61 | break; 62 | case 8212: // em dash 63 | cmark_render_ascii(renderer, "\\[em]"); 64 | break; 65 | case 8211: // en dash 66 | cmark_render_ascii(renderer, "\\[en]"); 67 | break; 68 | default: 69 | cmark_render_code_point(renderer, c); 70 | } 71 | } 72 | 73 | static int S_render_node(cmark_renderer *renderer, cmark_node *node, 74 | cmark_event_type ev_type, int options) { 75 | cmark_node *tmp; 76 | int list_number; 77 | bool entering = (ev_type == CMARK_EVENT_ENTER); 78 | 79 | // avoid unused parameter error: 80 | (void)(options); 81 | 82 | switch (node->type) { 83 | case CMARK_NODE_DOCUMENT: 84 | break; 85 | 86 | case CMARK_NODE_BLOCK_QUOTE: 87 | if (entering) { 88 | CR(); 89 | LIT(".RS"); 90 | CR(); 91 | } else { 92 | CR(); 93 | LIT(".RE"); 94 | CR(); 95 | } 96 | break; 97 | 98 | case CMARK_NODE_LIST: 99 | break; 100 | 101 | case CMARK_NODE_ITEM: 102 | if (entering) { 103 | CR(); 104 | LIT(".IP "); 105 | if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) { 106 | LIT("\\[bu] 2"); 107 | } else { 108 | list_number = cmark_node_get_list_start(node->parent); 109 | tmp = node; 110 | while (tmp->prev) { 111 | tmp = tmp->prev; 112 | list_number += 1; 113 | } 114 | char list_number_s[LIST_NUMBER_SIZE]; 115 | snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number); 116 | LIT(list_number_s); 117 | } 118 | CR(); 119 | } else { 120 | CR(); 121 | } 122 | break; 123 | 124 | case CMARK_NODE_HEADING: 125 | if (entering) { 126 | CR(); 127 | LIT(cmark_node_get_heading_level(node) == 1 ? ".SH" : ".SS"); 128 | CR(); 129 | } else { 130 | CR(); 131 | } 132 | break; 133 | 134 | case CMARK_NODE_CODE_BLOCK: 135 | CR(); 136 | LIT(".IP\n.nf\n\\f[C]\n"); 137 | OUT(cmark_node_get_literal(node), false, NORMAL); 138 | CR(); 139 | LIT("\\f[]\n.fi"); 140 | CR(); 141 | break; 142 | 143 | case CMARK_NODE_HTML_BLOCK: 144 | break; 145 | 146 | case CMARK_NODE_CUSTOM_BLOCK: 147 | CR(); 148 | OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), 149 | false, LITERAL); 150 | CR(); 151 | break; 152 | 153 | case CMARK_NODE_THEMATIC_BREAK: 154 | CR(); 155 | LIT(".PP\n * * * * *"); 156 | CR(); 157 | break; 158 | 159 | case CMARK_NODE_PARAGRAPH: 160 | if (entering) { 161 | // no blank line if first paragraph in list: 162 | if (node->parent && node->parent->type == CMARK_NODE_ITEM && 163 | node->prev == NULL) { 164 | // no blank line or .PP 165 | } else { 166 | CR(); 167 | LIT(".PP"); 168 | CR(); 169 | } 170 | } else { 171 | CR(); 172 | } 173 | break; 174 | 175 | case CMARK_NODE_TEXT: 176 | OUT(cmark_node_get_literal(node), true, NORMAL); 177 | break; 178 | 179 | case CMARK_NODE_LINEBREAK: 180 | LIT(".PD 0\n.P\n.PD"); 181 | CR(); 182 | break; 183 | 184 | case CMARK_NODE_SOFTBREAK: 185 | if (renderer->width == 0) { 186 | CR(); 187 | } else { 188 | OUT(" ", true, LITERAL); 189 | } 190 | break; 191 | 192 | case CMARK_NODE_CODE: 193 | LIT("\\f[C]"); 194 | OUT(cmark_node_get_literal(node), true, NORMAL); 195 | LIT("\\f[]"); 196 | break; 197 | 198 | case CMARK_NODE_HTML_INLINE: 199 | break; 200 | 201 | case CMARK_NODE_CUSTOM_INLINE: 202 | OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), 203 | false, LITERAL); 204 | break; 205 | 206 | case CMARK_NODE_STRONG: 207 | if (entering) { 208 | LIT("\\f[B]"); 209 | } else { 210 | LIT("\\f[]"); 211 | } 212 | break; 213 | 214 | case CMARK_NODE_EMPH: 215 | if (entering) { 216 | LIT("\\f[I]"); 217 | } else { 218 | LIT("\\f[]"); 219 | } 220 | break; 221 | 222 | case CMARK_NODE_LINK: 223 | if (!entering) { 224 | LIT(" ("); 225 | OUT(cmark_node_get_url(node), true, URL); 226 | LIT(")"); 227 | } 228 | break; 229 | 230 | case CMARK_NODE_IMAGE: 231 | if (entering) { 232 | LIT("[IMAGE: "); 233 | } else { 234 | LIT("]"); 235 | } 236 | break; 237 | 238 | default: 239 | assert(false); 240 | break; 241 | } 242 | 243 | return 1; 244 | } 245 | 246 | char *cmark_render_man(cmark_node *root, int options, int width) { 247 | return cmark_render(root, options, width, S_outc, S_render_node); 248 | } 249 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/module.modulemap: -------------------------------------------------------------------------------- 1 | module libcmark [system][extern_c] { 2 | header "node.h" 3 | header "cmark.h" 4 | export * 5 | } -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/node.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_NODE_H 2 | #define CMARK_NODE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | #include "cmark.h" 12 | #include "buffer.h" 13 | #include "chunk.h" 14 | 15 | typedef struct { 16 | cmark_list_type list_type; 17 | int marker_offset; 18 | int padding; 19 | int start; 20 | cmark_delim_type delimiter; 21 | unsigned char bullet_char; 22 | bool tight; 23 | } cmark_list; 24 | 25 | typedef struct { 26 | cmark_chunk info; 27 | cmark_chunk literal; 28 | int fence_length; 29 | /* fence_offset must be 0-3, so we can use int8_t */ 30 | int8_t fence_offset; 31 | unsigned char fence_char; 32 | bool fenced; 33 | } cmark_code; 34 | 35 | typedef struct { 36 | int level; 37 | bool setext; 38 | } cmark_heading; 39 | 40 | typedef struct { 41 | cmark_chunk url; 42 | cmark_chunk title; 43 | } cmark_link; 44 | 45 | typedef struct { 46 | cmark_chunk on_enter; 47 | cmark_chunk on_exit; 48 | } cmark_custom; 49 | 50 | struct cmark_node { 51 | struct cmark_node *next; 52 | struct cmark_node *prev; 53 | struct cmark_node *parent; 54 | struct cmark_node *first_child; 55 | struct cmark_node *last_child; 56 | 57 | void *user_data; 58 | 59 | int start_line; 60 | int start_column; 61 | int end_line; 62 | int end_column; 63 | 64 | cmark_node_type type; 65 | 66 | bool open; 67 | bool last_line_blank; 68 | 69 | cmark_strbuf string_content; 70 | 71 | union { 72 | cmark_chunk literal; 73 | cmark_list list; 74 | cmark_code code; 75 | cmark_heading heading; 76 | cmark_link link; 77 | cmark_custom custom; 78 | int html_block_type; 79 | } as; 80 | }; 81 | 82 | CMARK_EXPORT int cmark_node_check(cmark_node *node, FILE *out); 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_AST_H 2 | #define CMARK_AST_H 3 | 4 | #include 5 | #include "node.h" 6 | #include "buffer.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define MAX_LINK_LABEL_LENGTH 1000 13 | 14 | struct cmark_parser { 15 | struct cmark_reference_map *refmap; 16 | struct cmark_node *root; 17 | struct cmark_node *current; 18 | int line_number; 19 | bufsize_t offset; 20 | bufsize_t column; 21 | bufsize_t first_nonspace; 22 | bufsize_t first_nonspace_column; 23 | int indent; 24 | bool blank; 25 | bool partially_consumed_tab; 26 | cmark_strbuf *curline; 27 | bufsize_t last_line_length; 28 | cmark_strbuf *linebuf; 29 | int options; 30 | bool last_buffer_ended_with_cr; 31 | }; 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/references.c: -------------------------------------------------------------------------------- 1 | #include "cmark.h" 2 | #include "utf8.h" 3 | #include "parser.h" 4 | #include "references.h" 5 | #include "inlines.h" 6 | #include "chunk.h" 7 | 8 | static unsigned int refhash(const unsigned char *link_ref) { 9 | unsigned int hash = 0; 10 | 11 | while (*link_ref) 12 | hash = (*link_ref++) + (hash << 6) + (hash << 16) - hash; 13 | 14 | return hash; 15 | } 16 | 17 | static void reference_free(cmark_reference *ref) { 18 | if (ref != NULL) { 19 | free(ref->label); 20 | cmark_chunk_free(&ref->url); 21 | cmark_chunk_free(&ref->title); 22 | free(ref); 23 | } 24 | } 25 | 26 | // normalize reference: collapse internal whitespace to single space, 27 | // remove leading/trailing whitespace, case fold 28 | // Return NULL if the reference name is actually empty (i.e. composed 29 | // solely from whitespace) 30 | static unsigned char *normalize_reference(cmark_chunk *ref) { 31 | cmark_strbuf normalized = GH_BUF_INIT; 32 | unsigned char *result; 33 | 34 | if (ref == NULL) 35 | return NULL; 36 | 37 | if (ref->len == 0) 38 | return NULL; 39 | 40 | cmark_utf8proc_case_fold(&normalized, ref->data, ref->len); 41 | cmark_strbuf_trim(&normalized); 42 | cmark_strbuf_normalize_whitespace(&normalized); 43 | 44 | result = cmark_strbuf_detach(&normalized); 45 | assert(result); 46 | 47 | if (result[0] == '\0') { 48 | free(result); 49 | return NULL; 50 | } 51 | 52 | return result; 53 | } 54 | 55 | static void add_reference(cmark_reference_map *map, cmark_reference *ref) { 56 | cmark_reference *t = ref->next = map->table[ref->hash % REFMAP_SIZE]; 57 | 58 | while (t) { 59 | if (t->hash == ref->hash && !strcmp((char *)t->label, (char *)ref->label)) { 60 | reference_free(ref); 61 | return; 62 | } 63 | 64 | t = t->next; 65 | } 66 | 67 | map->table[ref->hash % REFMAP_SIZE] = ref; 68 | } 69 | 70 | void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label, 71 | cmark_chunk *url, cmark_chunk *title) { 72 | cmark_reference *ref; 73 | unsigned char *reflabel = normalize_reference(label); 74 | 75 | /* empty reference name, or composed from only whitespace */ 76 | if (reflabel == NULL) 77 | return; 78 | 79 | ref = (cmark_reference *)calloc(1, sizeof(*ref)); 80 | if (ref != NULL) { 81 | ref->label = reflabel; 82 | ref->hash = refhash(ref->label); 83 | ref->url = cmark_clean_url(url); 84 | ref->title = cmark_clean_title(title); 85 | ref->next = NULL; 86 | 87 | add_reference(map, ref); 88 | } 89 | } 90 | 91 | // Returns reference if refmap contains a reference with matching 92 | // label, otherwise NULL. 93 | cmark_reference *cmark_reference_lookup(cmark_reference_map *map, 94 | cmark_chunk *label) { 95 | cmark_reference *ref = NULL; 96 | unsigned char *norm; 97 | unsigned int hash; 98 | 99 | if (label->len > MAX_LINK_LABEL_LENGTH) 100 | return NULL; 101 | 102 | if (map == NULL) 103 | return NULL; 104 | 105 | norm = normalize_reference(label); 106 | if (norm == NULL) 107 | return NULL; 108 | 109 | hash = refhash(norm); 110 | ref = map->table[hash % REFMAP_SIZE]; 111 | 112 | while (ref) { 113 | if (ref->hash == hash && !strcmp((char *)ref->label, (char *)norm)) 114 | break; 115 | ref = ref->next; 116 | } 117 | 118 | free(norm); 119 | return ref; 120 | } 121 | 122 | void cmark_reference_map_free(cmark_reference_map *map) { 123 | unsigned int i; 124 | 125 | if (map == NULL) 126 | return; 127 | 128 | for (i = 0; i < REFMAP_SIZE; ++i) { 129 | cmark_reference *ref = map->table[i]; 130 | cmark_reference *next; 131 | 132 | while (ref) { 133 | next = ref->next; 134 | reference_free(ref); 135 | ref = next; 136 | } 137 | } 138 | 139 | free(map); 140 | } 141 | 142 | cmark_reference_map *cmark_reference_map_new(void) { 143 | return (cmark_reference_map *)calloc(1, sizeof(cmark_reference_map)); 144 | } 145 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/references.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_REFERENCES_H 2 | #define CMARK_REFERENCES_H 3 | 4 | #include "chunk.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define REFMAP_SIZE 16 11 | 12 | struct cmark_reference { 13 | struct cmark_reference *next; 14 | unsigned char *label; 15 | cmark_chunk url; 16 | cmark_chunk title; 17 | unsigned int hash; 18 | }; 19 | 20 | typedef struct cmark_reference cmark_reference; 21 | 22 | struct cmark_reference_map { 23 | cmark_reference *table[REFMAP_SIZE]; 24 | }; 25 | 26 | typedef struct cmark_reference_map cmark_reference_map; 27 | 28 | cmark_reference_map *cmark_reference_map_new(void); 29 | void cmark_reference_map_free(cmark_reference_map *map); 30 | cmark_reference *cmark_reference_lookup(cmark_reference_map *map, 31 | cmark_chunk *label); 32 | extern void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label, 33 | cmark_chunk *url, cmark_chunk *title); 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/render.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "buffer.h" 3 | #include "chunk.h" 4 | #include "cmark.h" 5 | #include "utf8.h" 6 | #include "render.h" 7 | 8 | static CMARK_INLINE void S_cr(cmark_renderer *renderer) { 9 | if (renderer->need_cr < 1) { 10 | renderer->need_cr = 1; 11 | } 12 | } 13 | 14 | static CMARK_INLINE void S_blankline(cmark_renderer *renderer) { 15 | if (renderer->need_cr < 2) { 16 | renderer->need_cr = 2; 17 | } 18 | } 19 | 20 | static void S_out(cmark_renderer *renderer, const char *source, bool wrap, 21 | cmark_escaping escape) { 22 | int length = cmark_strbuf_safe_strlen(source); 23 | unsigned char nextc; 24 | int32_t c; 25 | int i = 0; 26 | int last_nonspace; 27 | int len; 28 | cmark_chunk remainder = cmark_chunk_literal(""); 29 | int k = renderer->buffer->size - 1; 30 | 31 | wrap = wrap && !renderer->no_wrap; 32 | 33 | if (renderer->in_tight_list_item && renderer->need_cr > 1) { 34 | renderer->need_cr = 1; 35 | } 36 | while (renderer->need_cr) { 37 | if (k < 0 || renderer->buffer->ptr[k] == '\n') { 38 | k -= 1; 39 | } else { 40 | cmark_strbuf_putc(renderer->buffer, '\n'); 41 | if (renderer->need_cr > 1) { 42 | cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, 43 | renderer->prefix->size); 44 | } 45 | } 46 | renderer->column = 0; 47 | renderer->begin_line = true; 48 | renderer->begin_content = true; 49 | renderer->need_cr -= 1; 50 | } 51 | 52 | while (i < length) { 53 | if (renderer->begin_line) { 54 | cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, 55 | renderer->prefix->size); 56 | // note: this assumes prefix is ascii: 57 | renderer->column = renderer->prefix->size; 58 | } 59 | 60 | len = cmark_utf8proc_iterate((const uint8_t *)source + i, length - i, &c); 61 | if (len == -1) { // error condition 62 | return; // return without rendering rest of string 63 | } 64 | nextc = source[i + len]; 65 | if (c == 32 && wrap) { 66 | if (!renderer->begin_line) { 67 | last_nonspace = renderer->buffer->size; 68 | cmark_strbuf_putc(renderer->buffer, ' '); 69 | renderer->column += 1; 70 | renderer->begin_line = false; 71 | renderer->begin_content = false; 72 | // skip following spaces 73 | while (source[i + 1] == ' ') { 74 | i++; 75 | } 76 | // We don't allow breaks that make a digit the first character 77 | // because this causes problems with commonmark output. 78 | if (!cmark_isdigit(source[i + 1])) { 79 | renderer->last_breakable = last_nonspace; 80 | } 81 | } 82 | 83 | } else if (c == 10) { 84 | cmark_strbuf_putc(renderer->buffer, '\n'); 85 | renderer->column = 0; 86 | renderer->begin_line = true; 87 | renderer->begin_content = true; 88 | renderer->last_breakable = 0; 89 | } else if (escape == LITERAL) { 90 | cmark_render_code_point(renderer, c); 91 | renderer->begin_line = false; 92 | // we don't set 'begin_content' to false til we've 93 | // finished parsing a digit. Reason: in commonmark 94 | // we need to escape a potential list marker after 95 | // a digit: 96 | renderer->begin_content = 97 | renderer->begin_content && cmark_isdigit(c) == 1; 98 | } else { 99 | (renderer->outc)(renderer, escape, c, nextc); 100 | renderer->begin_line = false; 101 | renderer->begin_content = 102 | renderer->begin_content && cmark_isdigit(c) == 1; 103 | } 104 | 105 | // If adding the character went beyond width, look for an 106 | // earlier place where the line could be broken: 107 | if (renderer->width > 0 && renderer->column > renderer->width && 108 | !renderer->begin_line && renderer->last_breakable > 0) { 109 | 110 | // copy from last_breakable to remainder 111 | cmark_chunk_set_cstr(&remainder, (char *)renderer->buffer->ptr + 112 | renderer->last_breakable + 1); 113 | // truncate at last_breakable 114 | cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable); 115 | // add newline, prefix, and remainder 116 | cmark_strbuf_putc(renderer->buffer, '\n'); 117 | cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, 118 | renderer->prefix->size); 119 | cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len); 120 | renderer->column = renderer->prefix->size + remainder.len; 121 | cmark_chunk_free(&remainder); 122 | renderer->last_breakable = 0; 123 | renderer->begin_line = false; 124 | renderer->begin_content = false; 125 | } 126 | 127 | i += len; 128 | } 129 | } 130 | 131 | // Assumes no newlines, assumes ascii content: 132 | void cmark_render_ascii(cmark_renderer *renderer, const char *s) { 133 | int origsize = renderer->buffer->size; 134 | cmark_strbuf_puts(renderer->buffer, s); 135 | renderer->column += renderer->buffer->size - origsize; 136 | } 137 | 138 | void cmark_render_code_point(cmark_renderer *renderer, uint32_t c) { 139 | cmark_utf8proc_encode_char(c, renderer->buffer); 140 | renderer->column += 1; 141 | } 142 | 143 | char *cmark_render(cmark_node *root, int options, int width, 144 | void (*outc)(cmark_renderer *, cmark_escaping, int32_t, 145 | unsigned char), 146 | int (*render_node)(cmark_renderer *renderer, 147 | cmark_node *node, 148 | cmark_event_type ev_type, int options)) { 149 | cmark_strbuf pref = GH_BUF_INIT; 150 | cmark_strbuf buf = GH_BUF_INIT; 151 | cmark_node *cur; 152 | cmark_event_type ev_type; 153 | char *result; 154 | cmark_iter *iter = cmark_iter_new(root); 155 | 156 | cmark_renderer renderer = {&buf, &pref, 0, width, 0, 157 | 0, true, true, false, false, 158 | outc, S_cr, S_blankline, S_out}; 159 | 160 | while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { 161 | cur = cmark_iter_get_node(iter); 162 | if (!render_node(&renderer, cur, ev_type, options)) { 163 | // a false value causes us to skip processing 164 | // the node's contents. this is used for 165 | // autolinks. 166 | cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT); 167 | } 168 | } 169 | 170 | // ensure final newline 171 | if (renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') { 172 | cmark_strbuf_putc(renderer.buffer, '\n'); 173 | } 174 | 175 | result = (char *)cmark_strbuf_detach(renderer.buffer); 176 | 177 | cmark_iter_free(iter); 178 | cmark_strbuf_free(renderer.prefix); 179 | cmark_strbuf_free(renderer.buffer); 180 | 181 | return result; 182 | } 183 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/render.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_RENDER_H 2 | #define CMARK_RENDER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "buffer.h" 10 | #include "chunk.h" 11 | 12 | typedef enum { LITERAL, NORMAL, TITLE, URL } cmark_escaping; 13 | 14 | struct cmark_renderer { 15 | cmark_strbuf *buffer; 16 | cmark_strbuf *prefix; 17 | int column; 18 | int width; 19 | int need_cr; 20 | bufsize_t last_breakable; 21 | bool begin_line; 22 | bool begin_content; 23 | bool no_wrap; 24 | bool in_tight_list_item; 25 | void (*outc)(struct cmark_renderer *, cmark_escaping, int32_t, unsigned char); 26 | void (*cr)(struct cmark_renderer *); 27 | void (*blankline)(struct cmark_renderer *); 28 | void (*out)(struct cmark_renderer *, const char *, bool, cmark_escaping); 29 | }; 30 | 31 | typedef struct cmark_renderer cmark_renderer; 32 | 33 | void cmark_render_ascii(cmark_renderer *renderer, const char *s); 34 | 35 | void cmark_render_code_point(cmark_renderer *renderer, uint32_t c); 36 | 37 | char *cmark_render(cmark_node *root, int options, int width, 38 | void (*outc)(cmark_renderer *, cmark_escaping, int32_t, 39 | unsigned char), 40 | int (*render_node)(cmark_renderer *renderer, 41 | cmark_node *node, 42 | cmark_event_type ev_type, int options)); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/scanners.h: -------------------------------------------------------------------------------- 1 | #include "cmark.h" 2 | #include "chunk.h" 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, 9 | bufsize_t offset); 10 | bufsize_t _scan_scheme(const unsigned char *p); 11 | bufsize_t _scan_autolink_uri(const unsigned char *p); 12 | bufsize_t _scan_autolink_email(const unsigned char *p); 13 | bufsize_t _scan_html_tag(const unsigned char *p); 14 | bufsize_t _scan_html_block_start(const unsigned char *p); 15 | bufsize_t _scan_html_block_start_7(const unsigned char *p); 16 | bufsize_t _scan_html_block_end_1(const unsigned char *p); 17 | bufsize_t _scan_html_block_end_2(const unsigned char *p); 18 | bufsize_t _scan_html_block_end_3(const unsigned char *p); 19 | bufsize_t _scan_html_block_end_4(const unsigned char *p); 20 | bufsize_t _scan_html_block_end_5(const unsigned char *p); 21 | bufsize_t _scan_link_url(const unsigned char *p); 22 | bufsize_t _scan_link_title(const unsigned char *p); 23 | bufsize_t _scan_spacechars(const unsigned char *p); 24 | bufsize_t _scan_atx_heading_start(const unsigned char *p); 25 | bufsize_t _scan_setext_heading_line(const unsigned char *p); 26 | bufsize_t _scan_thematic_break(const unsigned char *p); 27 | bufsize_t _scan_open_code_fence(const unsigned char *p); 28 | bufsize_t _scan_close_code_fence(const unsigned char *p); 29 | bufsize_t _scan_entity(const unsigned char *p); 30 | bufsize_t _scan_dangerous_url(const unsigned char *p); 31 | 32 | #define scan_scheme(c, n) _scan_at(&_scan_scheme, c, n) 33 | #define scan_autolink_uri(c, n) _scan_at(&_scan_autolink_uri, c, n) 34 | #define scan_autolink_email(c, n) _scan_at(&_scan_autolink_email, c, n) 35 | #define scan_html_tag(c, n) _scan_at(&_scan_html_tag, c, n) 36 | #define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n) 37 | #define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n) 38 | #define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n) 39 | #define scan_html_block_end_2(c, n) _scan_at(&_scan_html_block_end_2, c, n) 40 | #define scan_html_block_end_3(c, n) _scan_at(&_scan_html_block_end_3, c, n) 41 | #define scan_html_block_end_4(c, n) _scan_at(&_scan_html_block_end_4, c, n) 42 | #define scan_html_block_end_5(c, n) _scan_at(&_scan_html_block_end_5, c, n) 43 | #define scan_link_url(c, n) _scan_at(&_scan_link_url, c, n) 44 | #define scan_link_title(c, n) _scan_at(&_scan_link_title, c, n) 45 | #define scan_spacechars(c, n) _scan_at(&_scan_spacechars, c, n) 46 | #define scan_atx_heading_start(c, n) _scan_at(&_scan_atx_heading_start, c, n) 47 | #define scan_setext_heading_line(c, n) \ 48 | _scan_at(&_scan_setext_heading_line, c, n) 49 | #define scan_thematic_break(c, n) _scan_at(&_scan_thematic_break, c, n) 50 | #define scan_open_code_fence(c, n) _scan_at(&_scan_open_code_fence, c, n) 51 | #define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n) 52 | #define scan_entity(c, n) _scan_at(&_scan_entity, c, n) 53 | #define scan_dangerous_url(c, n) _scan_at(&_scan_dangerous_url, c, n) 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/utf8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "cmark_ctype.h" 6 | #include "utf8.h" 7 | 8 | static const int8_t utf8proc_utf8class[256] = { 9 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18 | 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 19 | 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0}; 20 | 21 | static void encode_unknown(cmark_strbuf *buf) { 22 | static const uint8_t repl[] = {239, 191, 189}; 23 | cmark_strbuf_put(buf, repl, 3); 24 | } 25 | 26 | static int utf8proc_charlen(const uint8_t *str, bufsize_t str_len) { 27 | int length, i; 28 | 29 | if (!str_len) 30 | return 0; 31 | 32 | length = utf8proc_utf8class[str[0]]; 33 | 34 | if (!length) 35 | return -1; 36 | 37 | if (str_len >= 0 && (bufsize_t)length > str_len) 38 | return -str_len; 39 | 40 | for (i = 1; i < length; i++) { 41 | if ((str[i] & 0xC0) != 0x80) 42 | return -i; 43 | } 44 | 45 | return length; 46 | } 47 | 48 | // Validate a single UTF-8 character according to RFC 3629. 49 | static int utf8proc_valid(const uint8_t *str, bufsize_t str_len) { 50 | int length = utf8proc_utf8class[str[0]]; 51 | 52 | if (!length) 53 | return -1; 54 | 55 | if ((bufsize_t)length > str_len) 56 | return -str_len; 57 | 58 | switch (length) { 59 | case 2: 60 | if ((str[1] & 0xC0) != 0x80) 61 | return -1; 62 | if (str[0] < 0xC2) { 63 | // Overlong 64 | return -length; 65 | } 66 | break; 67 | 68 | case 3: 69 | if ((str[1] & 0xC0) != 0x80) 70 | return -1; 71 | if ((str[2] & 0xC0) != 0x80) 72 | return -2; 73 | if (str[0] == 0xE0) { 74 | if (str[1] < 0xA0) { 75 | // Overlong 76 | return -length; 77 | } 78 | } else if (str[0] == 0xED) { 79 | if (str[1] >= 0xA0) { 80 | // Surrogate 81 | return -length; 82 | } 83 | } 84 | break; 85 | 86 | case 4: 87 | if ((str[1] & 0xC0) != 0x80) 88 | return -1; 89 | if ((str[2] & 0xC0) != 0x80) 90 | return -2; 91 | if ((str[3] & 0xC0) != 0x80) 92 | return -3; 93 | if (str[0] == 0xF0) { 94 | if (str[1] < 0x90) { 95 | // Overlong 96 | return -length; 97 | } 98 | } else if (str[0] >= 0xF4) { 99 | if (str[0] > 0xF4 || str[1] >= 0x90) { 100 | // Above 0x10FFFF 101 | return -length; 102 | } 103 | } 104 | break; 105 | } 106 | 107 | return length; 108 | } 109 | 110 | void cmark_utf8proc_check(cmark_strbuf *ob, const uint8_t *line, 111 | bufsize_t size) { 112 | bufsize_t i = 0; 113 | 114 | while (i < size) { 115 | bufsize_t org = i; 116 | int charlen = 0; 117 | 118 | while (i < size) { 119 | if (line[i] < 0x80 && line[i] != 0) { 120 | i++; 121 | } else if (line[i] >= 0x80) { 122 | charlen = utf8proc_valid(line + i, size - i); 123 | if (charlen < 0) { 124 | charlen = -charlen; 125 | break; 126 | } 127 | i += charlen; 128 | } else if (line[i] == 0) { 129 | // ASCII NUL is technically valid but rejected 130 | // for security reasons. 131 | charlen = 1; 132 | break; 133 | } 134 | } 135 | 136 | if (i > org) { 137 | cmark_strbuf_put(ob, line + org, i - org); 138 | } 139 | 140 | if (i >= size) { 141 | break; 142 | } else { 143 | // Invalid UTF-8 144 | encode_unknown(ob); 145 | i += charlen; 146 | } 147 | } 148 | } 149 | 150 | int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, 151 | int32_t *dst) { 152 | int length; 153 | int32_t uc = -1; 154 | 155 | *dst = -1; 156 | length = utf8proc_charlen(str, str_len); 157 | if (length < 0) 158 | return -1; 159 | 160 | switch (length) { 161 | case 1: 162 | uc = str[0]; 163 | break; 164 | case 2: 165 | uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F); 166 | if (uc < 0x80) 167 | uc = -1; 168 | break; 169 | case 3: 170 | uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6) + (str[2] & 0x3F); 171 | if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000)) 172 | uc = -1; 173 | break; 174 | case 4: 175 | uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) + 176 | ((str[2] & 0x3F) << 6) + (str[3] & 0x3F); 177 | if (uc < 0x10000 || uc >= 0x110000) 178 | uc = -1; 179 | break; 180 | } 181 | 182 | if (uc < 0) 183 | return -1; 184 | 185 | *dst = uc; 186 | return length; 187 | } 188 | 189 | void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf) { 190 | uint8_t dst[4]; 191 | bufsize_t len = 0; 192 | 193 | assert(uc >= 0); 194 | 195 | if (uc < 0x80) { 196 | dst[0] = (uint8_t)(uc); 197 | len = 1; 198 | } else if (uc < 0x800) { 199 | dst[0] = (uint8_t)(0xC0 + (uc >> 6)); 200 | dst[1] = 0x80 + (uc & 0x3F); 201 | len = 2; 202 | } else if (uc == 0xFFFF) { 203 | dst[0] = 0xFF; 204 | len = 1; 205 | } else if (uc == 0xFFFE) { 206 | dst[0] = 0xFE; 207 | len = 1; 208 | } else if (uc < 0x10000) { 209 | dst[0] = (uint8_t)(0xE0 + (uc >> 12)); 210 | dst[1] = 0x80 + ((uc >> 6) & 0x3F); 211 | dst[2] = 0x80 + (uc & 0x3F); 212 | len = 3; 213 | } else if (uc < 0x110000) { 214 | dst[0] = (uint8_t)(0xF0 + (uc >> 18)); 215 | dst[1] = 0x80 + ((uc >> 12) & 0x3F); 216 | dst[2] = 0x80 + ((uc >> 6) & 0x3F); 217 | dst[3] = 0x80 + (uc & 0x3F); 218 | len = 4; 219 | } else { 220 | encode_unknown(buf); 221 | return; 222 | } 223 | 224 | cmark_strbuf_put(buf, dst, len); 225 | } 226 | 227 | void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str, 228 | bufsize_t len) { 229 | int32_t c; 230 | 231 | #define bufpush(x) cmark_utf8proc_encode_char(x, dest) 232 | 233 | while (len > 0) { 234 | bufsize_t char_len = cmark_utf8proc_iterate(str, len, &c); 235 | 236 | if (char_len >= 0) { 237 | #include "case_fold_switch.inc" 238 | } else { 239 | encode_unknown(dest); 240 | char_len = -char_len; 241 | } 242 | 243 | str += char_len; 244 | len -= char_len; 245 | } 246 | } 247 | 248 | // matches anything in the Zs class, plus LF, CR, TAB, FF. 249 | int cmark_utf8proc_is_space(int32_t uc) { 250 | return (uc == 9 || uc == 10 || uc == 12 || uc == 13 || uc == 32 || 251 | uc == 160 || uc == 5760 || (uc >= 8192 && uc <= 8202) || uc == 8239 || 252 | uc == 8287 || uc == 12288); 253 | } 254 | 255 | // matches anything in the P[cdefios] classes. 256 | int cmark_utf8proc_is_punctuation(int32_t uc) { 257 | return ( 258 | (uc < 128 && cmark_ispunct((char)uc)) || uc == 161 || uc == 167 || 259 | uc == 171 || uc == 182 || uc == 183 || uc == 187 || uc == 191 || 260 | uc == 894 || uc == 903 || (uc >= 1370 && uc <= 1375) || uc == 1417 || 261 | uc == 1418 || uc == 1470 || uc == 1472 || uc == 1475 || uc == 1478 || 262 | uc == 1523 || uc == 1524 || uc == 1545 || uc == 1546 || uc == 1548 || 263 | uc == 1549 || uc == 1563 || uc == 1566 || uc == 1567 || 264 | (uc >= 1642 && uc <= 1645) || uc == 1748 || (uc >= 1792 && uc <= 1805) || 265 | (uc >= 2039 && uc <= 2041) || (uc >= 2096 && uc <= 2110) || uc == 2142 || 266 | uc == 2404 || uc == 2405 || uc == 2416 || uc == 2800 || uc == 3572 || 267 | uc == 3663 || uc == 3674 || uc == 3675 || (uc >= 3844 && uc <= 3858) || 268 | uc == 3860 || (uc >= 3898 && uc <= 3901) || uc == 3973 || 269 | (uc >= 4048 && uc <= 4052) || uc == 4057 || uc == 4058 || 270 | (uc >= 4170 && uc <= 4175) || uc == 4347 || (uc >= 4960 && uc <= 4968) || 271 | uc == 5120 || uc == 5741 || uc == 5742 || uc == 5787 || uc == 5788 || 272 | (uc >= 5867 && uc <= 5869) || uc == 5941 || uc == 5942 || 273 | (uc >= 6100 && uc <= 6102) || (uc >= 6104 && uc <= 6106) || 274 | (uc >= 6144 && uc <= 6154) || uc == 6468 || uc == 6469 || uc == 6686 || 275 | uc == 6687 || (uc >= 6816 && uc <= 6822) || (uc >= 6824 && uc <= 6829) || 276 | (uc >= 7002 && uc <= 7008) || (uc >= 7164 && uc <= 7167) || 277 | (uc >= 7227 && uc <= 7231) || uc == 7294 || uc == 7295 || 278 | (uc >= 7360 && uc <= 7367) || uc == 7379 || (uc >= 8208 && uc <= 8231) || 279 | (uc >= 8240 && uc <= 8259) || (uc >= 8261 && uc <= 8273) || 280 | (uc >= 8275 && uc <= 8286) || uc == 8317 || uc == 8318 || uc == 8333 || 281 | uc == 8334 || (uc >= 8968 && uc <= 8971) || uc == 9001 || uc == 9002 || 282 | (uc >= 10088 && uc <= 10101) || uc == 10181 || uc == 10182 || 283 | (uc >= 10214 && uc <= 10223) || (uc >= 10627 && uc <= 10648) || 284 | (uc >= 10712 && uc <= 10715) || uc == 10748 || uc == 10749 || 285 | (uc >= 11513 && uc <= 11516) || uc == 11518 || uc == 11519 || 286 | uc == 11632 || (uc >= 11776 && uc <= 11822) || 287 | (uc >= 11824 && uc <= 11842) || (uc >= 12289 && uc <= 12291) || 288 | (uc >= 12296 && uc <= 12305) || (uc >= 12308 && uc <= 12319) || 289 | uc == 12336 || uc == 12349 || uc == 12448 || uc == 12539 || uc == 42238 || 290 | uc == 42239 || (uc >= 42509 && uc <= 42511) || uc == 42611 || 291 | uc == 42622 || (uc >= 42738 && uc <= 42743) || 292 | (uc >= 43124 && uc <= 43127) || uc == 43214 || uc == 43215 || 293 | (uc >= 43256 && uc <= 43258) || uc == 43310 || uc == 43311 || 294 | uc == 43359 || (uc >= 43457 && uc <= 43469) || uc == 43486 || 295 | uc == 43487 || (uc >= 43612 && uc <= 43615) || uc == 43742 || 296 | uc == 43743 || uc == 43760 || uc == 43761 || uc == 44011 || uc == 64830 || 297 | uc == 64831 || (uc >= 65040 && uc <= 65049) || 298 | (uc >= 65072 && uc <= 65106) || (uc >= 65108 && uc <= 65121) || 299 | uc == 65123 || uc == 65128 || uc == 65130 || uc == 65131 || 300 | (uc >= 65281 && uc <= 65283) || (uc >= 65285 && uc <= 65290) || 301 | (uc >= 65292 && uc <= 65295) || uc == 65306 || uc == 65307 || 302 | uc == 65311 || uc == 65312 || (uc >= 65339 && uc <= 65341) || 303 | uc == 65343 || uc == 65371 || uc == 65373 || 304 | (uc >= 65375 && uc <= 65381) || (uc >= 65792 && uc <= 65794) || 305 | uc == 66463 || uc == 66512 || uc == 66927 || uc == 67671 || uc == 67871 || 306 | uc == 67903 || (uc >= 68176 && uc <= 68184) || uc == 68223 || 307 | (uc >= 68336 && uc <= 68342) || (uc >= 68409 && uc <= 68415) || 308 | (uc >= 68505 && uc <= 68508) || (uc >= 69703 && uc <= 69709) || 309 | uc == 69819 || uc == 69820 || (uc >= 69822 && uc <= 69825) || 310 | (uc >= 69952 && uc <= 69955) || uc == 70004 || uc == 70005 || 311 | (uc >= 70085 && uc <= 70088) || uc == 70093 || 312 | (uc >= 70200 && uc <= 70205) || uc == 70854 || 313 | (uc >= 71105 && uc <= 71113) || (uc >= 71233 && uc <= 71235) || 314 | (uc >= 74864 && uc <= 74868) || uc == 92782 || uc == 92783 || 315 | uc == 92917 || (uc >= 92983 && uc <= 92987) || uc == 92996 || 316 | uc == 113823); 317 | } 318 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/utf8.h: -------------------------------------------------------------------------------- 1 | #ifndef CMARK_UTF8_H 2 | #define CMARK_UTF8_H 3 | 4 | #include 5 | #include "buffer.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str, 12 | bufsize_t len); 13 | void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf); 14 | int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst); 15 | void cmark_utf8proc_check(cmark_strbuf *dest, const uint8_t *line, 16 | bufsize_t size); 17 | int cmark_utf8proc_is_space(int32_t uc); 18 | int cmark_utf8proc_is_punctuation(int32_t uc); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Pods/Down/Source/cmark/xml.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "config.h" 7 | #include "cmark.h" 8 | #include "node.h" 9 | #include "buffer.h" 10 | #include "houdini.h" 11 | 12 | #define BUFFER_SIZE 100 13 | 14 | // Functions to convert cmark_nodes to XML strings. 15 | 16 | static void escape_xml(cmark_strbuf *dest, const unsigned char *source, 17 | bufsize_t length) { 18 | houdini_escape_html0(dest, source, length, 0); 19 | } 20 | 21 | struct render_state { 22 | cmark_strbuf *xml; 23 | int indent; 24 | }; 25 | 26 | static CMARK_INLINE void indent(struct render_state *state) { 27 | int i; 28 | for (i = 0; i < state->indent; i++) { 29 | cmark_strbuf_putc(state->xml, ' '); 30 | } 31 | } 32 | 33 | static int S_render_node(cmark_node *node, cmark_event_type ev_type, 34 | struct render_state *state, int options) { 35 | cmark_strbuf *xml = state->xml; 36 | bool literal = false; 37 | cmark_delim_type delim; 38 | bool entering = (ev_type == CMARK_EVENT_ENTER); 39 | char buffer[BUFFER_SIZE]; 40 | 41 | if (entering) { 42 | indent(state); 43 | cmark_strbuf_putc(xml, '<'); 44 | cmark_strbuf_puts(xml, cmark_node_get_type_string(node)); 45 | 46 | if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) { 47 | snprintf(buffer, BUFFER_SIZE, " sourcepos=\"%d:%d-%d:%d\"", 48 | node->start_line, node->start_column, node->end_line, 49 | node->end_column); 50 | cmark_strbuf_puts(xml, buffer); 51 | } 52 | 53 | literal = false; 54 | 55 | switch (node->type) { 56 | case CMARK_NODE_DOCUMENT: 57 | cmark_strbuf_puts(xml, " xmlns=\"http://commonmark.org/xml/1.0\""); 58 | break; 59 | case CMARK_NODE_TEXT: 60 | case CMARK_NODE_CODE: 61 | case CMARK_NODE_HTML_BLOCK: 62 | case CMARK_NODE_HTML_INLINE: 63 | cmark_strbuf_puts(xml, ">"); 64 | escape_xml(xml, node->as.literal.data, node->as.literal.len); 65 | cmark_strbuf_puts(xml, "as.heading.level); 95 | cmark_strbuf_puts(xml, buffer); 96 | break; 97 | case CMARK_NODE_CODE_BLOCK: 98 | if (node->as.code.info.len > 0) { 99 | cmark_strbuf_puts(xml, " info=\""); 100 | escape_xml(xml, node->as.code.info.data, node->as.code.info.len); 101 | cmark_strbuf_putc(xml, '"'); 102 | } 103 | cmark_strbuf_puts(xml, ">"); 104 | escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len); 105 | cmark_strbuf_puts(xml, "as.custom.on_enter.data, 113 | node->as.custom.on_enter.len); 114 | cmark_strbuf_putc(xml, '"'); 115 | cmark_strbuf_puts(xml, " on_exit=\""); 116 | escape_xml(xml, node->as.custom.on_exit.data, 117 | node->as.custom.on_exit.len); 118 | cmark_strbuf_putc(xml, '"'); 119 | break; 120 | case CMARK_NODE_LINK: 121 | case CMARK_NODE_IMAGE: 122 | cmark_strbuf_puts(xml, " destination=\""); 123 | escape_xml(xml, node->as.link.url.data, node->as.link.url.len); 124 | cmark_strbuf_putc(xml, '"'); 125 | cmark_strbuf_puts(xml, " title=\""); 126 | escape_xml(xml, node->as.link.title.data, node->as.link.title.len); 127 | cmark_strbuf_putc(xml, '"'); 128 | break; 129 | default: 130 | break; 131 | } 132 | if (node->first_child) { 133 | state->indent += 2; 134 | } else if (!literal) { 135 | cmark_strbuf_puts(xml, " /"); 136 | } 137 | cmark_strbuf_puts(xml, ">\n"); 138 | 139 | } else if (node->first_child) { 140 | state->indent -= 2; 141 | indent(state); 142 | cmark_strbuf_puts(xml, "\n"); 145 | } 146 | 147 | return 1; 148 | } 149 | 150 | char *cmark_render_xml(cmark_node *root, int options) { 151 | char *result; 152 | cmark_strbuf xml = GH_BUF_INIT; 153 | cmark_event_type ev_type; 154 | cmark_node *cur; 155 | struct render_state state = {&xml, 0}; 156 | 157 | cmark_iter *iter = cmark_iter_new(root); 158 | 159 | cmark_strbuf_puts(state.xml, "\n"); 160 | cmark_strbuf_puts(state.xml, 161 | "\n"); 162 | while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { 163 | cur = cmark_iter_get_node(iter); 164 | S_render_node(cur, ev_type, &state, options); 165 | } 166 | result = (char *)cmark_strbuf_detach(&xml); 167 | 168 | cmark_iter_free(iter); 169 | return result; 170 | } 171 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Down (0.3.4) 3 | 4 | DEPENDENCIES: 5 | - Down 6 | 7 | SPEC CHECKSUMS: 8 | Down: 3f35b61e51a603df3e9e7e0289b15752e72f82e6 9 | 10 | PODFILE CHECKSUM: 390b72be4a2772d690fda4f93f87102e224636f9 11 | 12 | COCOAPODS: 1.3.1 13 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/Luka.xcuserdatad/xcschemes/Down.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/Luka.xcuserdatad/xcschemes/Pods-markr.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 68 | 69 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/Luka.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Down.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 0 13 | 14 | Pods-Markr.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 1 20 | 21 | 22 | SuppressBuildableAutocreation 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/Down-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Down : NSObject 3 | @end 4 | @implementation PodsDummy_Down 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/Down-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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/Down-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 | #import "Down.h" 14 | 15 | FOUNDATION_EXPORT double DownVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char DownVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/Down.modulemap: -------------------------------------------------------------------------------- 1 | framework module Down { 2 | umbrella header "Down-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/Down.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Down 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}/Down 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | SWIFT_INCLUDE_PATHS = $(SRCROOT)/Down/Source/cmark/** 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Down/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 | 0.3.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Markr/Pods-Markr.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CODE_SIGN_IDENTITY = 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Down" 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/Down/Down.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Down" 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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Markr/Pods-Markr.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CODE_SIGN_IDENTITY = 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Down" 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/Down/Down.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Down" 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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Down 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2016 Rob Phillips. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | Generated by CocoaPods - https://cocoapods.org 28 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-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 | The MIT License (MIT) 18 | 19 | Copyright (c) 2016 Rob Phillips. 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in 29 | all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. 38 | License 39 | MIT 40 | Title 41 | Down 42 | Type 43 | PSGroupSpecifier 44 | 45 | 46 | FooterText 47 | Generated by CocoaPods - https://cocoapods.org 48 | Title 49 | 50 | Type 51 | PSGroupSpecifier 52 | 53 | 54 | StringsTable 55 | Acknowledgements 56 | Title 57 | Acknowledgements 58 | 59 | 60 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Markr : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Markr 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-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}/Down/Down.framework" 106 | fi 107 | if [[ "$CONFIGURATION" == "Release" ]]; then 108 | install_framework "${BUILT_PRODUCTS_DIR}/Down/Down.framework" 109 | fi 110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 111 | wait 112 | fi 113 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr-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_MarkrVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_MarkrVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-markr/Pods-markr.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Markr { 2 | umbrella header "Pods-Markr-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Markr 2 | 3 | ![Github All Releases](https://img.shields.io/github/downloads/lukakerr/markr/total.svg) 4 | 5 | **Also check out [Twig](https://github.com/lukakerr/twig), a modern MacOS markdown editor and the successor to Markr** 6 | 7 | Markr is a minimal, lightweight MacOS desktop application for markdown editing. 8 | 9 | Simply start typing and immediately see rendered markdown. 10 | 11 | ### Features 12 | - Split panels 13 | - No delay in rendering markdown 14 | - Change font-size and font of editor 15 | - Minimal, lightweight and easy to use 16 | - Dark and light modes 17 | - Word count 18 | 19 | ### Screenshots 20 | 21 |
22 | markr 23 |
24 |

25 |
26 | markr-2 27 |
28 | -------------------------------------------------------------------------------- /markr.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /markr.xcworkspace/xcuserdata/Luka.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukakerr/markr/286b2779ababb2a9e8e36fecab9b0f48154a43f6/markr.xcworkspace/xcuserdata/Luka.xcuserdatad/UserInterfaceState.xcuserstate --------------------------------------------------------------------------------