All Projects → NSHipster → Hypertextliteral

NSHipster / Hypertextliteral

Licence: mit
Generate HTML, XML, and other web content using Swift string literal interpolation

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Hypertextliteral

Xsd2php
Convert XSD into PHP classes and JMS serializer definitions
Stars: ✭ 190 (-13.24%)
Mutual labels:  xml
Go Xml
utility and code-generation libraries for XML
Stars: ✭ 197 (-10.05%)
Mutual labels:  xml
Home
A configurable and eXtensible Xml serializer for .NET.
Stars: ✭ 208 (-5.02%)
Mutual labels:  xml
Saxy
A fast, easy-to-use and XML 1.0 compliant XML SAX parser in Elixir
Stars: ✭ 192 (-12.33%)
Mutual labels:  xml
Xesmf
Universal Regridder for Geospatial Data
Stars: ✭ 197 (-10.05%)
Mutual labels:  interpolation
Iran
Administrative divisions of Iran in json and xml formats - تقسیمات کشوری ایران با فرمت جی‌سان و ایکس ام ال
Stars: ✭ 201 (-8.22%)
Mutual labels:  xml
Libxo
The libxo library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application decides at run time which output style should be produced.
Stars: ✭ 185 (-15.53%)
Mutual labels:  xml
Biblia
Bíblia: XML + SQL + JSON
Stars: ✭ 211 (-3.65%)
Mutual labels:  xml
Xlog
Android logger, pretty, powerful and flexible, log to everywhere, save to file, all you want is here.
Stars: ✭ 2,468 (+1026.94%)
Mutual labels:  xml
Unbescape
Advanced yet easy to use escaping library for Java
Stars: ✭ 207 (-5.48%)
Mutual labels:  xml
Validation
validation api extracted from play
Stars: ✭ 194 (-11.42%)
Mutual labels:  xml
Awesome Explainable Ai
A collection of research materials on explainable AI/ML
Stars: ✭ 186 (-15.07%)
Mutual labels:  xml
Dd Plist
A java library providing support for ASCII, XML and binary property lists.
Stars: ✭ 201 (-8.22%)
Mutual labels:  xml
Publisher
speedata Publisher - a professional database Publishing system
Stars: ✭ 191 (-12.79%)
Mutual labels:  xml
Python Benedict
dict subclass with keylist/keypath support, I/O shortcuts (base64, csv, json, pickle, plist, query-string, toml, xml, yaml) and many utilities. 📘
Stars: ✭ 204 (-6.85%)
Mutual labels:  xml
Tagalong.vim
Change an HTML(ish) opening tag and take the closing one along as well
Stars: ✭ 184 (-15.98%)
Mutual labels:  xml
Xmlschema
XML Schema validator and data conversion library for Python
Stars: ✭ 201 (-8.22%)
Mutual labels:  xml
Codejam
Set of handy reusable .NET components that can simplify your daily work and save your time when you copy and paste your favorite helper methods and classes from one project to another
Stars: ✭ 217 (-0.91%)
Mutual labels:  xml
Xmlquery
xmlquery is Golang XPath package for XML query.
Stars: ✭ 209 (-4.57%)
Mutual labels:  xml
Farm
Zerocrat Core Engine
Stars: ✭ 207 (-5.48%)
Mutual labels:  xml

HypertextLiteral

CI Documentation

HypertextLiteral is a Swift package for generating HTML, XML, and other SGML dialects.

It uses custom string interpolation to append and escape values based on context, with built-in affordances for common patterns and an extensible architecture for defining your own behavior.

import HypertextLiteral

let attributes = [
    "style": [
        "background": "yellow",
        "font-weight": "bold"
    ]
]

let html: HTML = "<span \(attributes)>whoa</span>"
// <span style="background: yellow; font-weight: bold;">whoa</span>

HypertextLiteral is small and self-contained with no external dependencies. You can get up to speed in just a few minutes, without needing to learn any new APIs or domain-specific languages (DSLs). Less time fighting your tools means more time spent generating web content.

This project is inspired by and borrows implementation details from Hypertext Literal by Mike Bostock (@mbostock). You can read more about it here.

Requirements

  • Swift 5.1+

Installation

Swift Package Manager

Add the HypertextLiteral package to your target dependencies in Package.swift:

import PackageDescription

let package = Package(
  name: "YourProject",
  dependencies: [
    .package(
        url: "https://github.com/NSHipster/HypertextLiteral",
        from: "0.0.3"
    ),
  ]
)

Then run the swift build command to build your project.

Usage

Hypertext literals automatically escape interpolated values based on the context in which they appear.

  • By default, interpolated content escapes the XML entities <, >, &, ", and ' as named character references (for example, < becomes &lt;)
  • In the context of an attribute value, quotation marks are escaped with a backslash (\")
  • In a context of comment, any start and end delimiters (<!-- and -->) are removed

Interpolating Content

To get a better sense of how this works in practice, consider the following examples:

let level: Int = 1
"<h\(level)>Hello, world!</h\(level)>" as HTML
// <h1>Hello, world!</h1>

let elementName: String = "h1"
"<\(elementName)>Hello, world!</\(elementName)>" as HTML
// <h1>Hello, world!</h1>

let startTag: String = "<h1>", endTag: String = "</h1>"
"\(startTag)Hello, world!\(endTag)" as HTML
// &lt;h1&gt;Hello, world!&lt;/h1&gt;

Interpolation for an element's name in part or whole work as intended, but interpolation of the tag itself causes the string to have its angle bracket (< and >) escaped.

When you don't want this to happen, such as when you're embedding HTML content in a template, you can either pass that content as an HTML value or interpolate using the unsafeUnescaped argument label.

let startTag: HTML = "<h1>", endTag: HTML = "</h1>"
"\(startTag)Hello, world!\(endTag)" as HTML
// <h1>Hello, world!</h1>

"\(unsafeUnescaped: "<h1>")Hello, world!\(unsafeUnescaped: "</h1>")" as HTML
// <h1>Hello, world!</h1>

Note: Interpolation with the unsafeUnescaped argument label appends the provided literal directly, which may lead to invalid results. For this reason, use of HTML values for composition is preferred.

Interpolating Attribute Values

Attributes in hypertext literals may be interchangeably specified with or without quotation marks, either single (') or double (").

let id: String = "logo
let title: String = #"Swift.org | "Welcome to Swift.org""#
let url = URL(string: "https://swift.org/")!

#"<a id='\#(logo)' title="\#(title)" href=\#(url)>Swift.org</a>"# as HTML
/* <a id='logo'
      title="Swift.org | \"Welcome to Swift.org\""
      href="https://swift.org/">Swift.org</a>
*/

Some attributes have special, built-in rules for value interpolation.

When you interpolate an array of strings for an element's class attribute, the resulting value is a space-delimited list.

let classNames: [String] = ["alpha", "bravo", "charlie"]

"<div class=\(classNames)>…</div>" as HTML
// <div class="alpha bravo charlie">…</div>

If you interpolate a dictionary for the value of an element's style attribute, it's automatically converted to CSS.

let style: [String: Any] = [
    "background": "orangered",
    "font-weight": 700
]

"<span style=\(style)>Swift</span>" as HTML
// <span style="background: orangered; font-weight: 700;">Swift</span>

The Boolean value true interpolates to different values depending the attribute.

"""
<input type="text" aria-enabled=\(true)
                   autocomplete=\(true)
                   spellcheck=\(true)
                   translate=\(true) />
""" as HTML
/* <input type="text" aria-enabled="true"
                      autocomplete="on"
                      spellcheck="spellcheck"
                      translate="yes"/> */

Interpolating Attributes with Dictionaries

You can specify multiple attributes at once by interpolating dictionaries keyed by strings.

let attributes: [String: Any] = [
    "id": "primary",
    "class": ["alpha", "bravo", "charlie"],
    "style": [
        "font-size": "larger"
    ]
]

"<div \(attributes)>…</div>" as HTML
/* <div id="primary"
        class="alpha bravo charlie"
        style="font-size: larger;">…</div> */

Attributes with a common aria- or data- prefix can be specified with a nested dictionary.

let attributes: [String: Any] = [
    "id": "article",
    "aria": [
        "role": "article",
    ],
    "data": [
        "index": 1,
        "count": 3,
    ]
]

"<section \(attributes)>…</section>" as HTML
/* <section id="article"
            aria-role="article"
            data-index="1"
            data-count="3">…</section> */

Support for Other Formats

In addition to HTML, you can use hypertext literals for XML and other SGML formats. Below is an example of how HypertextLiteral can be used to generate an SVG document.

import HypertextLiteral

typealias SVG = HTML

let groupAttributes: [String: Any] = [
    "stroke-width": 3,
    "stroke": "#FFFFEE"
]

func box(_ rect: CGRect, radius: CGVector = CGVector(dx: 10, dy: 10), attributes: [String: Any] = [:]) -> SVG {
    #"""
    <rect x=\#(rect.origin.x) y=\#(rect.origin.y)
          width=\#(rect.size.width) height=\#(rect.size.height)
          rx=\#(radius.dx) ry=\#(radius.dy)
          \#(attributes)/>
    """#
}

let svg: SVG = #"""
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
  <g \#(groupAttributes)>
    \#(box(CGRect(x: 12, y: 28, width: 60, height: 60), attributes: ["fill": "#F06507"]))
    \#(box(CGRect(x: 27, y: 18, width: 55, height: 55), attributes: ["fill": "#F2A02D"]))
    \#(box(CGRect(x: 47, y: 11, width: 40, height: 40), attributes: ["fill": "#FEC352"]))
  </g>
</svg>
"""#

License

MIT

Contact

Mattt (@mattt)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].