Html.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //
  2. // Html.swift
  3. // Swifter
  4. //
  5. // Copyright © 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. private var htmlStackBuffer = [UInt64: [UInt8]]()
  9. public class HtmlResponse: Response {
  10. public required init(integerLiteral value: Int) {
  11. super.init(200)
  12. self.headers.append(("Content-Type", "text/html"))
  13. }
  14. public init(_ status: Int = Status.ok.rawValue, _ closure: ((Void) -> Void)) {
  15. super.init(status)
  16. self.headers.append(("Content-Type", "text/html"))
  17. htmlStackBuffer.removeAll(keepingCapacity: true)
  18. closure()
  19. if let buffer = htmlStackBuffer[Process.tid] {
  20. self.body = Array<UInt8>(buffer)
  21. }
  22. }
  23. }
  24. public func html(_ status: Int = Status.ok.rawValue, _ closure: ((Void) -> Void)? = nil) -> HtmlResponse {
  25. return HtmlResponse(status) {
  26. htmlStackBuffer[Process.tid] = [UInt8]()
  27. htmlStackBuffer[Process.tid]?.reserveCapacity(1024)
  28. htmlStackBuffer[Process.tid]?.append(contentsOf: "<!DOCTYPE html>".utf8)
  29. "html" ~ {
  30. if let closureFound = closure {
  31. closureFound()
  32. }
  33. }
  34. }
  35. }
  36. infix operator ~
  37. public func ~ (_ left: String, _ closure: ((Void) -> Void)?) {
  38. htmlStackBuffer[Process.tid]?.append(UInt8.lessThan)
  39. var tagName = [UInt8]()
  40. var tagEnd = false
  41. for c in left.utf8 {
  42. switch c {
  43. case UInt8.openingParenthesis:
  44. tagEnd = true
  45. htmlStackBuffer[Process.tid]?.append(.space)
  46. case UInt8.closingParenthesis:
  47. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  48. case UInt8.equal:
  49. htmlStackBuffer[Process.tid]?.append(.equal)
  50. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  51. case UInt8.comma:
  52. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  53. htmlStackBuffer[Process.tid]?.append(.space)
  54. default:
  55. htmlStackBuffer[Process.tid]?.append(c)
  56. }
  57. if !tagEnd {
  58. tagName.append(c)
  59. }
  60. }
  61. htmlStackBuffer[Process.tid]?.append(UInt8.greaterThan)
  62. if let closure = closure {
  63. closure()
  64. }
  65. htmlStackBuffer[Process.tid]?.append(UInt8.lessThan)
  66. htmlStackBuffer[Process.tid]?.append(UInt8.slash)
  67. htmlStackBuffer[Process.tid]?.append(contentsOf: tagName)
  68. htmlStackBuffer[Process.tid]?.append(UInt8.greaterThan)
  69. }
  70. public func ~ (_ left: String, _ right: String) {
  71. htmlStackBuffer[Process.tid]?.append(UInt8.lessThan)
  72. var tagName = [UInt8]()
  73. var tagEnd = false
  74. for c in left.utf8 {
  75. switch c {
  76. case UInt8.openingParenthesis:
  77. tagEnd = true
  78. htmlStackBuffer[Process.tid]?.append(.space)
  79. case UInt8.closingParenthesis:
  80. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  81. case UInt8.equal:
  82. htmlStackBuffer[Process.tid]?.append(.equal)
  83. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  84. case UInt8.comma:
  85. htmlStackBuffer[Process.tid]?.append(.doubleQuotes)
  86. htmlStackBuffer[Process.tid]?.append(.space)
  87. default:
  88. htmlStackBuffer[Process.tid]?.append(c)
  89. }
  90. if !tagEnd {
  91. tagName.append(c)
  92. }
  93. }
  94. htmlStackBuffer[Process.tid]?.append(UInt8.greaterThan)
  95. htmlStackBuffer[Process.tid]?.append(contentsOf: right.utf8)
  96. htmlStackBuffer[Process.tid]?.append(UInt8.lessThan)
  97. htmlStackBuffer[Process.tid]?.append(UInt8.slash)
  98. htmlStackBuffer[Process.tid]?.append(contentsOf: tagName)
  99. htmlStackBuffer[Process.tid]?.append(UInt8.greaterThan)
  100. }
  101. public func 🦄(port: Int, closure: @escaping (((Response) -> Void) -> Void)) {
  102. do {
  103. let server = try Server()
  104. while true {
  105. try server.serve { (request, responder) in
  106. closure(responder)
  107. }
  108. }
  109. } catch {
  110. print(error)
  111. }
  112. }
  113. public func 🚀(_ responder: ((Response) -> Void), _ text: String? = nil) {
  114. if let text = text {
  115. responder(Response([UInt8](text.utf8)))
  116. } else {
  117. responder(Response(404))
  118. }
  119. }