-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathname.js
87 lines (76 loc) · 2.76 KB
/
name.js
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
const NUMBER_POSTFIX = / (\d+)$/;
//@ (Number), state -> (String)
export async function load(windowId) {
return await browser.sessions.getWindowValue(windowId, 'givenName') || '';
}
//@ (Number, String) -> (Boolean), state
export function save(windowId, name) {
return browser.sessions.setWindowValue(windowId, 'givenName', name).then(() => true).catch(() => false);
}
// Add " 2" at the end of name, or increment an existing number postfix.
//@ (String) -> (String)
function addNumberPostfix(name) {
const found = name.match(NUMBER_POSTFIX);
return found ?
`${name.slice(0, found.index)} ${+found[1] + 1}` : `${name} 2`;
}
// Remove spaces and illegal characters from name.
//@ (String) -> (String)
export function validify(name) {
name = name.trim();
return startsWithSlash(name) ?
validify(name.slice(1)) : name;
}
//@ (String) -> (Boolean)
function startsWithSlash(name) {
return name.startsWith('/');
}
// Map windowIds to names, and provide methods that work in the context of all present names.
export class NameMap extends Map {
// `objects` is either an array of $names, or an array of winfos containing givenNames.
//@ ([Object]) -> (Map(Number:String)), state
populate(objects) {
if (objects[0] instanceof HTMLInputElement) {
for (const { _id, value } of objects) // $names
this.set(_id, value);
} else {
for (const { id, givenName } of objects) // winfos
this.set(id, givenName);
}
return this;
}
// Has at least one name.
//@ state -> (Boolean)
hasName() {
for (const [, name] of this)
if (name)
return true;
}
// Find name in map. Ignores blank. Return associated id if found, else return 0.
//@ (String), state -> (Number)
findId(name) {
if (name)
for (const [id, _name] of this)
if (name === _name)
return id;
return 0;
}
// Check name against map for errors, including duplication.
// Return 0 if name is blank or valid-and-unique or conflicting windowId is excludeId. Else return -1 or conflicting windowId.
//@ (String, Number), state -> (Number)
checkForErrors(name, excludeId) {
if (!name)
return 0;
if (startsWithSlash(name))
return -1;
const foundId = this.findId(name);
return foundId === excludeId ?
0 : foundId;
}
// Check valid name against map for duplication. Ignores blank. If name is not unique, add/increment number postfix. Return unique result.
//@ (String), state -> (String)
uniquify(name) {
return (name && this.findId(name)) ?
this.uniquify(addNumberPostfix(name)) : name;
}
}