diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 8c50098..0000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -3.1 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..d1f1d28 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,3 @@ +included: + - Sources + - Tests diff --git a/.travis.yml b/.travis.yml index 87e058b..99e1887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ language: generic sudo: required dist: trusty -osx_image: xcode9 +osx_image: xcode9.4 before_install: - if [ $TRAVIS_OS_NAME == "osx" ]; then - HOMEBREW_NO_AUTO_UPDATE=1 brew install vapor/tap/vapor; + brew install vapor/tap/vapor; else eval "$(curl -sL https://apt.vapor.sh)"; sudo apt-get install vapor; @@ -19,13 +19,6 @@ script: - swift build - swift build -c release - swift test - - if [ $TRAVIS_OS_NAME != "osx" ]; then - sudo apt-get remove vapor; - sudo apt-get install swift=3.1.1; - swift build; - swift build -c release; - swift test; - fi after_success: - eval "$(curl -sL https://raw.githubusercontent.com/vapor-community/swift/swift-4-codecov/codecov-swift4)" diff --git a/Package.swift b/Package.swift index b72764e..0553068 100644 --- a/Package.swift +++ b/Package.swift @@ -1,10 +1,19 @@ +// swift-tools-version:4.0 + import PackageDescription let package = Package( - name: "MarkdownProvider", + name: "LeafMarkdown", + products: [ + .library(name: "LeafMarkdown", targets: ["LeafMarkdown"]), + ], dependencies: [ - .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 2), - .Package(url: "https://github.com/vapor/leaf-provider.git", majorVersion: 1), - .Package(url: "https://github.com/vapor-community/markdown.git", majorVersion: 0) + .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), + .package(url: "https://github.com/vapor/leaf.git", from: "3.0.0"), + .package(url: "https://github.com/vapor-community/markdown.git", .upToNextMajor(from: "0.4.0")), + ], + targets: [ + .target(name: "LeafMarkdown", dependencies: ["Vapor", "Leaf", "SwiftMarkdown"]), + .testTarget(name: "LeafMarkdownTests", dependencies: ["LeafMarkdown"]), ] ) diff --git a/Package@swift-4.swift b/Package@swift-4.swift deleted file mode 100644 index 383d279..0000000 --- a/Package@swift-4.swift +++ /dev/null @@ -1,19 +0,0 @@ -// swift-tools-version:4.0 - -import PackageDescription - -let package = Package( - name: "MarkdownProvider", - products: [ - .library(name: "MarkdownProvider", targets: ["MarkdownProvider"]), - ], - dependencies: [ - .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "2.1.0")), - .package(url: "https://github.com/vapor/leaf-provider.git", .upToNextMajor(from: "1.0.0")), - .package(url: "https://github.com/vapor-community/markdown.git", .upToNextMajor(from: "0.4.0")), - ], - targets: [ - .target(name: "MarkdownProvider", dependencies: ["Vapor", "LeafProvider", "SwiftMarkdown"]), - .testTarget(name: "MarkdownProviderTests", dependencies: ["MarkdownProvider"]), - ] -) diff --git a/README.md b/README.md index cb6916e..8c6b8d3 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# Markdown Provider +# Leaf Markdown [![Language](https://img.shields.io/badge/Swift-4-brightgreen.svg)](http://swift.org) -[![Build Status](https://travis-ci.org/vapor-community/markdown-provider.svg?branch=master)](https://travis-ci.org/vapor-community/markdown-provider) -[![codecov](https://codecov.io/gh/vapor-community/markdown-provider/branch/master/graph/badge.svg)](https://codecov.io/gh/vapor-community/mmarkdown-provider) -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/vapor-community/markdown-provider/master/LICENSE) +[![Build Status](https://travis-ci.org/vapor-community/leaf-markdown.svg?branch=master)](https://travis-ci.org/vapor-community/leaf-markdown) +[![codecov](https://codecov.io/gh/vapor-community/leaf-markdown/branch/master/graph/badge.svg)](https://codecov.io/gh/vapor-community/leaf-markdown) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/vapor-community/leaf-markdown/master/LICENSE) -A Markdown renderer for Vapor and Leaf. This uses the [Vapor Markdown](https://github.com/vapor/markdown) package to wrap [cmark](https://github.com/jgm/cmark) (though a [fork](https://github.com/brokenhandsio/cmark-gfm) is used to make it work with Swift PM), so it understands [Common Mark](http://commonmark.org). A quick reference guide for Common Mark can be found [here](http://commonmark.org/help/). It also support [Github Flavored Markdown](https://guides.github.com/features/mastering-markdown/) +A Markdown renderer for Vapor and Leaf. This uses the [Vapor Markdown](https://github.com/vapor/markdown) package to wrap [cmark](https://github.com/jgm/cmark) (though a [fork](https://github.com/brokenhandsio/cmark-gfm) is used to make it work with Swift PM), so it understands [Common Mark](http://commonmark.org). A quick reference guide for Common Mark can be found [here](http://commonmark.org/help/). It also supports [Github Flavored Markdown](https://guides.github.com/features/mastering-markdown/). -## Use +## Usage Once set up, you can use it in your Leaf template files like any other tag: @@ -27,34 +27,26 @@ Check out my *awesome* markdown! It is easy to use in `tags` ### Add as dependency -Add Markdown Provider as a dependency in your `Package.swift` file: +Add Leaf Markdown as a dependency in your `Package.swift` file: ```swift dependencies: [ ..., - .package(url: "https://github.com/vapor-community/markdown-provider.git", .upToNextMajor(from: "1.1.0")) + .package(url: "https://github.com/vapor-community/leaf-markdown.git", .upToNextMajor(from: "2.0.0")) ] ``` -### Add the Provider - -You can add a provider to you `Config`, which will do all of the setup for you and register your tag. Just add it as so: - -```swift -let config = try Config() -try config.addProvider(MarkdownProvider.Provider.self) -let drop = try Droplet(config) -``` - - ### Register with Leaf -Alternatively, you can also directly add the Tag onto your `LeafRenderer` if desired. During your setup (for example, in `Droplet+Setup.swift`), register your tag as so: +To add the tag to Leaf, add it to your `LeafTagConfig`: ```swift -if let leaf = drop.view as? LeafRenderer { - leaf.stem.register(Markdown()) -} +try services.register(LeafProvider()) +var tags = LeafTagConfig.default() +tags.use(Markdown(), as: "markdown") +services.register(tags) ``` -Don't forget to import MarkdownProvider in the file you register the tag or add the provider in with `import MarkdownProvider` +**Note:** it's important that you register the `LeafProvider` first otherwise this will override your `LeafTagConfig`. + +Don't forget to import LeafMarkdown in the file you register the tag with `import LeafMarkdown`. diff --git a/Sources/LeafMarkdown/Tag.swift b/Sources/LeafMarkdown/Tag.swift new file mode 100644 index 0000000..b5c3004 --- /dev/null +++ b/Sources/LeafMarkdown/Tag.swift @@ -0,0 +1,33 @@ +import Leaf +import SwiftMarkdown +import Async + +public final class Markdown: TagRenderer { + + public enum Error: Swift.Error { + case invalidArgument(TemplateData?) + } + + public let name = "markdown" + + public init() {} + + public func render(tag: TagContext) throws -> Future { + + var markdown = "" + + if let markdownArgument = tag.parameters.first, !markdownArgument.isNull { + guard let markdownArgumentValue = markdownArgument.string else { + throw Error.invalidArgument(tag.parameters.first) + } + markdown = markdownArgumentValue + } + + let markdownHTML = try markdownToHTML(markdown) + + return Future.map(on: tag) { + .string(markdownHTML) + } + } + +} diff --git a/Sources/MarkdownProvider/Provider.swift b/Sources/MarkdownProvider/Provider.swift deleted file mode 100644 index 7894cbe..0000000 --- a/Sources/MarkdownProvider/Provider.swift +++ /dev/null @@ -1,21 +0,0 @@ -import Vapor -import LeafProvider - -public struct Provider: Vapor.Provider { - - public static let repositoryName = "markdown-provider" - - public func boot(_ drop: Droplet) { - guard let renderer = drop.view as? LeafRenderer else { - print("Markdown Provider only supports Leaf as a renderer") - return - } - - renderer.stem.register(Markdown()) - } - - public init(config: Config) throws {} - public init() {} - public func boot(_ config: Config) throws {} - public func beforeRun(_: Vapor.Droplet) {} -} diff --git a/Sources/MarkdownProvider/Tag.swift b/Sources/MarkdownProvider/Tag.swift deleted file mode 100644 index 1ae7e2f..0000000 --- a/Sources/MarkdownProvider/Tag.swift +++ /dev/null @@ -1,33 +0,0 @@ -import Leaf -import SwiftMarkdown - -public final class Markdown: Tag { - - public enum Error: Swift.Error { - case invalidArgument(Argument?) - } - - public init() { } - - public let name = "markdown" - - public func shouldRender(stem: Stem, context: Context, tagTemplate: TagTemplate, arguments: [Argument], value: Node?) -> Bool{ - return true - } - - public func run(tagTemplate: TagTemplate, arguments: ArgumentList) throws -> Node? { - var markdown = "" - - if let markdownArgument = arguments.first { - guard let markdownArgumentValue = markdownArgument.string else { - throw Error.invalidArgument(arguments.list.first) - } - markdown = markdownArgumentValue - } - - let markdownHtml = try markdownToHTML(markdown) - let unescaped = markdownHtml.bytes - return .bytes(unescaped) - } - -} diff --git a/Tests/LeafMarkdownTests/LeafTests.swift b/Tests/LeafMarkdownTests/LeafTests.swift new file mode 100644 index 0000000..c41daae --- /dev/null +++ b/Tests/LeafMarkdownTests/LeafTests.swift @@ -0,0 +1,44 @@ +import XCTest +import Vapor + +@testable import Leaf +import LeafMarkdown + +class LeafTests: XCTestCase { + static var allTests = [ + ("testRunTag", testRunTag), + ("testNilParameterDoesNotCrashLeaf", testNilParameterDoesNotCrashLeaf) + ] + + var renderer: LeafRenderer! + let template = "#markdown(data)" + + override func setUp() { + let queue = EmbeddedEventLoop() + let container = BasicContainer(config: .init(), environment: .testing, services: .init(), on: queue) + let tag = Markdown() + var leafTagConfig = LeafTagConfig.default() + leafTagConfig.use(tag, as: tag.name) + self.renderer = LeafRenderer(config: LeafConfig(tags: leafTagConfig, viewsDir: "", shouldCache: false), + using: container) + } + + func testRunTag() throws { + let inputMarkdown = "# This is a test\n\nWe have some text in a tag" + let data = TemplateData.dictionary(["data": .string(inputMarkdown)]) + let expectedHtml = "

This is a test

\n

We have some text in a tag

\n" + + let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() + let resultString = String(data: result.data, encoding: .utf8)! + XCTAssertEqual(resultString, expectedHtml) + } + + func testNilParameterDoesNotCrashLeaf() throws { + let data = TemplateData.dictionary(["data": .null]) + let expectedHtml = "" + + let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() + let resultString = String(data: result.data, encoding: .utf8)! + XCTAssertEqual(resultString, expectedHtml) + } +} diff --git a/Tests/LeafMarkdownTests/ServicesTests.swift b/Tests/LeafMarkdownTests/ServicesTests.swift new file mode 100644 index 0000000..a5b40f7 --- /dev/null +++ b/Tests/LeafMarkdownTests/ServicesTests.swift @@ -0,0 +1,23 @@ +import XCTest +import Vapor +import Leaf + +import LeafMarkdown + +class ServicesTests: XCTestCase { + static var allTests = [ + ("testTagsCanBeAddedToServices", testTagsCanBeAddedToServices) + ] + + func testTagsCanBeAddedToServices() throws { + var services = Services.default() + try services.register(LeafProvider()) + var tags = LeafTagConfig.default() + tags.use(Markdown(), as: "markdown") + services.register(tags) + let app = try Application(services: services) + let renderer = try app.make(LeafRenderer.self) + + XCTAssertNotNil(renderer.tags[Markdown().name]) + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index c456759..6f98444 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,8 +1,8 @@ import XCTest -@testable import MarkdownProviderTests +@testable import LeafMarkdownTests XCTMain([ testCase(LeafTests.allTests), - testCase(ProviderTests.allTests) + testCase(ServicesTests.allTests) ]) diff --git a/Tests/MarkdownProviderTests/LeafTests.swift b/Tests/MarkdownProviderTests/LeafTests.swift deleted file mode 100644 index b2e5488..0000000 --- a/Tests/MarkdownProviderTests/LeafTests.swift +++ /dev/null @@ -1,51 +0,0 @@ -import XCTest -import Vapor - -@testable import Leaf -@testable import MarkdownProvider - -class LeafTests: XCTestCase { - static var allTests = [ - ("testRunTag", testRunTag), - ("testNilParameterDoesNotCrashLeaf", testNilParameterDoesNotCrashLeaf), - ] - - func testRunTag() { - let tag = Markdown() - let inputMarkdown = "# This is a test\n\nWe have some text in a tag" - let expectedHtml = "

This is a test

\n

We have some text in a tag

\n" - - do { - let node = try run(tag: tag, context: inputMarkdown.makeNode(in: nil), arguments: [.constant(Leaf(raw: inputMarkdown, components: [.raw(inputMarkdown.makeBytes())]))]) - XCTAssertEqual(node?.string, expectedHtml) - } - catch { - XCTFail() - } - } - - func testNilParameterDoesNotCrashLeaf() { - let tag = Markdown() - let expectedHtml = "" - - do { - let node = try run(tag: tag, context: nil, arguments: []) - XCTAssertEqual(node?.string, expectedHtml) - } - catch { - XCTFail("Markdown Tag threw exception") - } - } -} - -extension LeafTests { - func run(tag: Tag, context node: Node, arguments: [Argument]) throws -> Node? { - let context = Context(node) - let argumentList = ArgumentList(list: arguments, stem: Stem(DataFile(workDir: "")), context: context) - - return try tag.run( - tagTemplate: TagTemplate(name: "", parameters: [], body: nil), - arguments: argumentList - ) - } -} diff --git a/Tests/MarkdownProviderTests/ProviderTests.swift b/Tests/MarkdownProviderTests/ProviderTests.swift deleted file mode 100644 index 9b1a7c5..0000000 --- a/Tests/MarkdownProviderTests/ProviderTests.swift +++ /dev/null @@ -1,35 +0,0 @@ -import XCTest -import Vapor -import LeafProvider - -@testable import MarkdownProvider - -class ProviderTests: XCTestCase { - static var allTests = [ - ("testProviderCreation", testProviderAddsTagToLeaf), - ("testProviderGracefullyHandlesNonLeafRenderer", testProviderGracefullyHandlesNonLeafRenderer) - ] - - func testProviderAddsTagToLeaf() throws { - var config = Config([:]) - try config.set("droplet.view", "leaf") - try config.addProvider(LeafProvider.Provider.self) - let drop = try Droplet(config) - let leafProvider = MarkdownProvider.Provider() - leafProvider.boot(drop) - - guard let leaf = drop.view as? LeafRenderer else { - XCTFail() - return - } - - XCTAssertNotNil(leaf.stem.tags[Markdown().name]) - } - - func testProviderGracefullyHandlesNonLeafRenderer() throws { - let drop = try Droplet() - let leafProvider = MarkdownProvider.Provider() - leafProvider.boot(drop) - XCTAssert(true, "We should reach this point") - } -}