Skip to content

Commit f98464d

Browse files
authored
Fix some logic and logistics (#103)
* Revise some of the vapor provider * Rename the vapor provider The target within the package might get in a naming conflict with the other vapor provider package. As long the other package is not archived, renaming it, prevents the conflict and secures the back compatibility. * Add support for localization to the provider again * Revise the vapor provider * Add a test for the environment modifier * Update the readme file * Fix the components plugin
1 parent 52ede3f commit f98464d

File tree

17 files changed

+500
-384
lines changed

17 files changed

+500
-384
lines changed

Package.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let package = Package(
1010
products: [
1111
.library(
1212
name: "HTMLKit",
13-
targets: ["HTMLKit", "HTMLKitComponents", "HTMLKitVaporProvider"]
13+
targets: ["HTMLKit", "HTMLKitComponents", "HTMLKitVapor"]
1414
),
1515
.plugin(
1616
name: "ComponentsPlugin",
@@ -51,10 +51,11 @@ let package = Package(
5151
]
5252
),
5353
.target(
54-
name: "HTMLKitVaporProvider",
54+
name: "HTMLKitVapor",
5555
dependencies: [
5656
.target(name: "HTMLKit"),
57-
.product(name: "Vapor", package: "vapor")
57+
.product(name: "Vapor", package: "vapor"),
58+
.product(name: "Lingo", package: "lingo")
5859
]
5960
),
6061
.testTarget(
@@ -83,11 +84,14 @@ let package = Package(
8384
]
8485
),
8586
.testTarget(
86-
name: "HTMLKitVaporProviderTests",
87+
name: "HTMLKitVaporTests",
8788
dependencies: [
88-
.target(name: "HTMLKitVaporProvider"),
89+
.target(name: "HTMLKitVapor"),
8990
.target(name: "HTMLKit"),
9091
.product(name: "XCTVapor", package: "vapor")
92+
],
93+
resources: [
94+
.process("Localization")
9195
]
9296
),
9397
.executableTarget(

Plugins/ComponentsPlugin/plugin.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import PackagePlugin
22
import Foundation
33

44
@main
5-
struct ConverterPlugin: CommandPlugin {
5+
struct ComponentsPlugin: CommandPlugin {
66

77
func performCommand(context: PluginContext, arguments: [String]) async throws {
88

@@ -16,6 +16,8 @@ struct ConverterPlugin: CommandPlugin {
1616

1717
let explanation = """
1818
USAGE: deploy
19+
20+
ARGUMENTS:
1921
"""
2022

2123
print(explanation)

README.md

Lines changed: 14 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,14 @@
1-
# HTMLKit
2-
3-
Render dynamic HTML templates in a typesafe and performant way! By using Swift's powerful language features and a pre-rendering algorithm, HTMLKit will render insanely fast templates but also catch bugs that otherwise might occur with other templating options.
4-
5-
## Getting Started
6-
7-
### Installation
8-
9-
Add the packages as dependecies and targets to your package file.
10-
11-
```swift
12-
/// [Package.swift]
13-
14-
...
15-
dependencies: [
16-
...
17-
///1. Add the packages
18-
.package(name: "HTMLKit", url: "https://github.com/vapor-community/HTMLKit.git", from: "2.4.5"),
19-
.package(name: "HTMLKitVaporProvider", url: "https://github.com/vapor-community/htmlkit-vapor-provider.git", from: "1.2.1")
20-
],
21-
targets: [
22-
.target(
23-
...
24-
dependencies: [
25-
...
26-
/// 2. Add the products
27-
.product(name: "HTMLKit", package: "HTMLKit"),
28-
.product(name: "HTMLKitVaporProvider", package: "HTMLKitVaporProvider")
29-
]
30-
),
31-
...
32-
```
33-
34-
Read the [installation instructions](/Instructions/Installation.md) for more information.
35-
36-
### Definition
37-
38-
Create a new file in your project. Add the import at the top of your file and declare a new structure. Extend your structure by adding a [layout definition](/Instructions/Essential/Layouts.md) to adopt the required properties and methods. Add your content to the `body` property.
39-
40-
```swift
41-
/// [SimplePage.swift]
42-
43-
/// 1. Add the import
44-
import HTMLKit
45-
46-
/// 2. Define a new structure
47-
struct SimplePage: Page {
48-
49-
/// 3. Add some content
50-
var body: AnyContent {
51-
Document(type: .html5)
52-
Html {
53-
Head {
54-
Title {
55-
"SimplePage"
56-
}
57-
}
58-
Body {
59-
Paragraph {
60-
"Hello World!"
61-
}
62-
}
63-
}
64-
}
65-
}
66-
```
67-
68-
### Implementation
69-
70-
Call the structure you have created in your controller handler and use the render method to render the view for the request.
71-
72-
```swift
73-
/// [SimpleController.swift]
74-
75-
...
76-
final class SimpleController {
77-
...
78-
func getPage(req: Request) throws -> EventLoopFuture<View> {
79-
/// 1. Call the structure
80-
return SimplePage().render(for: req)
81-
}
82-
...
83-
}
84-
```
85-
86-
## Features
87-
88-
### Localization
89-
90-
HTMLKit offers localization by the help of the [Lingo framework](https://github.com/miroslavkovac/Lingo.git). See the [instructions](/Instructions/Features/Localization.md) for more information.
91-
92-
### Conversion
93-
94-
You dont have to rewrite your whole codebase to use HTMLKit. HTMLKit offers a converter to translate HTML into HTMLKit. See the [instructions](/Instructions/Features/Conversion.md) for more information.
95-
96-
### Validation
97-
98-
HTMLKit is build with the intention to lead you writing valid code. So you don't need to think about it in particular.
99-
100-
## Resources
101-
102-
### Instructions
103-
104-
See the [instructions](/Instructions/Overview.md) to learn more about the package and the features.
105-
106-
### Components
107-
108-
See the [package](https://github.com/vapor-community/HTMLKit-Components) to extend your experience with HTMLKit. The package is still work in progress, but
109-
it will be available soon.
110-
111-
### Live Example
112-
113-
See the [package](https://github.com/mattesmohr/Website) of our contributor, how he uses HTMLKit in his website.
1+
<div align="center">
2+
<img src="https://avatars.githubusercontent.com/u/26165732?s=200&v=4" width="100" height="100" alt="avatar" />
3+
<h1/>HTMLKit</h1>
4+
<p>Render dynamic HTML templates in a typesafe and performant way! By using Swift's powerful language features and a pre-rendering algorithm, HTMLKit will render insanely fast templates but also catch bugs that otherwise might occur with other templating options.</p>
5+
<a href="https://swiftpackageindex.com/vapor-community/htmlkit/documentation">
6+
<img src="https://img.shields.io/badge/Documentation-17.10.2022-red" alt="documentation" />
7+
</a>
8+
<a href="https://swiftpackageindex.com/vapor-community/HTMLKit">
9+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fvapor-community%2FHTMLKit%2Fbadge%3Ftype%3Dswift-versions" alt="versions" />
10+
</a>
11+
<a href="https://swiftpackageindex.com/vapor-community/HTMLKit">
12+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fvapor-community%2FHTMLKit%2Fbadge%3Ftype%3Dplatforms" alt="platforms" />
13+
</a>
14+
</div>

Sources/Commands/Components/DeployCommand.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ internal struct DeployCommand {
2424
.appendingPathComponent("Resources", isDirectory: true)
2525

2626
let distributionFile = URL(fileURLWithPath: targetPath)
27-
.appendingPathComponent("Public")
27+
.appendingPathComponent("Public", isDirectory: true)
28+
.appendingPathComponent("HtmlKit", isDirectory: true)
2829
.appendingPathComponent("css")
2930
.appendingPathComponent("all")
3031
.appendingPathExtension("css")

Sources/HTMLKit/Framework/Environment/EnvironmentModifier.swift renamed to Sources/HTMLKit/Framework/Environment/Localization/EnvironmentModifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/// The modifier is for
77
///
88
///
9-
public struct EnvironmentModifier: AnyContent {
9+
public struct EnvironmentModifier: GlobalElement {
1010

1111
public let view: AnyContent
1212

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
Abstract:
3+
The file contains the extensions of some Vapor directives.
4+
*/
5+
6+
import HTMLKit
7+
import Vapor
8+
9+
extension Application.Views.Provider {
10+
11+
/// Access to the view renderer
12+
public static var htmlkit: Self {
13+
return .init {
14+
$0.views.use {
15+
$0.htmlkit.renderer
16+
}
17+
}
18+
}
19+
}
20+
21+
extension Application {
22+
23+
/// Access to the vapor provider
24+
public var htmlkit: HtmlKit {
25+
return .init(application: self)
26+
}
27+
28+
/// The vapor provider
29+
public struct HtmlKit {
30+
31+
internal struct CacheStorageKey: StorageKey {
32+
33+
public typealias Value = ViewCache
34+
}
35+
36+
/// The view cache
37+
public var views: ViewCache {
38+
39+
if let cache = self.application.storage[CacheStorageKey.self] {
40+
return cache
41+
}
42+
43+
let cache = ViewCache()
44+
45+
self.application.storage[CacheStorageKey.self] = cache
46+
47+
return cache
48+
}
49+
50+
internal struct LingoStorageKey: StorageKey {
51+
52+
public typealias Value = LingoConfiguration
53+
}
54+
55+
/// The view localization
56+
public var lingo: LingoConfiguration {
57+
58+
if let configuration = self.application.storage[LingoStorageKey.self] {
59+
return configuration
60+
}
61+
62+
let configuration = LingoConfiguration()
63+
64+
self.application.storage[LingoStorageKey.self] = configuration
65+
66+
return configuration
67+
}
68+
69+
/// The view renderer
70+
internal var renderer: ViewRenderer {
71+
return .init(eventLoop: self.application.eventLoopGroup.next(), cache: self.views, lingo: lingo)
72+
}
73+
74+
/// The application dependency
75+
public let application: Application
76+
77+
/// Creates the provider
78+
public init(application: Application) {
79+
80+
self.application = application
81+
}
82+
}
83+
}
84+
85+
extension Request {
86+
87+
/// Access to the view renderer
88+
public var htmlkit: ViewRenderer {
89+
return .init(eventLoop: self.eventLoop, cache: self.application.htmlkit.views, lingo: self.application.htmlkit.lingo)
90+
}
91+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Abstract:
3+
The file contains the configuration for Lingo.
4+
*/
5+
6+
import Foundation
7+
8+
/// The localization
9+
public class LingoConfiguration {
10+
11+
/// A enumeration of possible locale identifier
12+
public enum Locale: String {
13+
14+
case arabic = "ar"
15+
case english = "en"
16+
case french = "fr"
17+
case german = "de"
18+
case hindi = "es"
19+
case bengali = "bn"
20+
case russian = "ru"
21+
case portuguese = "pt"
22+
case indonesian = "id"
23+
}
24+
25+
/// The root path
26+
internal var defaultDirectory: String
27+
28+
/// The locale indentifier
29+
internal var defaultLocale: String
30+
31+
/// Creates a configuration
32+
internal init() {
33+
34+
self.defaultDirectory = "Resources/Localization"
35+
self.defaultLocale = "en"
36+
}
37+
38+
/// Sets the root path
39+
public func set(directory: URL) {
40+
self.defaultDirectory = directory.path
41+
}
42+
43+
/// Sets the default locale indentifier
44+
public func set(locale: Locale) {
45+
self.defaultLocale = locale.rawValue
46+
}
47+
}

Sources/HTMLKitVapor/ViewCache.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
Abstract:
3+
The file contains the cache of the Vapor renderer.
4+
*/
5+
6+
import HTMLKit
7+
import Vapor
8+
9+
/// The cache
10+
public class ViewCache {
11+
12+
/// The cache storage
13+
internal var storage: [String: HTMLKit.Formula]
14+
15+
/// Creates the cache
16+
internal init() {
17+
self.storage = [:]
18+
}
19+
20+
/// Retrieves a formula from the storage
21+
internal func retrieve(name: String, on loop: EventLoop) -> EventLoopFuture<HTMLKit.Formula?> {
22+
23+
if let cache = self.storage[name] {
24+
return loop.makeSucceededFuture(cache)
25+
26+
} else {
27+
return loop.makeSucceededFuture(nil)
28+
}
29+
}
30+
31+
/// Sets or updates a formula at the storage
32+
internal func upsert(name: String, formula: HTMLKit.Formula) {
33+
self.storage.updateValue(formula, forKey: name)
34+
}
35+
36+
/// Removes a formula from the storage
37+
internal func remove(name: String) {
38+
self.storage.removeValue(forKey: name)
39+
}
40+
41+
/// Adds a view to the storage
42+
public func add<T: HTMLKit.AnyLayout>(view: T) {
43+
44+
let formula = HTMLKit.Formula()
45+
46+
try? view.prerender(formula)
47+
48+
self.storage.updateValue(formula, forKey: String(reflecting: T.self))
49+
}
50+
}

0 commit comments

Comments
 (0)