Add inline SVG and styles/scripts to example code

This commit is contained in:
Max Desiatov 2020-06-23 11:41:59 +01:00
parent 83730ca55a
commit 96ef5d123a
No known key found for this signature in database
GPG Key ID: FE08EBF9CF58CBA2
4 changed files with 100 additions and 27 deletions

View File

@ -5,9 +5,10 @@
![CI status](https://github.com/swiftwasm/Tokamak/workflows/CI/badge.svg?branch=main)
At the moment Tokamak implements a very basic subset of SwiftUI. Its DOM renderer supports
a few view types, namely `Button`, `Text`, `HStack`/`VStack`, and the `@State` property wrapper.
The long-term goal of Tokamak is to implement as much of SwiftUI API as possible and to provide
a few helpful additions that simplify HTML and CSS interactions.
a few view types, namely `Button`, `Text`, `HStack`/`VStack`, the `@State` property wrapper
and a new `HTML` view for constructing arbitrary HTML. The long-term goal of Tokamak is to implement
as much of SwiftUI API as possible and to provide a few more helpful additions that simplify HTML
and CSS interactions.
## Getting started
@ -16,8 +17,8 @@ Tokamak relies on [`carton`](https://carton.dev) as a primary build tool. Please
After `carton` is successfully installed, type `carton dev --product TokamakDemo` in the
root directory of the cloned Tokamak repository. This will build the demo project and its
dependencies and launch a development HTTP server. You can then open [http://127.0.0.1:8080/](http://127.0.0.1:8080/)
in your browser to interact with the demo.
dependencies and launch a development HTTP server. You can then open
[http://127.0.0.1:8080/](http://127.0.0.1:8080/) in your browser to interact with the demo.
### Example code
@ -27,11 +28,11 @@ that you add `import TokamakDOM` instead of `import SwiftUI` in your files:
```swift
import TokamakDOM
public struct Counter: View {
struct Counter: View {
@State public var count: Int
let limit: Int
public var body: some View {
var body: some View {
count < limit ?
AnyView(
VStack {
@ -62,6 +63,46 @@ let body = document.body.object!
_ = body.appendChild!(divElement)
```
### Arbitrary HTML
With the `HTML` view you can also render any HTML you want, including inline SVG:
```swift
struct SVGCircle: View {
var body: some View {
HTML("svg", ["width": "100", "height": "100"]) {
HTML("circle", [
"cx": "50", "cy": "50", "r": "40",
"stroke": "green", "stroke-width": "4", "fill": "yellow",
])
}
}
}
```
### Arbitrary styles and scripts
While `JavaScriptKit` is a great option for occasional interactions with JavaScript,
sometimes you need to inject arbitrary scripts or styles, which can be done through direct
DOM access:
```swift
let script = #"""
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
"""#
let style = #"""
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css">
"""#
_ = document.head.object!.insertAdjacentHTML!("beforeend", JSValue(stringLiteral: style))
_ = document.head.object!.insertAdjacentHTML!("beforeend", JSValue(stringLiteral: script))
```
This way both [Semantic UI](https://semantic-ui.com/) styles and [moment.js](https://momentjs.com/)
localized date formatting (or any arbitrary style/script/font added that way) are available in your
app.
## Acknowledgments
- Thanks to the [Swift community](https://swift.org/community/) for

View File

@ -0,0 +1,26 @@
// Copyright 2020 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import TokamakDOM
struct SVGCircle: View {
var body: some View {
HTML("svg", ["width": "100", "height": "100"]) {
HTML("circle", [
"cx": "50", "cy": "50", "r": "40",
"stroke": "green", "stroke-width": "4", "fill": "yellow",
])
}
}
}

View File

@ -25,6 +25,12 @@ let style = #"""
_ = document.head.object!.insertAdjacentHTML!("beforeend", JSValue(stringLiteral: style))
let div = document.createElement!("div").object!
let renderer = DOMRenderer(Counter(count: 5, limit: 7), div)
let renderer = DOMRenderer(
VStack {
Counter(count: 5, limit: 7)
SVGCircle()
},
div
)
_ = document.body.object!.appendChild!(div)

View File

@ -2,30 +2,30 @@
import XCTest
extension ColorTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__ColorTests = [
("testHexColors", testHexColors),
]
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__ColorTests = [
("testHexColors", testHexColors),
]
}
extension ReconcilerTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__ReconcilerTests = [
("testDoubleUpdate", testDoubleUpdate),
("testMount", testMount),
("testUnmount", testUnmount),
("testUpdate", testUpdate),
]
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__ReconcilerTests = [
("testDoubleUpdate", testDoubleUpdate),
("testMount", testMount),
("testUnmount", testUnmount),
("testUpdate", testUpdate),
]
}
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(ColorTests.__allTests__ColorTests),
testCase(ReconcilerTests.__allTests__ReconcilerTests),
]
[
testCase(ColorTests.__allTests__ColorTests),
testCase(ReconcilerTests.__allTests__ReconcilerTests),
]
}
#endif