-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathencode.ts
179 lines (169 loc) · 7.55 KB
/
encode.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
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
/*
* @nevware21/ts-utils
* https://github.com/nevware21/ts-utils
*
* Copyright (c) 2022 NevWare21 Solutions LLC
* Licensed under the MIT license.
*/
import { NULL_VALUE, TO_STRING, UNDEF_VALUE } from "../internal/constants";
import { asString } from "../string/as_string";
import { strCamelCase } from "../string/conversion";
import { strPadStart } from "../string/pad";
import { strUpper } from "../string/upper_lower";
import { isNumber, isString, isUndefined } from "./base";
import { dumpObj } from "./diagnostics";
const DBL_QUOTE = "\"";
const INVALID_JS_NAME = /([^\w\d_$])/g;
let _htmlEntityCache: { [key: string]: string};
/**
* Validates that the string name conforms to the JS IdentifierName specification and if not
* normalizes the name so that it would. This method does not identify or change any keywords
* meaning that if you pass in a known keyword the same value will be returned.
* @since 0.9.0
* @group Conversion
* @group Value
* @param jsName - The string value to validate
* @param camelCase - Optionally (see [1]) convert into CamelCase with the leading character either
* - `true` =\> lowercase
* - 'false' =\> uppercase
* - undefined =\> not converted
* @return The original string name, if it conforms to the JS naming convention otherwise an encoded version.
*
* **[1]**: Camel casing the name will remove all non-word characters from the result
* so you will NOT end up with any leading, embedded or trailing `_` characters which may cause
* duplicate results for different string values.
* @example
* ```ts
* normalizeJsName("HelloDarkness"); // "HelloDarkness"
* normalizeJsName("Hello Darkness"); // "Hello_Darkness"
* normalizeJsName("hello Darkness"); // "hello_Darkness"
* normalizeJsName("hello Darkness"); // "hello_Darkness"
* normalizeJsName("hello.Darkness"); // "hello_Darkness"
* normalizeJsName("hello-Darkness"); // "hello_Darkness"
* normalizeJsName("hello_Darkness"); // "hello_Darkness"
* normalizeJsName("abc-123"); // "abc_123"
* normalizeJsName("0abc0"); // "0abc0"
* normalizeJsName("\"HelloDarkness\""); // "_HelloDarkness_"
* normalizeJsName("\"Hello Darkness\""); // "_Hello_Darkness_"
* normalizeJsName("\"hello Darkness\""); // "_hello_Darkness_"
* normalizeJsName("\"hello Darkness\""); // "_hello_Darkness_"
* normalizeJsName("\"hello .,#[]Darkness\""); // "_hello______Darkness_"
*
* normalizeJsName("HelloDarkness", true); // "helloDarkness"
* normalizeJsName("Hello Darkness", true); // "helloDarkness"
* normalizeJsName("hello Darkness", true); // "helloDarkness"
* normalizeJsName("hello Darkness", true); // "helloDarkness"
* normalizeJsName("hello.Darkness", true); // "helloDarkness"
* normalizeJsName("hello-Darkness", true); // "helloDarkness"
* normalizeJsName("hello_Darkness", true); // "helloDarkness"
* normalizeJsName("abc-123", true); // "abc123"
* normalizeJsName("0abc0", true); // "0abc0"
* normalizeJsName("\"HelloDarkness\"", true); // "helloDarkness"
* normalizeJsName("\"Hello Darkness\"", true); // "helloDarkness"
* normalizeJsName("hello \"Darkness\"", true); // "helloDarkness"
* normalizeJsName("hello \"Darkness\"", true); // "helloDarkness"
* normalizeJsName("\"hello .,#[]Darkness\"", true); // "helloDarkness"
* ```
*/
/*#__NO_SIDE_EFFECTS__*/
export function normalizeJsName(jsName: string, camelCase?: boolean): string {
let result = asString(jsName).replace(INVALID_JS_NAME, "_");
return !isUndefined(camelCase) ? strCamelCase(result, !camelCase) : result;
}
/**
* Encode the value into a JSON string, if the provided value is a string this will encode
* any character that is not an alpha, numeric, space or some special characters as `\uXXXX`
* and will always be returned wrapped in double quotes `"xxx"`, if the value is any other
* object it will be encoded using JSON.stringify() and if there is an exception encoding
* with JSON.stringify() it will return the exception as a string using {@link dumpObj}().
* @since 0.9.0
* @group Conversion
* @group Value
* @param value - The value to be encoded as JSON
* @param format - Identifies whether the JSON value should be formatted when an object
* - `true` - Format with 4 spaces
* - 'number' - The number of spaces to format with
* - `false` (or not Truthy) - Do not format*
* @returns A JSON encoded string representation of the value.
* @example
* ```ts
* // String values
* encodeAsJson("abc.123"); // "\"abc.123\""
* encodeAsJson("321-abc"); // "\"321-abc\""
* encodeAsJson("Hello darkness, my \"old\" friend..."); // "\"Hello darkness, my \\\"old\\\" friend...\""
* encodeAsJson("Hello: Darkness"); // "\"Hello: Darkness\""
* encodeAsJson("Hello\\u003A Darkness"); // "\"Hello\\\\u003A Darkness\""
* encodeAsJson("`!@#$%^&*()_-+=[]{}:;'<>?"); // "\"\\u0060!@#$%^&*()_-+=[]{}:;\\u0027<>?\""
* encodeAsJson("0"); // "\"0\""
* encodeAsJson("1"); // "\"1\""
*
* encodeAsJson([]); // "[]"
* encodeAsJson(["A"]); // "[\"A\"]"
* encodeAsJson([0]); // "[0]"
* encodeAsJson([false]); // "[false]"
* encodeAsJson(new Array(1)); // "[null]"
* encodeAsJson(true); // "true",
* encodeAsJson(false); // "false"
*
* encodeAsJson({}); // "{}"
* encodeAsJson({ Hello: "Darkness" }); // "{\"Hello\":\"Darkness\"}");
* ```
*/
/*#__NO_SIDE_EFFECTS__*/
export function encodeAsJson<T>(value: T, format?: boolean | number): string {
let result: string;
if (isString(value)) {
// encode if a character is not an alpha, numeric, space or some special characters
result = DBL_QUOTE + value.replace(/[^\w .,\-!@#$%\^&*\(\)_+={}\[\]:;|<>?]/g, (match) => {
if(match === DBL_QUOTE || match === "\\") {
return "\\" + match;
}
var hex = match.charCodeAt(0)[TO_STRING](16);
return "\\u" + strPadStart(strUpper(hex), 4, "0");
}) + DBL_QUOTE;
} else {
try {
result = JSON.stringify(value, NULL_VALUE, format ? (isNumber(format) ? format : 4) : UNDEF_VALUE);
} catch (e) {
// Unable to convert to JSON
result = DBL_QUOTE + dumpObj(e) + DBL_QUOTE;
}
}
return result;
}
/**
* Encode the provided string to a safe HTML form, converting the base `&`, `<`, `>`, `\"` and `'`
* characters into their HTML encoded representations
* @since 0.9.0
* @group Conversion
* @group Value
* @param value - The string value to be converted into a HTML safe form
* @returns The converted string as HTML
* @example
* ```ts
* encodeAsHtml("HelloDarkness"); // "HelloDarkness"
* encodeAsHtml("Hello Darkness"); // "Hello Darkness"
* encodeAsHtml("hello.Darkness"); // "hello.Darkness"
* encodeAsHtml("hello-Darkness"); // "hello-Darkness"
* encodeAsHtml("hello_Darkness"); // "hello_Darkness"
* encodeAsHtml("abc-123"); // "abc-123"
* encodeAsHtml("0abc0"); // "0abc0"
* encodeAsHtml("\"HelloDarkness\""); // ""HelloDarkness""
* encodeAsHtml("\"Hello Darkness\""); // ""Hello Darkness""
* encodeAsHtml("\"hello Darkness\""); // ""hello Darkness""
* encodeAsHtml("\"hello Darkness\""); // ""hello Darkness""
* encodeAsHtml("\"hello .,#<[]>Darkness\""); // ""hello .,#<[]>Darkness""
* encodeAsHtml("<script src=\"javascript:alert('Hello');\"></script>"); // "<script src="javascript:alert('Hello');"></script>"
* ```
*/
/*#__NO_SIDE_EFFECTS__*/
export function encodeAsHtml(value: string) {
!_htmlEntityCache && (_htmlEntityCache = {
"&": "amp",
"<": "lt",
">": "gt",
"\"": "quot",
"'": "#39"
});
return asString(value).replace(/[&<>"']/g, match => "&" + _htmlEntityCache[match] + ";");
}