diff --git a/README.md b/README.md index 1c69e956..b95e5b9f 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,18 @@ struct SimpleView: ContextualTemplate { } ``` +Note: You can also use `+` or in most cases `,` to concat multiple elements. Eg: +```swift +// Using `+` +div.child( + "Some text " + variable(\.name) + p.child("View More") +) + +// Using `,` +div.child( + "Some text ", variable(\.name), p.child("View More") +) +``` ### Now how do we render the views? @@ -154,8 +166,10 @@ struct SomeView: ContextualTemplate { runtimeIf( \.values.count > 0, - forEach(in: \.values, - render: SimpleView()) + forEach( + in: \.values, + render: SimpleView() + ) ).else( p.child( "There is no values!" diff --git a/Sources/HTMLKit/CompiledTemplate.swift b/Sources/HTMLKit/CompiledTemplate.swift index f569fed9..0e1e8b28 100644 --- a/Sources/HTMLKit/CompiledTemplate.swift +++ b/Sources/HTMLKit/CompiledTemplate.swift @@ -128,3 +128,22 @@ extension UUID: CompiledTemplate { formula.add(string: self.uuidString) } } + + +/// Concats two values +public func + (lhs: CompiledTemplate, rhs: CompiledTemplate) -> CompiledTemplate { + var output: Array = [] + + if let list = lhs as? Array { + output.append(contentsOf: list) + } else { + output.append(lhs) + } + + if let list = rhs as? Array { + output.append(list) + } else { + output.append(rhs) + } + return output +} diff --git a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/AttributeNode+CompiledTemplate.swift b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/AttributeNode+CompiledTemplate.swift index e5f493d8..3439813f 100644 --- a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/AttributeNode+CompiledTemplate.swift +++ b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/AttributeNode+CompiledTemplate.swift @@ -21,6 +21,15 @@ extension HTML.AttributeNode: CompiledTemplate { } } +extension HTML.AttributeNode: CustomDebugStringConvertible { + public var debugDescription: String { + if let value = value { + return "Tag: \(attribute), Value: \(value)" + } + return "Tag: " + attribute + } +} + extension HTML.AttributeNode { // MARK: - Non HTML standard diff --git a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/ContentNode+CompiledTemplate.swift b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/ContentNode+CompiledTemplate.swift index 69cf82c5..74b304c0 100644 --- a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/ContentNode+CompiledTemplate.swift +++ b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/ContentNode+CompiledTemplate.swift @@ -73,3 +73,9 @@ extension HTML.ContentNode: AttributableNode, DynamicAttributable { return .init(name: name, attributes: attributes, content: content, dynamicAttributes: [dynamicAttributes, ifCondition]) } } + +extension HTML.ContentNode: CustomDebugStringConvertible { + public var debugDescription: String { + return "Tag: \(name), Attributes: \(attributes), Content: \(content)" + } +} diff --git a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/Variable+CompiledTemplate.swift b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/Variable+CompiledTemplate.swift index b28a001d..7ccea1f0 100644 --- a/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/Variable+CompiledTemplate.swift +++ b/Sources/HTMLKit/CompiledTemplate/HTML+CompiledTemplate/Variable+CompiledTemplate.swift @@ -30,6 +30,13 @@ extension TemplateVariable: CompiledTemplate { } } +extension TemplateVariable: CustomDebugStringConvertible { + public var debugDescription: String { + return "Variable: \(referance), escaping: \(escaping)" + } +} + + extension ContextualTemplate { /// References an optional variable in the `Context` type diff --git a/Sources/HTMLKit/HTML.swift b/Sources/HTMLKit/HTML.swift index 520589fc..c892d53c 100644 --- a/Sources/HTMLKit/HTML.swift +++ b/Sources/HTMLKit/HTML.swift @@ -4,9 +4,16 @@ import Foundation /// /// - unsafeNone: No escaping. This will render the variable as given /// - safeHTML: This will escape characters that may cause security problems -public enum EscapingOption { +public enum EscapingOption: CustomDebugStringConvertible { case unsafeNone case safeHTML + + public var debugDescription: String { + switch self { + case .unsafeNone: return "Unsafe" + case .safeHTML: return "Safe" + } + } } enum ContextReferance where T : ContextualTemplate { diff --git a/Sources/HTMLKit/HTMLKitProvider.swift b/Sources/HTMLKit/HTMLKitProvider.swift index 2184cd19..0eed5cad 100644 --- a/Sources/HTMLKit/HTMLKitProvider.swift +++ b/Sources/HTMLKit/HTMLKitProvider.swift @@ -5,7 +5,6 @@ // Created by Mats Mollestad on 11/03/2019. // -#if canImport(Service) import Service extension HTMLRenderer: Service {} @@ -27,4 +26,3 @@ public final class HTMLKitProvider: Provider { return .done(on: container) } } -#endif diff --git a/Sources/HTMLKit/Localize.swift b/Sources/HTMLKit/Localize.swift index 646dbb1a..7db9c0db 100644 --- a/Sources/HTMLKit/Localize.swift +++ b/Sources/HTMLKit/Localize.swift @@ -8,12 +8,19 @@ import Lingo import Foundation +/// A compiled template that returnes a localized string struct Localize: CompiledTemplate { + /// The key/text to localize let key: String + + /// The path to the local let localePath: KeyPath + + /// The path to the content needed to render the string, if needed let contentPath: KeyPath? + // View `CompiledTempalte` func render(with manager: HTMLRenderer.ContextManager) throws -> String { let locale = try manager.value(at: localePath) @@ -31,6 +38,7 @@ struct Localize: CompiledTemplate { } } + // View `Brewable` func brew(_ formula: HTMLRenderer.Formula) throws where T : ContextualTemplate { formula.add(mappable: self) } diff --git a/Sources/HTMLKit/Markdown.swift b/Sources/HTMLKit/Markdown.swift index 47531386..1c87e046 100644 --- a/Sources/HTMLKit/Markdown.swift +++ b/Sources/HTMLKit/Markdown.swift @@ -7,15 +7,21 @@ import SwiftMarkdown +/// A compiled template that converts markdown to html struct Markdown: CompiledTemplate { + /// The markdown to convert let markdown: CompiledTemplate + + /// The rendering options let options: MarkdownOptions + // View `Brewable` func brew(_ formula: HTMLRenderer.Formula) throws where T : ContextualTemplate { formula.add(mappable: self) } + // View `CompiledTemplate` func render(with manager: HTMLRenderer.ContextManager) throws -> String { return try markdownToHTML(markdown.render(with: manager), options: options) } diff --git a/Tests/HTMLKitTests/HTMLKitTests.swift b/Tests/HTMLKitTests/HTMLKitTests.swift index 4b030a15..26db8ea4 100644 --- a/Tests/HTMLKitTests/HTMLKitTests.swift +++ b/Tests/HTMLKitTests/HTMLKitTests.swift @@ -12,7 +12,7 @@ final class HTMLKitTests: XCTestCase { try! FileManager().createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) try! HTMLKitTests.enLocalizations.write(toFile: path + "/en.json", atomically: true, encoding: .utf8) - try! HTMLKitTests.noLocalizations.write(toFile: path + "/no.json", atomically: true, encoding: .utf8) + try! HTMLKitTests.nbLocalizations.write(toFile: path + "/nb.json", atomically: true, encoding: .utf8) var renderer = HTMLRenderer() @@ -48,7 +48,7 @@ final class HTMLKitTests: XCTestCase { let twoDynamic = try renderer.renderRaw(DynamicAttribute.self, with: .init(isChecked: true, isActive: true, isOptional: false)) let markdown = try renderer.renderRaw(MarkdownView.self, with: .init(title: "Hello", description: "World")) let english = try renderer.renderRaw(LocalizedView.self, with: .init(local: "en", description: .init(numberTest: 1))) - let norwegian = try renderer.renderRaw(LocalizedView.self, with: .init(local: "no", description: .init(numberTest: 2))) + let norwegian = try renderer.renderRaw(LocalizedView.self, with: .init(local: "nb", description: .init(numberTest: 2))) let simpleRender = try renderer.renderRaw(SimpleView.self) let chainedRender = try renderer.renderRaw(ChainedEqualAttributes.self) @@ -87,7 +87,7 @@ final class HTMLKitTests: XCTestCase { """ } - private static var noLocalizations: String { + private static var nbLocalizations: String { return """ { "hello.world": "Hei Verden!", diff --git a/Tests/HTMLKitTests/HTMLTestDocuments.swift b/Tests/HTMLKitTests/HTMLTestDocuments.swift index d352e25d..bd569d8a 100644 --- a/Tests/HTMLKitTests/HTMLTestDocuments.swift +++ b/Tests/HTMLKitTests/HTMLTestDocuments.swift @@ -31,10 +31,10 @@ struct StaticEmbedView: ContextualTemplate { func build() -> CompiledTemplate { return div.child( - SimpleView(), + SimpleView() + p.child( variable(\.string) - ), + ) + runtimeIf( \.int != nil, @@ -44,13 +44,6 @@ struct StaticEmbedView: ContextualTemplate { ) ) ) -// div( -// SimpleView.build(), -// p( variable(\.string)), -// runtimeIf(\.int != nil, -// small( variable(\.int)) -// ) -// ) } } @@ -77,12 +70,6 @@ struct BaseView: ContextualTemplate { // Used to check for an error ocurring when embedding two different `ContextualTemplate`s and a `localFormula` is involved runtimeIf(\.title == "May Cause an error when embedding multiple views", div) ) -// html( -// head( -// title(variable(\.title)) -// ), -// body(context.body) -// ) } } @@ -153,7 +140,7 @@ struct IFView: ContextualTemplate { \.name == "Mats", p.child( - "My name is: ", variable(\.name), "!" + "My name is: " + variable(\.name) + "!" ) ), @@ -178,25 +165,6 @@ struct IFView: ContextualTemplate { ) ) -// div( -// runtimeIf(\.name == "Mats", -// p("My name is: ", variable(\.name), "!") -// ), -// -// runtimeIf(\.age < 20, -// "I am a child" -// ).elseIf(\.age > 20, -// "I am older" -// ).else(render: -// "I am growing" -// ), -// -// runtimeIf(\.nullable != nil, -// b( variable(\.nullable)) -// ).elseIf(\.bool, -// p("Simple bool") -// ) -// ) } }