This repository has been archived by the owner on Jan 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Note: class name is set to "Map" so that snapshots and inspect output aren't affected.
- Loading branch information
Showing
2 changed files
with
95 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// package children are represented with a Map object, but many file systems | ||
// are case-insensitive and unicode-normalizing, so we need to treat | ||
// node.children.get('FOO') and node.children.get('foo') as the same thing. | ||
|
||
const _keys = Symbol('keys') | ||
const _normKey = Symbol('normKey') | ||
const normalize = s => s.normalize('NFKD').toLowerCase() | ||
const OGMap = Map | ||
module.exports = class Map extends OGMap { | ||
constructor (items = []) { | ||
super() | ||
this[_keys] = new OGMap() | ||
for (const [key, val] of items) | ||
this.set(key, val) | ||
} | ||
|
||
[_normKey] (key) { | ||
return typeof key === 'string' ? normalize(key) : key | ||
} | ||
|
||
get (key) { | ||
const normKey = this[_normKey](key) | ||
return this[_keys].has(normKey) ? super.get(this[_keys].get(normKey)) | ||
: undefined | ||
} | ||
|
||
set (key, val) { | ||
const normKey = this[_normKey](key) | ||
if (this[_keys].has(normKey)) | ||
super.delete(this[_keys].get(normKey)) | ||
this[_keys].set(normKey, key) | ||
return super.set(key, val) | ||
} | ||
|
||
delete (key) { | ||
const normKey = this[_normKey](key) | ||
if (this[_keys].has(normKey)) { | ||
const prevKey = this[_keys].get(normKey) | ||
this[_keys].delete(normKey) | ||
return super.delete(prevKey) | ||
} | ||
} | ||
|
||
has (key) { | ||
const normKey = this[_normKey](key) | ||
return this[_keys].has(normKey) && super.has(this[_keys].get(normKey)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
const t = require('tap') | ||
const CMap = require('../lib/case-insensitive-map.js') | ||
|
||
t.test('set values in ctor', t => { | ||
const cmap = new CMap([['a', 'a'], [null, 'null'], [{a: 1}, 'a:1'], ['A', 'A']]) | ||
t.strictSame([...cmap.entries()], [[null, 'null'], [{a: 1}, 'a:1'], ['A', 'A']]) | ||
t.equal(cmap.has('a'), true) | ||
t.equal(cmap.has('A'), true) | ||
t.equal(cmap.get('a'), 'A') | ||
cmap.delete('a') | ||
t.equal(cmap.has('a'), false) | ||
t.equal(cmap.has('A'), false) | ||
t.equal(cmap.get('A'), undefined) | ||
t.end() | ||
}) | ||
|
||
t.test('set values after ctor', t => { | ||
const cmap = new CMap() | ||
cmap.set('a', 'a') | ||
t.equal(cmap.has('a'), true) | ||
t.equal(cmap.has('A'), true) | ||
cmap.set(null, 'null') | ||
cmap.set({a: 1}, 'a:1') | ||
cmap.set('A', 'A') | ||
t.strictSame([...cmap.entries()], [[null, 'null'], [{a: 1}, 'a:1'], ['A', 'A']]) | ||
cmap.delete('a') | ||
t.equal(cmap.has('a'), false) | ||
t.equal(cmap.has('A'), false) | ||
t.equal(cmap.get('A'), undefined) | ||
t.end() | ||
}) | ||
|
||
t.test('dont get confused with undefined or weird values', t => { | ||
const cmap = new CMap() | ||
cmap.set(undefined, 'this is not defined') | ||
cmap.set(NaN, 'this is not a number') | ||
cmap.set('NaN', 'this is a string') | ||
cmap.set('nan', 'this is a quieter string') | ||
|
||
cmap.delete('foo') | ||
cmap.delete('NAN') | ||
t.strictSame([...cmap.entries()], [ | ||
[undefined, 'this is not defined'], | ||
[NaN, 'this is not a number'], | ||
]) | ||
t.end() | ||
}) |