Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b79f8a0a50 | |||
| 31d0ead0d7 | |||
| bb22b86c8f | |||
| a8186a3d82 | |||
| 01858a2277 | |||
| 9c28de3237 | |||
| afbcee0ac4 |
+3
-2
@@ -1,16 +1,17 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Down"
|
||||
spec.summary = "Blazing fast Markdown rendering in Swift, built upon cmark."
|
||||
spec.version = "0.1"
|
||||
spec.version = "0.2"
|
||||
spec.homepage = "https://github.com/iwasrobbed/Down"
|
||||
spec.license = { :type => "MIT", :file => "LICENSE" }
|
||||
spec.authors = { "Rob Phillips" => "rob@desideratalabs.co" }
|
||||
spec.source = { :git => "https://github.com/iwasrobbed/Down.git", :tag => "v" + spec.version.to_s }
|
||||
spec.source_files = "Source/**/*"
|
||||
spec.public_header_files = "Source/*.h"
|
||||
spec.platform = :ios, "9.0"
|
||||
spec.platform = :ios, "8.0"
|
||||
spec.requires_arc = true
|
||||
spec.module_name = "Down"
|
||||
spec.preserve_path = 'Source/cmark/module.modulemap'
|
||||
spec.pod_target_xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(SRCROOT)/Down/Source/cmark/**' }
|
||||
spec.resource = 'Resources/DownView.bundle'
|
||||
end
|
||||
@@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D41689B31CFFE28200E5802B /* DownViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41689B21CFFE28200E5802B /* DownViewTests.swift */; };
|
||||
D41689B61CFFE6BB00E5802B /* DownView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D41689B51CFFE6BB00E5802B /* DownView.bundle */; };
|
||||
D4201E8B1CFA5151008EEC6E /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4201E801CFA5151008EEC6E /* Down.framework */; };
|
||||
D4201EEF1CFA59AD008EEC6E /* BindingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4201EC51CFA59A5008EEC6E /* BindingTests.swift */; };
|
||||
D4201EF11CFA59F2008EEC6E /* Down.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4201EF01CFA59F2008EEC6E /* Down.swift */; };
|
||||
@@ -47,6 +49,9 @@
|
||||
D4201F431CFA5D63008EEC6E /* utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F1C1CFA5D63008EEC6E /* utf8.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
||||
D4201F441CFA5D63008EEC6E /* utf8.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F1D1CFA5D63008EEC6E /* utf8.h */; };
|
||||
D4201F451CFA5D63008EEC6E /* xml.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F1E1CFA5D63008EEC6E /* xml.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
||||
D43AE5CA1CFFAE4D006E1522 /* NSAttributedString+HTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43AE5C91CFFAE4D006E1522 /* NSAttributedString+HTML.swift */; };
|
||||
D43AE5DA1CFFD0D0006E1522 /* DownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43AE5D91CFFD0D0006E1522 /* DownView.swift */; };
|
||||
D43AE5DC1CFFD473006E1522 /* String+ToHTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43AE5DB1CFFD473006E1522 /* String+ToHTML.swift */; };
|
||||
D44875E41CFA6B200037A624 /* DownRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44875E31CFA6B200037A624 /* DownRenderable.swift */; };
|
||||
D44875E61CFA6B660037A624 /* DownHTMLRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44875E51CFA6B660037A624 /* DownHTMLRenderable.swift */; };
|
||||
D44875EA1CFA6CF30037A624 /* DownErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44875E81CFA6CF30037A624 /* DownErrors.swift */; };
|
||||
@@ -55,6 +60,7 @@
|
||||
D486E9961CFDD4860059FD7C /* DownASTRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D486E9951CFDD4860059FD7C /* DownASTRenderable.swift */; };
|
||||
D486E9981CFDE2730059FD7C /* DownLaTeXRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D486E9971CFDE2730059FD7C /* DownLaTeXRenderable.swift */; };
|
||||
D486E99A1CFDE28B0059FD7C /* DownGroffRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D486E9991CFDE28B0059FD7C /* DownGroffRenderable.swift */; };
|
||||
D4CF88981CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CF88971CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift */; };
|
||||
D4DC91141CFDED4B0091CE09 /* DownCommonMarkRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DC91131CFDED4B0091CE09 /* DownCommonMarkRenderable.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -69,6 +75,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D41689B21CFFE28200E5802B /* DownViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownViewTests.swift; sourceTree = "<group>"; };
|
||||
D41689B51CFFE6BB00E5802B /* DownView.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = DownView.bundle; sourceTree = "<group>"; };
|
||||
D4201E801CFA5151008EEC6E /* Down.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Down.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D4201E8A1CFA5151008EEC6E /* DownTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DownTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D4201E9A1CFA59A5008EEC6E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@@ -112,6 +120,9 @@
|
||||
D4201F1D1CFA5D63008EEC6E /* utf8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utf8.h; sourceTree = "<group>"; };
|
||||
D4201F1E1CFA5D63008EEC6E /* xml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xml.c; sourceTree = "<group>"; };
|
||||
D42869501CFF501200FACB4C /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D43AE5C91CFFAE4D006E1522 /* NSAttributedString+HTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+HTML.swift"; sourceTree = "<group>"; };
|
||||
D43AE5D91CFFD0D0006E1522 /* DownView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownView.swift; sourceTree = "<group>"; };
|
||||
D43AE5DB1CFFD473006E1522 /* String+ToHTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+ToHTML.swift"; sourceTree = "<group>"; };
|
||||
D44875E31CFA6B200037A624 /* DownRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownRenderable.swift; sourceTree = "<group>"; };
|
||||
D44875E51CFA6B660037A624 /* DownHTMLRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownHTMLRenderable.swift; sourceTree = "<group>"; };
|
||||
D44875E81CFA6CF30037A624 /* DownErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownErrors.swift; sourceTree = "<group>"; };
|
||||
@@ -121,6 +132,7 @@
|
||||
D486E9971CFDE2730059FD7C /* DownLaTeXRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownLaTeXRenderable.swift; sourceTree = "<group>"; };
|
||||
D486E9991CFDE28B0059FD7C /* DownGroffRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownGroffRenderable.swift; sourceTree = "<group>"; };
|
||||
D4CF88961CFF94B300F07FD1 /* Down.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Down.h; sourceTree = "<group>"; };
|
||||
D4CF88971CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownAttributedStringRenderable.swift; sourceTree = "<group>"; };
|
||||
D4DC91131CFDED4B0091CE09 /* DownCommonMarkRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownCommonMarkRenderable.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -143,11 +155,20 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D41689B41CFFE6BB00E5802B /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D41689B51CFFE6BB00E5802B /* DownView.bundle */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D4201E761CFA5151008EEC6E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D4201E9A1CFA59A5008EEC6E /* Info.plist */,
|
||||
D4201E9B1CFA59A5008EEC6E /* Source */,
|
||||
D41689B41CFFE6BB00E5802B /* Resources */,
|
||||
D4201EC41CFA59A5008EEC6E /* Tests */,
|
||||
D4201E811CFA5151008EEC6E /* Products */,
|
||||
);
|
||||
@@ -168,7 +189,9 @@
|
||||
D4CF88961CFF94B300F07FD1 /* Down.h */,
|
||||
D4201EF01CFA59F2008EEC6E /* Down.swift */,
|
||||
D44875E71CFA6CF30037A624 /* Enums & Options */,
|
||||
D43AE5C81CFFAE39006E1522 /* Extensions */,
|
||||
D44875E21CFA6B120037A624 /* Renderers */,
|
||||
D43AE5CB1CFFD068006E1522 /* Views */,
|
||||
D4201EF61CFA5D63008EEC6E /* cmark */,
|
||||
);
|
||||
path = Source;
|
||||
@@ -178,6 +201,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D4201EC51CFA59A5008EEC6E /* BindingTests.swift */,
|
||||
D41689B21CFFE28200E5802B /* DownViewTests.swift */,
|
||||
);
|
||||
path = Tests;
|
||||
sourceTree = "<group>";
|
||||
@@ -227,10 +251,28 @@
|
||||
path = cmark;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D43AE5C81CFFAE39006E1522 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D43AE5C91CFFAE4D006E1522 /* NSAttributedString+HTML.swift */,
|
||||
D43AE5DB1CFFD473006E1522 /* String+ToHTML.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D43AE5CB1CFFD068006E1522 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D43AE5D91CFFD0D0006E1522 /* DownView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D44875E21CFA6B120037A624 /* Renderers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D486E9951CFDD4860059FD7C /* DownASTRenderable.swift */,
|
||||
D4CF88971CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift */,
|
||||
D4DC91131CFDED4B0091CE09 /* DownCommonMarkRenderable.swift */,
|
||||
D486E9991CFDE28B0059FD7C /* DownGroffRenderable.swift */,
|
||||
D44875E51CFA6B660037A624 /* DownHTMLRenderable.swift */,
|
||||
@@ -358,6 +400,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D41689B61CFFE6BB00E5802B /* DownView.bundle in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -379,11 +422,14 @@
|
||||
D486E9941CFDD33C0059FD7C /* DownXMLRenderable.swift in Sources */,
|
||||
D4201F361CFA5D63008EEC6E /* iterator.c in Sources */,
|
||||
D4201F391CFA5D63008EEC6E /* man.c in Sources */,
|
||||
D4CF88981CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift in Sources */,
|
||||
D4201F3D1CFA5D63008EEC6E /* references.c in Sources */,
|
||||
D43AE5DC1CFFD473006E1522 /* String+ToHTML.swift in Sources */,
|
||||
D4201F301CFA5D63008EEC6E /* houdini_html_e.c in Sources */,
|
||||
D4201F3F1CFA5D63008EEC6E /* render.c in Sources */,
|
||||
D486E9981CFDE2730059FD7C /* DownLaTeXRenderable.swift in Sources */,
|
||||
D4201F2A1CFA5D63008EEC6E /* commonmark.c in Sources */,
|
||||
D43AE5CA1CFFAE4D006E1522 /* NSAttributedString+HTML.swift in Sources */,
|
||||
D4201EF11CFA59F2008EEC6E /* Down.swift in Sources */,
|
||||
D4201F2F1CFA5D63008EEC6E /* houdini_href_e.c in Sources */,
|
||||
D4201F451CFA5D63008EEC6E /* xml.c in Sources */,
|
||||
@@ -393,6 +439,7 @@
|
||||
D4201F201CFA5D63008EEC6E /* buffer.c in Sources */,
|
||||
D4201F431CFA5D63008EEC6E /* utf8.c in Sources */,
|
||||
D4DC91141CFDED4B0091CE09 /* DownCommonMarkRenderable.swift in Sources */,
|
||||
D43AE5DA1CFFD0D0006E1522 /* DownView.swift in Sources */,
|
||||
D4201F411CFA5D63008EEC6E /* scanners.c in Sources */,
|
||||
D4201F381CFA5D63008EEC6E /* latex.c in Sources */,
|
||||
D4201F321CFA5D63008EEC6E /* html.c in Sources */,
|
||||
@@ -411,6 +458,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D41689B31CFFE28200E5802B /* DownViewTests.swift in Sources */,
|
||||
D4201EEF1CFA59AD008EEC6E /* BindingTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -465,7 +513,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -509,7 +557,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -24,16 +24,31 @@ pod 'Down'
|
||||
> 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).
|
||||
|
||||
### Output Formats
|
||||
* Web View (see DownView class)
|
||||
* HTML
|
||||
* XML
|
||||
* LaTeX
|
||||
* groff man
|
||||
* CommonMark Markdown
|
||||
* NSAttributedString
|
||||
* AST (abstract syntax tree)
|
||||
|
||||
### API
|
||||
### View Rendering
|
||||
|
||||
The `Down` struct has everything you need if you just want out-of-the-box setup.
|
||||
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:
|
||||
|
||||
```swift
|
||||
let downView = try? DownView(frame: self.view.bounds, markdownString: "**Oh Hai**")
|
||||
// Now add to view or constrain w/ Autolayout
|
||||
```
|
||||
|
||||
Meta example of rendering this README:
|
||||
|
||||

|
||||
|
||||
### Parsing API
|
||||
|
||||
The `Down` struct has everything you need if you just want out-of-the-box setup for parsing and conversion.
|
||||
|
||||
```swift
|
||||
let down = Down(markdownString: "## [Down](https://github.com/iwasrobbed/Down)")
|
||||
@@ -58,6 +73,10 @@ let latex = try? down.toLaTeX()
|
||||
let commonMark = try? down.toCommonMark()
|
||||
// "## [Down](https://github.com/iwasrobbed/Down)\n"
|
||||
|
||||
// Convert to an attributed string
|
||||
let attributedString = try? down.toAttributedString()
|
||||
// NSAttributedString representation of the rendered HTML
|
||||
|
||||
// Convert to abstract syntax tree
|
||||
let ast = try? down.toAST()
|
||||
// Returns pointer to AST that you can manipulate
|
||||
@@ -74,6 +93,7 @@ If you'd like more granularity for the output types you want to support, you can
|
||||
* DownGroffRenderable
|
||||
* DownCommonMarkRenderable
|
||||
* DownASTRenderable
|
||||
* DownAttributedStringRenderable
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*! 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}
|
||||
|
||||
/* Modified version of github.com/sindresorhus/github-markdown-css | MIT License */
|
||||
/* Unminify it @ unminify.com */
|
||||
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}
|
||||
|
||||
/*! highlightjs */
|
||||
.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}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=640"/>
|
||||
<link charset="utf-8" href="css/down.min.css" rel="stylesheet">
|
||||
<script charset="utf-8" src="js/highlight.min.js" type="text/javascript"></script>
|
||||
<script charset="utf-8" src="js/down.js" type="text/javascript"></script>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
DOWN_HTML
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
hljs.initHighlightingOnLoad();
|
||||
File diff suppressed because one or more lines are too long
+2
-1
@@ -9,7 +9,8 @@
|
||||
import Foundation
|
||||
|
||||
public struct Down: DownASTRenderable, DownHTMLRenderable, DownXMLRenderable,
|
||||
DownLaTeXRenderable, DownGroffRenderable, DownCommonMarkRenderable {
|
||||
DownLaTeXRenderable, DownGroffRenderable, DownCommonMarkRenderable,
|
||||
DownAttributedStringRenderable {
|
||||
/**
|
||||
A string containing CommonMark Markdown
|
||||
*/
|
||||
|
||||
@@ -18,4 +18,9 @@ public enum DownErrors: ErrorType {
|
||||
Thrown when the abstract syntax tree could not be rendered into another format
|
||||
*/
|
||||
case ASTRenderingError
|
||||
|
||||
/**
|
||||
Thrown when an HTML string cannot be converted into an `NSData` representation
|
||||
*/
|
||||
case HTMLDataConversionError
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// NSAttributedString+HTML.swift
|
||||
// Down
|
||||
//
|
||||
// Created by Rob Phillips on 6/1/16.
|
||||
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension NSAttributedString {
|
||||
|
||||
/**
|
||||
Instantiates an attributed string with the given HTML string
|
||||
|
||||
- parameter htmlString: An HTML string
|
||||
|
||||
- throws: `HTMLDataConversionError` or an instantiation error
|
||||
|
||||
- returns: An attributed string
|
||||
*/
|
||||
convenience init(htmlString: String) throws {
|
||||
guard let data = htmlString.dataUsingEncoding(NSUTF8StringEncoding) else {
|
||||
throw DownErrors.HTMLDataConversionError
|
||||
}
|
||||
|
||||
let options = [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
|
||||
NSCharacterEncodingDocumentAttribute: NSNumber(unsignedInteger:NSUTF8StringEncoding)]
|
||||
try self.init(data: data, options: options, documentAttributes: nil)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// String+ToHTML.swift
|
||||
// Down
|
||||
//
|
||||
// Created by Rob Phillips on 6/1/16.
|
||||
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import libcmark
|
||||
|
||||
extension String {
|
||||
|
||||
/**
|
||||
Generates an HTML string from the contents of the string (self), which should contain CommonMark Markdown
|
||||
|
||||
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default`
|
||||
|
||||
- throws: `DownErrors` depending on the scenario
|
||||
|
||||
- returns: HTML string
|
||||
*/
|
||||
public func toHTML(options: DownOptions = .Default) throws -> String {
|
||||
let ast = try DownASTRenderer.stringToAST(self, options: options)
|
||||
let html = try DownHTMLRenderer.astToHTML(ast, options: options)
|
||||
cmark_node_free(ast)
|
||||
return html
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// DownAttributedStringRenderable.swift
|
||||
// Down
|
||||
//
|
||||
// Created by Rob Phillips on 6/1/16.
|
||||
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import libcmark
|
||||
|
||||
public protocol DownAttributedStringRenderable: DownHTMLRenderable {
|
||||
/**
|
||||
Generates an `NSAttributedString` from the `markdownString` property
|
||||
|
||||
- parameter options: `DownOptions` to modify parsing or rendering
|
||||
|
||||
- throws: `DownErrors` depending on the scenario
|
||||
|
||||
- returns: An `NSAttributedString`
|
||||
*/
|
||||
@warn_unused_result
|
||||
func toAttributedString(options: DownOptions) throws -> NSAttributedString
|
||||
}
|
||||
|
||||
public extension DownAttributedStringRenderable {
|
||||
/**
|
||||
Generates an `NSAttributedString` from the `markdownString` property
|
||||
|
||||
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.Default`
|
||||
|
||||
- throws: `DownErrors` depending on the scenario
|
||||
|
||||
- returns: An `NSAttributedString`
|
||||
*/
|
||||
@warn_unused_result
|
||||
public func toAttributedString(options: DownOptions = .Default) throws -> NSAttributedString {
|
||||
let html = try self.toHTML(options)
|
||||
return try NSAttributedString(htmlString: html)
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,7 @@ public extension DownHTMLRenderable {
|
||||
*/
|
||||
@warn_unused_result
|
||||
public func toHTML(options: DownOptions = .Default) throws -> String {
|
||||
let ast = try DownASTRenderer.stringToAST(markdownString, options: options)
|
||||
let html = try DownHTMLRenderer.astToHTML(ast, options: options)
|
||||
cmark_node_free(ast)
|
||||
return html
|
||||
return try markdownString.toHTML(options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// DownView.swift
|
||||
// Down
|
||||
//
|
||||
// Created by Rob Phillips on 6/1/16.
|
||||
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import WebKit
|
||||
|
||||
// MARK: - Public API
|
||||
|
||||
public class DownView: WKWebView {
|
||||
|
||||
/**
|
||||
Initializes a web view with the results of rendering a CommonMark Markdown string
|
||||
|
||||
- parameter frame: The frame size of the web view
|
||||
- parameter markdownString: A string containing CommonMark Markdown
|
||||
- parameter openLinksInBrowser: Whether or not to open links using an external browser
|
||||
|
||||
- returns: An instance of Self
|
||||
*/
|
||||
@warn_unused_result
|
||||
public init(frame: CGRect, markdownString: String, openLinksInBrowser: Bool = true) throws {
|
||||
super.init(frame: frame, configuration: WKWebViewConfiguration())
|
||||
|
||||
if openLinksInBrowser { navigationDelegate = self }
|
||||
try loadHTMLView(markdownString)
|
||||
}
|
||||
|
||||
// MARK: - Private Properties
|
||||
|
||||
private let bundle: NSBundle = {
|
||||
let bundle = NSBundle(forClass: DownView.self)
|
||||
let url = bundle.URLForResource("DownView", withExtension: "bundle")!
|
||||
return NSBundle(URL: url)!
|
||||
}()
|
||||
|
||||
private lazy var baseURL: NSURL = {
|
||||
return self.bundle.URLForResource("index", withExtension: "html")!
|
||||
}()
|
||||
}
|
||||
|
||||
// MARK: - Private API
|
||||
|
||||
private extension DownView {
|
||||
|
||||
func loadHTMLView(markdownString: String) throws {
|
||||
let htmlString = try markdownString.toHTML()
|
||||
let pageHTMLString = try htmlFromTemplate(htmlString)
|
||||
loadHTMLString(pageHTMLString, baseURL: baseURL)
|
||||
}
|
||||
|
||||
func htmlFromTemplate(htmlString: String) throws -> String {
|
||||
let template = try NSString(contentsOfURL: baseURL, encoding: NSUTF8StringEncoding)
|
||||
return template.stringByReplacingOccurrencesOfString("DOWN_HTML", withString: htmlString)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - WKNavigationDelegate
|
||||
|
||||
extension DownView: WKNavigationDelegate {
|
||||
|
||||
public func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
|
||||
guard let url = navigationAction.request.URL else { return }
|
||||
|
||||
switch navigationAction.navigationType {
|
||||
case .LinkActivated:
|
||||
decisionHandler(.Cancel)
|
||||
UIApplication.sharedApplication().openURL(url)
|
||||
default:
|
||||
decisionHandler(.Allow)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
import XCTest
|
||||
@testable import Down
|
||||
|
||||
class RenderableTests: XCTestCase {
|
||||
class BindingTests: XCTestCase {
|
||||
|
||||
let down = Down(markdownString: "## [Down](https://github.com/iwasrobbed/Down)")
|
||||
|
||||
@@ -47,5 +47,11 @@ class RenderableTests: XCTestCase {
|
||||
XCTAssertNotNil(commonMark)
|
||||
XCTAssertTrue(commonMark == "## [Down](https://github.com/iwasrobbed/Down)\n")
|
||||
}
|
||||
|
||||
func testAttributedStringBindingsWork() {
|
||||
let attributedString = try? down.toAttributedString()
|
||||
XCTAssertNotNil(attributedString)
|
||||
XCTAssertTrue(attributedString!.string == "Down\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// DownViewTests.swift
|
||||
// Down
|
||||
//
|
||||
// Created by Rob Phillips on 6/1/16.
|
||||
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Down
|
||||
|
||||
class DownViewTests: XCTestCase {
|
||||
|
||||
func testInstantiation() {
|
||||
let string = "## [Down](https://github.com/iwasrobbed/Down)"
|
||||
let downView = try? DownView(frame: CGRectZero, markdownString: string)
|
||||
XCTAssertNotNil(downView)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user