From 436bdb49acf74483fb74376330caddcb2aeb7d22 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:07:44 -0700 Subject: [PATCH 1/7] Rename from `.mjs` => `.js` --- src/{underscore-plus.mjs => underscore-plus.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{underscore-plus.mjs => underscore-plus.js} (100%) diff --git a/src/underscore-plus.mjs b/src/underscore-plus.js similarity index 100% rename from src/underscore-plus.mjs rename to src/underscore-plus.js From 6b5bd4b75242c6cfca3697d3e983ed0aa087ed8c Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:24:28 -0700 Subject: [PATCH 2/7] Shift how we export --- src/underscore-plus.js | 634 +++++++++++++++++++---------------------- 1 file changed, 301 insertions(+), 333 deletions(-) diff --git a/src/underscore-plus.js b/src/underscore-plus.js index cda78b5..a04a267 100644 --- a/src/underscore-plus.js +++ b/src/underscore-plus.js @@ -1,7 +1,4 @@ -export * from 'underscore' - -// import * as _ from 'underscore' // if we needed all -import {every, flatten, has, include, isArray, isElement, isEqual as _isEqual, isFunction, isObject, isRegExp, uniq} from "underscore"; +const {every, flatten, has, include, isArray, isElement, isEqual: _isEqual, isFunction, isObject, isRegExp, uniq } = require("underscore"); const macModifierKeyMap = { cmd: '\u2318', @@ -64,333 +61,6 @@ function splitKeyPath(keyPath) { const isPlainObject = value => isObject(value) && !isArray(value); -export function adviseBefore(object, methodName, advice) { - const original = object[methodName]; - return object[methodName] = function(...args) { - if (advice.apply(this, args) !== false) { - return original.apply(this, args); - } - }; -} - -export function camelize(string) { - if (string) { - return string.replace(/[_-]+(\w)/g, m => m[1].toUpperCase()); - } else { - return ''; - } -} - -export function capitalize(word) { - if (!word) { return ''; } - - if (word.toLowerCase() === 'github') { - return 'GitHub'; - } else { - return word[0].toUpperCase() + word.slice(1); - } -} - -export function compactObject(object) { - const newObject = {}; - for (let key in object) { - const value = object[key]; - if (value != null) { newObject[key] = value; } - } - return newObject; -} - -export function dasherize(string) { - if (!string) { return ''; } - - string = string[0].toLowerCase() + string.slice(1); - return string.replace(/([A-Z])|(_)/g, function(m, letter) { - if (letter) { - return "-" + letter.toLowerCase(); - } else { - return "-"; - } - }); -} - -// Deep clones the given JSON object. -// -// `object` - The JSON object to clone. -// -// Returns a deep clone of the JSON object. -export function deepClone(object) { - if (isArray(object)) { - return object.map(value => deepClone(value)); - } else if (isObject(object) && !isFunction(object)) { - return mapObject(object, (key, value) => [key, deepClone(value)]); - } else { - return object; - } -} - -export function deepExtend(target) { - let result = target; - let i = 0; - while (++i < arguments.length) { - const object = arguments[i]; - if (isPlainObject(result) && isPlainObject(object)) { - const keys = Object.keys(object) - for (let key of keys) { - result[key] = deepExtend(result[key], object[key]); - } - } else { - result = deepClone(object); - } - } - return result; -} - -export function deepContains(array, target) { - if (array == null) { return false; } - for (let object of array) { - if (_isEqual(object, target)) { return true; } - } - return false; -} - -export function endsWith(string, suffix) { - if (suffix == null) { suffix = ''; } - if (string) { - return string.indexOf(suffix, string.length - suffix.length) !== -1; - } else { - return false; - } -} - -export function escapeAttribute(string) { - if (string) { - return string.replace(/"/g, '"').replace(/\n/g, '').replace(/\\/g, '-'); - } else { - return ''; - } -} - -export function escapeRegExp(string) { - if (string) { - return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } else { - return ''; - } -} - -export function humanizeEventName(eventName, eventDoc) { - const [namespace, event] = eventName.split(':'); - if (event == null) { return undasherize(namespace); } - - const namespaceDoc = undasherize(namespace); - if (eventDoc == null) { eventDoc = undasherize(event); } - - return `${namespaceDoc}: ${eventDoc}`; -} - -export function humanizeKey(key, platform=process.platform) { - if (!key) { return key; } - - const modifierKeyMap = platform === 'darwin' ? macModifierKeyMap : nonMacModifierKeyMap; - - if (modifierKeyMap[key]) { - return modifierKeyMap[key]; - } else if ((key.length === 1) && (shiftKeyMap[key] != null)) { - return [modifierKeyMap.shift, shiftKeyMap[key]]; - } else if ((key.length === 1) && (key === key.toUpperCase()) && (key.toUpperCase() !== key.toLowerCase())) { - return [modifierKeyMap.shift, key.toUpperCase()]; - } else if ((key.length === 1) || /f[0-9]{1,2}/.test(key)) { - return key.toUpperCase(); - } else { - if (platform === 'darwin') { - return key; - } else { - return capitalize(key); - } - } -} - -// Humanize the keystroke according to platform conventions. This method -// attempts to mirror the text the given keystroke would have if displayed in -// a system menu. -// -// keystroke - A String keystroke to humanize such as `ctrl-O`. -// platform - An optional String platform to humanize for (default: -// `process.platform`). -// -// Returns a humanized representation of the keystroke. -export function humanizeKeystroke(keystroke, platform=process.platform) { - if (!keystroke) { return keystroke; } - - const keystrokes = keystroke.split(' '); - const humanizedKeystrokes = []; - for (keystroke of keystrokes) { - let keys = []; - const splitKeystroke = keystroke.split('-'); - for (let index = 0; index < splitKeystroke.length; index++) { - // Check for consecutive dashes such as cmd-- - let key = splitKeystroke[index]; - if ((key === '') && (splitKeystroke[index-1] === '')) { key = '-'; } - if (key) { keys.push(humanizeKey(key, platform)); } - } - - keys = uniq(flatten(keys)); - if (platform === 'darwin') { - keys = keys.join(''); - } else { - keys = keys.join('+'); - } - humanizedKeystrokes.push(keys); - } - - return humanizedKeystrokes.join(' '); -} - -export function isSubset(potentialSubset, potentialSuperset) { - return every(potentialSubset, element => include(potentialSuperset, element)); -} - -export function losslessInvert(hash) { - const inverted = {}; - for (let key in hash) { - const value = hash[key]; - if (inverted[value] == null) { inverted[value] = []; } - inverted[value].push(key); - } - return inverted; -} - -// Transform the given object into another object. -// -// `object` - The object to transform. -// `iterator` - -// A function that takes `(key, value)` arguments and returns a -// `[key, value]` tuple. -// -// Returns a new object based with the key/values returned by the iterator. -export function mapObject(object, iterator) { - const newObject = {}; - const keys = Object.keys(object) - for (let key of keys) { - let value; - [key, value] = iterator(key, object[key]); - newObject[key] = value; - } - - return newObject; -} - -export function multiplyString(string, n) { - let finalString = ""; - let i = 0; - while (i < n) { - finalString += string; - i++; - } - return finalString; -} - -export function pluralize(count=0, singular, plural=singular+'s') { - if (count === 1) { - return `${count} ${singular}`; - } else { - return `${count} ${plural}`; - } -} - -export function remove(array, element) { - const index = array.indexOf(element); - if (index >= 0) { array.splice(index, 1); } - return array; -} - -export function setValueForKeyPath(object, keyPath, value) { - const keys = splitKeyPath(keyPath); - while (keys.length > 1) { - const key = keys.shift(); - if (object[key] == null) { object[key] = {}; } - object = object[key]; - } - if (value != null) { - object[keys.shift()] = value; - } else { - delete object[keys.shift()]; - } -} - -export function hasKeyPath(object, keyPath) { - const keys = splitKeyPath(keyPath); - for (let key of keys) { - if (!object.hasOwnProperty(key)) { return false; } - object = object[key]; - } - return true; -} - -export function spliceWithArray(originalArray, start, length, insertedArray, chunkSize=100000) { - if (insertedArray.length < chunkSize) { - originalArray.splice(start, length, ...insertedArray); - } else { - originalArray.splice(start, length); - for (let chunkStart = 0, end = insertedArray.length; chunkStart <= end; chunkStart += chunkSize) { - originalArray.splice(start + chunkStart, 0, ...insertedArray.slice(chunkStart, chunkStart + chunkSize)); - } - } -} - -export function sum(array) { - let sum = 0; - for (let elt of array) { sum += elt; } - return sum; -} - -export function uncamelcase(string) { - if (!string) { return ''; } - - const result = string.replace(/([A-Z])|_+/g, (match, letter='') => ` ${letter}`); - return capitalize(result.trim()); -} - -export function undasherize(string) { - if (string) { - return string.split('-').map(capitalize).join(' '); - } else { - return ''; - } -} - -export function underscore(string) { - if (!string) { return ''; } - - string = string[0].toLowerCase() + string.slice(1); - return string.replace(/([A-Z])|-+/g, (match, letter='') => `_${letter.toLowerCase()}`); -} - -export function valueForKeyPath(object, keyPath) { - const keys = splitKeyPath(keyPath); - for (let key of keys) { - object = object[key]; - if (object == null) { return; } - } - return object; -} - -export function isEqual(a, b, aStack, bStack) { - if (isArray(aStack) && isArray(bStack)) { - return isEqual_(a, b, aStack, bStack); - } else { - return isEqual_(a, b); - } -} - -export function isEqualForProperties(a, b, ...properties) { - // TODO is Array.from needed? - for (let property of Array.from(properties)) { - if (!_isEqual(a[property], b[property])) { return false; } - } - return true; -} - function isEqual_(a, b, aStack=[], bStack=[]) { if (a === b) { return _isEqual(a, b); } if (isFunction(a) || isFunction(b)) { return _isEqual(a, b); } @@ -458,5 +128,303 @@ function isEqual_(a, b, aStack=[], bStack=[]) { return equal; } -// TODO: Consider shorter variations of null checks: -// https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md#ds207-consider-shorter-variations-of-null-checks +module.exports = { + ...require("underscore"), + adviseBefore(object, methodName, advice) { + const original = object[methodName]; + return object[methodName] = function(...args) { + if (advice.apply(this, args) !== false) { + return original.apply(this, args); + } + }; + }, + camelize(string) { + if (string) { + return string.replace(/[_-]+(\w)/g, m => m[1].toUpperCase()); + } else { + return ''; + } + }, + capitalize(word) { + if (!word) { return ''; } + + if (word.toLowerCase() === 'github') { + return 'GitHub'; + } else { + return word[0].toUpperCase() + word.slice(1); + } + }, + compactObject(object) { + const newObject = {}; + for (let key in object) { + const value = object[key]; + if (value != null) { newObject[key] = value; } + } + return newObject; + }, + dasherize(string) { + if (!string) { return ''; } + + string = string[0].toLowerCase() + string.slice(1); + return string.replace(/([A-Z])|(_)/g, function(m, letter) { + if (letter) { + return "-" + letter.toLowerCase(); + } else { + return "-"; + } + }); + }, + // Deep clones the given JSON object. + // + // `object` - The JSON object to clone. + // + // Returns a deep clone of the JSON object. + deepClone(object) { + if (isArray(object)) { + return object.map(value => deepClone(value)); + } else if (isObject(object) && !isFunction(object)) { + return mapObject(object, (key, value) => [key, deepClone(value)]); + } else { + return object; + } + }, + deepExtend(target) { + let result = target; + let i = 0; + while (++i < arguments.length) { + const object = arguments[i]; + if (isPlainObject(result) && isPlainObject(object)) { + const keys = Object.keys(object) + for (let key of keys) { + result[key] = deepExtend(result[key], object[key]); + } + } else { + result = deepClone(object); + } + } + return result; + }, + deepContains(array, target) { + if (array == null) { return false; } + for (let object of array) { + if (_isEqual(object, target)) { return true; } + } + return false; + }, + endsWith(string, suffix) { + if (suffix == null) { suffix = ''; } + if (string) { + return string.indexOf(suffix, string.length - suffix.length) !== -1; + } else { + return false; + } + }, + escapeAttribute(string) { + if (string) { + return string.replace(/"/g, '"').replace(/\n/g, '').replace(/\\/g, '-'); + } else { + return ''; + } + }, + escapeRegExp(string) { + if (string) { + return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } else { + return ''; + } + }, + humanizeEventName(eventName, eventDoc) { + const [namespace, event] = eventName.split(':'); + if (event == null) { return undasherize(namespace); } + + const namespaceDoc = undasherize(namespace); + if (eventDoc == null) { eventDoc = undasherize(event); } + + return `${namespaceDoc}: ${eventDoc}`; + }, + humanizeKey(key, platform=process.platform) { + if (!key) { return key; } + + const modifierKeyMap = platform === 'darwin' ? macModifierKeyMap : nonMacModifierKeyMap; + + if (modifierKeyMap[key]) { + return modifierKeyMap[key]; + } else if ((key.length === 1) && (shiftKeyMap[key] != null)) { + return [modifierKeyMap.shift, shiftKeyMap[key]]; + } else if ((key.length === 1) && (key === key.toUpperCase()) && (key.toUpperCase() !== key.toLowerCase())) { + return [modifierKeyMap.shift, key.toUpperCase()]; + } else if ((key.length === 1) || /f[0-9]{1,2}/.test(key)) { + return key.toUpperCase(); + } else { + if (platform === 'darwin') { + return key; + } else { + return capitalize(key); + } + } + }, + // Humanize the keystroke according to platform conventions. This method + // attempts to mirror the text the given keystroke would have if displayed in + // a system menu. + // + // keystroke - A String keystroke to humanize such as `ctrl-O`. + // platform - An optional String platform to humanize for (default: + // `process.platform`). + // + // Returns a humanized representation of the keystroke. + humanizeKeystroke(keystroke, platform=process.platform) { + if (!keystroke) { return keystroke; } + + const keystrokes = keystroke.split(' '); + const humanizedKeystrokes = []; + for (keystroke of keystrokes) { + let keys = []; + const splitKeystroke = keystroke.split('-'); + for (let index = 0; index < splitKeystroke.length; index++) { + // Check for consecutive dashes such as cmd-- + let key = splitKeystroke[index]; + if ((key === '') && (splitKeystroke[index-1] === '')) { key = '-'; } + if (key) { keys.push(humanizeKey(key, platform)); } + } + + keys = uniq(flatten(keys)); + if (platform === 'darwin') { + keys = keys.join(''); + } else { + keys = keys.join('+'); + } + humanizedKeystrokes.push(keys); + } + + return humanizedKeystrokes.join(' '); + }, + isSubset(potentialSubset, potentialSuperset) { + return every(potentialSubset, element => include(potentialSuperset, element)); + }, + losslessInvert(hash) { + const inverted = {}; + for (let key in hash) { + const value = hash[key]; + if (inverted[value] == null) { inverted[value] = []; } + inverted[value].push(key); + } + return inverted; + }, + // Transform the given object into another object. + // + // `object` - The object to transform. + // `iterator` - + // A function that takes `(key, value)` arguments and returns a + // `[key, value]` tuple. + // + // Returns a new object based with the key/values returned by the iterator. + mapObject(object, iterator) { + const newObject = {}; + const keys = Object.keys(object) + for (let key of keys) { + let value; + [key, value] = iterator(key, object[key]); + newObject[key] = value; + } + + return newObject; + }, + multiplyString(string, n) { + let finalString = ""; + let i = 0; + while (i < n) { + finalString += string; + i++; + } + return finalString; + }, + pluralize(count=0, singular, plural=singular+'s') { + if (count === 1) { + return `${count} ${singular}`; + } else { + return `${count} ${plural}`; + } + }, + remove(array, element) { + const index = array.indexOf(element); + if (index >= 0) { array.splice(index, 1); } + return array; + }, + setValueForKeyPath(object, keyPath, value) { + const keys = splitKeyPath(keyPath); + while (keys.length > 1) { + const key = keys.shift(); + if (object[key] == null) { object[key] = {}; } + object = object[key]; + } + if (value != null) { + object[keys.shift()] = value; + } else { + delete object[keys.shift()]; + } + }, + hasKeyPath(object, keyPath) { + const keys = splitKeyPath(keyPath); + for (let key of keys) { + if (!object.hasOwnProperty(key)) { return false; } + object = object[key]; + } + return true; + }, + spliceWithArray(originalArray, start, length, insertedArray, chunkSize=100000) { + if (insertedArray.length < chunkSize) { + originalArray.splice(start, length, ...insertedArray); + } else { + originalArray.splice(start, length); + for (let chunkStart = 0, end = insertedArray.length; chunkStart <= end; chunkStart += chunkSize) { + originalArray.splice(start + chunkStart, 0, ...insertedArray.slice(chunkStart, chunkStart + chunkSize)); + } + } + }, + sum(array) { + let sum = 0; + for (let elt of array) { sum += elt; } + return sum; + }, + uncamelcase(string) { + if (!string) { return ''; } + + const result = string.replace(/([A-Z])|_+/g, (match, letter='') => ` ${letter}`); + return capitalize(result.trim()); + }, + undasherize(string) { + if (string) { + return string.split('-').map(capitalize).join(' '); + } else { + return ''; + } + }, + underscore(string) { + if (!string) { return ''; } + + string = string[0].toLowerCase() + string.slice(1); + return string.replace(/([A-Z])|-+/g, (match, letter='') => `_${letter.toLowerCase()}`); + }, + valueForKeyPath(object, keyPath) { + const keys = splitKeyPath(keyPath); + for (let key of keys) { + object = object[key]; + if (object == null) { return; } + } + return object; + }, + isEqual(a, b, aStack, bStack) { + if (isArray(aStack) && isArray(bStack)) { + return isEqual_(a, b, aStack, bStack); + } else { + return isEqual_(a, b); + } + }, + isEqualForProperties(a, b, ...properties) { + // TODO is Array.from needed? + for (let property of Array.from(properties)) { + if (!_isEqual(a[property], b[property])) { return false; } + } + return true; + } +}; From 77a6d650c1513545d7acf1b6d2391903e4ff5234 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:29:37 -0700 Subject: [PATCH 3/7] Fix references to our own exported functions --- src/underscore-plus.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/underscore-plus.js b/src/underscore-plus.js index a04a267..31e626f 100644 --- a/src/underscore-plus.js +++ b/src/underscore-plus.js @@ -181,9 +181,9 @@ module.exports = { // Returns a deep clone of the JSON object. deepClone(object) { if (isArray(object)) { - return object.map(value => deepClone(value)); + return object.map(value => this.deepClone(value)); } else if (isObject(object) && !isFunction(object)) { - return mapObject(object, (key, value) => [key, deepClone(value)]); + return this.mapObject(object, (key, value) => [key, this.deepClone(value)]); } else { return object; } @@ -196,10 +196,10 @@ module.exports = { if (isPlainObject(result) && isPlainObject(object)) { const keys = Object.keys(object) for (let key of keys) { - result[key] = deepExtend(result[key], object[key]); + result[key] = this.deepExtend(result[key], object[key]); } } else { - result = deepClone(object); + result = this.deepClone(object); } } return result; @@ -235,10 +235,10 @@ module.exports = { }, humanizeEventName(eventName, eventDoc) { const [namespace, event] = eventName.split(':'); - if (event == null) { return undasherize(namespace); } + if (event == null) { return this.undasherize(namespace); } - const namespaceDoc = undasherize(namespace); - if (eventDoc == null) { eventDoc = undasherize(event); } + const namespaceDoc = this.undasherize(namespace); + if (eventDoc == null) { eventDoc = this.undasherize(event); } return `${namespaceDoc}: ${eventDoc}`; }, @@ -259,7 +259,7 @@ module.exports = { if (platform === 'darwin') { return key; } else { - return capitalize(key); + return this.capitalize(key); } } }, @@ -284,7 +284,7 @@ module.exports = { // Check for consecutive dashes such as cmd-- let key = splitKeystroke[index]; if ((key === '') && (splitKeystroke[index-1] === '')) { key = '-'; } - if (key) { keys.push(humanizeKey(key, platform)); } + if (key) { keys.push(this.humanizeKey(key, platform)); } } keys = uniq(flatten(keys)); @@ -390,11 +390,11 @@ module.exports = { if (!string) { return ''; } const result = string.replace(/([A-Z])|_+/g, (match, letter='') => ` ${letter}`); - return capitalize(result.trim()); + return this.capitalize(result.trim()); }, undasherize(string) { if (string) { - return string.split('-').map(capitalize).join(' '); + return string.split('-').map(this.capitalize).join(' '); } else { return ''; } From bb6eb6d6a4b7186839f2eb0cc8a3dd074f760c62 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:29:52 -0700 Subject: [PATCH 4/7] Point specs in the right place --- spec/underscore-plus-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/underscore-plus-spec.coffee b/spec/underscore-plus-spec.coffee index 541f393..76226af 100644 --- a/spec/underscore-plus-spec.coffee +++ b/spec/underscore-plus-spec.coffee @@ -1,4 +1,4 @@ -_ = require '../lib/underscore-plus.js' +_ = require '../src/underscore-plus.js' describe "underscore extensions", -> describe "::adviseBefore(object, methodName, advice)", -> From e97c648d7a37c5d2b0e6d6166f6dc33a69102ffe Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:30:39 -0700 Subject: [PATCH 5/7] Remove build artifacts --- .gitignore | 1 - .npmignore | 1 - dist/underscore-plus.js | 647 ---------------------------------------- 3 files changed, 649 deletions(-) delete mode 100644 dist/underscore-plus.js diff --git a/.gitignore b/.gitignore index 9fad026..35e6d38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules/ -lib/ .DS_Store npm-debug.log package-lock.json diff --git a/.npmignore b/.npmignore index 4ac9f03..3a93ddb 100644 --- a/.npmignore +++ b/.npmignore @@ -4,5 +4,4 @@ script/ .DS_Store npm-debug.log .travis.yml -dist/ bower.json diff --git a/dist/underscore-plus.js b/dist/underscore-plus.js deleted file mode 100644 index 5f0a7a5..0000000 --- a/dist/underscore-plus.js +++ /dev/null @@ -1,647 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -var _exportNames = { - adviseBefore: true, - camelize: true, - capitalize: true, - compactObject: true, - dasherize: true, - deepClone: true, - deepExtend: true, - deepContains: true, - endsWith: true, - escapeAttribute: true, - escapeRegExp: true, - humanizeEventName: true, - humanizeKey: true, - humanizeKeystroke: true, - isSubset: true, - losslessInvert: true, - mapObject: true, - multiplyString: true, - pluralize: true, - remove: true, - setValueForKeyPath: true, - hasKeyPath: true, - spliceWithArray: true, - sum: true, - uncamelcase: true, - undasherize: true, - underscore: true, - valueForKeyPath: true, - isEqual: true, - isEqualForProperties: true -}; -exports.adviseBefore = adviseBefore; -exports.camelize = camelize; -exports.capitalize = capitalize; -exports.compactObject = compactObject; -exports.dasherize = dasherize; -exports.deepClone = deepClone; -exports.deepExtend = deepExtend; -exports.deepContains = deepContains; -exports.endsWith = endsWith; -exports.escapeAttribute = escapeAttribute; -exports.escapeRegExp = escapeRegExp; -exports.humanizeEventName = humanizeEventName; -exports.humanizeKey = humanizeKey; -exports.humanizeKeystroke = humanizeKeystroke; -exports.isSubset = isSubset; -exports.losslessInvert = losslessInvert; -exports.mapObject = mapObject; -exports.multiplyString = multiplyString; -exports.pluralize = pluralize; -exports.remove = remove; -exports.setValueForKeyPath = setValueForKeyPath; -exports.hasKeyPath = hasKeyPath; -exports.spliceWithArray = spliceWithArray; -exports.sum = sum; -exports.uncamelcase = uncamelcase; -exports.undasherize = undasherize; -exports.underscore = underscore; -exports.valueForKeyPath = valueForKeyPath; -exports.isEqual = isEqual; -exports.isEqualForProperties = isEqualForProperties; - -var _underscore = require("underscore"); - -Object.keys(_underscore).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _underscore[key]; - } - }); -}); -// import * as _ from 'underscore' // if we needed all -const macModifierKeyMap = { - cmd: '\u2318', - ctrl: '\u2303', - alt: '\u2325', - option: '\u2325', - shift: '\u21e7', - enter: '\u23ce', - left: '\u2190', - right: '\u2192', - up: '\u2191', - down: '\u2193', - cmdorctrl: '\u2318' -}; -const nonMacModifierKeyMap = { - cmd: 'Cmd', - ctrl: 'Ctrl', - alt: 'Alt', - option: 'Alt', - shift: 'Shift', - enter: 'Enter', - left: 'Left', - right: 'Right', - up: 'Up', - down: 'Down', - cmdorctrl: 'Ctrl' -}; // Human key combos should always explicitly state the shift key. This map is a disambiguator. -// 'shift-version': 'no-shift-version' - -const shiftKeyMap = { - '~': '`', - '_': '-', - '+': '=', - '|': '\\', - '{': '[', - '}': ']', - ':': ';', - '"': '\'', - '<': ',', - '>': '.', - '?': '/' -}; - -function splitKeyPath(keyPath) { - let startIndex = 0; - const keyPathArray = []; - - if (keyPath == null) { - return keyPathArray; - } - - for (let i = 0; i < keyPath.length; i++) { - const char = keyPath[i]; - - if (char === '.' && (i === 0 || keyPath[i - 1] !== '\\')) { - keyPathArray.push(keyPath.substring(startIndex, i)); - startIndex = i + 1; - } - } - - keyPathArray.push(keyPath.substr(startIndex, keyPath.length)); - return keyPathArray; -} - -const isPlainObject = value => (0, _underscore.isObject)(value) && !(0, _underscore.isArray)(value); - -function adviseBefore(object, methodName, advice) { - const original = object[methodName]; - return object[methodName] = function (...args) { - if (advice.apply(this, args) !== false) { - return original.apply(this, args); - } - }; -} - -function camelize(string) { - if (string) { - return string.replace(/[_-]+(\w)/g, m => m[1].toUpperCase()); - } else { - return ''; - } -} - -function capitalize(word) { - if (!word) { - return ''; - } - - if (word.toLowerCase() === 'github') { - return 'GitHub'; - } else { - return word[0].toUpperCase() + word.slice(1); - } -} - -function compactObject(object) { - const newObject = {}; - - for (let key in object) { - const value = object[key]; - - if (value != null) { - newObject[key] = value; - } - } - - return newObject; -} - -function dasherize(string) { - if (!string) { - return ''; - } - - string = string[0].toLowerCase() + string.slice(1); - return string.replace(/([A-Z])|(_)/g, function (m, letter) { - if (letter) { - return "-" + letter.toLowerCase(); - } else { - return "-"; - } - }); -} // Deep clones the given JSON object. -// -// `object` - The JSON object to clone. -// -// Returns a deep clone of the JSON object. - - -function deepClone(object) { - if ((0, _underscore.isArray)(object)) { - return object.map(value => deepClone(value)); - } else if ((0, _underscore.isObject)(object) && !(0, _underscore.isFunction)(object)) { - return mapObject(object, (key, value) => [key, deepClone(value)]); - } else { - return object; - } -} - -function deepExtend(target) { - let result = target; - let i = 0; - - while (++i < arguments.length) { - const object = arguments[i]; - - if (isPlainObject(result) && isPlainObject(object)) { - const keys = Object.keys(object); - - for (let key of keys) { - result[key] = deepExtend(result[key], object[key]); - } - } else { - result = deepClone(object); - } - } - - return result; -} - -function deepContains(array, target) { - if (array == null) { - return false; - } - - for (let object of array) { - if ((0, _underscore.isEqual)(object, target)) { - return true; - } - } - - return false; -} - -function endsWith(string, suffix) { - if (suffix == null) { - suffix = ''; - } - - if (string) { - return string.indexOf(suffix, string.length - suffix.length) !== -1; - } else { - return false; - } -} - -function escapeAttribute(string) { - if (string) { - return string.replace(/"/g, '"').replace(/\n/g, '').replace(/\\/g, '-'); - } else { - return ''; - } -} - -function escapeRegExp(string) { - if (string) { - return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } else { - return ''; - } -} - -function humanizeEventName(eventName, eventDoc) { - const [namespace, event] = eventName.split(':'); - - if (event == null) { - return undasherize(namespace); - } - - const namespaceDoc = undasherize(namespace); - - if (eventDoc == null) { - eventDoc = undasherize(event); - } - - return `${namespaceDoc}: ${eventDoc}`; -} - -function humanizeKey(key, platform = process.platform) { - if (!key) { - return key; - } - - const modifierKeyMap = platform === 'darwin' ? macModifierKeyMap : nonMacModifierKeyMap; - - if (modifierKeyMap[key]) { - return modifierKeyMap[key]; - } else if (key.length === 1 && shiftKeyMap[key] != null) { - return [modifierKeyMap.shift, shiftKeyMap[key]]; - } else if (key.length === 1 && key === key.toUpperCase() && key.toUpperCase() !== key.toLowerCase()) { - return [modifierKeyMap.shift, key.toUpperCase()]; - } else if (key.length === 1 || /f[0-9]{1,2}/.test(key)) { - return key.toUpperCase(); - } else { - if (platform === 'darwin') { - return key; - } else { - return capitalize(key); - } - } -} // Humanize the keystroke according to platform conventions. This method -// attempts to mirror the text the given keystroke would have if displayed in -// a system menu. -// -// keystroke - A String keystroke to humanize such as `ctrl-O`. -// platform - An optional String platform to humanize for (default: -// `process.platform`). -// -// Returns a humanized representation of the keystroke. - - -function humanizeKeystroke(keystroke, platform = process.platform) { - if (!keystroke) { - return keystroke; - } - - const keystrokes = keystroke.split(' '); - const humanizedKeystrokes = []; - - for (keystroke of keystrokes) { - let keys = []; - const splitKeystroke = keystroke.split('-'); - - for (let index = 0; index < splitKeystroke.length; index++) { - // Check for consecutive dashes such as cmd-- - let key = splitKeystroke[index]; - - if (key === '' && splitKeystroke[index - 1] === '') { - key = '-'; - } - - if (key) { - keys.push(humanizeKey(key, platform)); - } - } - - keys = (0, _underscore.uniq)((0, _underscore.flatten)(keys)); - - if (platform === 'darwin') { - keys = keys.join(''); - } else { - keys = keys.join('+'); - } - - humanizedKeystrokes.push(keys); - } - - return humanizedKeystrokes.join(' '); -} - -function isSubset(potentialSubset, potentialSuperset) { - return (0, _underscore.every)(potentialSubset, element => (0, _underscore.include)(potentialSuperset, element)); -} - -function losslessInvert(hash) { - const inverted = {}; - - for (let key in hash) { - const value = hash[key]; - - if (inverted[value] == null) { - inverted[value] = []; - } - - inverted[value].push(key); - } - - return inverted; -} // Transform the given object into another object. -// -// `object` - The object to transform. -// `iterator` - -// A function that takes `(key, value)` arguments and returns a -// `[key, value]` tuple. -// -// Returns a new object based with the key/values returned by the iterator. - - -function mapObject(object, iterator) { - const newObject = {}; - const keys = Object.keys(object); - - for (let key of keys) { - let value; - [key, value] = iterator(key, object[key]); - newObject[key] = value; - } - - return newObject; -} - -function multiplyString(string, n) { - let finalString = ""; - let i = 0; - - while (i < n) { - finalString += string; - i++; - } - - return finalString; -} - -function pluralize(count = 0, singular, plural = singular + 's') { - if (count === 1) { - return `${count} ${singular}`; - } else { - return `${count} ${plural}`; - } -} - -function remove(array, element) { - const index = array.indexOf(element); - - if (index >= 0) { - array.splice(index, 1); - } - - return array; -} - -function setValueForKeyPath(object, keyPath, value) { - const keys = splitKeyPath(keyPath); - - while (keys.length > 1) { - const key = keys.shift(); - - if (object[key] == null) { - object[key] = {}; - } - - object = object[key]; - } - - if (value != null) { - object[keys.shift()] = value; - } else { - delete object[keys.shift()]; - } -} - -function hasKeyPath(object, keyPath) { - const keys = splitKeyPath(keyPath); - - for (let key of keys) { - if (!object.hasOwnProperty(key)) { - return false; - } - - object = object[key]; - } - - return true; -} - -function spliceWithArray(originalArray, start, length, insertedArray, chunkSize = 100000) { - if (insertedArray.length < chunkSize) { - originalArray.splice(start, length, ...insertedArray); - } else { - originalArray.splice(start, length); - - for (let chunkStart = 0, end = insertedArray.length; chunkStart <= end; chunkStart += chunkSize) { - originalArray.splice(start + chunkStart, 0, ...insertedArray.slice(chunkStart, chunkStart + chunkSize)); - } - } -} - -function sum(array) { - let sum = 0; - - for (let elt of array) { - sum += elt; - } - - return sum; -} - -function uncamelcase(string) { - if (!string) { - return ''; - } - - const result = string.replace(/([A-Z])|_+/g, (match, letter = '') => ` ${letter}`); - return capitalize(result.trim()); -} - -function undasherize(string) { - if (string) { - return string.split('-').map(capitalize).join(' '); - } else { - return ''; - } -} - -function underscore(string) { - if (!string) { - return ''; - } - - string = string[0].toLowerCase() + string.slice(1); - return string.replace(/([A-Z])|-+/g, (match, letter = '') => `_${letter.toLowerCase()}`); -} - -function valueForKeyPath(object, keyPath) { - const keys = splitKeyPath(keyPath); - - for (let key of keys) { - object = object[key]; - - if (object == null) { - return; - } - } - - return object; -} - -function isEqual(a, b, aStack, bStack) { - if ((0, _underscore.isArray)(aStack) && (0, _underscore.isArray)(bStack)) { - return isEqual_(a, b, aStack, bStack); - } else { - return isEqual_(a, b); - } -} - -function isEqualForProperties(a, b, ...properties) { - // TODO is Array.from needed? - for (let property of Array.from(properties)) { - if (!(0, _underscore.isEqual)(a[property], b[property])) { - return false; - } - } - - return true; -} - -function isEqual_(a, b, aStack = [], bStack = []) { - if (a === b) { - return (0, _underscore.isEqual)(a, b); - } - - if ((0, _underscore.isFunction)(a) || (0, _underscore.isFunction)(b)) { - return (0, _underscore.isEqual)(a, b); - } - - let stackIndex = aStack.length; - - while (stackIndex--) { - if (aStack[stackIndex] === a) { - return bStack[stackIndex] === b; - } - } - - aStack.push(a); - bStack.push(b); - let equal = false; - - if ((0, _underscore.isFunction)(a === null || a === void 0 ? void 0 : a.isEqual)) { - equal = a.isEqual(b, aStack, bStack); - } else if ((0, _underscore.isFunction)(b === null || b === void 0 ? void 0 : b.isEqual)) { - equal = b.isEqual(a, bStack, aStack); - } else if ((0, _underscore.isArray)(a) && (0, _underscore.isArray)(b) && a.length === b.length) { - equal = true; - - for (let i = 0; i < a.length; i++) { - const aElement = a[i]; - - if (!isEqual_(aElement, b[i], aStack, bStack)) { - equal = false; - break; - } - } - } else if ((0, _underscore.isRegExp)(a) && (0, _underscore.isRegExp)(b)) { - equal = (0, _underscore.isEqual)(a, b); - } else if ((0, _underscore.isElement)(a) && (0, _underscore.isElement)(b)) { - equal = a === b; - } else if ((0, _underscore.isObject)(a) && (0, _underscore.isObject)(b)) { - const aCtor = a.constructor; - const bCtor = b.constructor; - const aCtorValid = (0, _underscore.isFunction)(aCtor) && aCtor instanceof aCtor; - const bCtorValid = (0, _underscore.isFunction)(bCtor) && bCtor instanceof bCtor; - - if (aCtor !== bCtor && !(aCtorValid && bCtorValid)) { - equal = false; - } else { - let key; - let aKeyCount = 0; - equal = true; - - for (key in a) { - const aValue = a[key]; - - if (!(0, _underscore.has)(a, key)) { - continue; - } - - aKeyCount++; - - if (!(0, _underscore.has)(b, key) || !isEqual_(aValue, b[key], aStack, bStack)) { - equal = false; - break; - } - } - - if (equal) { - let bKeyCount = 0; - - for (key in b) { - const bValue = b[key]; - - if ((0, _underscore.has)(b, key)) { - bKeyCount++; - } - } - - equal = aKeyCount === bKeyCount; - } - } - } else { - equal = (0, _underscore.isEqual)(a, b); - } - - aStack.pop(); - bStack.pop(); - return equal; -} // TODO: Consider shorter variations of null checks: -// https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md#ds207-consider-shorter-variations-of-null-checks \ No newline at end of file From deba2b8dc196e9db4979af5443ab1c3037b4f2c5 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:32:21 -0700 Subject: [PATCH 6/7] Remove build configuration --- babel.config.js | 20 -------------------- bower.json | 29 ----------------------------- package.json | 17 ++--------------- 3 files changed, 2 insertions(+), 64 deletions(-) delete mode 100644 babel.config.js delete mode 100644 bower.json diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 0d779b8..0000000 --- a/babel.config.js +++ /dev/null @@ -1,20 +0,0 @@ -let presets = []; - -let plugins = [ - ["@babel/plugin-proposal-optional-chaining", { loose: false }], - ["@babel/plugin-proposal-nullish-coalescing-operator", { loose: false }], -]; - -if (process.env.BABEL_ENV === "development") { - plugins.push(...[ - "@babel/plugin-transform-modules-commonjs", - "@babel/plugin-proposal-export-namespace-from", - ]); -} - -module.exports = { - presets: presets, - plugins: plugins, - exclude: "node_modules/**", - sourceMap: true, -}; diff --git a/bower.json b/bower.json deleted file mode 100644 index 484a2f4..0000000 --- a/bower.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "underscore-plus", - "homepage": "https://github.com/atom/underscore-plus", - "authors": [ - "Kevin Sawicki ", - "Matt Colyer ", - "benogle ", - "nathansobo " - ], - "description": "Underscore with some extensions", - "main": "./dist/underscore-plus.js", - "keywords": [ - "underscore" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "spec", - "src", - "lib", - "Gruntfile.coffee", - "package.json" - ], - "dependencies": { - "underscore": "1.x" - } -} diff --git a/package.json b/package.json index 24f55fe..f101f79 100644 --- a/package.json +++ b/package.json @@ -8,15 +8,10 @@ "url": "http://github.com/atom/underscore-plus/raw/master/LICENSE.md" } ], - "main": "./lib/underscore-plus.js", + "main": "./src/underscore-plus.js", "scripts": { - "clean": "shx rm -rf lib", "test": "jasmine-focused --captureExceptions --coffee spec", "lint": "coffeelint spec/*.coffee", - "bower": "shx mkdir -p dist && shx cp -r lib/*.js ./dist", - "babel": "npm run clean && shx cp -r src lib && cross-env NODE_ENV=development cross-env BABEL_ENV=development babel lib --out-dir lib && shx rm -f lib/*.mjs", - "build": "npm run babel", - "prepare": "npm run clean && npm run build && npm run bower" }, "repository": { "type": "git", @@ -34,15 +29,7 @@ "devDependencies": { "@types/underscore": "^1.10.3", "jasmine-focused": "1.x", - "coffeelint": "^2.1.0", - "@babel/cli": "7.10.3", - "@babel/core": "7.10.3", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "shx": "^0.3.2", - "cross-env": "^7.0.2" + "coffeelint": "^2.1.0" }, "coffeelintConfig": { "no_empty_param_list": { From 1a8baa2bdec12fb5177069cfb0cc2d0756436cb3 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Tue, 31 Mar 2026 22:35:26 -0700 Subject: [PATCH 7/7] Remove missed `,` from `package.json` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f101f79..b1959b2 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "main": "./src/underscore-plus.js", "scripts": { "test": "jasmine-focused --captureExceptions --coffee spec", - "lint": "coffeelint spec/*.coffee", + "lint": "coffeelint spec/*.coffee" }, "repository": { "type": "git",