149 lines
4.2 KiB
Swift
149 lines
4.2 KiB
Swift
//
|
|
// Attribute.swift
|
|
// SwifSoup
|
|
//
|
|
// Created by Nabil Chatbi on 29/09/16.
|
|
// Copyright © 2016 Nabil Chatbi.. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
open class Attribute {
|
|
/// The element type of a dictionary: a tuple containing an individual
|
|
/// key-value pair.
|
|
|
|
static let booleanAttributes: [String] = [
|
|
"allowfullscreen", "async", "autofocus", "checked", "compact", "controls", "declare", "default", "defer",
|
|
"disabled", "formnovalidate", "hidden", "inert", "ismap", "itemscope", "multiple", "muted", "nohref",
|
|
"noresize", "noshade", "novalidate", "nowrap", "open", "readonly", "required", "reversed", "seamless",
|
|
"selected", "sortable", "truespeed", "typemustmatch"
|
|
]
|
|
|
|
var key: String
|
|
var value: String
|
|
|
|
public init(key: String, value: String) throws {
|
|
try Validate.notEmpty(string: key)
|
|
self.key = key.trim()
|
|
self.value = value
|
|
}
|
|
|
|
/**
|
|
Get the attribute key.
|
|
@return the attribute key
|
|
*/
|
|
open func getKey() -> String {
|
|
return key
|
|
}
|
|
|
|
/**
|
|
Set the attribute key; case is preserved.
|
|
@param key the new key; must not be null
|
|
*/
|
|
open func setKey(key: String) throws {
|
|
try Validate.notEmpty(string: key)
|
|
self.key = key.trim()
|
|
}
|
|
|
|
/**
|
|
Get the attribute value.
|
|
@return the attribute value
|
|
*/
|
|
open func getValue() -> String {
|
|
return value
|
|
}
|
|
|
|
/**
|
|
Set the attribute value.
|
|
@param value the new attribute value; must not be null
|
|
*/
|
|
@discardableResult
|
|
open func setValue(value: String) -> String {
|
|
let old = self.value
|
|
self.value = value
|
|
return old
|
|
}
|
|
|
|
/**
|
|
Get the HTML representation of this attribute; e.g. {@code href="index.html"}.
|
|
@return HTML
|
|
*/
|
|
public func html() -> String {
|
|
let accum = StringBuilder()
|
|
html(accum: accum, out: (Document("")).outputSettings())
|
|
return accum.toString()
|
|
}
|
|
|
|
public func html(accum: StringBuilder, out: OutputSettings ) {
|
|
accum.append(key)
|
|
if (!shouldCollapseAttribute(out: out)) {
|
|
accum.append("=\"")
|
|
Entities.escape(accum, value, out, true, false, false)
|
|
accum.append("\"")
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get the string representation of this attribute, implemented as {@link #html()}.
|
|
@return string
|
|
*/
|
|
open func toString() -> String {
|
|
return html()
|
|
}
|
|
|
|
/**
|
|
* Create a new Attribute from an unencoded key and a HTML attribute encoded value.
|
|
* @param unencodedKey assumes the key is not encoded, as can be only run of simple \w chars.
|
|
* @param encodedValue HTML attribute encoded value
|
|
* @return attribute
|
|
*/
|
|
public static func createFromEncoded(unencodedKey: String, encodedValue: String) throws ->Attribute {
|
|
let value = try Entities.unescape(string: encodedValue, strict: true)
|
|
return try Attribute(key: unencodedKey, value: value)
|
|
}
|
|
|
|
public func isDataAttribute() -> Bool {
|
|
return key.startsWith(Attributes.dataPrefix) && key.count > Attributes.dataPrefix.count
|
|
}
|
|
|
|
/**
|
|
* Collapsible if it's a boolean attribute and value is empty or same as name
|
|
*
|
|
* @param out Outputsettings
|
|
* @return Returns whether collapsible or not
|
|
*/
|
|
public final func shouldCollapseAttribute(out: OutputSettings) -> Bool {
|
|
return ("" == value || value.equalsIgnoreCase(string: key))
|
|
&& out.syntax() == OutputSettings.Syntax.html
|
|
&& isBooleanAttribute()
|
|
}
|
|
|
|
public func isBooleanAttribute() -> Bool {
|
|
return Attribute.booleanAttributes.contains(key.lowercased())
|
|
}
|
|
|
|
public func hashCode() -> Int {
|
|
var result = key.hashValue
|
|
result = 31 * result + value.hashValue
|
|
return result
|
|
}
|
|
|
|
public func clone() -> Attribute {
|
|
do {
|
|
return try Attribute(key: key, value: value)
|
|
} catch Exception.Error( _, let msg) {
|
|
print(msg)
|
|
} catch {
|
|
|
|
}
|
|
return try! Attribute(key: "", value: "")
|
|
}
|
|
}
|
|
|
|
extension Attribute: Equatable {
|
|
static public func == (lhs: Attribute, rhs: Attribute) -> Bool {
|
|
return lhs.value == rhs.value && lhs.key == rhs.key
|
|
}
|
|
|
|
}
|