Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pointfreeco/swift-web
🕸 A collection of Swift server-side frameworks for handling HTML, CSS, routing and middleware.
https://github.com/pointfreeco/swift-web
applicative composition css functional-programming html middleware routing swift
Last synced: 3 days ago
JSON representation
🕸 A collection of Swift server-side frameworks for handling HTML, CSS, routing and middleware.
- Host: GitHub
- URL: https://github.com/pointfreeco/swift-web
- Owner: pointfreeco
- License: mit
- Created: 2017-07-06T13:09:55.000Z (over 7 years ago)
- Default Branch: main
- Last Pushed: 2024-07-04T01:03:32.000Z (7 months ago)
- Last Synced: 2025-01-11T13:07:41.746Z (10 days ago)
- Topics: applicative, composition, css, functional-programming, html, middleware, routing, swift
- Language: Swift
- Homepage:
- Size: 557 KB
- Stars: 482
- Watchers: 14
- Forks: 36
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# swift-web
[![CI](https://github.com/pointfreeco/swift-web/workflows/CI/badge.svg)](https://actions-badge.atrox.dev/pointfreeco/swift-web/goto)
[![Swift 5.3](https://img.shields.io/badge/swift-5.3-ED523F.svg?style=flat)](https://swift.org/download/)
[![@pointfreeco](https://img.shields.io/badge/[email protected]?style=flat)](https://twitter.com/pointfreeco)A collection of frameworks for solving various problems in building a Swift web framework. Each framework focuses on a single problem, like HTML rendering, CSS preprocessing, routing, middleware, and more. They also do not depend on any other framework in the collection. You can choose which pieces you want and don't want, for example you can use `Html` without `Css`.
## Stability
This library should be considered experimental. If you find its contents useful, please consider maintaining a fork.
## Installation
```swift
import PackageDescriptionlet package = Package(
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-web.git", .branch("master")),
]
)
```## Getting started
This library contains an extensive test suite and a set of playgrounds that can be explored. To get it running:
* `git clone https://github.com/pointfreeco/swift-web.git`
* `cd swift-web`
* `swift package generate-xcodeproj`
* `xed .`
* Run tests: Command+U
* Build: Command+B
* Open a playground!## Included modules
#### Primary modules
* [`Css`](#css)
* [`HttpPipeline`](#httppipeline)
* [`ApplicativeRouter`](#applicativerouter)#### Supporting modules
* [`HttpPipelineHtmlSupport`](#httppipelinehtmlsupport)
* [`HtmlCssSupport`](#htmlcsssupport)
* [`CssReset`](#cssreset)## `Css`
An EDSL for a CSS preprocessor like [Sass](http://sass-lang.com). A few simple value types and functions allow you to model most of CSS, and allow you express new things not possible in standard CSS.
```swift
import Csslet css = body % (
padding(all: .rem(2))
<> background(Color.hsl(60, 0.5, 0.8))
)render(css: css)
```
```css
body {
padding-top : 2rem;
padding-right : 2rem;
padding-bottom : 2rem;
padding-left : 2rem;
background : #e6e6b3;
}
```## `HttpPipeline`
A few types and functions for modeling server middleware as a simple function that transforms a request to a response. It uses phantom types express the state transitions of when you are allowed to write the status, headers and response body.
```swift
import HttpPipelinelet middleware = writeStatus(.ok)
>>> writeHeader(.contentType(.html))
>>> closeHeaders
>>> send(render(document).data(using: .utf8))
>>> endlet request = URLRequest(url: URL(string: "/")!)
let conn = connection(from: request).map(const(Data?.none))
```
```text
â–ż Step
ResponseEndedâ–ż Request
GET /(Data, 0 bytes)
â–ż Response
Status 200 OK
Content-Type: text/html; charset=utf8
Hello world!
Goodbye!
Home
```## `ApplicativeRouter`
A router built on the principles of “applicatives” that unifies parsing requests and printing routes. It is robust, composable and type-safe. Its job is to take the incoming, unstructured `URLRequest` from the browser and turn it into a structured value so that your app can do what it needs to do to produce a response. Additionally, given a value, it can do the reverse in which it generates a request that can be used in a hyperlink. Most of the ideas for this library were taking from [this paper](http://www.informatik.uni-marburg.de/~rendel/unparse/).
```swift
import ApplicativeRouterstruct UserData: Decodable {
let email: String
}enum Route {
case home
case episodes
case episode(String)
case search(String?)
case signup(UserData?)
}let router = [
// Matches: GET /
Route.iso.home
<¢> .get <% end,// Matches: GET /episode/:str
Route.iso.episode
<¢> get %> lit("episode") %> pathParam(.string) <% end,// Matches: GET /episodes
Route.iso.episodes
<¢> get %> lit("episodes") <% end,// Matches: GET /search?query=:optional_string
Route.iso.search
<¢> get %> lit("search") %> queryParam("query", opt(.string)) <% end,// Matches: POST /signup
Route.iso.signup
<¢> post %> jsonBody(Episode.self) <%> lit("signup") %> opt(.jsonBody)) <% end,
]
.reduce(.empty, <|>)// Match a route given a request
let request = URLRequest(url: URL(string: "https://www.pointfree.co/episode/001-hello-world")!)
let route = router.match(request: request)
// => Route.episode("001-hello-world")// Generate a string from a route:
router.absoluteString(for: .episode("001-hello-world"))
// => /episode/001-hello-world
```## `HttpPipelineHtmlSupport`
Adds middleware for rendering an `Html` view:
```swift
import Foundation
import Html
import HttpPipeline
import HttpPipelineHtmlSupportlet view = View(p(["Hello world!"]))
let middleware = writeStatus(.ok)
>>> respond(view)let conn = connection(from: URLRequest(url: URL(string: "/")!))
middleware(conn).response.description
```
```text
Status 200
Content-Type: text/htmlHello world!
```## `HtmlCssSupport`
Adds an element and attribute function to `Html` for render `Css` values into an internal stylesheet or inline styles. The element function `style` allows you to provide a `Stylesheet` value that will be rendered to an internal stylesheet:
```swift
import Css
import Html
import HtmlCssSupportlet css = body % background(red)
let document = html([head([style(css)])])
render(document)
```
```html
body{background:#ff0000}
```
The attribute function `style` allows you to render a stylesheet inline directly on an element:
```swift
import Css
import Html
import HtmlCssSupportlet anchorStyle = color(.red)
<> textTransform(.capitalize)let styledDocument = p([
"Go back ",
a([style(anchorStyle)], ["Home"])
])print(render(styledDocument, config: pretty))
```
```html
Go back
Home
```## `CssReset`
Contains a single value `reset` of type `Stylesheet` that resets all of the defaults for a webpage. It can be combined with another stylesheet via `reset <> otherStyles`, or can be directly rendered to a stylesheet string via `render(reset)`.
## License
All modules are released under the MIT license. See [LICENSE](LICENSE) for details.