Parameter.ts 5.83 KB
Newer Older
Mark Stenglein's avatar
Mark Stenglein committed
1
import { isAlpha, isIamaToken, isXName } from "./util";
2
import { ICalElement } from "./ICalElement";
Mark Stenglein's avatar
Mark Stenglein committed
3 4 5 6 7 8 9 10

/**
 * Implementation of a Content Line Parameter from RFC 5545
 *
 * Chapter 3.1 defines the general ruleset for a parameter. This implementation
 * will utilize an abstract Class which is meant to be extended by specific
 * types of parameters.
 *
11 12 13 14 15
 *     param = param-name "=" param-value *("," param-value)
 *     ; Each property defines the specific ABNF for the parameters
 *     ; allowed on the property. Refer to specific properties for
 *     ; precise parameter ABNF.
 *
Mark Stenglein's avatar
Mark Stenglein committed
16 17
 * @author Mark Stenglein <mark@stengle.in>
 */
18
export default class Parameter implements ICalElement {
Mark Stenglein's avatar
Mark Stenglein committed
19
    private _paramName: string;
20
    private _paramValues: string[];
Mark Stenglein's avatar
Mark Stenglein committed
21 22 23 24

    /**
     * Constructor builds the Parameter from the parameter name and an array of
     * values.
25 26 27 28
     *
     * For more specific implementations that use non-string datatypes, look at
     * extended implementations of this class.
     *
Mark Stenglein's avatar
Mark Stenglein committed
29 30 31
     * @author Mark Stenglein
     * @since 0.1.0
     * @param inName string The name of the new Parameter in iama-token / x-name
32
     * @param inValues string[] array of string values
Mark Stenglein's avatar
Mark Stenglein committed
33
     */
34
    constructor(inName: string, inValues: string[]) {
Mark Stenglein's avatar
Mark Stenglein committed
35
        this.paramName = inName;
36
        this.paramValues = inValues;
Mark Stenglein's avatar
Mark Stenglein committed
37 38
    }

39

Mark Stenglein's avatar
Mark Stenglein committed
40 41 42 43 44 45
    /** Get Methods */

    get paramName() {
        return this._paramName;
    }

46

Mark Stenglein's avatar
Mark Stenglein committed
47 48 49 50
    get paramValues() {
        return this.paramValues;
    }

51

Mark Stenglein's avatar
Mark Stenglein committed
52 53 54 55 56
    /** Set Methods */

    /**
     * Validates input param names and saves them to the object.
     *
57 58
     *     param-name = iana-token / x-name
     *
Mark Stenglein's avatar
Mark Stenglein committed
59 60 61 62 63 64 65 66 67 68 69
     * @author Mark Stenglein <mark@stengle.in>
     * @since 0.1.0
     * @param newName The new name to be tested and saved.
     * @returns void
     * @throws TypeError if newName is not a valid iCal name.
     */
    set paramName(newName: string) {
        /**
         * Note that the X-Name also passes these rules, the X-Name can be
         * defined separately.
         */
70
        if (isIamaToken(newName) || isXName(newName)) {
Mark Stenglein's avatar
Mark Stenglein committed
71 72 73 74 75 76 77
            this._paramName = newName;
        }
        else {
            throw new TypeError("Parameter must be valid iama-token or x-token");
        }
    }

78

Mark Stenglein's avatar
Mark Stenglein committed
79 80
    /**
     * Validates input param values and saves them to the object.
81 82 83
     *
     *     param-value = paramtext / quoted-string
     *
Mark Stenglein's avatar
Mark Stenglein committed
84 85 86 87
     * @author
     * @since 0.1.0
     * @param newValues The input values to be tested and saved.
     */
88 89 90 91 92 93 94 95 96 97 98 99
    set paramValues(newValues: string[]) {
        newValues.forEach(newValue => {
            if (
                !(Parameter.isParamText(newValue)) ||
                !(Parameter.isQuotedString(newValue))
            ) {
                throw new TypeError(
                    "param-value must either be valid paramtext or" +
                    "quoted-string"
                );
            }
        })
Mark Stenglein's avatar
Mark Stenglein committed
100 101 102
        this._paramValues = newValues;
    }

103

Mark Stenglein's avatar
Mark Stenglein committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    /**
     * Generates the proper string representation for a Parameter as defined by
     * RFC 5545:
     *
     *     param = param-name "=" param-value *("," param-value)
     *
     * @author Mark Stenglein
     * @since 0.1.0
     * @returns string Representation of the Parameter as defined in RFC 5545
     */
    public generate(): string {
        let outputString = this.paramName;
        /**
         * Goes through each parameter value and adds it, being sure to place
         * the comma for the 2nd parameter onwards.
         */
        for (let i = 0; i < this.paramValues.length; i++) {
            if (i !== 0) {
                outputString += ",";
            }
            outputString += this.paramValues[i];
        }

        return outputString;
    }
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205


    /**
     * Tests to make sure input is compliant with the definition of `param-text`
     *
     *     paramtext = *SAFE-CHAR
     *
     * @author Mark Stenglein
     * @since 0.1.0
     * @param testString string to be tested
     * @returns boolean If the input is valid param-test
     */
    public static isParamText(testString: string): boolean {
        return Parameter.isSafeChar(testString);
    }


    /**
     * Tests to make sure the input is compliant with the definition of
     * `SAFE-CHAR`
     *
     *     SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-US-ASCII
     *     ; Any character except CONTROL, DQUOTE, ";", ":", ","
     *
     * @author Mark Stenglein
     * @since 0.1.0
     * @param testString string to be tested
     * @returns boolean If the input is valid SAFE-CHAR
     *
     * TODO: verify this regex
     */
    public static isSafeChar(testString: string): boolean {
        return /[\s\x21\x23-\x2b\x2d-\x39\x3c-\x7e\x80-\xff]/.test(testString);
    }


    /**
     * Tests to make sure the input is compliant with the definition of
     * `quoted-string`
     *
     *     quoted-string = DQUOTE *QSAFE-CHAR DQUOTE
     *
     * @author Mark Stenglein
     * @since 0.1.0
     * @param testString string to be tested
     * @returns boolean If the input is a valid `quoted-string`
     */
    public static isQuotedString(test: string): boolean {
        let result = false;
        if (
            test.charAt(0) === "\"" &&
            test.charAt(test.length - 1) === "\"" &&
            Parameter.isQSafeChar(test.substring(1, test.length - 1))
        ) {
            result = true;
        }
        return result;
    }


    /**
     * Tests to make sure the input is compliant with the definition of
     * `QSAFE-CHAR`
     *
     *     QSAFE-CHAR = WSP / %x21 / %x23-7E / NON-US-ASCII
     *     ; Any character except CONTROL and DQUOTE
     *
     * @author Mark Stenglein
     * @since 0.1.0
     * @param test string to be tested
     * @returns boolean If the input is a valid `QSAFE-CHAR` string
     *
     * TODO: verify this regex
     */
    public static isQSafeChar(test: string): boolean {
        return /[\s\x21\x23-\x7e\x80-\xff]/.test(test);
    }
Mark Stenglein's avatar
Mark Stenglein committed
206
}