Skip to content

Commit

Permalink
Prepare for release (#145)
Browse files Browse the repository at this point in the history
* Make the features flag available to vapor

* Tidy up a bit

* Silence deprecation warning of nsdictionary

* Update readme

* Silence warning of shadowing type parameters
  • Loading branch information
mattesmohr authored Feb 20, 2024
1 parent cb34198 commit 57ec613
Show file tree
Hide file tree
Showing 14 changed files with 195 additions and 144 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ The HTMLKit framework consists of a list of features to create HTML templates in
- **UI components** - Construct user interfaces with the components library.
- **Symbol bundle** - Use the symbols which come within the framework.

The framework comes with an integration for the web framework [Vapor](https://swiftpackageindex.com/vapor/vapor). Interested? Lets get started: [Tutorials](https://swiftpackageindex.com/vapor-community/HTMLKit/3.0.0-alpha.8/documentation/htmlkit)
The framework comes with an integration for the web framework [Vapor](https://github.com/vapor/vapor). Interested? Lets get started: [Tutorials](https://swiftpackageindex.com/vapor-community/htmlkit/main/tutorials/introduction)
14 changes: 7 additions & 7 deletions Sources/HTMLKit/Framework/Environment/EnvironmentObject.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import Foundation

/// A property wrapper type to initate an environment object
@frozen @propertyWrapper public struct EnvironmentObject<Value> {
@frozen @propertyWrapper public struct EnvironmentObject<ObjectType> {

/// The wrapped value
public var wrappedValue: Wrapper<Value>
public var wrappedValue: Wrapper<ObjectType>

/// Converts the type into the wrapped value
public init(_ type: Value.Type) {
public init(_ type: ObjectType.Type) {

self.wrappedValue = .init()
}

/// A type, that holds the environment object informationen
@dynamicMemberLookup public struct Wrapper<Value> {
@dynamicMemberLookup public struct Wrapper<WrapperType> {

/// The path of the parent
internal var parent: AnyKeyPath?
Expand All @@ -24,7 +24,7 @@ import Foundation
/// Initiates a wrapper
public init() {

self.path = \Value.self
self.path = \WrapperType.self
}

/// Initiates a wrapper with the necessary information for the environment object
Expand All @@ -35,7 +35,7 @@ import Foundation
}

/// Looks up for a containing property
public subscript<T>(dynamicMember member: KeyPath<Value, T>) -> EnvironmentValue {
public subscript<T>(dynamicMember member: KeyPath<WrapperType, T>) -> EnvironmentValue {

guard let newPath = self.path.appending(path: member) else {
fatalError()
Expand All @@ -49,7 +49,7 @@ import Foundation
}

/// Looks up for a containing model
public subscript<T>(dynamicMember member: KeyPath<Value, T>) -> Wrapper<T> where T: ViewModel {
public subscript<T>(dynamicMember member: KeyPath<WrapperType, T>) -> Wrapper<T> where T: ViewModel {

guard let newPath = self.path.appending(path: member) else {
fatalError()
Expand Down
15 changes: 11 additions & 4 deletions Sources/HTMLKit/Framework/Localization/Localization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Localization {
case missingTables
case unkownTable
case noFallback
case loadingDataFailed

public var description: String {

Expand All @@ -30,6 +31,9 @@ public class Localization {

case .noFallback:
return "The fallback needs to be set up first."

case .loadingDataFailed:
return "Unable to load data."
}
}
}
Expand Down Expand Up @@ -81,11 +85,14 @@ public class Localization {

if var translationTables = localizationTables[locale] {

if let translations = NSDictionary(contentsOf: path) as? [String: String] {
translationTables.append(TranslationTable(name: path.deletingPathExtension().lastPathComponent, translations: translations))
if let data = try? Foundation.Data(contentsOf: path) {

if let translations = try? PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil) as? [String: String] {
translationTables.append(TranslationTable(name: path.deletingPathExtension().lastPathComponent, translations: translations))
}

localizationTables[locale] = translationTables
}

localizationTables[locale] = translationTables
}
}

Expand Down
11 changes: 11 additions & 0 deletions Sources/HTMLKit/Framework/Rendering/Features.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// An option set of features.
public struct Features: OptionSet {

public var rawValue: Int

public static let markdown = Features(rawValue: 1 << 0)

public init(rawValue: Int) {
self.rawValue = rawValue
}
}
14 changes: 0 additions & 14 deletions Sources/HTMLKit/Framework/Rendering/Renderer+FeatureSet.swift

This file was deleted.

100 changes: 49 additions & 51 deletions Sources/HTMLKit/Framework/Rendering/Renderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@
import Foundation
import OrderedCollections

/// A struct containing the different formulas for the different views.
@_documentation(visibility: internal)
public class Renderer {
public final class Renderer {

/// A enumeration of possible render errors
/// An enumeration of possible rendering errors.
public enum Errors: Error {

/// Indicates a casting error.
case unableToCastEnvironmentValue

/// Indicates a wrong environment key.
case unindendedEnvironmentKey

/// Indicates a missing environment object.
case environmentObjectNotFound

/// Indicates a missing environment value.
case environmentValueNotFound

/// Indicates a missing localization configuration.
case missingLocalization

/// A brief error description.
public var description: String {

switch self {
Expand All @@ -40,47 +49,35 @@ public class Renderer {
}
}

/// The context environment
private var environment: Environment

/// The localization configuration
private var localization: Localization?

/// The security configuration
private var security: Security

/// The markdown parser
private var markdown: Markdown

public var features: FeatureSet
/// The feature flag used to manage the visibility of new and untested features.
private var features: Features

/// Initiates the renderer.
public init(localization: Localization? = nil) {

self.localization = localization
self.environment = Environment()
self.security = Security()
self.markdown = Markdown()
self.features = []
}

/// Initiates the renderer.
public init(localization: Localization? = nil, security: Security) {

self.localization = localization
self.environment = Environment()
self.security = security
self.markdown = Markdown()
self.features = []
}

/// Initiates the renderer.
public init(localization: Localization? = nil, environment: Environment, security: Security) {
public init(localization: Localization? = nil,
environment: Environment = Environment(),
security: Security = Security(),
features: Features = []) {

self.localization = localization
self.environment = environment
self.security = security
self.markdown = Markdown()
self.features = []
self.features = features
}

/// Renders a view
/// Renders a view and transforms it into a string representation.
public func render(view: some View) throws -> String {

var result = ""
Expand All @@ -92,7 +89,8 @@ public class Renderer {
return result
}

internal func render(contents: [Content]) throws -> String {
/// Reads the view content and transforms it.
private func render(contents: [Content]) throws -> String {

var result = ""

Expand Down Expand Up @@ -156,8 +154,8 @@ public class Renderer {
return result
}

/// Renders a content element
internal func render(element: some ContentNode) throws -> String {
/// Renders a content element. A content element usually has descendants, which need to be rendered as well.
private func render(element: some ContentNode) throws -> String {

var result = ""

Expand Down Expand Up @@ -234,8 +232,8 @@ public class Renderer {
return result
}

/// Renders a empty element
internal func render(element: some EmptyNode) throws -> String {
/// Renders a empty element. An empty element has no descendants.
private func render(element: some EmptyNode) throws -> String {

var result = ""

Expand All @@ -250,11 +248,11 @@ public class Renderer {
return result
}

/// Renders a document element
internal func render(element: some DocumentNode) -> String {
/// Renders a document element. The document element holds the metadata.
private func render(element: some DocumentNode) -> String {

var result = ""

result += "<!DOCTYPE "

result += element.content
Expand All @@ -264,8 +262,8 @@ public class Renderer {
return result
}

/// Renders a comment element
internal func render(element: some CommentNode) -> String {
/// Renders a comment element.
private func render(element: some CommentNode) -> String {

var result = ""

Expand All @@ -278,8 +276,8 @@ public class Renderer {
return result
}

/// Renders a content element
internal func render(element: some CustomNode) throws -> String {
/// Renders a custom element.
private func render(element: some CustomNode) throws -> String {

var result = ""

Expand Down Expand Up @@ -352,8 +350,8 @@ public class Renderer {
return result
}

/// Renders a localized string key
internal func render(stringkey: LocalizedStringKey) throws -> String {
/// Renders a localized string key.
private func render(stringkey: LocalizedStringKey) throws -> String {

guard let localization = self.localization else {
throw Errors.missingLocalization
Expand All @@ -366,8 +364,8 @@ public class Renderer {
return try localization.localize(key: stringkey.key, locale: environment.locale, interpolation: stringkey.interpolation)
}

/// Renders a environment modifier
internal func render(modifier: EnvironmentModifier) throws -> String {
/// Renders a environment modifier.
private func render(modifier: EnvironmentModifier) throws -> String {

if let value = modifier.value {
self.environment.upsert(value, for: modifier.key)
Expand Down Expand Up @@ -401,8 +399,8 @@ public class Renderer {
return try render(contents: modifier.content)
}

/// Renders a environment value
internal func render(value: EnvironmentValue) throws -> String {
/// Renders a environment value.
private func render(value: EnvironmentValue) throws -> String {

guard let parent = self.environment.retrieve(for: value.parentPath) else {
throw Errors.environmentObjectNotFound
Expand Down Expand Up @@ -439,8 +437,8 @@ public class Renderer {
}
}

/// Renders the node attributes
internal func render(attributes: OrderedDictionary<String, Any>) throws -> String {
/// Renders the node attributes.
private func render(attributes: OrderedDictionary<String, Any>) throws -> String {

var result = ""

Expand All @@ -461,13 +459,13 @@ public class Renderer {
return result
}

/// Renders the markdown content
internal func render(markdown: MarkdownString) throws -> String {
/// Renders the markdown content.
private func render(markdown: MarkdownString) throws -> String {
return self.markdown.render(string: escape(content: markdown.raw))
}

/// Converts specific charaters into encoded values.
internal func escape(attribute value: String) -> String {
private func escape(attribute value: String) -> String {

if security.autoEscaping {
return value.replacingOccurrences(of: "&", with: "&amp;")
Expand All @@ -479,7 +477,7 @@ public class Renderer {
}

/// Converts specific charaters into encoded values.
internal func escape(content value: String) -> String {
private func escape(content value: String) -> String {

if security.autoEscaping {
return value.replacingOccurrences(of: "<", with: "&lt;")
Expand Down
2 changes: 1 addition & 1 deletion Sources/HTMLKit/Framework/Security/Security.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public class Security {
public final class Security {

public var autoEscaping: Bool

Expand Down
26 changes: 26 additions & 0 deletions Sources/HTMLKitVapor/Configuration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import HTMLKit

/// Holds the renderer configuration
public final class Configuration {

/// Holds the localization configuration
internal var localization: HTMLKit.Localization

/// Holds the environment configuration
internal var environment: HTMLKit.Environment

/// Holds the security configuration
internal var security: HTMLKit.Security

/// Holds the enabled features
internal var features: HTMLKit.Features

/// Creates a configuration
public init() {

self.localization = Localization()
self.environment = Environment()
self.security = Security()
self.features = []
}
}
Loading

0 comments on commit 57ec613

Please sign in to comment.