├── .gitignore ├── LICENSE ├── Makefile ├── Package.swift ├── README.md ├── Sources ├── SwiftHtml │ ├── Attributes │ │ ├── Crossorigin.swift │ │ ├── Enctype.swift │ │ ├── Events.swift │ │ ├── Global.swift │ │ ├── Loading.swift │ │ ├── Method.swift │ │ ├── RefererPolicy.swift │ │ └── Target.swift │ ├── Exported.swift │ ├── MediaQuery.swift │ ├── Tags │ │ ├── A.swift │ │ ├── Abbr.swift │ │ ├── Address.swift │ │ ├── Area.swift │ │ ├── Article.swift │ │ ├── Aside.swift │ │ ├── Audio.swift │ │ ├── B.swift │ │ ├── Base.swift │ │ ├── Bdi.swift │ │ ├── Bdo.swift │ │ ├── Blockquote.swift │ │ ├── Body.swift │ │ ├── Br.swift │ │ ├── Button.swift │ │ ├── Canvas.swift │ │ ├── Caption.swift │ │ ├── Cite.swift │ │ ├── Code.swift │ │ ├── Col.swift │ │ ├── Colgroup.swift │ │ ├── Comment.swift │ │ ├── Data.swift │ │ ├── Datalist.swift │ │ ├── Dd.swift │ │ ├── Del.swift │ │ ├── Details.swift │ │ ├── Dfn.swift │ │ ├── Dialog.swift │ │ ├── Div.swift │ │ ├── Dl.swift │ │ ├── Dt.swift │ │ ├── Em.swift │ │ ├── Embed.swift │ │ ├── Fieldset.swift │ │ ├── Figcaption.swift │ │ ├── Figure.swift │ │ ├── Footer.swift │ │ ├── Form.swift │ │ ├── H1.swift │ │ ├── H2.swift │ │ ├── H3.swift │ │ ├── H4.swift │ │ ├── H5.swift │ │ ├── H6.swift │ │ ├── Head.swift │ │ ├── Header.swift │ │ ├── Hr.swift │ │ ├── Html.swift │ │ ├── I.swift │ │ ├── Iframe.swift │ │ ├── Img.swift │ │ ├── Input.swift │ │ ├── Ins.swift │ │ ├── Kbd.swift │ │ ├── Label.swift │ │ ├── Legend.swift │ │ ├── Li.swift │ │ ├── Link.swift │ │ ├── MainTag.swift │ │ ├── Map.swift │ │ ├── Mark.swift │ │ ├── Meta.swift │ │ ├── Meter.swift │ │ ├── Nav.swift │ │ ├── Noscript.swift │ │ ├── Object.swift │ │ ├── Ol.swift │ │ ├── Optgroup.swift │ │ ├── Option.swift │ │ ├── Output.swift │ │ ├── P.swift │ │ ├── Param.swift │ │ ├── Picture.swift │ │ ├── Pre.swift │ │ ├── Progress.swift │ │ ├── Q.swift │ │ ├── Rp.swift │ │ ├── Rt.swift │ │ ├── Ruby.swift │ │ ├── S.swift │ │ ├── Samp.swift │ │ ├── Script.swift │ │ ├── Section.swift │ │ ├── Select.swift │ │ ├── Small.swift │ │ ├── Source.swift │ │ ├── Span.swift │ │ ├── Strong.swift │ │ ├── Style.swift │ │ ├── Sub.swift │ │ ├── Summary.swift │ │ ├── Sup.swift │ │ ├── Table.swift │ │ ├── Tbody.swift │ │ ├── Td.swift │ │ ├── Template.swift │ │ ├── Textarea.swift │ │ ├── Tfoot.swift │ │ ├── Th.swift │ │ ├── Thead.swift │ │ ├── Time.swift │ │ ├── Title.swift │ │ ├── Tr.swift │ │ ├── Track.swift │ │ ├── U.swift │ │ ├── Ul.swift │ │ ├── Var.swift │ │ ├── Video.swift │ │ └── Wbr.swift │ └── Text.swift ├── SwiftRss │ ├── Channel.swift │ ├── Description.swift │ ├── Exported.swift │ ├── Guid.swift │ ├── Item.swift │ ├── Language.swift │ ├── LastBuildDate.swift │ ├── Link.swift │ ├── PubDate.swift │ ├── Rss.swift │ ├── Title.swift │ └── Ttl.swift ├── SwiftSgml │ ├── Attribute.swift │ ├── Document.swift │ ├── DocumentRenderer.swift │ ├── EmptyTag.swift │ ├── GroupTag.swift │ ├── Node.swift │ ├── Tag.swift │ └── TagBuilder.swift ├── SwiftSitemap │ ├── ChangeFreq.swift │ ├── Exported.swift │ ├── LastMod.swift │ ├── Loc.swift │ ├── Priority.swift │ ├── Sitemap.swift │ ├── SitemapIndex.swift │ ├── Url.swift │ └── UrlSet.swift └── SwiftSvg │ ├── Circle.swift │ ├── Double+PreciseString.swift │ ├── Ellipse.swift │ ├── Exported.swift │ ├── G.swift │ ├── Line.swift │ ├── Path.swift │ ├── Polygon.swift │ ├── Polyline.swift │ ├── Rect.swift │ ├── Svg.swift │ └── Text.swift └── Tests ├── SwiftHtmlTests ├── SwiftHtmlTests.swift ├── TagCompositionTests.swift ├── Tags │ ├── ATagTests.swift │ ├── BrTagTests.swift │ ├── CommentTagTests.swift │ ├── FormTagTests.swift │ ├── H1TagTests.swift │ ├── InputTagTests.swift │ ├── LabelTagTests.swift │ ├── LinkTagTests.swift │ ├── MetaTagTests.swift │ ├── PTagTests.swift │ ├── ScriptTagTests.swift │ ├── SourceTagTests.swift │ ├── TableTagTests.swift │ ├── TextareaTagTests.swift │ └── UlTagTests.swift └── assert.swift ├── SwiftRssTests ├── SwiftRssTests.swift └── assert.swift ├── SwiftSgmlTests ├── AttributeTests.swift ├── CustomTags.swift ├── NodeTests.swift ├── SwiftSgmlTests.swift ├── TagBuilderTests.swift ├── TagTests.swift └── assert.swift ├── SwiftSitemapTests ├── SwiftSitemapTests.swift └── assert.swift └── SwiftSvgTests ├── SwiftSvgTests.swift └── assert.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .build 3 | .swiftpm 4 | .env 5 | .env.development 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2022 Tibor Bödecs 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | swift test --enable-test-discovery --parallel 3 | 4 | docs: 5 | jazzy \ 6 | --clean \ 7 | --author "Tibor Bödecs" \ 8 | --author_url https://twitter.com/tiborbodecs/ \ 9 | --module-version 1.6.0 \ 10 | --module SwiftHtml \ 11 | --output docs/ 12 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "swift-html", 6 | platforms: [ 7 | .macOS(.v10_15) 8 | ], 9 | products: [ 10 | .library(name: "SwiftSgml", targets: ["SwiftSgml"]), 11 | .library(name: "SwiftHtml", targets: ["SwiftHtml"]), 12 | .library(name: "SwiftSvg", targets: ["SwiftSvg"]), 13 | .library(name: "SwiftSitemap", targets: ["SwiftSitemap"]), 14 | .library(name: "SwiftRss", targets: ["SwiftRss"]), 15 | ], 16 | dependencies: [ 17 | 18 | ], 19 | targets: [ 20 | .target(name: "SwiftSgml", dependencies: []), 21 | .target(name: "SwiftHtml", dependencies: [ 22 | .target(name: "SwiftSgml") 23 | ]), 24 | .target(name: "SwiftSvg", dependencies: [ 25 | .target(name: "SwiftSgml") 26 | ]), 27 | .target(name: "SwiftSitemap", dependencies: [ 28 | .target(name: "SwiftSgml") 29 | ]), 30 | .target(name: "SwiftRss", dependencies: [ 31 | .target(name: "SwiftSgml") 32 | ]), 33 | .testTarget(name: "SwiftSgmlTests", dependencies: [ 34 | .target(name: "SwiftSgml"), 35 | ]), 36 | .testTarget(name: "SwiftHtmlTests", dependencies: [ 37 | .target(name: "SwiftHtml"), 38 | ]), 39 | .testTarget(name: "SwiftSvgTests", dependencies: [ 40 | .target(name: "SwiftSvg"), 41 | ]), 42 | .testTarget(name: "SwiftSitemapTests", dependencies: [ 43 | .target(name: "SwiftSitemap"), 44 | ]), 45 | .testTarget(name: "SwiftRssTests", dependencies: [ 46 | .target(name: "SwiftRss"), 47 | ]), 48 | ] 49 | ) 50 | 51 | 52 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/Crossorigin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Crossorigin.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum Crossorigin: String { 9 | case anonymous 10 | case useCredentials = "use-credentials" 11 | } 12 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/Enctype.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Enctype.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum Enctype: String { 9 | case urlencoded = "application/x-www-form-urlencoded" 10 | case multipart = "multipart/form-data" 11 | case plain = "text/plain" 12 | } 13 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/Loading.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Loading.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum Loading: String { 9 | case eager 10 | case lazy 11 | } 12 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/Method.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Method.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum Method: String { 9 | case get 10 | case post 11 | } 12 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/RefererPolicy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RefererPolicy.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum RefererPolicy: String { 9 | /// No referrer information is sent 10 | case noReferrer = "no-referrer" 11 | /// Default. Sends the origin, path, and query string if the protocol security level stays the same or is higher (HTTP to HTTP, HTTPS to HTTPS, HTTP to HTTPS is ok). Sends nothing to less secure level (HTTPS to HTTP is not ok) 12 | case noReferrerWhenDowngrade = "no-referrer-when-downgrade" 13 | /// Sends the origin (scheme, host, and port) of the document 14 | case origin 15 | /// Sends the origin of the document for cross-origin request. Sends the origin, path, and query string for same-origin request 16 | case originWhenCrossOrigin = "origin-when-cross-origin" 17 | /// Sends a referrer for same-origin request. Sends no referrer for cross-origin request 18 | case sameOrigin = "same-origin" 19 | /// ??? 20 | ///case strictOrigin = "strict-origin" 21 | /// Sends the origin if the protocol security level stays the same or is higher (HTTP to HTTP, HTTPS to HTTPS, and HTTP to HTTPS is ok). Sends nothing to less secure level (HTTPS to HTTP) 22 | case strictOriginWhenCrossOrigin = "strict-origin-when-cross-origin" 23 | /// Sends the origin, path, and query string (regardless of security). Use this value carefully! 24 | case unsafeUrl = "unsafe-url" 25 | } 26 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Attributes/Target.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Target.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | public enum Target: String { 9 | /// Opens the link in a new window or tab 10 | case blank = "_blank" 11 | /// Default. Opens the link in the same frame as it was clicked 12 | case `default` = "_self" 13 | /// Opens the link in the parent frame 14 | case parent = "_parent" 15 | /// Opens the link in the full body of the window 16 | case top = "_top" 17 | } 18 | 19 | public enum TargetFrame { 20 | /// Opens the linked document in a new window or tab 21 | case blank 22 | /// Opens the linked document in the same frame as it was clicked (this is default) 23 | case `default` 24 | /// Opens the linked document in the parent frame 25 | case parent 26 | /// Opens the linked document in the full body of the window 27 | case top 28 | /// Opens the linked document in the named iframe 29 | case frame(String) 30 | 31 | var rawValue: String { 32 | switch self { 33 | case .blank: 34 | return "_blank" 35 | case .`default`: 36 | return "_self" 37 | case .parent: 38 | return "_parent" 39 | case .top: 40 | return "_top" 41 | case let .frame(name): 42 | return name 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Exported.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Exported.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 12. 19.. 6 | // 7 | 8 | @_exported import SwiftSgml 9 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/MediaQuery.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaQuery.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2022. 01. 24.. 6 | // 7 | 8 | /// represents a CSS media query 9 | public struct MediaQuery { 10 | 11 | /// device orientation 12 | public enum Orientation: String { 13 | /// portrait orientation 14 | case portrait 15 | /// landscape orientation 16 | case landscape 17 | } 18 | 19 | /// device color scheme 20 | public enum ColorScheme: String { 21 | /// light mode 22 | case light 23 | /// dark mode 24 | case dark 25 | } 26 | 27 | /// raw representation of the media query 28 | var value: String 29 | 30 | } 31 | 32 | public extension MediaQuery { 33 | 34 | /// screen 35 | static let screen = MediaQuery(value: "screen") 36 | 37 | /// device width in pixels 38 | static func deviceWidth(px: Int) -> MediaQuery { 39 | .init(value: "(device-width: \(px)px)") 40 | } 41 | 42 | /// device height in pixels 43 | static func deviceHeight(px: Int) -> MediaQuery { 44 | .init(value: "(device-height: \(px)px)") 45 | } 46 | 47 | /// device pixel ratio with webkit prefix 48 | static func webkitDevicePixelRatio(_ value: Int) -> MediaQuery { 49 | .init(value: "(-webkit-device-pixel-ratio: \(value))") 50 | } 51 | 52 | /// device orientation 53 | static func orientation(_ value: Orientation) -> MediaQuery { 54 | .init(value: "(orientation: \(value.rawValue))") 55 | } 56 | 57 | /// preferred color scheme 58 | static func prefersColorScheme(_ value: ColorScheme) -> MediaQuery { 59 | .init(value: "(prefers-color-scheme: \(value.rawValue))") 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/A.swift: -------------------------------------------------------------------------------- 1 | // 2 | // A.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 19.. 6 | // 7 | 8 | /// The `` tag defines a hyperlink, which is used to link from one page to another. 9 | /// 10 | /// The most important attribute of the `` element is the href attribute, which indicates the link's destination. 11 | /// 12 | /// By default, links will appear as follows in all browsers: 13 | /// 14 | /// - An unvisited link is underlined and blue 15 | /// - A visited link is underlined and purple 16 | /// - An active link is underlined and red 17 | open class A: Tag { 18 | 19 | } 20 | 21 | public extension A { 22 | 23 | enum Rel: String { 24 | /// Provides a link to an alternate representation of the document (i.e. print page, translated or mirror) 25 | case alternate 26 | /// Provides a link to the author of the document 27 | case author 28 | /// Permanent URL used for bookmarking 29 | case bookmark 30 | /// Indicates that the referenced document is not part of the same site as the current document 31 | case external 32 | /// Provides a link to a help document 33 | case help 34 | /// Provides a link to licensing information for the document 35 | case license 36 | /// Provides a link to the next document in the series 37 | case next 38 | /// Links to an unendorsed document, like a paid link. 39 | /// ("nofollow" is used by Google, to specify that the Google search spider should not follow that link) 40 | case nofollow 41 | /// Requires that any browsing context created by following the hyperlink must not have an opener browsing context 42 | case noopener 43 | /// Makes the referrer unknown. No referer header will be included when the user clicks the hyperlink 44 | case noreferrer 45 | /// The previous document in a selection 46 | case prev 47 | /// Links to a search tool for the document 48 | case search 49 | /// A tag (keyword) for the current document 50 | case tag 51 | } 52 | 53 | /// Specifies that the target will be downloaded when a user clicks on the hyperlink 54 | func download(_ value: String? = nil) -> Self { 55 | flagAttribute("download", value) 56 | } 57 | 58 | /// Specifies the URL of the page the link goes to 59 | func href(_ value: String) -> Self { 60 | attribute("href", value) 61 | } 62 | 63 | /// Specifies the language of the linked document 64 | func hreflang(_ value: String) -> Self { 65 | attribute("hreflang", value) 66 | } 67 | 68 | /// Specifies what media/device the linked document is optimized for 69 | func media(_ value: String) -> Self { 70 | attribute("media", value) 71 | } 72 | 73 | /// Specifies what media/device the linked document is optimized for 74 | /// 75 | /// If multiple queries were provided they're going to be concatenated with an `and` operand 76 | func media(_ queries: MediaQuery...) -> Self { 77 | return media(queries) 78 | } 79 | 80 | /// Specifies what media/device the linked document is optimized for 81 | /// 82 | /// If multiple queries were provided they're going to be concatenated with an `and` operand 83 | func media(_ queries: [MediaQuery]) -> Self { 84 | return media(queries.map(\.value).joined(separator: " and ")) 85 | } 86 | 87 | /// Specifies a space-separated list of URLs to which, when the link is followed, post requests with the body ping will be sent by the browser (in the background). 88 | /// 89 | /// Typically used for tracking. 90 | func ping(_ value: [String]) -> Self { 91 | attribute("ping", value.joined(separator: " ")) 92 | } 93 | 94 | /// Specifies which referrer information to send with the link 95 | func refererPolicy(_ value: RefererPolicy = .origin) -> Self { 96 | attribute("referrerpolicy", value.rawValue) 97 | } 98 | 99 | /// Specifies the relationship between the current document and the linked document 100 | func rel(_ value: Rel) -> Self { 101 | attribute("rel", value.rawValue) 102 | } 103 | 104 | /// Specifies where to open the linked document 105 | func target(_ value: TargetFrame, _ condition: Bool = true) -> Self { 106 | attribute("target", value.rawValue, condition) 107 | } 108 | 109 | /// The type attribute specifies the Internet media type (formerly known as MIME type) of the linked document. 110 | func type(_ value: String) -> Self { 111 | attribute("type", value) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/Abbr.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Abbr.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 19.. 6 | // 7 | 8 | /// The `` tag defines an abbreviation or an acronym, like "HTML", "CSS", "Mr.", "Dr.", "ASAP", "ATM". 9 | /// 10 | /// **Tip:** Use the global title attribute to show the description for the abbreviation/acronym when you mouse over the element. 11 | open class Abbr: Tag { 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/Address.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Address.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 19.. 6 | // 7 | 8 | /// The `
` tag defines the contact information for the author/owner of a document or an article. 9 | /// 10 | /// The contact information can be an email address, URL, physical address, phone number, social media handle, etc. 11 | /// 12 | /// The text in the `
` element usually renders in italic, and browsers will always add a line break before and after the `
` element. 13 | open class Address: Tag { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/Area.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Area.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 23.. 6 | // 7 | 8 | /// The tag defines an area inside an image map (an image map is an image with clickable areas). 9 | /// 10 | /// elements are always nested inside a tag. 11 | /// 12 | /// **Note:** The usemap attribute in is associated with the element's name attribute, and creates a relationship between the image and the map. 13 | open class Area: EmptyTag { 14 | 15 | public enum Rel: String { 16 | /// Links to an alternate version of the document (i.e. print page, translated or mirror) 17 | case alternate 18 | /// Links to the author of the document 19 | case author 20 | /// Permanent URL used for bookmarking 21 | case bookmark 22 | /// Links to a help document 23 | case help 24 | /// Links to copyright information for the document 25 | case license 26 | /// The next document in a selection 27 | case next 28 | /// Links to an unendorsed document, like a paid link. 29 | /// ("nofollow" is used by Google, to specify that the Google search spider should not follow that link) 30 | case nofollow 31 | /// Specifies that the browser should not send a HTTP referer header if the user follows the hyperlink 32 | case noreferrer 33 | /// Specifies that the target document should be cached 34 | case prefetch 35 | /// The previous document in a selection 36 | case prev 37 | /// Links to a search tool for the document 38 | case search 39 | /// A tag (keyword) for the current document 40 | case tag 41 | } 42 | 43 | public enum Shape: String { 44 | /// Specifies the entire region 45 | case `default` 46 | /// Defines a rectangular region 47 | case rect 48 | /// Defines a circular region 49 | case circle 50 | /// Defines a polygonal region 51 | case poly 52 | } 53 | 54 | } 55 | 56 | public extension Area { 57 | /// Specifies an alternate text for the area. Required if the href attribute is present 58 | func alt(_ value: String) -> Self { 59 | attribute("alt", value) 60 | } 61 | 62 | /// Specifies the coordinates of the area 63 | func coords(_ values: Double...) -> Self { 64 | attribute("coords", values.map {String($0) }.joined(separator: ",")) 65 | } 66 | 67 | /// Specifies that the target will be downloaded when a user clicks on the hyperlink 68 | func download(_ value: String) -> Self { 69 | attribute("download", value) 70 | } 71 | 72 | /// Specifies the hyperlink target for the area 73 | func href(_ value: String) -> Self { 74 | attribute("href", value) 75 | } 76 | 77 | /// Specifies the language of the target URL 78 | func hreflang(_ value: String) -> Self { 79 | attribute("hreflang", value) 80 | } 81 | 82 | /// Specifies what media/device the target URL is optimized for 83 | func media(_ value: String) -> Self { 84 | attribute("media", value) 85 | } 86 | 87 | /// Specifies what media/device the linked document is optimized for 88 | /// 89 | /// If multiple queries were provided they're going to be concatenated with an `and` operand 90 | func media(_ queries: MediaQuery...) -> Self { 91 | return media(queries) 92 | } 93 | 94 | /// Specifies what media/device the linked document is optimized for 95 | /// 96 | /// If multiple queries were provided they're going to be concatenated with an `and` operand 97 | func media(_ queries: [MediaQuery]) -> Self { 98 | return media(queries.map(\.value).joined(separator: " and ")) 99 | } 100 | 101 | /// Specifies which referrer information to send with the link 102 | func refererPolicy(_ value: RefererPolicy = .origin) -> Self { 103 | attribute("referrerpolicy", value.rawValue) 104 | } 105 | 106 | /// Specifies the relationship between the current document and the target URL 107 | func rel(_ value: Rel) -> Self { 108 | attribute("rel", value.rawValue) 109 | } 110 | 111 | /// Specifies the shape of the area 112 | func shape(_ value: Shape) -> Self { 113 | attribute("shape", value.rawValue) 114 | } 115 | 116 | /// Specifies where to open the target URL 117 | func target(_ value: TargetFrame) -> Self { 118 | attribute("target", value.rawValue) 119 | } 120 | 121 | /// Specifies the media type of the target URL 122 | func type(_ value: String) -> Self { 123 | attribute("type", value) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/Article.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Article.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 19.. 6 | // 7 | 8 | public extension Node { 9 | 10 | static func article() -> Node { 11 | Node(type: .standard, name: "article") 12 | } 13 | } 14 | 15 | /// The `
` tag specifies independent, self-contained content. 16 | /// 17 | /// An article should make sense on its own and it should be possible to distribute it independently from the rest of the site. 18 | /// 19 | /// Potential sources for the `
` element: 20 | /// 21 | /// - Forum post 22 | /// - Blog post 23 | /// - News story 24 | /// 25 | /// **Note:** The `
` element does not render as anything special in a browser. 26 | /// However, you can use CSS to style the `
` element (see example below). 27 | open class Article: Tag { 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Sources/SwiftHtml/Tags/Aside.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Aside.swift 3 | // SwiftHtml 4 | // 5 | // Created by Tibor Bodecs on 2021. 07. 19.. 6 | // 7 | 8 | /// The `