@nejs/basic-extensions 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.esdoc.json +9 -0
- package/README.md +2025 -11
- package/bin/clean +6 -0
- package/dist/@nejs/basic-extensions.bundle.1.6.1.js +4 -0
- package/dist/@nejs/basic-extensions.bundle.1.6.1.js.map +7 -0
- package/dist/cjs/arrayextensions.js +1 -0
- package/dist/cjs/arrayextensions.js.map +1 -0
- package/dist/cjs/functionextensions.js +1 -0
- package/dist/cjs/functionextensions.js.map +1 -0
- package/dist/cjs/globals.js +2 -1
- package/dist/cjs/globals.js.map +1 -0
- package/dist/cjs/index.d.ts +10 -19
- package/dist/cjs/index.js +69 -76
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mapextensions.d.ts +2 -0
- package/dist/cjs/mapextensions.js +30 -0
- package/dist/cjs/mapextensions.js.map +1 -0
- package/dist/cjs/newClasses/asyncIterable.d.ts +123 -0
- package/dist/cjs/{asyncIterable.js → newClasses/asyncIterable.js} +7 -4
- package/dist/cjs/newClasses/asyncIterable.js.map +1 -0
- package/dist/cjs/newClasses/descriptor.d.ts +401 -0
- package/dist/cjs/{descriptor.js → newClasses/descriptor.js} +150 -80
- package/dist/cjs/newClasses/descriptor.js.map +1 -0
- package/dist/cjs/newClasses/iterable.d.ts +125 -0
- package/dist/cjs/{iterable.js → newClasses/iterable.js} +36 -10
- package/dist/cjs/newClasses/iterable.js.map +1 -0
- package/dist/cjs/newClasses/refmap.d.ts +238 -0
- package/dist/cjs/newClasses/refmap.js +433 -0
- package/dist/cjs/newClasses/refmap.js.map +1 -0
- package/dist/cjs/newClasses/refset.d.ts +186 -0
- package/dist/cjs/{refset.js → newClasses/refset.js} +4 -2
- package/dist/cjs/newClasses/refset.js.map +1 -0
- package/dist/cjs/objectextensions.d.ts +7 -6
- package/dist/cjs/objectextensions.js +85 -43
- package/dist/cjs/objectextensions.js.map +1 -0
- package/dist/cjs/reflectextensions.js +16 -12
- package/dist/cjs/reflectextensions.js.map +1 -0
- package/dist/cjs/stringextensions.js +1 -0
- package/dist/cjs/stringextensions.js.map +1 -0
- package/dist/cjs/symbolextensions.js +3 -1
- package/dist/cjs/symbolextensions.js.map +1 -0
- package/dist/cjs/weakrefextensions.js +1 -0
- package/dist/cjs/weakrefextensions.js.map +1 -0
- package/dist/mjs/arrayextensions.js +1 -0
- package/dist/mjs/arrayextensions.js.map +1 -0
- package/dist/mjs/functionextensions.js +1 -0
- package/dist/mjs/functionextensions.js.map +1 -0
- package/dist/mjs/globals.js +2 -1
- package/dist/mjs/globals.js.map +1 -0
- package/dist/mjs/index.d.ts +10 -19
- package/dist/mjs/index.js +67 -60
- package/dist/mjs/index.js.map +1 -0
- package/dist/mjs/mapextensions.d.ts +2 -0
- package/dist/mjs/mapextensions.js +27 -0
- package/dist/mjs/mapextensions.js.map +1 -0
- package/dist/mjs/newClasses/asyncIterable.d.ts +123 -0
- package/dist/mjs/{asyncIterable.js → newClasses/asyncIterable.js} +106 -105
- package/dist/mjs/newClasses/asyncIterable.js.map +1 -0
- package/dist/mjs/newClasses/descriptor.d.ts +401 -0
- package/dist/mjs/{descriptor.js → newClasses/descriptor.js} +129 -67
- package/dist/mjs/newClasses/descriptor.js.map +1 -0
- package/dist/mjs/newClasses/iterable.d.ts +125 -0
- package/dist/mjs/newClasses/iterable.js +199 -0
- package/dist/mjs/newClasses/iterable.js.map +1 -0
- package/dist/mjs/newClasses/refmap.d.ts +238 -0
- package/dist/mjs/newClasses/refmap.js +417 -0
- package/dist/mjs/newClasses/refmap.js.map +1 -0
- package/dist/mjs/newClasses/refset.d.ts +186 -0
- package/dist/mjs/{refset.js → newClasses/refset.js} +3 -2
- package/dist/mjs/newClasses/refset.js.map +1 -0
- package/dist/mjs/objectextensions.d.ts +7 -6
- package/dist/mjs/objectextensions.js +84 -42
- package/dist/mjs/objectextensions.js.map +1 -0
- package/dist/mjs/reflectextensions.js +16 -12
- package/dist/mjs/reflectextensions.js.map +1 -0
- package/dist/mjs/stringextensions.js +1 -0
- package/dist/mjs/stringextensions.js.map +1 -0
- package/dist/mjs/symbolextensions.js +3 -1
- package/dist/mjs/symbolextensions.js.map +1 -0
- package/dist/mjs/weakrefextensions.js +1 -0
- package/dist/mjs/weakrefextensions.js.map +1 -0
- package/docs/assets/anchor.js +350 -0
- package/docs/assets/bass-addons.css +12 -0
- package/docs/assets/bass.css +544 -0
- package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
- package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
- package/docs/assets/fonts/LICENSE.txt +93 -0
- package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
- package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
- package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
- package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
- package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
- package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
- package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
- package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
- package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
- package/docs/assets/fonts/source-code-pro.css +23 -0
- package/docs/assets/github.css +123 -0
- package/docs/assets/site.js +168 -0
- package/docs/assets/split.css +15 -0
- package/docs/assets/split.js +782 -0
- package/docs/assets/style.css +147 -0
- package/docs/index.html +13060 -0
- package/jsdoc-config.json +31 -0
- package/package.json +12 -3
- package/src/globals.js +1 -1
- package/src/index.js +75 -82
- package/src/mapextensions.js +30 -0
- package/src/{asyncIterable.js → newClasses/asyncIterable.js} +117 -117
- package/src/{descriptor.js → newClasses/descriptor.js} +137 -74
- package/src/newClasses/iterable.js +221 -0
- package/src/newClasses/refmap.js +483 -0
- package/src/{refset.js → newClasses/refset.js} +2 -2
- package/src/objectextensions.js +97 -46
- package/src/reflectextensions.js +16 -14
- package/src/symbolextensions.js +2 -1
- package/tests/index.test.js +1 -1
- package/tests/{asyncIterable.test.js → newClasses/asyncIterable.test.js} +3 -4
- package/tests/newClasses/descriptor.test.js +252 -0
- package/tests/{iterable.test.js → newClasses/iterable.test.js} +2 -4
- package/tests/newClasses/refmap.test.js +69 -0
- package/tests/{refset.test.js → newClasses/refset.test.js} +2 -4
- package/tests/objectextensions.test.js +128 -0
- package/tsconfig.base.json +2 -1
- package/dist/@nejs/basic-extensions.bundle.1.6.0.js +0 -2
- package/dist/@nejs/basic-extensions.bundle.1.6.0.js.map +0 -7
- package/dist/cjs/asyncIterable.d.ts +0 -3
- package/dist/cjs/descriptor.d.ts +0 -2
- package/dist/cjs/iterable.d.ts +0 -3
- package/dist/cjs/refset.d.ts +0 -2
- package/dist/mjs/asyncIterable.d.ts +0 -3
- package/dist/mjs/descriptor.d.ts +0 -2
- package/dist/mjs/iterable.d.ts +0 -3
- package/dist/mjs/iterable.js +0 -184
- package/dist/mjs/refset.d.ts +0 -2
- package/src/iterable.js +0 -203
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { Patch } from '@nejs/extension';
|
|
2
2
|
/**
|
|
3
|
-
* `ObjectExtensions` is a patch for the JavaScript built-in `Object` class.
|
|
4
|
-
* adds utility methods to the `Object` class without modifying the global
|
|
5
|
-
* directly. This patch includes methods for key validation, object
|
|
6
|
-
* and retrieving the string tag of an object. These methods
|
|
7
|
-
* enhancing the capabilities of the standard `Object` class
|
|
8
|
-
* utility functions.
|
|
3
|
+
* `ObjectExtensions` is a patch for the JavaScript built-in `Object` class.
|
|
4
|
+
* It adds utility methods to the `Object` class without modifying the global
|
|
5
|
+
* namespace directly. This patch includes methods for key validation, object
|
|
6
|
+
* type checking, and retrieving the string tag of an object. These methods
|
|
7
|
+
* are useful for enhancing the capabilities of the standard `Object` class
|
|
8
|
+
* with additional utility functions.
|
|
9
9
|
*/
|
|
10
10
|
export const ObjectExtensions = new Patch(Object, {
|
|
11
|
+
/**
|
|
12
|
+
* The function checks if a value is either `undefined` or `null`.
|
|
13
|
+
*
|
|
14
|
+
* @param {any} value - The parameter "value" is a variable that can hold
|
|
15
|
+
* any value.
|
|
16
|
+
* @returns {boolean} `true` if the value is either `undefined` or `null`,
|
|
17
|
+
* and `false` otherwise.
|
|
18
|
+
*/
|
|
19
|
+
isNullDefined(value) {
|
|
20
|
+
return value === undefined || value === null;
|
|
21
|
+
},
|
|
11
22
|
/**
|
|
12
23
|
* Checks to see if the supplied `value` is both an object, and has the
|
|
13
24
|
* appropriate symbol defined.
|
|
@@ -20,18 +31,25 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
20
31
|
return Object.isObject(value) && Reflect.has(value, Symbol.toStringTag);
|
|
21
32
|
},
|
|
22
33
|
/**
|
|
23
|
-
* Retrieves the string tag of an object. The string tag is a representation
|
|
24
|
-
* the object's type, as defined by its `Object.prototype.toString`
|
|
25
|
-
* utility method is helpful for getting a more descriptive
|
|
26
|
-
* what is returned by the `typeof` operator,
|
|
34
|
+
* Retrieves the string tag of an object. The string tag is a representation
|
|
35
|
+
* of the object's type, as defined by its `Object.prototype.toString`
|
|
36
|
+
* method. This utility method is helpful for getting a more descriptive
|
|
37
|
+
* type of an object than what is returned by the `typeof` operator,
|
|
38
|
+
* especially for custom objects.
|
|
27
39
|
*
|
|
28
40
|
* @param {*} value - The object whose string tag is to be retrieved.
|
|
41
|
+
* @param {boolean} strict - if this is set to true, undefined will be
|
|
42
|
+
* returned whenever a supplied object does not have a
|
|
43
|
+
* `Symbol.toStringTag` defined, period. if false, the default,
|
|
29
44
|
* @returns {string} - The string tag of the object, indicating its type.
|
|
30
45
|
*/
|
|
31
|
-
getStringTag(value) {
|
|
46
|
+
getStringTag(value, strict = false) {
|
|
32
47
|
if (Object.hasStringTag(value)) {
|
|
33
48
|
return value[Symbol.toStringTag];
|
|
34
49
|
}
|
|
50
|
+
if (strict) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
35
53
|
if (value && (typeof value === 'function')) {
|
|
36
54
|
return value.name;
|
|
37
55
|
}
|
|
@@ -49,13 +67,13 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
49
67
|
*
|
|
50
68
|
* @param {any} value - The value whose type is to be determined.
|
|
51
69
|
* @param {object} [owner=globalThis] - The object in which to look up the
|
|
52
|
-
* constructor corresponding to the string tag. Defaults to `globalThis`,
|
|
53
|
-
* covers global constructors like `Array`, `Object`, etc.
|
|
54
|
-
* @returns {Function|object|null|undefined} - Returns the constructor or
|
|
55
|
-
* of the value based on its string tag. For 'Null' and 'Undefined',
|
|
56
|
-
* `null` and `undefined`, respectively. For other types, it
|
|
57
|
-
* corresponding constructor (e.g., `Array` for arrays) if
|
|
58
|
-
* `owner` object.
|
|
70
|
+
* constructor corresponding to the string tag. Defaults to `globalThis`,
|
|
71
|
+
* which covers global constructors like `Array`, `Object`, etc.
|
|
72
|
+
* @returns {Function|object|null|undefined} - Returns the constructor or
|
|
73
|
+
* type of the value based on its string tag. For 'Null' and 'Undefined',
|
|
74
|
+
* it returns `null` and `undefined`, respectively. For other types, it
|
|
75
|
+
* returns the corresponding constructor (e.g., `Array` for arrays) if
|
|
76
|
+
* available in the `owner` object.
|
|
59
77
|
*/
|
|
60
78
|
getType(value, owner = globalThis) {
|
|
61
79
|
const stringTag = Object.getStringTag(value);
|
|
@@ -67,13 +85,14 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
67
85
|
}
|
|
68
86
|
},
|
|
69
87
|
/**
|
|
70
|
-
* Determines if the provided value is an object. This method checks whether
|
|
71
|
-
* value is an instance of `Object` or if its type is 'object'. It's a
|
|
72
|
-
* method for type-checking, ensuring that a value is an object
|
|
73
|
-
* operations that are specific to objects.
|
|
88
|
+
* Determines if the provided value is an object. This method checks whether
|
|
89
|
+
* the value is an instance of `Object` or if its type is 'object'. It's a
|
|
90
|
+
* utility method for type-checking, ensuring that a value is an object
|
|
91
|
+
* before performing operations that are specific to objects.
|
|
74
92
|
*
|
|
75
93
|
* @param {*} value - The value to be checked.
|
|
76
|
-
* @returns {boolean} - Returns `true` if the value is an object,
|
|
94
|
+
* @returns {boolean} - Returns `true` if the value is an object,
|
|
95
|
+
* otherwise `false`.
|
|
77
96
|
*/
|
|
78
97
|
isObject(value) {
|
|
79
98
|
return value && (value instanceof Object || typeof value === 'object');
|
|
@@ -105,13 +124,14 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
105
124
|
}
|
|
106
125
|
},
|
|
107
126
|
/**
|
|
108
|
-
* Checks if the given value is a valid key for an object. In JavaScript, a
|
|
109
|
-
* key can be either a string or a symbol. This method is useful for
|
|
110
|
-
* object keys before using them in operations like setting or
|
|
127
|
+
* Checks if the given value is a valid key for an object. In JavaScript, a
|
|
128
|
+
* valid key can be either a string or a symbol. This method is useful for
|
|
129
|
+
* validating object keys before using them in operations like setting or
|
|
130
|
+
* getting object properties.
|
|
111
131
|
*
|
|
112
132
|
* @param {*} value - The value to be checked.
|
|
113
|
-
* @returns {boolean} - Returns `true` if the value is a valid object key
|
|
114
|
-
*
|
|
133
|
+
* @returns {boolean} - Returns `true` if the value is a valid object key
|
|
134
|
+
* (string or symbol), otherwise `false`.
|
|
115
135
|
*/
|
|
116
136
|
isValidKey(value) {
|
|
117
137
|
return (typeof value === 'string' || typeof value === 'symbol');
|
|
@@ -123,33 +143,55 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
123
143
|
* @param {object} object the object to pare down
|
|
124
144
|
* @param {Array<string|symbol>} keys the keys that should appear in the
|
|
125
145
|
* final reduced object
|
|
126
|
-
* @param {boolean} [bindAccessors = true] if this value is true
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* @returns {object} an object containing only the keys and symbols
|
|
131
|
-
* in the `keys` parameter.
|
|
146
|
+
* @param {boolean} [bindAccessors = true] if this value is true then any
|
|
147
|
+
* accessors from the source object will continue to have their `this`
|
|
148
|
+
* value bound to the source. If the getter or setter on that object is
|
|
149
|
+
* defined using an arrow function, this will not work as intended.
|
|
150
|
+
* @returns {object} an object containing only the keys and symbols
|
|
151
|
+
* specified in the `keys` parameter.
|
|
132
152
|
*/
|
|
133
153
|
stripTo(object, keys, bindAccessors = true) {
|
|
154
|
+
if (!object || typeof object !== 'object') {
|
|
155
|
+
throw new TypeError('Object.stripTo requires an object to strip. Received', object);
|
|
156
|
+
}
|
|
134
157
|
const result = {};
|
|
135
158
|
if (!Array.isArray(keys)) {
|
|
136
159
|
return result;
|
|
137
160
|
}
|
|
138
161
|
for (let key of keys) {
|
|
139
162
|
if (Reflect.has(object, key)) {
|
|
140
|
-
const
|
|
141
|
-
|
|
163
|
+
const originalDescriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
164
|
+
const descriptor = { ...originalDescriptor };
|
|
165
|
+
if (typeof descriptor.get === 'function' ||
|
|
166
|
+
typeof descriptor.set === 'function') {
|
|
142
167
|
if (bindAccessors) {
|
|
143
|
-
descriptor.get = descriptor
|
|
144
|
-
descriptor.set = descriptor
|
|
168
|
+
descriptor.get = descriptor.get?.bind(object);
|
|
169
|
+
descriptor.set = descriptor.set?.bind(object);
|
|
145
170
|
}
|
|
146
|
-
Object.defineProperty(result, descriptor);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
Object.defineProperty(result, descriptor);
|
|
150
171
|
}
|
|
172
|
+
Object.defineProperty(result, key, descriptor);
|
|
151
173
|
}
|
|
152
174
|
}
|
|
153
175
|
return result;
|
|
154
176
|
},
|
|
155
177
|
});
|
|
178
|
+
export const ObjectPrototypeExtensions = new Patch(Object.prototype, {
|
|
179
|
+
/**
|
|
180
|
+
* Strips an object down to only the keys specified. Optionally, any
|
|
181
|
+
* accessors can be made to retain their context on the source object.
|
|
182
|
+
* This is a passthrough to the static {@link Object.stripTo} function
|
|
183
|
+
*
|
|
184
|
+
* @param {Array<string|symbol>} keys the keys that should appear in the
|
|
185
|
+
* final reduced object
|
|
186
|
+
* @param {boolean} [bindAccessors = true] if this value is true then any
|
|
187
|
+
* accessors from the source object will continue to have their `this`
|
|
188
|
+
* value bound to the source. If the getter or setter on that object is
|
|
189
|
+
* defined using an arrow function, this will not work as intended.
|
|
190
|
+
* @returns {object} an object containing only the keys and symbols
|
|
191
|
+
* specified in the `keys` parameter.
|
|
192
|
+
*/
|
|
193
|
+
stripTo(keys, bindAccessors = true) {
|
|
194
|
+
return Object.stripTo(this, keys, bindAccessors);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
//# sourceMappingURL=objectextensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objectextensions.js","sourceRoot":"","sources":["../../src/objectextensions.js"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Patch } from '@nejs/extension';
|
|
2
2
|
import { ObjectExtensions } from './objectextensions.js';
|
|
3
|
+
const { isObject } = ObjectExtensions.patches;
|
|
3
4
|
/**
|
|
4
5
|
* The `ReflectExtensions` class is a patch applied to the built-in JavaScript
|
|
5
6
|
* `Reflect` object. It extends `Reflect` with additional utility methods that
|
|
@@ -28,23 +29,25 @@ export const ReflectExtensions = new Patch(Reflect, {
|
|
|
28
29
|
.map(key => Reflect.has(object, key))
|
|
29
30
|
.every(has => has));
|
|
30
31
|
},
|
|
32
|
+
/**
|
|
33
|
+
* Fetches all descriptors of an object, including those mapped to a
|
|
34
|
+
* symbol descriptor value.
|
|
35
|
+
*
|
|
36
|
+
* @param {object} object the object from whose descriptors need to be
|
|
37
|
+
* retrieved.
|
|
38
|
+
* @returns {object} with keys mapped to object descriptors
|
|
39
|
+
* @throws {TypeError} if the supplied `object` is null or not an object
|
|
40
|
+
* a TypeError exception will be thrown
|
|
41
|
+
*/
|
|
31
42
|
ownDescriptors(object) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
revertOnDone.doIt = false;
|
|
35
|
-
if (!Object.isObject) {
|
|
36
|
-
revertOnDone.doIt = true;
|
|
37
|
-
ObjectExtensions.apply();
|
|
38
|
-
}
|
|
39
|
-
if (!Object.isObject(object)) {
|
|
40
|
-
revertOnDone();
|
|
41
|
-
return {};
|
|
43
|
+
if (!isObject(object)) {
|
|
44
|
+
throw new TypeError('The supplied object must be non-null and an object');
|
|
42
45
|
}
|
|
46
|
+
const result = {};
|
|
43
47
|
const keys = Reflect.ownKeys(object);
|
|
44
48
|
for (const key of keys) {
|
|
45
49
|
result[key] = Object.getOwnPropertyDescriptor(key);
|
|
46
50
|
}
|
|
47
|
-
revertOnDone();
|
|
48
51
|
return result;
|
|
49
52
|
},
|
|
50
53
|
/**
|
|
@@ -59,7 +62,7 @@ export const ReflectExtensions = new Patch(Reflect, {
|
|
|
59
62
|
* at least one of the keys provided as arguments exists in the given object.
|
|
60
63
|
*/
|
|
61
64
|
hasSome(object, ...keys) {
|
|
62
|
-
return
|
|
65
|
+
return isObject(object) && (keys.flat(Infinity)
|
|
63
66
|
.map(key => Reflect.has(object, key))
|
|
64
67
|
.some(has => has));
|
|
65
68
|
},
|
|
@@ -102,3 +105,4 @@ export const ReflectExtensions = new Patch(Reflect, {
|
|
|
102
105
|
return Reflect.entries.map(([, value]) => value);
|
|
103
106
|
}
|
|
104
107
|
});
|
|
108
|
+
//# sourceMappingURL=reflectextensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflectextensions.js","sourceRoot":"","sources":["../../src/reflectextensions.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExD,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAA;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE;IAClD;;;;;;;;;OASG;IACH,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI;QACpB,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;aACnD,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;aACpC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CACnB,CAAA;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc,CAAC,MAAM;QACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAA;QAC3E,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,CAAA;QAEjB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAA;QACpD,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI;QACrB,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;aAC5C,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;aACpC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAClB,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM;QACZ,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAAC,OAAO,EAAE,CAAA;QAAC,CAAC;QAExD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,GAAG,EAAE,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC;SAClD,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,MAAM;QACX,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAA;IACjD,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stringextensions.js","sourceRoot":"","sources":["../../src/stringextensions.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE;IAChD;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK;QACZ,IAAI,KAAK,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,MAAM,CAAC,EAAE,CAAC;YACpE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -56,9 +56,11 @@ export const SymbolExtensions = new Patch(Symbol, {
|
|
|
56
56
|
* spec static symbols (`toStringTag`, `iterator`, etc...), and any symbols
|
|
57
57
|
* created by passing a value directly to the `Symbol` function, such as
|
|
58
58
|
* `Symbol('name')`
|
|
59
|
-
* @returns
|
|
59
|
+
* @returns true if the `value` in question is both a `symbol` and has
|
|
60
|
+
* returns `undefined` if passed to `Symbol.keyFor`
|
|
60
61
|
*/
|
|
61
62
|
isNonRegistered(value, allowOnlySymbols = false) {
|
|
62
63
|
return !Symbol.isRegistered(value, allowOnlySymbols);
|
|
63
64
|
},
|
|
64
65
|
});
|
|
66
|
+
//# sourceMappingURL=symbolextensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbolextensions.js","sourceRoot":"","sources":["../../src/symbolextensions.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE;IAChD;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK;QACZ,OAAO,KAAK,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,KAAK;QAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,IAAI,gBAAgB,EAAE,CAAC;gBACrB,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAA;YAC1E,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,CAAA;IAC3C,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,KAAK;QAC7C,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAA;IACtD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weakrefextensions.js","sourceRoot":"","sources":["../../src/weakrefextensions.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE;IAClD;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK;QACpB,OAAO,CAAC,CACN,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;YACjE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;YACxD,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CACxC,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* AnchorJS - v4.0.0 - 2017-06-02
|
|
3
|
+
* https://github.com/bryanbraun/anchorjs
|
|
4
|
+
* Copyright (c) 2017 Bryan Braun; Licensed MIT
|
|
5
|
+
*/
|
|
6
|
+
/* eslint-env amd, node */
|
|
7
|
+
|
|
8
|
+
// https://github.com/umdjs/umd/blob/master/templates/returnExports.js
|
|
9
|
+
(function (root, factory) {
|
|
10
|
+
'use strict';
|
|
11
|
+
if (typeof define === 'function' && define.amd) {
|
|
12
|
+
// AMD. Register as an anonymous module.
|
|
13
|
+
define([], factory);
|
|
14
|
+
} else if (typeof module === 'object' && module.exports) {
|
|
15
|
+
// Node. Does not work with strict CommonJS, but
|
|
16
|
+
// only CommonJS-like environments that support module.exports,
|
|
17
|
+
// like Node.
|
|
18
|
+
module.exports = factory();
|
|
19
|
+
} else {
|
|
20
|
+
// Browser globals (root is window)
|
|
21
|
+
root.AnchorJS = factory();
|
|
22
|
+
root.anchors = new root.AnchorJS();
|
|
23
|
+
}
|
|
24
|
+
})(this, function () {
|
|
25
|
+
'use strict';
|
|
26
|
+
function AnchorJS(options) {
|
|
27
|
+
this.options = options || {};
|
|
28
|
+
this.elements = [];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Assigns options to the internal options object, and provides defaults.
|
|
32
|
+
* @param {Object} opts - Options object
|
|
33
|
+
*/
|
|
34
|
+
function _applyRemainingDefaultOptions(opts) {
|
|
35
|
+
opts.icon = opts.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'.
|
|
36
|
+
opts.visible = opts.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' & 'touch'
|
|
37
|
+
opts.placement = opts.hasOwnProperty('placement')
|
|
38
|
+
? opts.placement
|
|
39
|
+
: 'right'; // Also accepts 'left'
|
|
40
|
+
opts.class = opts.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name.
|
|
41
|
+
// Using Math.floor here will ensure the value is Number-cast and an integer.
|
|
42
|
+
opts.truncate = opts.hasOwnProperty('truncate')
|
|
43
|
+
? Math.floor(opts.truncate)
|
|
44
|
+
: 64; // Accepts any value that can be typecast to a number.
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
_applyRemainingDefaultOptions(this.options);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Checks to see if this device supports touch. Uses criteria pulled from Modernizr:
|
|
51
|
+
* https://github.com/Modernizr/Modernizr/blob/da22eb27631fc4957f67607fe6042e85c0a84656/feature-detects/touchevents.js#L40
|
|
52
|
+
* @returns {Boolean} - true if the current device supports touch.
|
|
53
|
+
*/
|
|
54
|
+
this.isTouchDevice = function () {
|
|
55
|
+
return !!(
|
|
56
|
+
'ontouchstart' in window ||
|
|
57
|
+
(window.DocumentTouch && document instanceof DocumentTouch)
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Add anchor links to page elements.
|
|
63
|
+
* @param {String|Array|Nodelist} selector - A CSS selector for targeting the elements you wish to add anchor links
|
|
64
|
+
* to. Also accepts an array or nodeList containing the relavant elements.
|
|
65
|
+
* @returns {this} - The AnchorJS object
|
|
66
|
+
*/
|
|
67
|
+
this.add = function (selector) {
|
|
68
|
+
var elements,
|
|
69
|
+
elsWithIds,
|
|
70
|
+
idList,
|
|
71
|
+
elementID,
|
|
72
|
+
i,
|
|
73
|
+
index,
|
|
74
|
+
count,
|
|
75
|
+
tidyText,
|
|
76
|
+
newTidyText,
|
|
77
|
+
readableID,
|
|
78
|
+
anchor,
|
|
79
|
+
visibleOptionToUse,
|
|
80
|
+
indexesToDrop = [];
|
|
81
|
+
|
|
82
|
+
// We reapply options here because somebody may have overwritten the default options object when setting options.
|
|
83
|
+
// For example, this overwrites all options but visible:
|
|
84
|
+
//
|
|
85
|
+
// anchors.options = { visible: 'always'; }
|
|
86
|
+
_applyRemainingDefaultOptions(this.options);
|
|
87
|
+
|
|
88
|
+
visibleOptionToUse = this.options.visible;
|
|
89
|
+
if (visibleOptionToUse === 'touch') {
|
|
90
|
+
visibleOptionToUse = this.isTouchDevice() ? 'always' : 'hover';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Provide a sensible default selector, if none is given.
|
|
94
|
+
if (!selector) {
|
|
95
|
+
selector = 'h2, h3, h4, h5, h6';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
elements = _getElements(selector);
|
|
99
|
+
|
|
100
|
+
if (elements.length === 0) {
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_addBaselineStyles();
|
|
105
|
+
|
|
106
|
+
// We produce a list of existing IDs so we don't generate a duplicate.
|
|
107
|
+
elsWithIds = document.querySelectorAll('[id]');
|
|
108
|
+
idList = [].map.call(elsWithIds, function assign(el) {
|
|
109
|
+
return el.id;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
for (i = 0; i < elements.length; i++) {
|
|
113
|
+
if (this.hasAnchorJSLink(elements[i])) {
|
|
114
|
+
indexesToDrop.push(i);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (elements[i].hasAttribute('id')) {
|
|
119
|
+
elementID = elements[i].getAttribute('id');
|
|
120
|
+
} else if (elements[i].hasAttribute('data-anchor-id')) {
|
|
121
|
+
elementID = elements[i].getAttribute('data-anchor-id');
|
|
122
|
+
} else {
|
|
123
|
+
tidyText = this.urlify(elements[i].textContent);
|
|
124
|
+
|
|
125
|
+
// Compare our generated ID to existing IDs (and increment it if needed)
|
|
126
|
+
// before we add it to the page.
|
|
127
|
+
newTidyText = tidyText;
|
|
128
|
+
count = 0;
|
|
129
|
+
do {
|
|
130
|
+
if (index !== undefined) {
|
|
131
|
+
newTidyText = tidyText + '-' + count;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
index = idList.indexOf(newTidyText);
|
|
135
|
+
count += 1;
|
|
136
|
+
} while (index !== -1);
|
|
137
|
+
index = undefined;
|
|
138
|
+
idList.push(newTidyText);
|
|
139
|
+
|
|
140
|
+
elements[i].setAttribute('id', newTidyText);
|
|
141
|
+
elementID = newTidyText;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
readableID = elementID.replace(/-/g, ' ');
|
|
145
|
+
|
|
146
|
+
// The following code builds the following DOM structure in a more effiecient (albeit opaque) way.
|
|
147
|
+
// '<a class="anchorjs-link ' + this.options.class + '" href="#' + elementID + '" aria-label="Anchor link for: ' + readableID + '" data-anchorjs-icon="' + this.options.icon + '"></a>';
|
|
148
|
+
anchor = document.createElement('a');
|
|
149
|
+
anchor.className = 'anchorjs-link ' + this.options.class;
|
|
150
|
+
anchor.href = '#' + elementID;
|
|
151
|
+
anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID);
|
|
152
|
+
anchor.setAttribute('data-anchorjs-icon', this.options.icon);
|
|
153
|
+
|
|
154
|
+
if (visibleOptionToUse === 'always') {
|
|
155
|
+
anchor.style.opacity = '1';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (this.options.icon === '\ue9cb') {
|
|
159
|
+
anchor.style.font = '1em/1 anchorjs-icons';
|
|
160
|
+
|
|
161
|
+
// We set lineHeight = 1 here because the `anchorjs-icons` font family could otherwise affect the
|
|
162
|
+
// height of the heading. This isn't the case for icons with `placement: left`, so we restore
|
|
163
|
+
// line-height: inherit in that case, ensuring they remain positioned correctly. For more info,
|
|
164
|
+
// see https://github.com/bryanbraun/anchorjs/issues/39.
|
|
165
|
+
if (this.options.placement === 'left') {
|
|
166
|
+
anchor.style.lineHeight = 'inherit';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (this.options.placement === 'left') {
|
|
171
|
+
anchor.style.position = 'absolute';
|
|
172
|
+
anchor.style.marginLeft = '-1em';
|
|
173
|
+
anchor.style.paddingRight = '0.5em';
|
|
174
|
+
elements[i].insertBefore(anchor, elements[i].firstChild);
|
|
175
|
+
} else {
|
|
176
|
+
// if the option provided is `right` (or anything else).
|
|
177
|
+
anchor.style.paddingLeft = '0.375em';
|
|
178
|
+
elements[i].appendChild(anchor);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
for (i = 0; i < indexesToDrop.length; i++) {
|
|
183
|
+
elements.splice(indexesToDrop[i] - i, 1);
|
|
184
|
+
}
|
|
185
|
+
this.elements = this.elements.concat(elements);
|
|
186
|
+
|
|
187
|
+
return this;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Removes all anchorjs-links from elements targed by the selector.
|
|
192
|
+
* @param {String|Array|Nodelist} selector - A CSS selector string targeting elements with anchor links,
|
|
193
|
+
* OR a nodeList / array containing the DOM elements.
|
|
194
|
+
* @returns {this} - The AnchorJS object
|
|
195
|
+
*/
|
|
196
|
+
this.remove = function (selector) {
|
|
197
|
+
var index,
|
|
198
|
+
domAnchor,
|
|
199
|
+
elements = _getElements(selector);
|
|
200
|
+
|
|
201
|
+
for (var i = 0; i < elements.length; i++) {
|
|
202
|
+
domAnchor = elements[i].querySelector('.anchorjs-link');
|
|
203
|
+
if (domAnchor) {
|
|
204
|
+
// Drop the element from our main list, if it's in there.
|
|
205
|
+
index = this.elements.indexOf(elements[i]);
|
|
206
|
+
if (index !== -1) {
|
|
207
|
+
this.elements.splice(index, 1);
|
|
208
|
+
}
|
|
209
|
+
// Remove the anchor from the DOM.
|
|
210
|
+
elements[i].removeChild(domAnchor);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return this;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Removes all anchorjs links. Mostly used for tests.
|
|
218
|
+
*/
|
|
219
|
+
this.removeAll = function () {
|
|
220
|
+
this.remove(this.elements);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Urlify - Refine text so it makes a good ID.
|
|
225
|
+
*
|
|
226
|
+
* To do this, we remove apostrophes, replace nonsafe characters with hyphens,
|
|
227
|
+
* remove extra hyphens, truncate, trim hyphens, and make lowercase.
|
|
228
|
+
*
|
|
229
|
+
* @param {String} text - Any text. Usually pulled from the webpage element we are linking to.
|
|
230
|
+
* @returns {String} - hyphen-delimited text for use in IDs and URLs.
|
|
231
|
+
*/
|
|
232
|
+
this.urlify = function (text) {
|
|
233
|
+
// Regex for finding the nonsafe URL characters (many need escaping): & +$,:;=?@"#{}|^~[`%!'<>]./()*\
|
|
234
|
+
var nonsafeChars = /[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\]/g,
|
|
235
|
+
urlText;
|
|
236
|
+
|
|
237
|
+
// The reason we include this _applyRemainingDefaultOptions is so urlify can be called independently,
|
|
238
|
+
// even after setting options. This can be useful for tests or other applications.
|
|
239
|
+
if (!this.options.truncate) {
|
|
240
|
+
_applyRemainingDefaultOptions(this.options);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Note: we trim hyphens after truncating because truncating can cause dangling hyphens.
|
|
244
|
+
// Example string: // " ⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
|
245
|
+
urlText = text
|
|
246
|
+
.trim() // "⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
|
247
|
+
.replace(/\'/gi, '') // "⚡⚡ Dont forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
|
248
|
+
.replace(nonsafeChars, '-') // "⚡⚡-Dont-forget--URL-fragments-should-be-i18n-friendly--hyphenated--short--and-clean-"
|
|
249
|
+
.replace(/-{2,}/g, '-') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-short-and-clean-"
|
|
250
|
+
.substring(0, this.options.truncate) // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-"
|
|
251
|
+
.replace(/^-+|-+$/gm, '') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated"
|
|
252
|
+
.toLowerCase(); // "⚡⚡-dont-forget-url-fragments-should-be-i18n-friendly-hyphenated"
|
|
253
|
+
|
|
254
|
+
return urlText;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Determines if this element already has an AnchorJS link on it.
|
|
259
|
+
* Uses this technique: http://stackoverflow.com/a/5898748/1154642
|
|
260
|
+
* @param {HTMLElemnt} el - a DOM node
|
|
261
|
+
* @returns {Boolean} true/false
|
|
262
|
+
*/
|
|
263
|
+
this.hasAnchorJSLink = function (el) {
|
|
264
|
+
var hasLeftAnchor =
|
|
265
|
+
el.firstChild &&
|
|
266
|
+
(' ' + el.firstChild.className + ' ').indexOf(' anchorjs-link ') > -1,
|
|
267
|
+
hasRightAnchor =
|
|
268
|
+
el.lastChild &&
|
|
269
|
+
(' ' + el.lastChild.className + ' ').indexOf(' anchorjs-link ') > -1;
|
|
270
|
+
|
|
271
|
+
return hasLeftAnchor || hasRightAnchor || false;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Turns a selector, nodeList, or array of elements into an array of elements (so we can use array methods).
|
|
276
|
+
* It also throws errors on any other inputs. Used to handle inputs to .add and .remove.
|
|
277
|
+
* @param {String|Array|Nodelist} input - A CSS selector string targeting elements with anchor links,
|
|
278
|
+
* OR a nodeList / array containing the DOM elements.
|
|
279
|
+
* @returns {Array} - An array containing the elements we want.
|
|
280
|
+
*/
|
|
281
|
+
function _getElements(input) {
|
|
282
|
+
var elements;
|
|
283
|
+
if (typeof input === 'string' || input instanceof String) {
|
|
284
|
+
// See https://davidwalsh.name/nodelist-array for the technique transforming nodeList -> Array.
|
|
285
|
+
elements = [].slice.call(document.querySelectorAll(input));
|
|
286
|
+
// I checked the 'input instanceof NodeList' test in IE9 and modern browsers and it worked for me.
|
|
287
|
+
} else if (Array.isArray(input) || input instanceof NodeList) {
|
|
288
|
+
elements = [].slice.call(input);
|
|
289
|
+
} else {
|
|
290
|
+
throw new Error('The selector provided to AnchorJS was invalid.');
|
|
291
|
+
}
|
|
292
|
+
return elements;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* _addBaselineStyles
|
|
297
|
+
* Adds baseline styles to the page, used by all AnchorJS links irregardless of configuration.
|
|
298
|
+
*/
|
|
299
|
+
function _addBaselineStyles() {
|
|
300
|
+
// We don't want to add global baseline styles if they've been added before.
|
|
301
|
+
if (document.head.querySelector('style.anchorjs') !== null) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
var style = document.createElement('style'),
|
|
306
|
+
linkRule =
|
|
307
|
+
' .anchorjs-link {' +
|
|
308
|
+
' opacity: 0;' +
|
|
309
|
+
' text-decoration: none;' +
|
|
310
|
+
' -webkit-font-smoothing: antialiased;' +
|
|
311
|
+
' -moz-osx-font-smoothing: grayscale;' +
|
|
312
|
+
' }',
|
|
313
|
+
hoverRule =
|
|
314
|
+
' *:hover > .anchorjs-link,' +
|
|
315
|
+
' .anchorjs-link:focus {' +
|
|
316
|
+
' opacity: 1;' +
|
|
317
|
+
' }',
|
|
318
|
+
anchorjsLinkFontFace =
|
|
319
|
+
' @font-face {' +
|
|
320
|
+
' font-family: "anchorjs-icons";' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above
|
|
321
|
+
' src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype");' +
|
|
322
|
+
' }',
|
|
323
|
+
pseudoElContent =
|
|
324
|
+
' [data-anchorjs-icon]::after {' +
|
|
325
|
+
' content: attr(data-anchorjs-icon);' +
|
|
326
|
+
' }',
|
|
327
|
+
firstStyleEl;
|
|
328
|
+
|
|
329
|
+
style.className = 'anchorjs';
|
|
330
|
+
style.appendChild(document.createTextNode('')); // Necessary for Webkit.
|
|
331
|
+
|
|
332
|
+
// We place it in the head with the other style tags, if possible, so as to
|
|
333
|
+
// not look out of place. We insert before the others so these styles can be
|
|
334
|
+
// overridden if necessary.
|
|
335
|
+
firstStyleEl = document.head.querySelector('[rel="stylesheet"], style');
|
|
336
|
+
if (firstStyleEl === undefined) {
|
|
337
|
+
document.head.appendChild(style);
|
|
338
|
+
} else {
|
|
339
|
+
document.head.insertBefore(style, firstStyleEl);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
style.sheet.insertRule(linkRule, style.sheet.cssRules.length);
|
|
343
|
+
style.sheet.insertRule(hoverRule, style.sheet.cssRules.length);
|
|
344
|
+
style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length);
|
|
345
|
+
style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return AnchorJS;
|
|
350
|
+
});
|