A small menubar app that allows you to switch between R versions quickly (if you have multiple versions of R framework installed). https://rud.is/rswitch
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.2 KiB

5 years ago
//
// 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", "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)
}
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
}
}