Comparing version 1.1.1 to 1.2.1
@@ -5,2 +5,6 @@ # Change Log | ||
## 1.2.1 | ||
- Publish error messages in `error.ts` | ||
- Refactor `index.ts` methods | ||
## 1.1.1 | ||
@@ -7,0 +11,0 @@ - Refactor tests and add more tests |
@@ -14,3 +14,3 @@ /** | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
define(["require", "exports", "./errors"], factory); | ||
} | ||
@@ -20,2 +20,3 @@ })(function (require, exports) { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const errors_1 = require("./errors"); | ||
/** | ||
@@ -27,10 +28,23 @@ * Parse a string as a base-16 number. This is more strict than parseInt as it | ||
*/ | ||
function hexToInt(hex) { | ||
if (hex.match(/[^a-f0-9]/i) !== null) { | ||
// Matches the first non-hex symbol in the string | ||
return NaN; | ||
function parseHexToInt(hex) { | ||
const isOnlyHexChars = !hex.match(/[^a-f0-9]/i); | ||
return isOnlyHexChars ? parseInt(hex, 16) : NaN; | ||
} | ||
/** | ||
* Check the validity and length of a four-digit hexadecimal code. | ||
* @param hex The string to validate and parse. | ||
* @param errorName The name of the error message to throw a `SyntaxError` with | ||
* if `hex` is invalid. | ||
* @param enforcedLength If provided, will throw an error if `hex` is not this | ||
* long exactly. | ||
* @returns The parsed code. | ||
* @throws {SyntaxError} If the code is not valid. | ||
*/ | ||
function validateAndParseHex(hex, errorName, enforcedLength) { | ||
const parsedHex = parseHexToInt(hex); | ||
if (Number.isNaN(parsedHex) || | ||
(enforcedLength && hex.length !== enforcedLength)) { | ||
throw new SyntaxError(errors_1.errorMessages.get(errorName)); | ||
} | ||
else { | ||
return parseInt(hex, 16); | ||
} | ||
return parsedHex; | ||
} | ||
@@ -45,8 +59,4 @@ /** | ||
function parseHexadecimalCode(code) { | ||
const codeNumber = hexToInt(code); | ||
if (code.length !== 2 || Number.isNaN(codeNumber)) { | ||
// ie, "\xF" or "\x$$" | ||
throw new SyntaxError("malformed hexadecimal character escape sequence"); | ||
} | ||
return String.fromCharCode(codeNumber); | ||
const parsedCode = validateAndParseHex(code, "malformedHexadecimal", 2); | ||
return String.fromCharCode(parsedCode); | ||
} | ||
@@ -63,13 +73,5 @@ /** | ||
function parseUnicodeCode(code, surrogateCode) { | ||
const parsedCode = hexToInt(code); | ||
if (code.length !== 4 || Number.isNaN(parsedCode)) { | ||
// ie, "\u$$$$" or "\uF8" | ||
throw new SyntaxError("malformed Unicode character escape sequence"); | ||
} | ||
const parsedCode = validateAndParseHex(code, "malformedUnicode", 4); | ||
if (surrogateCode !== undefined) { | ||
const parsedSurrogateCode = hexToInt(surrogateCode); | ||
if (surrogateCode.length !== 4 || Number.isNaN(parsedSurrogateCode)) { | ||
// ie, "\u00FF\uF" or "\u00FF\u$$$$" | ||
throw new SyntaxError("malformed Unicode character escape sequence"); | ||
} | ||
const parsedSurrogateCode = validateAndParseHex(surrogateCode, "malformedUnicode", 4); | ||
return String.fromCharCode(parsedCode, parsedSurrogateCode); | ||
@@ -80,2 +82,10 @@ } | ||
/** | ||
* Test if the text is surrounded by curly braces (`{}`). | ||
* @param text Text to check. | ||
* @returns `true` if the text is in the form `{*}`. | ||
*/ | ||
function isCurlyBraced(text) { | ||
return text.charAt(0) === "{" && text.charAt(text.length - 1) === "}"; | ||
} | ||
/** | ||
* Parse a Unicode code point escape code. | ||
@@ -88,10 +98,7 @@ * @param codePoint A unicode escape code, including the surrounding curly | ||
function parseUnicodeCodePointCode(codePoint) { | ||
const lastIndex = codePoint.length - 1; | ||
const parsedCode = hexToInt(codePoint.substring(1, lastIndex)); | ||
if (codePoint.charAt(0) !== "{" || | ||
codePoint.charAt(lastIndex) !== "}" || | ||
Number.isNaN(parsedCode)) { | ||
// ie, "\u$$$$" or "\uF8" | ||
throw new SyntaxError("malformed Unicode character escape sequence"); | ||
if (!isCurlyBraced(codePoint)) { | ||
throw new SyntaxError(errors_1.errorMessages.get("malformedUnicode")); | ||
} | ||
const withoutBraces = codePoint.slice(1, -1); | ||
const parsedCode = validateAndParseHex(withoutBraces, "malformedUnicode"); | ||
try { | ||
@@ -101,8 +108,5 @@ return String.fromCodePoint(parsedCode); | ||
catch (err) { | ||
if (err instanceof RangeError) { | ||
throw new SyntaxError("Unicode codepoint must not be greater than 0x10FFFF in escape sequence"); | ||
} | ||
else { | ||
throw err; | ||
} | ||
throw err instanceof RangeError | ||
? new SyntaxError(errors_1.errorMessages.get("codePointLimit")) | ||
: err; | ||
} | ||
@@ -112,37 +116,29 @@ } | ||
if (error) { | ||
throw new SyntaxError('"0"-prefixed octal literals and octal escape sequences are ' + | ||
'deprecated; for octal literals use the "0o" prefix instead'); | ||
throw new SyntaxError(errors_1.errorMessages.get("octalDeprecation")); | ||
} | ||
else { | ||
// The original regex only allows digits so we don't need to have a strict | ||
// octal parser like hexToInt | ||
const parsedCode = parseInt(code, 8); | ||
return String.fromCharCode(parsedCode); | ||
} | ||
// The original regex only allows digits so we don't need to have a strict | ||
// octal parser like hexToInt. Length is not enforced for octals. | ||
const parsedCode = parseInt(code, 8); | ||
return String.fromCharCode(parsedCode); | ||
} | ||
/** | ||
* Map of unescaped letters to their corresponding special JS escape characters. | ||
* Intentionally does not include characters that map to themselves like "\'". | ||
*/ | ||
const singleCharacterEscapes = new Map([ | ||
["b", "\b"], | ||
["f", "\f"], | ||
["n", "\n"], | ||
["r", "\r"], | ||
["t", "\t"], | ||
["v", "\v"], | ||
["0", "\0"] | ||
]); | ||
/** | ||
* Parse a single character escape sequence and return the matching character. | ||
* If none is matched, returns `code`. Naively assumes `code.length == 1`. | ||
* If none is matched, defaults to `code`. | ||
* @param code A single character code. | ||
*/ | ||
function parseSingleCharacterCode(code) { | ||
switch (code) { | ||
case "b": | ||
return "\b"; | ||
case "f": | ||
return "\f"; | ||
case "n": | ||
return "\n"; | ||
case "r": | ||
return "\r"; | ||
case "t": | ||
return "\t"; | ||
case "v": | ||
return "\v"; | ||
case "0": | ||
return "\0"; | ||
default: | ||
// Handles quotes and backslashes as well as anything else | ||
return code; | ||
} | ||
return singleCharacterEscapes.get(code) || code; | ||
} | ||
@@ -182,26 +178,24 @@ /** | ||
} | ||
else if (singleCharacter !== undefined) { | ||
return parseSingleCharacterCode(singleCharacter); | ||
} | ||
else if (hex !== undefined) { | ||
if (hex !== undefined) { | ||
return parseHexadecimalCode(hex); | ||
} | ||
else if (codePoint !== undefined) { | ||
if (codePoint !== undefined) { | ||
return parseUnicodeCodePointCode(codePoint); | ||
} | ||
else if (unicodeWithSurrogate !== undefined) { | ||
if (unicodeWithSurrogate !== undefined) { | ||
return parseUnicodeCode(unicodeWithSurrogate, surrogate); | ||
} | ||
else if (unicode !== undefined) { | ||
if (unicode !== undefined) { | ||
return parseUnicodeCode(unicode); | ||
} | ||
else if (octal === "0") { | ||
if (octal === "0") { | ||
return "\0"; | ||
} | ||
else if (octal !== undefined) { | ||
if (octal !== undefined) { | ||
return parseOctalCode(octal, !allowOctals); | ||
} | ||
else { | ||
throw new SyntaxError("malformed escape sequence at end of string"); | ||
if (singleCharacter !== undefined) { | ||
return parseSingleCharacterCode(singleCharacter); | ||
} | ||
throw new SyntaxError(errors_1.errorMessages.get("endOfString")); | ||
}); | ||
@@ -208,0 +202,0 @@ } |
@@ -1,1 +0,1 @@ | ||
!function(e){if("object"==typeof module&&"object"==typeof module.exports){var r=e(require,exports);void 0!==r&&(module.exports=r)}else"function"==typeof define&&define.amd&&define(["require","exports"],e)}(function(e,r){"use strict";function t(e){return null!==e.match(/[^a-f0-9]/i)?NaN:parseInt(e,16)}function n(e,r){const n=t(e);if(4!==e.length||Number.isNaN(n))throw new SyntaxError("malformed Unicode character escape sequence");if(void 0!==r){const e=t(r);if(4!==r.length||Number.isNaN(e))throw new SyntaxError("malformed Unicode character escape sequence");return String.fromCharCode(n,e)}return String.fromCharCode(n)}Object.defineProperty(r,"__esModule",{value:!0});const o=/\\(?:(\\)|x([\s\S]{0,2})|u(\{[^}]*\}?)|u([\s\S]{4})\\u([^{][\s\S]{0,3})|u([\s\S]{0,4})|([0-3]?[0-7]{1,2})|([\s\S])|$)/g;r.default=function(e,r=!1){return e.replace(o,function(e,o,a,i,c,u,s,f,d){if(void 0!==o)return"\\";if(void 0!==d)return function(e){switch(e){case"b":return"\b";case"f":return"\f";case"n":return"\n";case"r":return"\r";case"t":return"\t";case"v":return"\v";case"0":return"\0";default:return e}}(d);if(void 0!==a)return function(e){const r=t(e);if(2!==e.length||Number.isNaN(r))throw new SyntaxError("malformed hexadecimal character escape sequence");return String.fromCharCode(r)}(a);if(void 0!==i)return function(e){const r=e.length-1,n=t(e.substring(1,r));if("{"!==e.charAt(0)||"}"!==e.charAt(r)||Number.isNaN(n))throw new SyntaxError("malformed Unicode character escape sequence");try{return String.fromCodePoint(n)}catch(e){throw e instanceof RangeError?new SyntaxError("Unicode codepoint must not be greater than 0x10FFFF in escape sequence"):e}}(i);if(void 0!==c)return n(c,u);if(void 0!==s)return n(s);if("0"===f)return"\0";if(void 0!==f)return function(e,r=!1){if(r)throw new SyntaxError('"0"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the "0o" prefix instead');{const r=parseInt(e,8);return String.fromCharCode(r)}}(f,!r);throw new SyntaxError("malformed escape sequence at end of string")})}}); | ||
!function(r){if("object"==typeof module&&"object"==typeof module.exports){var e=r(require,exports);void 0!==e&&(module.exports=e)}else"function"==typeof define&&define.amd&&define(["require","exports","./errors"],r)}(function(r,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const t=r("./errors");function o(r,e,o){const n=function(r){return r.match(/[^a-f0-9]/i)?NaN:parseInt(r,16)}(r);if(Number.isNaN(n)||o&&r.length!==o)throw new SyntaxError(t.errorMessages.get(e));return n}function n(r,e){const t=o(r,"malformedUnicode",4);if(void 0!==e){const r=o(e,"malformedUnicode",4);return String.fromCharCode(t,r)}return String.fromCharCode(t)}const i=new Map([["b","\b"],["f","\f"],["n","\n"],["r","\r"],["t","\t"],["v","\v"],["0","\0"]]);const f=/\\(?:(\\)|x([\s\S]{0,2})|u(\{[^}]*\}?)|u([\s\S]{4})\\u([^{][\s\S]{0,3})|u([\s\S]{0,4})|([0-3]?[0-7]{1,2})|([\s\S])|$)/g;e.default=function(r,e=!1){return r.replace(f,function(r,f,s,a,u,c,d,m,g){if(void 0!==f)return"\\";if(void 0!==s)return function(r){const e=o(r,"malformedHexadecimal",2);return String.fromCharCode(e)}(s);if(void 0!==a)return function(r){if("{"!==(e=r).charAt(0)||"}"!==e.charAt(e.length-1))throw new SyntaxError(t.errorMessages.get("malformedUnicode"));var e;const n=o(r.slice(1,-1),"malformedUnicode");try{return String.fromCodePoint(n)}catch(r){throw r instanceof RangeError?new SyntaxError(t.errorMessages.get("codePointLimit")):r}}(a);if(void 0!==u)return n(u,c);if(void 0!==d)return n(d);if("0"===m)return"\0";if(void 0!==m)return function(r,e=!1){if(e)throw new SyntaxError(t.errorMessages.get("octalDeprecation"));const o=parseInt(r,8);return String.fromCharCode(o)}(m,!e);if(void 0!==g)return l=g,i.get(l)||l;var l;throw new SyntaxError(t.errorMessages.get("endOfString"))})}}); |
{ | ||
"name": "unraw", | ||
"version": "1.1.1", | ||
"version": "1.2.1", | ||
"description": "Convert raw escape sequences to their respective characters (undo String.raw).", | ||
@@ -11,3 +11,3 @@ "main": "dist/index.js", | ||
"build": "tsc", | ||
"minify": "node-minify --compressor uglify-es --input dist/index.js --output dist/index.min.js", | ||
"minify": "node-minify --compressor uglify-es --input dist/index.js --output dist/index.min.js & node-minify --compressor uglify-es --input dist/errors.js --output dist/errors.min.js", | ||
"test": "ts-mocha src/**/*.test.ts", | ||
@@ -40,3 +40,3 @@ "testWithCoverage": "npm run build && nyc --reporter=text mocha src/**/*.test.ts --require ts-node/register --require source-map-support/register", | ||
"eslint-config-google": "^0.13.0", | ||
"eslint-plugin-jsdoc": "^15.7.2", | ||
"eslint-plugin-jsdoc": "^15.8.0", | ||
"eslint-plugin-mocha": "^6.0.0", | ||
@@ -72,3 +72,6 @@ "mocha": "^6.2.0", | ||
"dist/index.js.map", | ||
"dist/index.min.js" | ||
"dist/index.min.js", | ||
"dist/errors.js", | ||
"dist/errors.js.map", | ||
"dist/errors.min.js" | ||
], | ||
@@ -79,2 +82,3 @@ "keywords": [ | ||
"raw strings", | ||
"cooked strings", | ||
"template literal", | ||
@@ -81,0 +85,0 @@ "unescape", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24607
12
244