@cyberalien/svg-utils 0.0.1 → 0.0.2

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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Convert hash to a string, usable in CSS for class names and keyframes
3
+ */
4
+ declare function hashToCSSString(value: number[], limit?: number, hasPrefix?: boolean): string;
5
+ export { hashToCSSString };
@@ -0,0 +1,27 @@
1
+ const firstChars = "abcdefghijklmnopqrstuvwxyz";
2
+ const chars = firstChars + "0123456789_-";
3
+ const firstLetterRadix = 26;
4
+ const letterRadix = 38;
5
+ /**
6
+ * Convert hash to a string, usable in CSS for class names and keyframes
7
+ */
8
+ function hashToCSSString(value, limit = 8, hasPrefix = false) {
9
+ const result = [];
10
+ let num = value.shift() ?? 0;
11
+ if (!hasPrefix) {
12
+ result.push(firstChars[num % firstLetterRadix]);
13
+ num = Math.floor(num / firstLetterRadix);
14
+ }
15
+ while (true) {
16
+ while (num < 1) {
17
+ if (!value.length) return result.join("");
18
+ num = value.shift() ?? 0;
19
+ }
20
+ const isLastChar = result.length === limit - 1;
21
+ result.push(isLastChar ? firstChars[num % firstLetterRadix] : chars[num % letterRadix]);
22
+ if (result.length === limit) return result.join("");
23
+ num = Math.floor(num / letterRadix);
24
+ }
25
+ }
26
+
27
+ export { hashToCSSString };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Simple hashing function, based on https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
3
+ */
4
+ declare function hashString(str: string, seed?: number): [number, number];
5
+ export { hashString };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Simple hashing function, based on https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
3
+ */
4
+ function hashString(str, seed = 0) {
5
+ let h1 = 3735928559 ^ seed, h2 = 1103547991 ^ seed;
6
+ for (let i = 0, ch; i < str.length; i++) {
7
+ ch = str.charCodeAt(i);
8
+ h1 = Math.imul(h1 ^ ch, 2654435761);
9
+ h2 = Math.imul(h2 ^ ch, 1597334677);
10
+ }
11
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507);
12
+ h1 ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
13
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
14
+ h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
15
+ return [h2 >>> 0, h1 >>> 0];
16
+ }
17
+
18
+ export { hashString };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Hash an object, make sure hash is unique
3
+ */
4
+ declare function uniqueCSSHash(data: unknown, hasPrefix?: boolean): string;
5
+ export { uniqueCSSHash };
@@ -0,0 +1,23 @@
1
+ import { sortObject } from "../misc/sort-object.js";
2
+ import { hashString } from "./hash.js";
3
+ import { hashToCSSString } from "./css.js";
4
+
5
+ const uniqueHashes = Object.create(null);
6
+ const uniqueWithPrefixHashes = Object.create(null);
7
+ /**
8
+ * Hash an object, make sure hash is unique
9
+ */
10
+ function uniqueCSSHash(data, hasPrefix = false) {
11
+ const str = JSON.stringify(sortObject(data));
12
+ const hash = hashToCSSString(hashString(str), 6, hasPrefix);
13
+ const cache = hasPrefix ? uniqueWithPrefixHashes : uniqueHashes;
14
+ if (!cache[hash]) cache[hash] = str;
15
+ else if (cache[hash] !== str) {
16
+ console.warn("Data 1:", cache[hash]);
17
+ console.warn("Data 2:", str);
18
+ throw new Error(`Hash collision detected: ${hash}`);
19
+ }
20
+ return hash;
21
+ }
22
+
23
+ export { uniqueCSSHash };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Clone object, maintaining types
3
+ */
4
+ declare function cloneObject<T>(item: T): T;
5
+ export { cloneObject };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Clone object, maintaining types
3
+ */
4
+ function cloneObject(item) {
5
+ return JSON.parse(JSON.stringify(item));
6
+ }
7
+
8
+ export { cloneObject };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Compare sets, returns true if identical
3
+ */
4
+ declare function compareSets<T>(set1: Set<T> | undefined, set2: Set<T> | undefined): boolean;
5
+ /**
6
+ * Compare two values, returns true if identical
7
+ */
8
+ declare function compareValues<T>(value1: T, value2: T): boolean;
9
+ export { compareSets, compareValues };
@@ -0,0 +1,19 @@
1
+ import { sortObject } from "./sort-object.js";
2
+
3
+ /**
4
+ * Compare sets, returns true if identical
5
+ */
6
+ function compareSets(set1, set2) {
7
+ if (!set1 || !set2) return false;
8
+ if (set1.size !== set2.size) return false;
9
+ for (const value of set1) if (!set2.has(value)) return false;
10
+ return true;
11
+ }
12
+ /**
13
+ * Compare two values, returns true if identical
14
+ */
15
+ function compareValues(value1, value2) {
16
+ return value1 === value2 || JSON.stringify(sortObject(value1)) === JSON.stringify(sortObject(value2));
17
+ }
18
+
19
+ export { compareSets, compareValues };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Sort object keys to generate consistend JSON output
3
+ *
4
+ * Used to hash objects
5
+ */
6
+ declare function sortObject<T>(data: T): T;
7
+ export { sortObject };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Sort object keys to generate consistend JSON output
3
+ *
4
+ * Used to hash objects
5
+ */
6
+ function sortObject(data) {
7
+ if (typeof data !== "object" || data === null) return data;
8
+ if (Array.isArray(data)) return data.map(sortObject);
9
+ if (data instanceof Set) {
10
+ const values = Array.from(data).map(sortObject);
11
+ values.sort();
12
+ return new Set(values);
13
+ }
14
+ const keys = Object.keys(data);
15
+ keys.sort();
16
+ const newObject = Object.create(null);
17
+ for (const key of keys) newObject[key] = sortObject(data[key]);
18
+ return newObject;
19
+ }
20
+
21
+ export { sortObject };
package/lib/index.d.ts CHANGED
@@ -1,5 +1,9 @@
1
+ import { hashString } from "./helpers/hash/hash.js";
2
+ import { cloneObject } from "./helpers/misc/clone.js";
3
+ import { compareSets, compareValues } from "./helpers/misc/compare.js";
4
+ import { sortObject } from "./helpers/misc/sort-object.js";
1
5
  import { ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement } from "./xml/types.js";
2
6
  import { iterateXMLContent } from "./xml/iterate.js";
3
7
  import { parseXMLContent } from "./xml/parse.js";
4
8
  import { stringifyXMLContent } from "./xml/stringify.js";
5
- export { ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, iterateXMLContent, parseXMLContent, stringifyXMLContent };
9
+ export { ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, cloneObject, compareSets, compareValues, hashString, iterateXMLContent, parseXMLContent, sortObject, stringifyXMLContent };
package/lib/index.js CHANGED
@@ -1,5 +1,9 @@
1
+ import { cloneObject } from "./helpers/misc/clone.js";
2
+ import { sortObject } from "./helpers/misc/sort-object.js";
3
+ import { compareSets, compareValues } from "./helpers/misc/compare.js";
4
+ import { hashString } from "./helpers/hash/hash.js";
1
5
  import { iterateXMLContent } from "./xml/iterate.js";
2
6
  import { parseXMLContent } from "./xml/parse.js";
3
7
  import { stringifyXMLContent } from "./xml/stringify.js";
4
8
 
5
- export { iterateXMLContent, parseXMLContent, stringifyXMLContent };
9
+ export { cloneObject, compareSets, compareValues, hashString, iterateXMLContent, parseXMLContent, sortObject, stringifyXMLContent };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "type": "module",
4
4
  "description": "Common functions for working with SVG used by various packages.",
5
5
  "author": "Vjacheslav Trushkin",
6
- "version": "0.0.1",
6
+ "version": "0.0.2",
7
7
  "license": "MIT",
8
8
  "bugs": "https://github.com/cyberalien/svg-utils/issues",
9
9
  "homepage": "https://cyberalien.dev/",