Comparing version 3.2.0 to 3.3.0
{ | ||
"name": "slug", | ||
"description": "slugifies even utf-8 chars!", | ||
"version": "3.2.0", | ||
"version": "3.3.0", | ||
"homepage": "https://github.com/Trott/slug", | ||
@@ -22,14 +22,16 @@ "author": "dodo (https://github.com/dodo)", | ||
"scripts": { | ||
"test": "standard && c8 mocha test/**/*.js --reporter spec --colors && karma start --single-run --browsers ChromeHeadless,FirefoxHeadless .karma.config.js" | ||
"test": "standard && nyc --reporter none mocha test/**/*.js && karma start --single-run --browsers ChromeHeadless,FirefoxHeadless .karma.config.js && nyc report --reporter=text --reporter=html && nyc check-coverage --lines 100 --branches 100 --statements 100 --functions 100" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"c8": "^7.0.0", | ||
"chai": "^4.2.0", | ||
"karma": "^5.0.7", | ||
"karma": "^5.0.9", | ||
"karma-chai": "^0.1.0", | ||
"karma-chrome-launcher": "^3.1.0", | ||
"karma-coverage": "^2.0.2", | ||
"karma-firefox-launcher": "^1.3.0", | ||
"karma-mocha": "^2.0.1", | ||
"mocha": "^7.0.0", | ||
"nyc": "^15.0.1", | ||
"requirejs": "^2.3.6", | ||
"standard": "^14.3.3" | ||
@@ -36,0 +38,0 @@ }, |
62
slug.js
@@ -0,3 +1,54 @@ | ||
/* global btoa */ | ||
(function (root) { | ||
var base64 | ||
// This function's sole purpose is to help us ignore lone surrogates so that | ||
// malformed strings don't throw in the browser while being processed | ||
// permissively in Node.js. If we didn't care about parity, we could get rid | ||
// of it. | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt | ||
function getWholeCharAndI (str, i) { | ||
const code = str.charCodeAt(i) | ||
// This is a coherence check. `code` should never be `NaN`. | ||
/* istanbul ignore if */ | ||
if (Number.isNaN(code)) { | ||
throw new RangeError(`Index ${i} out of range for string "${str}"; please open an issue at https://github.com/Trott/slug/issues/new`) | ||
} | ||
if (code < 0xD800 || code > 0xDFFF) { | ||
return [str.charAt(i), i] // Non-surrogate character, keeping 'i' the same | ||
} | ||
// High surrogate | ||
if (code >= 0xD800 && code <= 0xDBFF) { | ||
if (str.length <= (i + 1)) { | ||
// High surrogate without following low surrogate | ||
return [' ', i] | ||
} | ||
const next = str.charCodeAt(i + 1) | ||
if (next < 0xDC00 || next > 0xDFFF) { | ||
// High surrogate without following low surrogate | ||
return [' ', i] | ||
} | ||
return [str.charAt(i) + str.charAt(i + 1), i + 1] | ||
} | ||
// Low surrogate (0xDC00 <= code && code <= 0xDFFF) | ||
if (i === 0) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
} | ||
const prev = str.charCodeAt(i - 1) | ||
/* istanbul ignore else */ | ||
if (prev < 0xD800 || prev > 0xDBFF) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
} | ||
/* istanbul ignore next */ | ||
throw new Error(`String "${str}" reaches code believed to be unreachable; please open an issue at https://github.com/Trott/slug/issues/new`) | ||
} | ||
if (typeof window === 'undefined') { | ||
@@ -9,3 +60,2 @@ base64 = function (input) { | ||
base64 = function (input) { | ||
// eslint-disable-next-line no-undef | ||
return btoa(unescape(encodeURIComponent(input))) | ||
@@ -19,3 +69,9 @@ } | ||
if (result === '') { | ||
result = slugify(base64(string), opts) | ||
// Get rid of lone surrogates. | ||
let input = '' | ||
for (let i = 0, chr; i < string.length; i++) { | ||
[chr, i] = getWholeCharAndI(string, i) | ||
input += chr | ||
} | ||
result = slugify(base64(input), opts) | ||
} | ||
@@ -34,3 +90,3 @@ return result | ||
if (typeof string !== 'string') { | ||
throw new Error('slug() requires a string argument') | ||
throw new Error(`slug() requires a string argument, received ${typeof string}`) | ||
} | ||
@@ -37,0 +93,0 @@ if (typeof opts === 'string') { opts = { replacement: opts } } |
Sorry, the diff of this file is not supported yet
21682
809
11