Giter Club home page Giter Club logo

htmlkit's Introduction

avatar

HTMLKit

Create and render HTML templates with HTMLKit.

documentation versions platforms

The HTMLKit framework consists of a list of features to create HTML templates in a type-safe and performant way:

  • Declarative syntax - The declarative syntax helps you write valid HTML markup.
  • Template system - Scaffold your code into various, reusable views to create an entire template.
  • Dynamic context - Apply context to your template to process content dynamically.
  • Language localization - Specify the parts that should be translated or formatted for local languages and cultures.
  • 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. Interested? Lets get started: Tutorials

htmlkit's People

Contributors

b-straub avatar kaishin avatar kyle-ye avatar litso avatar matsmoll avatar mattesmohr avatar maximkrouk avatar natebird avatar renaudjenny avatar siemensikkema avatar steve-h avatar thecb4 avatar tonyarnold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

htmlkit's Issues

HTMLComponent rendered as String?

Hello
When i am trying to render a template nesting other HTML components they are rendered as String:

public struct HTMLFieldComponent: HTMLComponent {

	var content: HTML

	init(@HTMLBuilder builder: () -> HTML) {
		self.content = builder()
	}

	public var body: HTML {
		self.content
	}

}

public protocol FormFieldRepresentable {

	var html: HTMLField { get }

}

extension StringField: FormFieldRepresentable {

	...

	public var html: HTMLField {
		HTMLField {
			Label {
				self.label
			}.class("control-label").for(self.key)
			Input(type: .text, id: self.key).class("form-control")
		}
	}

}

struct CreatePage: HTMLTemplate {

	public struct Context {
		var fields: [FormFieldRepresentable]

		init(with fields: [FormFieldRepresentable]) {
			self.fields = fields
		}
	}

	@TemplateValue(Context.self)
	public var context

	public var body: HTML {
		TemplatedDocument {
			Row {
				ForEach(in: self.context.fields) { field in
					field.html
				}			
			}
		}
	}

}

Result:

<div class="row">
	"<label  >Email</label><input   >"
	"<label  >Email</label><input   >"
</div>

The components are well rendered if they are not reached from field.html but written statically.

Inline CSS?

Is there a way to add inline CSS? I am trying to send an email and it's recommended that you use inline CSS for that.

Example:

struct TemplateData {
    let title: String
}

struct SimpleTemplate: HTMLTemplate {

    @TemplateValue(TemplateData.self)
    var context

    var body: HTML {
        Document(type: .html5) {
            Head {
                Title { context.title }
                Viewport(.acordingToDevice)
            }
            Body {
                Div {
                    "My Div"
                }.color(.white)
            }.backgroundColor(.black)
        }
    }
}

Transforms to:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>$(title)</title>
</head>
<body style="background-color:black">
    <div style="color:white">My Div</div>
</body>
</html>

Roadmap for Vapor 4

According to the discussion Replacing Leaf with DSL syntax, HTMLKit might be a good DSL replacement for Leaf.

Is there a roadmap when HTMLKit will be Vapor 4 ready? Currently I‘m evaluating Vapor4/LeafKit, but the HTMLKit approach looks even more promising to me since SwiftUI skills can be reused easily. With the Bootstrap add-on usage feels even more swifty.

Deprecated documentation

Hi! 👋

I really like the implementation of HTMLKit, but it seems the documentation is kind of deprecated now.
I'm really new with Vapor and want to use this framework, but it's hard to figure out a lot of things as I can't rely on the documentation.

Is it possible to get an update in the near future?

Add a modal component

Since the tests for the interactions went well, a modal component should be possible now.

How do I add an onClick attribute to a div?

I've tried, I've searched and I can't work this out.

Nothing seems to support this:

Division {
  // Content
}
.role(.button)
.onClick("this.classList.toggle('open')")

Is this possible?

Revise the component naming

It should be possible to use the html element from HTMLKit package. Thats why its important to use a different name for the components, but still have some consistency.

Unwrap else causes both branches to be displayed

Hello,

I'm still trying to get to grips with this library, but I think I might possibly have hit a bug.

In the example below (re-structured to make it easier to reproduce), you will see that I call a route with a parameter of name which is passed as an optional String in the struct.

When I call Unwrap, I get the expected output, but in addition, I also get the output from the else branch

Screenshot 2022-11-27 at 11 50 42 AM

import Vapor
import HTMLKit
import HTMLKitVapor

struct SimpleContext: Codable {
    let name: String?
}

struct SimpleView: HTMLKit.View {
    @TemplateValue(SimpleContext.self)
    var context
    
    var body: AnyContent {
        Unwrap(context.name) { name in
            Heading1 {
                "Hello " + name + "!"
            }
        }.else {
            Heading1 {
                "Hello, World!"
            }
        }
    }
}

func routes(_ app: Application) throws {
    app.get("hello", ":name") { req async throws -> Vapor.View in
        req.application.htmlkit.views.add(view: SimpleView())
        let name = req.parameters.get("name")
        let context = SimpleContext(name: name)
        
        return try await req.view.render("App.SimpleView", context)
    }
}

"According" Typo ("Acording")

When specifying the viewport, the enum type ".acordingToDevice" is mispelled.

import HTMLKit

struct HomePage: HTMLPage {
  var body: HTML {
    Document(type: .html5) {
      Head {
        Title { "HomePage" }
        Viewport(.acordingToDevice) // Here
      }
      Body {
        NavBar()
        H1 { "Home" }
      }
    }
  }
}

Ambiguous use of 'buildBlock'

I'm seeing quite a few instances where I use an if let unwrap within the body of a View where Swift can't make up it's mind about which method to use:

For instance:

Nav {
  Anchor {  }

  if let authenticatedUser = context.authenticatedUser {
    Div {  }
  }
}

results in:

HeaderViewComponent.swift:48:74: error: ambiguous use of 'buildBlock'
                    if let authenticatedUser = context.authenticatedUser {
                                                                         ^
HTMLKit/Sources/HTMLKit/Framework/Builders/ContentBuilder.swift:41:24: note: found this candidate
    public static func buildBlock(_ components: T...) -> [T] {
                       ^
HTMLKit/Sources/HTMLKit/Framework/Builders/ContentBuilder.swift:121:24: note: found this candidate
    public static func buildBlock(_ content: [T], _ components: T...) -> [T] {

IF vs SwiftUI if

Is there any future plans of making the if statements work natively like they do with SwiftUI. And also what about support for opaque types for the body property?

I think this project has huge potential (definitely like it more than Leaf), I would like to know more about the future plans and direction, as I'm possibly interested in contributing.

Escape special characters for attributes

Currently, HTMLKit wraps any attribute with ' and does no escaping. Whenever an attribute contains ', it will be wrongly rendered.

The correct path is to use " with standardized escaping.

Extend ContentBuilder

Could we add such method to ContentBuilder so that we can have native Swift if in our contentBuilder instead of the IF statement?

@resultBuilder public class ContentBuilder<T> {
    
    public static func buildBlock() -> [T] {
        return []
    }

    public static func buildBlock(_ component: T...) -> [T] {
        return component
    }
    
    public static func buildBlock(_ component: [T]...) -> [T] {
        return component.flatMap( { $0 } )
    }
    
    // Support if
    public static func buildEither(first component: [T]) -> [T] {
        <#code#>
    }
    
    // Support if
    public static func buildEither(second component: [T]) -> [T] {
        <#code#>
    }
    // Support if #availablity
    public static func buildLimitedAvailability(_ component: [T]) -> [T] {
        <#code#>
    }
    
    // Support unwrap
    public static func buildOptional(_ component: [T]?) -> [T] {
        <#code#>
    }
}
public struct IF: GlobalElement

Provide example in the README to what to do in the controller to render something

Hi There,

I'm really sorry, but I don't understand how this framework works.
I tried to render an HTMLTemplate but firstly it's not clear to how and what you should call in your controllers.

I tried that:

    func get(req: Request) throws -> EventLoopFuture<View> {
        guard
        let groomingSessionIdString = req.parameters.get("groomingSessionID"),
        let groomingSessionId = UUID(uuidString: groomingSessionIdString)
        else {
            return req.eventLoop.makeFailedFuture(Abort(.badRequest))
        }

        return GroomingSession.query(on: req.db)
            .filter(\.$id == groomingSessionId)
            .with(\.$userStories)
            .first()
            .unwrap(or: Abort(.notFound))
            .flatMapThrowing {
                let renderer = HTMLRenderer()
                try renderer.add(view: GroomingSessionTemplate())
                let context = GroomingSessionData(groomingSession: $0)
                let data = ByteBuffer(string: try renderer.render(raw: GroomingSessionTemplate.self, with: context))
                return View(data: data)
            }
    }

And that's the closer I can get to have something rendered, but I got Grooming Session: dynamic(HTMLKit.HTMLContext) instead of the results of what I want, in this case H1 { "Grooming Session: \(context.groomingSession.name)" }, so I'm quite sure that I'm not doing this well. However there is no concrete example in the README 😞. I'm lost...

I put a comment in #21 as it's more or less related I think.

Thanks!

Unable to use IF on nested structure

Hi, I'm trying to wrap IF around a ListItem that's inside a UnorderedList inside a Form, but I keep getting this error on Form
Trailing closure passed to parameter of type '[HTMLAttribute]' that does not accept a closure

I had resorted to using css to hide stuff :(

the tags inside <head> can't be converted, because they don't have a closing tag

I get the following error

Error Domain=NSXMLParserErrorDomain Code=76 "Line 5: Opening and ending tag mismatch: meta line 4 and head
" UserInfo={NSLocalizedDescription=Line 5: Opening and ending tag mismatch: meta line 4 and head
}

example Html file content is below.
When I remove the content of the head tag, I get the parsed swift code without any problem.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
</head>
<body>
	<div class="container">
		<table class="table">
			<thead>
			  <tr>
				<th scope="col">#</th>
				<th scope="col">First</th>
				<th scope="col">Last</th>
				<th scope="col">Handle</th>
			  </tr>
			</thead>
			<tbody>
			  <tr>
				<th scope="row">1</th>
				<td>Mark</td>
				<td>Otto</td>
				<td>@mdo</td>
			  </tr>
			  <tr>
				<th scope="row">2</th>
				<td>Jacob</td>
				<td>Thornton</td>
				<td>@fat</td>
			  </tr>
			  <tr>
				<th scope="row">3</th>
				<td colspan="2">Larry the Bird</td>
				<td>@twitter</td>
			  </tr>
			</tbody>
		  </table>
	</div>
</body>
</html>

Playground code:

do {
    let path = Bundle.main.path(forResource: "ConvertUntitled", ofType: "html")!
    try Converter.default.convert(file: URL(fileURLWithPath: path), option: .print)
} catch {
    print(error)
}

renderIf(…) is ambiguous without more context

Hi, thanks for this project - it seems really promising!

I'm using HTMLKit 1.3.0 in a Vapor 3.x project.

I've hit an issue where I have a template component (my site's navigation) that I'd like to render differently depending on specific parameters, so I've created the following struct:

struct NavigationView: StaticView {
    let route: String
    let organization: Organization?

    func build() -> CompiledTemplate {
        return nav.add(.id("navigation")).child(
            ul.class("links").child(
                renderNavigationLinks()
            )
        )
    }

    func renderNavigationLinks() -> CompiledTemplate {
        return
            renderIf(\.route == "administration", administrationNavigationItems()) +
            renderIf(\.route == "organization", organizationNavigationItems()) +
            renderIf(\.route == "personal", personalNavigationItems())
    }

    func administrationNavigationItems() -> CompiledTemplate {
        // …
    }

    func organizationNavigationItems() -> CompiledTemplate {
        // …
    }

    func personalNavigationItems() -> CompiledTemplate {
        // …
    }
}

However, I then get the following error:

Type of expression is ambiguous without more context

Swift appears to be struggling to differentiate between the following two methods:

public func renderIf(_ condition: TemplateIF<Self>.Condition, _ view: CompiledTemplate...) -> TemplateIF<Self> {
condition.view = view
return TemplateIF(conditions: condition)
}

public func renderIf(_ path: KeyPath<Self.Context, Bool>, _ view: CompiledTemplate...) -> TemplateIF<Self> {
let condition = TemplateIF<Self>.Condition(condition: BoolCondition<Self>(path: path))
condition.view = view
return TemplateIF(conditions: condition)
}

Swift Updates

HTMLKit/Sources/HTMLKit/HTMLRenderer.swift:6:33: warning: using 'class' keyword to define a class-constrained protocol is deprecated; use 'AnyObject' instead
public protocol HTMLRenderable: class {
                                ^~~~~
                                AnyObject

HTMLKit/Sources/HTMLKit/View Builders/TemplateBuilder.swift:9:2: warning: '@_functionBuilder' has been renamed to '@resultBuilder'
@_functionBuilder
 ^~~~~~~~~~~~~~~~
 resultBuilder

Integrate the provider back into the main repository

Hey Mats,

would you mind, if I bring back the provider into the main repository?

  • mainly maintain towards Vapor
  • there are no other web frameworks at the moment except Vapor
  • easier for the user. The user just need to pay attention to the main repository

app.htmlkit.localization.set is getting overridden

Hi,

Even tho i'm setting the locale using app.htmlkit.localization.set(locale: "pt") I keep getting the error .missingTables because the currentLocale keeps defaulting to my browser's locale "en".

Not sure it's a bug or I'm doing something wrong 😄

Interpolating Template Values

I’m really struggling to get my head around the design of the templating system. In the following example, how do I access values from the context and use them in the template to build text content and HTML attributes?

import HTMLKitVaporProvider

struct WidgetsIndexView: View {
    typealias Context = ListWidgetsQuery.Data

    var body: AnyContent {
        BasicPage {
            Div {
                Div {
                    Heading1 {
                        Span { "Widgets" }
                            .class("text-3xl")

                        // 1. How to pull a number out of the context?
                        // - Interpolation doesn’t seem to work
                        // - String(context.widgets.count) also doesn’t work
                        Span { "\(context.widgets.count)" }
                            .class("font-mono text-slate-500 ml-auto text-3xl")
                    }
                    .class("flex")
                }

                ForEach(in: context.widgets) { widget in
                    Anchor {
                        Unwrap(widget.name) { name in
                            Span { name }
                        }

                        Span { widget.id }
                            .class("text-lg text-slate-500 ml-auto font-mono")
                    }
                    // 2. How to construct a link dynamically?
                    // - Interpolation doesn’t seem to work
                    // - Adding an extention on `TemplateValue where Value == Widget` also fails
                    .reference("/widgets\(widget.id)/")
                    .class("text-xl flex")
                }
            }
            .class("flex flex-col flex-1 gap-8 p-4 md:p-8")
        }
    }
}

Access raw value from TemplateValue

public struct ListPage<O: AnyModel, V: CustomStringConvertible>: HTMLTemplate {

	// MARK: - Context
	public struct Context {

		public var base: Template.Context

		public var objects: [O]
		public var properties: [KeyPath<O, V>]
	}

	@TemplateValue(Context.self) public var context

	// MARK: - Body
	public var body: HTML {
		Template(context: self.context.base) {
			ForEach(in: self.context.objects) { object in
				ForEach(in: self.context.properties) { property in
					P { "\(object[keyPath: property].description)" }
				}
			}
		}
	}

}

That's a really little example showing the issue I am encountering.
There is a way to unwrap values from TemplateValue ?
How my objects/properties properties from Context are TemplateValue even if I didn't flag them ?

Thx

Fix value types in converter

Currently the converter converts any value from a ValueProperty to a type of String. With the pull request #76 some of the attributes accept a different value type. Therefor the converter has to be changed.

<img> support for HTML initialiser

While I was trying out adding an image from a TemplateValue, I can't seem to find a way to initialise that easily.

Would it make sense to add an overload which would allow:

struct Movie {
    let poster: URL
}

struct MovieTemplate {
    @TemplateValue(Movie.self)
     var movie

    var body: HTML {
         Img(source: movie.poster.absoluteString)
    }
}

Additionally, was also wondering if it would make sense to haveURL conform to HTML.

Happy to contribute, but wanted to reach out first to get more context.

ForEach in StaticView

I've started spiking out using HTMLKit 2 in a Vapor 3 project, but I've hit a problem I can't figure out: how do I use ForEach(…) in a StaticView?

Given the following somewhat contrived example:

import Flash
import HTMLKit
import Vapor

struct FlashView: StaticView {
    let flashes: [Flash]

    var body: HTMLKit.View {
        return Div {
            ForEach(in: flashes) { flash in
                Div {
                    P { flash.message }
                }
                .class("message \(flash.kind)")
            }
        }
        .id("flash")
    }
}

I get the following error, pointing at the line with the ForEach(…) on it:

Generic parameter 'Root' could not be inferred

Change the symbol-component initialisation

Change or enhance the initialisation of the symbol-component so the user can use a custom path for a symbol asset or the system symbols, wich come with the package.

// the custom path needs to be set first
Symbol(custom: "house-fill")
Symbol(system: "house-fill")

Help to use your framework

Hello @MatsMoll:

I newbie with vapor and I try to use your framework but only have compilation errors, even Xcode doesn't let me build my app could you help us how use it please. Thank you. I sent you my errors...

    router.get("markdown") { req in
        return try KORVHomeTemplate().render(with: .init(title: "Home Page", author: "Raul Silva", twitter: "@raulsilvamx"))
    }

'HTMLRenderer.ContextManager' initializer is inaccessible due to 'internal' protection level

Does it support parse html node

If I could use it like, SwiftSoup, It can not use in the vapor project.
I am searching one like SwiftSoup, which can crawl some elements of html.

RawValue for optional value

The rawValue implementation is call description method

case .constant(let value): return "\(value)"
default: return ""
}

So if a TemplateValue's Value is an Optional type, it's result will surprisingly be "Optional(xx)"

A example is the following

id is UUID? type and a property in Post model
post is TemplateValue<Post> here

A { "Hello" }.id(post.id.rawValue)

This will give me "Optional(xx)" or "nil".
But what I want is "xx" or "".
However I can't do it, since I can not get a Post type or UUID? here.
All I can get is TemplateValue<Post> and TemplateValue<UUID?> and then call the rawValue method.

2.4.0 - Known issues

I use HTMLKit 2.4.0 in my projects and so far I encounter some issues. I list them here, so so you know I am aware of them and they will get fixed very soon.

The alternate attribute gets rendered as alternate="" instead of alt="".

The link element is BodyElement instead of a HeadElement. Quick workaround, till I release a fix:

extension Link: HeadElement {}

The ForEach should be a GlobalElement.

Using on Linux

I can't get the server to render the view on Linux (on a server in fly.io)
I am using the htmlkit-3.0-2 Branch

I am getting this error:

 HTMLKitComponents/resource_bundle_accessor.swift:11: Fatal error: could not load resource bundle: from /app/HTMLKit_HTMLKitComponents.resources or /build/.build/x86_64-unknown-linux-gnu/release/HTMLKit_HTMLKitComponents.resources

The full backtrace looks like this:

2023-02-10T21:04:24.423 app[d91f8cc0] lhr [info] HTMLKitComponents/resource_bundle_accessor.swift:11: Fatal error: could not load resource bundle: from /app/HTMLKit_HTMLKitComponents.resources or /build/.build/x86_64-unknown-linux-gnu/release/HTMLKit_HTMLKitComponents.resources
2023-02-10T21:04:24.424 app[d91f8cc0] lhr [info] Received signal 4. Backtrace:
2023-02-10T21:04:24.631 app[d91f8cc0] lhr [info] 0x55933a15e7c2, Backtrace.(printBacktrace in _B82A8C0ED7C904841114FDF244F9E58E)(signal: Swift.Int32) -> () at /build/.build/checkouts/swift-backtrace/Sources/Backtrace/Backtrace.swift:66
2023-02-10T21:04:24.631 app[d91f8cc0] lhr [info] 0x55933a15ea57, closure #1 (Swift.Int32) -> () in static Backtrace.Backtrace.install(signals: Swift.Array<Swift.Int32>) -> () at /build/.build/checkouts/swift-backtrace/Sources/Backtrace/Backtrace.swift:80
2023-02-10T21:04:24.631 app[d91f8cc0] lhr [info] 0x55933a15ea57, @objc closure #1 (Swift.Int32) -> () in static Backtrace.Backtrace.install(signals: Swift.Array<Swift.Int32>) -> () at /build/<compiler-generated>:79
2023-02-10T21:04:24.631 app[d91f8cc0] lhr [info] 0x7f65a418e41f
2023-02-10T21:04:24.632 app[d91f8cc0] lhr [info] 0x7f65a327a39f
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x55933a549d61, closure #1 () -> Foundation.Bundle in variable initialization expression of static (extension in HTMLKitComponents):Foundation.Bundle.module : Foundation.Bundle at /build/.build/x86_64-unknown-linux-gnu/release/HTMLKitComponents.build/DerivedSources/resource_bundle_accessor.swift:11
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x7f65a418b4de one-time initialization function for module at /build/.build/x86_64-unknown-linux-gnu/release/HTMLKitComponents.build/DerivedSources/resource_bundle_accessor.swift:4
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x7f65a418b4de
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x7f65a35688a5
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x55933a53d4b5, (extension in HTMLKitComponents):Foundation.Bundle.module.unsafeMutableAddressor : Foundation.Bundle at .build/x86_64-unknown-linux-gnu/release/HTMLKitComponents.build/DerivedSources/resource_bundle_accessor.swift:4
2023-02-10T21:04:24.637 app[d91f8cc0] lhr [info] 0x55933a53d4b5, HTMLKitComponents.Symbol.init(system: Swift.String) -> HTMLKitComponents.Symbol at /build/.build/checkouts/HTMLKit/Sources/HTMLKitComponents/Components/Symbol.swift:25
2023-02-10T21:04:24.638 app[d91f8cc0] lhr [info] 0x55933ab16a59
2023-02-10T21:04:24.638 app[d91f8cc0] lhr [info] 0x55933a5354f8, HTMLKitComponents.Group.init(content: () -> Swift.Array<HTMLKit.Content>) -> HTMLKitComponents.Group at /build/.build/checkouts/HTMLKit/Sources/HTMLKitComponents/Components/Group.swift:19
2023-02-10T21:04:24.638 app[d91f8cc0] lhr [info] 0x55933ab16957
2023-02-10T21:04:24.638 app[d91f8cc0] lhr [info] 0x55933a52b9d2, HTMLKitComponents.LinkButton.init(destination: Swift.String, content: () -> Swift.Array<HTMLKit.Content>) -> HTMLKitComponents.LinkButton at /build/.build/checkouts/HTMLKit/Sources/HTMLKitComponents/Components/Button.swift:116
2023-02-10T21:04:24.640 app[d91f8cc0] lhr [info] 0x55933ab16687, closure #1 () -> Swift.Array<HTMLKit.Content> in closure #2 () -> Swift.Array<HTMLKit.Content> in closure #2 () -> Swift.Array<HTMLKit.Content> in closure #1 () -> Swift.Array<HTMLKit.Content> in Website.EmployeesPage.IndexView.body.getter : HTMLKit.Content at /build/Sources/Website/Views/EmployeesPage.swift:51
2023-02-10T21:04:24.640 app[d91f8cc0] lhr [info] 0x55933a53c90d, HTMLKitComponents.StackColumn.init(size: HTMLKitComponents.Tokens.ColumnSize, content: () -> Swift.Array<HTMLKit.Content>) -> HTMLKitComponents.StackColumn at /build/.build/checkouts/HTMLKit/Sources/HTMLKitComponents/Components/Stack.swift:256
2023-02-10T21:04:24.640 app[d91f8cc0] lhr [info] 0x55933ab184ab
2023-02-10T21:04:24.640 app[d91f8cc0] lhr [info] 0x55933a53b572, HTMLKitComponents.HStack.init(alignment: HTMLKitComponents.Tokens.VerticalAlignment, content: () -> Swift.Array<HTMLKit.Content>) -> HTMLKitComponents.HStack at /build/.build/checkouts/HTMLKit/Sources/HTMLKitComponents/Components/Stack.swift:26
2023-02-10T21:04:24.640 app[d91f8cc0] lhr [info] 0x55933ab15799, closure #2 () -> Swift.Array<HTMLKit.Content> in closure #1 () -> Swift.Array<HTMLKit.Content> in Website.EmployeesPage.IndexView.body.getter : HTMLKit.Content at /build/Sources/Website/Views/EmployeesPage.swift:49
2023-02-10T21:04:24.642 app[d91f8cc0] lhr [info] 0x55933a487cc6, HTMLKit.Blockquote.init(content: () -> Swift.Array<HTMLKit.Content>) -> HTMLKit.Blockquote at /build/.build/checkouts/HTMLKit/Sources/HTMLKit/Abstraction/Elements/BodyElements.swift:4578
2023-02-10T21:04:24.642 app[d91f8cc0] lhr [info] 0x55933ab1418f, closure #1 () -> Swift.Array<HTMLKit.Content> in Website.EmployeesPage.IndexView.body.getter : HTMLKit.Content at /build/Sources/Website/Views/EmployeesPage.swift:23
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933ab14077, Website.ViewContainer.init(_: Swift.Optional<Swift.String>, content: () -> Swift.Array<HTMLKit.Content>) -> Website.ViewContainer at Sources/Website/Views/Shared/ViewContainer.swift:14
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933ab14077, Website.EmployeesPage.IndexView.body.getter : HTMLKit.Content at /build/Sources/Website/Views/EmployeesPage.swift:12
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933ab16c47, protocol witness for HTMLKit.View.body.getter : HTMLKit.Content in conformance Website.EmployeesPage.IndexView : HTMLKit.View in Website at /build/<compiler-generated>:0
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933a526462, HTMLKit.Renderer.render<A where A: HTMLKit.View>(view: A) throws -> Swift.String at /build/.build/checkouts/HTMLKit/Sources/HTMLKit/Framework/Rendering/Renderer.swift:70
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933a54a7aa, HTMLKitVapor.ViewRenderer.render<A where A: HTMLKit.View>(A) -> NIOCore.EventLoopFuture<Vapor.View> at /build/.build/checkouts/HTMLKit/Sources/HTMLKitVapor/ViewRenderer.swift:32
2023-02-10T21:04:24.643 app[d91f8cc0] lhr [info] 0x55933a54a984, (1) suspend resume partial function for HTMLKitVapor.ViewRenderer.render<A where A: HTMLKit.View>(A) async throws -> Vapor.View at /build/.build/checkouts/HTMLKit/Sources/HTMLKitVapor/ViewRenderer.swift:43

Change the type of the scripts property

The AnyContent protocol has a property scripts, wich has the type AnyContent. I would like to change it to a type of String.

public protocol AnyContent {
    ...
    var scripts: AnyContent { get }

}

My idea is if its a String, it can be accumulated to the top node (mostly the Page) where it can be used on the script element:

...
    public var body: AnyContent {
            ...
            Body {
                content
            }
            Script {
                self.scripts
            }
        }
    }

Would it change your first intention @MatsMoll? Or what was the intention of using scripts in the first place? Did you use scripts to accumulated it to the top? Did it work?

API consideration

Why we not using SwiftUI-like "some Content" to constraint body rather using "AnyContent"?

Is there some limitation keeping us away from using it?

Image component and optional context values

Hi, love the library, but I'm having an extremely hard time trying to display an image using an url that comes from an optional field from the model
These are some scenarios that I'm facing
image

I had to create a computed var to try to drill down the model and fetch the url or default to "" and still doesn't work

var profile_thumb_url: String {
    attributes.profile_thumb.data?.attributes.url ?? ""
}

image

If I try to use the whole path I get these scenarios
image

And if I try to get fancy
image

Why template instantiation throws?

I've noticed that the template instantiation features using a throwing init. It even states it in the readme

try SimpleTemplate()

But why does it throw? What can go wrong during instantiation?

missing data function on Input

Hi,

I was able to do this back on version 2.1.0
image

I searched around the codebase but it doesn't seem to be a way to add custom data attributes like
data-inputmask="'alias': 'phone'"

Add a dropdown-component

Add a dropdown-component for like a dropdown button or context menu similar to this:

Dropdown {
    Action {
        Symbol(name: "arrow-down")
    }
    List {
        ListItem {
            Link(destination: "/edit")
        }
        ListItem {
            Link(destination: "/remove")
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.