From 3c2836781be9bc96355aa459792817ab8db950e3 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 19:17:48 +0200 Subject: [PATCH 01/15] refactor: update/simplify fxparam handling in snippet API - update fxparam deserializers & utils as per postspectacular/fxlens@7d0a50b --- project/public/index.html | 253 +++++++++++++++----------------------- 1 file changed, 102 insertions(+), 151 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 392ca18..b97f9b7 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -40,177 +40,128 @@ let fxparams = search.get('fxparams') fxparams = fxparams ? fxparams.replace("0x", "") : fxparams + function* asBytes(hex, n) { + n *= 2 + for (let i = 0; i < n; i += 2) + yield parseInt(hex.substring(i, i + 2), 16) + } + + function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER) { + return { + min: + $min !== undefined + ? Math.max(Number($min), minDef) + : minDef, + max: + $max !== undefined + ? Math.min(Number($max), maxDef) + : maxDef, + } + } + // the parameter processor, used to parse fxparams const processors = { number: { - deserialize: (input) => { - const view = new DataView(new ArrayBuffer(8)) - for (let i = 0; i < 8; i++) { - view.setUint8(i, parseInt(input.substring(i * 2, i * 2 + 2), 16)) - } - return view.getFloat64(0) - }, bytesLength: () => 8, - constrain: (value, definition) => { - let min = Number.MIN_SAFE_INTEGER - if (typeof definition.options?.min !== "undefined") - min = Number(definition.options.min) - let max = Number.MAX_SAFE_INTEGER - if (typeof definition.options?.max !== "undefined") - max = Number(definition.options.max) - max = Math.min(max, Number.MAX_SAFE_INTEGER) - min = Math.max(min, Number.MIN_SAFE_INTEGER) - const v = Math.min(Math.max(value, min), max) - return v; - }, - random: (definition) => { - let min = Number.MIN_SAFE_INTEGER - if (typeof definition.options?.min !== "undefined") - min = Number(definition.options.min) - let max = Number.MAX_SAFE_INTEGER - if (typeof definition.options?.max !== "undefined") - max = Number(definition.options.max) - max = Math.min(max, Number.MAX_SAFE_INTEGER) - min = Math.max(min, Number.MIN_SAFE_INTEGER) - const v = Math.random() * (max - min) + min - if (definition?.options?.step) { - const t = 1.0 / definition?.options?.step - return Math.round(v * t) / t - } - return v; - }, + deserialize: (input) => new Float64Array(new BigUint64Array([BigInt(`0x${input}`)]).buffer)[0], + constrain: (value, { options }) => { + const { min, max } = minmax(options?.min, options?.max) + return Math.min(Math.max(value, min), max) + }, + random: ({ options }) => { + const { min, max } = minmax(options?.min, options?.max) + const v = Math.random() * (max - min) + min + if (options?.step) { + const t = 1.0 / options.step + return Math.round(v * t) / t + } + return v + }, }, bigint: { - deserialize: (input) => { - const view = new DataView(new ArrayBuffer(8)) - for (let i = 0; i < 8; i++) { - view.setUint8(i, parseInt(input.substring(i * 2, i * 2 + 2), 16)) - } - return view.getBigInt64(0) - }, bytesLength: () => 8, - random: (definition) => { - const MIN_SAFE_INT64 = -9223372036854775808n - const MAX_SAFE_INT64 = 9223372036854775807n - let min = MIN_SAFE_INT64 - let max = MAX_SAFE_INT64 - if (typeof definition.options?.min !== "undefined") - min = BigInt(definition.options.min) - if (typeof definition.options?.max !== "undefined") - max = BigInt(definition.options.max) - const range = max - min - const bits = range.toString(2).length - let random - do { - random = BigInt( - "0b" + - Array.from( - crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8))) - ) - .map((b) => b.toString(2).padStart(8, "0")) - .join("") - ) - } while (random > range) - return random + min - }, + deserialize: (input) => BigInt.asIntN(64, BigInt("0x" + input)), + random: ({ options }) => { + const MIN_SAFE_INT64 = -9223372036854775808n + const MAX_SAFE_INT64 = 9223372036854775807n + if (options?.min !== undefined) { + min = BigInt(options.min) + if (min < MIN_SAFE_INT64) min = MIN_SAFE_INT64 + } + if (options?.max !== undefined) { + max = BigInt(options.max) + if (max > MAX_SAFE_INT64) max = MAX_SAFE_INT64 + } + const range = max - min + const bits = range.toString(2).length + let random + do { + random = BigInt( + "0x" + + Array.from(crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8)))) + .map((x) => x < 10 ? "0" + x : x.toString(16)) + .join("") + ) + } while (random > range) + return random + min + }, }, boolean: { - // if value is "00" -> 0 -> false, otherwise we consider it's 1 - deserialize: (input) => { - return input === "00" ? false : true - }, bytesLength: () => 1, + deserialize: (input) => input !== "00", random: () => Math.random() < 0.5, }, color: { - deserialize: (input) => input, bytesLength: () => 4, + deserialize: (input) => input, transform: (input) => { - const r = parseInt(input.slice(0,2), 16) - const g = parseInt(input.slice(2,4), 16) - const b = parseInt(input.slice(4,6), 16) - const a = parseInt(input.slice(6,8), 16) - return { - hex: { - rgb: '#' + input.slice(0,6), - rgba: '#' + input, - }, - obj: { - rgb: { r, g, b}, - rgba: { r, g, b, a}, - }, - arr: { - rgb: [r,g,b], - rgba: [r,g,b,a], - } - } - }, - constrain: (value, definition) => { - const hex = value.replace("#", "") - return hex.slice(0, 8).padEnd(8, "f") - }, - random: () => - `${[...Array(8)] - .map(() => Math.floor(Math.random() * 16).toString(16)) - .join("")}`, - }, + const [r, g, b, a] = asBytes(input, 4) + return { + hex: { + rgb: "#" + input.slice(0, 6), + rgba: "#" + input, + }, + obj: { + rgb: { r, g, b }, + rgba: { r, g, b, a }, + }, + arr: { + rgb: [r, g, b], + rgba: [r, g, b, a], + }, + } + }, + constrain: (value) => value.replace("#", "").slice(0, 8).padEnd(8, "f"), + random: () => ((Math.random() * 0x100000000) >>> 0).toString(16).padStart(8, "0"), + }, string: { + bytesLength: () => 64, deserialize: (input) => { - const hx = input.match(/.{1,4}/g) || [] - let rtn = "" - for (let i = 0; i < hx.length; i++) { - const int = parseInt(hx[i], 16) - if (int === 0) break - rtn += String.fromCharCode(int) - } - return rtn - }, - bytesLength: () => 64 * 2, - constrain: (value, definition) => { - let min = 0 - if (typeof definition.options?.minLength !== "undefined") - min = definition.options.minLength - let max = 64 - if (typeof definition.options?.maxLength !== "undefined") - max = definition.options.maxLength - max = Math.min(max, 64) - let v = value.slice(0, max); - if (v.length < min) { - return v.padEnd(min) - } - return v; - }, - random: (definition) => { - let min = 0 - if (typeof definition.options?.minLength !== "undefined") - min = definition.options.minLength - let max = 64 - if (typeof definition.options?.maxLength !== "undefined") - max = definition.options.maxLength - max = Math.min(max, 64) - const length = Math.round(Math.random() * (max - min) + min) - return [...Array(length)] - .map((i) => (~~(Math.random() * 36)).toString(36)) - .join("") - }, + const buf = new Uint8Array(asBytes(input, 64)) + const idx = buf.indexOf(0) + return new TextDecoder().decode(idx !== -1 ? buf.slice(0, idx) : buf) + }, + constrain: (value, { options }) => { + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64) + return value.length > max + ? value.slice(0, max) + : value.length < min + ? value.padEnd(min) + : value + }, + random: ({ options }) => { + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64) + const length = Math.round(Math.random() * (max - min) + min) + return [...Array(length)].map(() => (~~(Math.random() * 36)).toString(36)).join("") + }, }, select: { - deserialize: (input, definition) => { - return definition.options.options[parseInt(input, 16)] || definition.default - }, bytesLength: () => 1, - constrain: (value, definition) => { - if(definition.options.options.includes(value)) { - return value; - } - return definition.options.options[0] - }, - random: (definition) => { - const index = Math.round( - Math.random() * (definition?.options?.options?.length - 1) + 0 - ) - return definition?.options?.options[index] - }, + deserialize: (input, def) => def.options.options[parseInt(input, 16)] || def.default, + constrain: (value, { options }) => options.options.includes(value) + ? value + : options.options[0], + random: ({ options }) => options.options[~~(Math.random() * options.options.length)], } } From 42eb37b15d605a551340351bfa2f6de97bec9254 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 19:20:22 +0200 Subject: [PATCH 02/15] style: uniform code style - replace remaining single quote occurrences w/ double quotes - remove remaining semicolons --- project/public/index.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index b97f9b7..21ee608 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -7,10 +7,10 @@ //---- do not edit the following code (you can indent as you wish) let search = new URLSearchParams(window.location.search) let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" - var fxhash = search.get('fxhash') || "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join('') + var fxhash = search.get("fxhash") || "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0) let fxhashTrunc = fxhash.slice(2) - let regex = new RegExp(".{" + ((fxhash.length/4)|0) + "}", 'g') + let regex = new RegExp(".{" + ((fxhash.length/4)|0) + "}", "g") let hashes = fxhashTrunc.match(regex).map(h => b58dec(h)) let sfc32 = (a, b, c, d) => { return () => { @@ -27,7 +27,7 @@ var fxrand = sfc32(...hashes) // true if preview mode active, false otherwise // you can append preview=1 to the URL to simulate preview active - var isFxpreview = search.get('preview') === "1" + var isFxpreview = search.get("preview") === "1" // call this method to trigger the preview function fxpreview() { window.dispatchEvent(new Event("fxhash-preview")) @@ -37,7 +37,7 @@ // NEW: v2 of the fxhash SDK lol // // get the byte params from the URL - let fxparams = search.get('fxparams') + let fxparams = search.get("fxparams") fxparams = fxparams ? fxparams.replace("0x", "") : fxparams function* asBytes(hex, n) { @@ -177,7 +177,7 @@ let v if (typeof def.default === "undefined") v = processor.random(def) else v = def.default - params[def.id] = processor.constrain?.(v, def) || v; + params[def.id] = processor.constrain?.(v, def) || v continue } // extract the length from the bytes & shift the initial bytes string @@ -185,7 +185,7 @@ bytes = bytes.substring(processor.bytesLength() * 2) // deserialize the bytes into the params const value = processor.deserialize(valueBytes, def) - params[def.id] = processor.constrain?.(value, def) || value; + params[def.id] = processor.constrain?.(value, def) || value } return params } @@ -196,9 +196,9 @@ const processor = processors[def.type] const value = values[def.id] // deserialize the bytes into the params - paramValues[def.id] = processor.transform ? processor.transform(value) : value; + paramValues[def.id] = processor.transform ? processor.transform(value) : value } - return paramValues; + return paramValues } window.$fx = { From 2a08ff2e8cad68720b45b21a3b190e1a309bb8cf Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 19:24:30 +0200 Subject: [PATCH 03/15] refactor: update default handling in deserializeParams() --- project/public/index.html | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 21ee608..c3e2835 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -167,16 +167,14 @@ // takes the parameters as bytes and outputs an object with the // deserialized parameters, identified by their id in an object - const deserializeParams = (bytes, definition) => { + const deserializeParams = (bytes, definitions) => { const params = {} - for (const def of definition) { + for (const def of definitions) { const processor = processors[def.type] // if we don't have any parameters defined in the URL, set the // default value and move on if (!bytes) { - let v - if (typeof def.default === "undefined") v = processor.random(def) - else v = def.default + const v = def.default === undefined ? processor.random(def) : def.default params[def.id] = processor.constrain?.(v, def) || v continue } From 222f3c3b646032adffb23c0285859ae81b8cb5a0 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 19:26:15 +0200 Subject: [PATCH 04/15] refactor: update "this"-object handling in $fx --- project/public/index.html | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index c3e2835..e035292 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -211,38 +211,39 @@ rand: fxrand, preview: fxpreview, isPreview: isFxpreview, - params: function(definition) { + + params(definition) { // todo: maybe do some validation on the dev side ? // or maybe not ? this._params = definition this._rawValues = deserializeParams(fxparams, definition) this._paramValues = transformParamValues(this._rawValues, definition) }, - features: function(features) { + features(features) { this._features = features }, - getFeature: function(id) { + getFeature(id) { return this._features[id] }, - getFeatures: function() { + getFeatures() { return this._features }, - getParam: function(id) { + getParam(id) { return this._paramValues[id] }, - getParams: function() { + getParams() { return this._paramValues }, - getRawParam: function(id) { + getRawParam(id) { return this._rawValues[id] }, - getRawParams: function() { + getRawParams() { return this._rawValues }, - getDefinitions: function() { - return this._params; + getDefinitions() { + return this._params }, - stringifyParams: function(params) { + stringifyParams(params) { return JSON.stringify( params, (key, value) => { From a12283cb21f41c487146245a491149bcbae5a120 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 19:26:29 +0200 Subject: [PATCH 05/15] refactor: minor update event handlers --- project/public/index.html | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index e035292..ca6d4c6 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -253,24 +253,19 @@ 2, ) } - } - window.addEventListener("message", (event) => { - if (event.data === "fxhash_getHash") { + window.addEventListener("message", ({data}) => { + if (data === "fxhash_getHash") { parent.postMessage({ id: "fxhash_getHash", data: window.$fx.hash }, "*") - } - - if (event.data === "fxhash_getFeatures") { + } else if (data === "fxhash_getFeatures") { parent.postMessage({ id: "fxhash_getFeatures", data: window.$fx.getFeatures() }, "*") - } - - if (event.data === "fxhash_getParams") { + } else if (data === "fxhash_getParams") { parent.postMessage({ id: "fxhash_getParams", data: { From 5ad57a64d23bbafe87b8677f83ef1667bb759db5 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 22:36:29 +0200 Subject: [PATCH 06/15] fix: update string maxLength handling --- project/public/index.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 9fd0746..46e1717 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -52,15 +52,15 @@ yield parseInt(hex.substring(i, i + 2), 16) } - function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER) { + function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER, clamp = true) { return { min: $min !== undefined - ? Math.max(Number($min), minDef) + ? clamp ? Math.max(Number($min), minDef) : Number($min) : minDef, max: $max !== undefined - ? Math.min(Number($max), maxDef) + ? clamp ? Math.min(Number($max), maxDef) : Number($max) : maxDef, } } @@ -69,7 +69,7 @@ const processors = { number: { bytesLength: () => 8, - deserialize: (input) => new Float64Array(new BigUint64Array([BigInt(`0x${input}`)]).buffer)[0], + deserialize: (input) => new Float64Array(new BigUint64Array([BigInt("0x" + input)]).buffer)[0], constrain: (value, { options }) => { const { min, max } = minmax(options?.min, options?.max) return Math.min(Math.max(value, min), max) @@ -142,13 +142,13 @@ }, string: { bytesLength: (options) => options?.maxLength !== undefined ? Number(options.maxLength) : 64, - deserialize: (input) => { - const buf = new Uint8Array(asBytes(input, 64)) + deserialize: (input, { options }) => { + const buf = new Uint8Array(asBytes(input, processors.string.bytesLength(options))) const idx = buf.indexOf(0) - return new TextDecoder().decode(idx !== -1 ? buf.slice(0, idx) : buf) + return new TextDecoder().decode(idx !== -1 ? buf.subarray(0, idx) : buf) }, constrain: (value, { options }) => { - const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64) + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) return value.length > max ? value.slice(0, max) : value.length < min @@ -156,7 +156,7 @@ : value }, random: ({ options }) => { - const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64) + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) const length = Math.round(Math.random() * (max - min) + min) return [...Array(length)].map(() => (~~(Math.random() * 36)).toString(36)).join("") }, From c925e9611dbe21c29fdda152d9faad46857bae1f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 14 Apr 2023 22:39:56 +0200 Subject: [PATCH 07/15] refactor: minor regexp updates --- project/public/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 46e1717..cd7766e 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -11,8 +11,8 @@ // make fxrand from hash var fxhash = search.get("fxhash") || "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") let fxhashTrunc = fxhash.slice(2) - let regex = new RegExp(".{" + ((fxhash.length/4)|0) + "}", "g") - let hashes = fxhashTrunc.match(regex).map(h => b58dec(h)) + let regex = new RegExp(".{" + (fxhash.length >> 2) + "}", "g") + let hashes = fxhashTrunc.match(regex).map(b58dec) let sfc32 = (a, b, c, d) => { return () => { a |= 0; b |= 0; c |= 0; d |= 0 @@ -29,7 +29,7 @@ // make fxrandminter from minter address var fxminter = search.get("fxminter") || "tz1" + Array(33).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") let fxminterTrunc = fxminter.slice(3) - regex = new RegExp(".{" + ((fxminterTrunc.length/4)|0) + "}", "g") + regex = new RegExp(".{" + (fxminterTrunc.length >> 2) + "}", "g") hashes = fxminterTrunc.match(regex).map(h => b58dec(h)) var fxrandminter = sfc32(...hashes) From c4b6a51021b41173eb8dc7e711acb5335cd75804 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 10:32:08 +0200 Subject: [PATCH 08/15] style: fix indentation (2 spaces) --- project/public/index.html | 140 +++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index cd7766e..1c35088 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -47,12 +47,12 @@ fxparams = fxparams ? fxparams.replace("0x", "") : fxparams function* asBytes(hex, n) { - n *= 2 - for (let i = 0; i < n; i += 2) - yield parseInt(hex.substring(i, i + 2), 16) - } + n *= 2 + for (let i = 0; i < n; i += 2) + yield parseInt(hex.substring(i, i + 2), 16) + } - function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER, clamp = true) { + function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER, clamp = true) { return { min: $min !== undefined @@ -71,46 +71,46 @@ bytesLength: () => 8, deserialize: (input) => new Float64Array(new BigUint64Array([BigInt("0x" + input)]).buffer)[0], constrain: (value, { options }) => { - const { min, max } = minmax(options?.min, options?.max) - return Math.min(Math.max(value, min), max) - }, + const { min, max } = minmax(options?.min, options?.max) + return Math.min(Math.max(value, min), max) + }, random: ({ options }) => { - const { min, max } = minmax(options?.min, options?.max) - const v = Math.random() * (max - min) + min - if (options?.step) { - const t = 1.0 / options.step - return Math.round(v * t) / t - } - return v - }, + const { min, max } = minmax(options?.min, options?.max) + const v = Math.random() * (max - min) + min + if (options?.step) { + const t = 1.0 / options.step + return Math.round(v * t) / t + } + return v + }, }, bigint: { bytesLength: () => 8, deserialize: (input) => BigInt.asIntN(64, BigInt("0x" + input)), random: ({ options }) => { - const MIN_SAFE_INT64 = -9223372036854775808n - const MAX_SAFE_INT64 = 9223372036854775807n - if (options?.min !== undefined) { - min = BigInt(options.min) - if (min < MIN_SAFE_INT64) min = MIN_SAFE_INT64 - } - if (options?.max !== undefined) { - max = BigInt(options.max) - if (max > MAX_SAFE_INT64) max = MAX_SAFE_INT64 - } - const range = max - min - const bits = range.toString(2).length - let random - do { - random = BigInt( - "0x" + - Array.from(crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8)))) - .map((x) => x < 10 ? "0" + x : x.toString(16)) - .join("") - ) - } while (random > range) - return random + min - }, + const MIN_SAFE_INT64 = -9223372036854775808n + const MAX_SAFE_INT64 = 9223372036854775807n + if (options?.min !== undefined) { + min = BigInt(options.min) + if (min < MIN_SAFE_INT64) min = MIN_SAFE_INT64 + } + if (options?.max !== undefined) { + max = BigInt(options.max) + if (max > MAX_SAFE_INT64) max = MAX_SAFE_INT64 + } + const range = max - min + const bits = range.toString(2).length + let random + do { + random = BigInt( + "0x" + + Array.from(crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8)))) + .map((x) => x < 10 ? "0" + x : x.toString(16)) + .join("") + ) + } while (random > range) + return random + min + }, }, boolean: { bytesLength: () => 1, @@ -121,45 +121,45 @@ bytesLength: () => 4, deserialize: (input) => input, transform: (input) => { - const [r, g, b, a] = asBytes(input, 4) - return { - hex: { - rgb: "#" + input.slice(0, 6), - rgba: "#" + input, - }, - obj: { - rgb: { r, g, b }, - rgba: { r, g, b, a }, - }, - arr: { - rgb: [r, g, b], - rgba: [r, g, b, a], - }, - } - }, + const [r, g, b, a] = asBytes(input, 4) + return { + hex: { + rgb: "#" + input.slice(0, 6), + rgba: "#" + input, + }, + obj: { + rgb: { r, g, b }, + rgba: { r, g, b, a }, + }, + arr: { + rgb: [r, g, b], + rgba: [r, g, b, a], + }, + } + }, constrain: (value) => value.replace("#", "").slice(0, 8).padEnd(8, "f"), random: () => ((Math.random() * 0x100000000) >>> 0).toString(16).padStart(8, "0"), }, string: { bytesLength: (options) => options?.maxLength !== undefined ? Number(options.maxLength) : 64, deserialize: (input, { options }) => { - const buf = new Uint8Array(asBytes(input, processors.string.bytesLength(options))) - const idx = buf.indexOf(0) - return new TextDecoder().decode(idx !== -1 ? buf.subarray(0, idx) : buf) - }, + const buf = new Uint8Array(asBytes(input, processors.string.bytesLength(options))) + const idx = buf.indexOf(0) + return new TextDecoder().decode(idx !== -1 ? buf.subarray(0, idx) : buf) + }, constrain: (value, { options }) => { - const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) - return value.length > max - ? value.slice(0, max) - : value.length < min - ? value.padEnd(min) - : value - }, + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) + return value.length > max + ? value.slice(0, max) + : value.length < min + ? value.padEnd(min) + : value + }, random: ({ options }) => { - const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) - const length = Math.round(Math.random() * (max - min) + min) - return [...Array(length)].map(() => (~~(Math.random() * 36)).toString(36)).join("") - }, + const { min, max } = minmax(options?.minLength, options?.maxLength, 0, 64, false) + const length = Math.round(Math.random() * (max - min) + min) + return [...Array(length)].map(() => (~~(Math.random() * 36)).toString(36)).join("") + }, }, select: { bytesLength: () => 1, From a0f58e0614d3a62fe0c8417329a91dfb20d96cbf Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 11:05:25 +0200 Subject: [PATCH 09/15] refactor: simplify hash/PRNG initialization - add rndHash() & matcher() helpers - improve internal re-use for fxhash & fxminter init --- project/public/index.html | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 1c35088..80001d7 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -8,11 +8,6 @@ let search = new URLSearchParams(window.location.search) let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0) - // make fxrand from hash - var fxhash = search.get("fxhash") || "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") - let fxhashTrunc = fxhash.slice(2) - let regex = new RegExp(".{" + (fxhash.length >> 2) + "}", "g") - let hashes = fxhashTrunc.match(regex).map(b58dec) let sfc32 = (a, b, c, d) => { return () => { a |= 0; b |= 0; c |= 0; d |= 0 @@ -25,13 +20,14 @@ return (t >>> 0) / 4294967296 } } - var fxrand = sfc32(...hashes) + let rndHash = (n) => Array(n).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") + let matcher = (str, start) => str.slice(start).match(new RegExp(".{"+((str.length-start)>>2)+"}","g")).map(b58dec) + // make fxrand from hash + var fxhash = search.get("fxhash") || "oo" + rndHash(49) + var fxrand = sfc32(...matcher(fxhash, 2)) // make fxrandminter from minter address - var fxminter = search.get("fxminter") || "tz1" + Array(33).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join("") - let fxminterTrunc = fxminter.slice(3) - regex = new RegExp(".{" + (fxminterTrunc.length >> 2) + "}", "g") - hashes = fxminterTrunc.match(regex).map(h => b58dec(h)) - var fxrandminter = sfc32(...hashes) + var fxminter = search.get("fxminter") || "tz1" + rndHash(33) + var fxrandminter = sfc32(...matcher(fxminter, 3)) // true if preview mode active, false otherwise // you can append preview=1 to the URL to simulate preview active From a393769ec7d6405f863e4cc94c0787c80b86c614 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 11:05:55 +0200 Subject: [PATCH 10/15] style: update formatting --- project/public/index.html | 51 +++++++++------------------------------ 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/project/public/index.html b/project/public/index.html index 80001d7..a8b398a 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -50,14 +50,8 @@ function minmax($min, $max, minDef = Number.MIN_SAFE_INTEGER, maxDef = Number.MAX_SAFE_INTEGER, clamp = true) { return { - min: - $min !== undefined - ? clamp ? Math.max(Number($min), minDef) : Number($min) - : minDef, - max: - $max !== undefined - ? clamp ? Math.min(Number($max), maxDef) : Number($max) - : maxDef, + min: $min !== undefined ? clamp ? Math.max(Number($min), minDef) : Number($min) : minDef, + max: $max !== undefined ? clamp ? Math.min(Number($max), maxDef) : Number($max) : maxDef, } } @@ -227,39 +221,16 @@ this._rawValues = deserializeParams(fxparams, definition) this._paramValues = transformParamValues(this._rawValues, definition) }, - features(features) { - this._features = features - }, - getFeature(id) { - return this._features[id] - }, - getFeatures() { - return this._features - }, - getParam(id) { - return this._paramValues[id] - }, - getParams() { - return this._paramValues - }, - getRawParam(id) { - return this._rawValues[id] - }, - getRawParams() { - return this._rawValues - }, - getDefinitions() { - return this._params - }, + features(features) { this._features = features }, + getFeature(id) { return this._features[id] }, + getFeatures() { return this._features }, + getParam(id) { return this._paramValues[id] }, + getParams() { return this._paramValues }, + getRawParam(id) { return this._rawValues[id] }, + getRawParams() { return this._rawValues }, + getDefinitions() { return this._params }, stringifyParams(params) { - return JSON.stringify( - params, - (key, value) => { - if (typeof value === "bigint") return value.toString() - return value - }, - 2, - ) + return JSON.stringify(params, (_, v) => typeof v === "bigint" ? v.toString() : v, 2) } } From ee3020bbb712ee9d817991facda6e1fc6b3d6b6c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 11:07:12 +0200 Subject: [PATCH 11/15] feat: add fxminter output to project scaffolding --- project/src/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project/src/index.js b/project/src/index.js index dfaaed3..0bb2de0 100644 --- a/project/src/index.js +++ b/project/src/index.js @@ -105,6 +105,9 @@ url: ${window.location.href} hash: ${$fx.hash}

+hash: ${$fx.minter} +

+

params:


From efa34e6d49dc47d90833e0c1ef87a07e9737542f Mon Sep 17 00:00:00 2001
From: Karsten Schmidt 
Date: Sat, 15 Apr 2023 11:09:08 +0200
Subject: [PATCH 12/15] minor: fix typo

---
 project/src/index.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/project/src/index.js b/project/src/index.js
index 0bb2de0..3ab7b76 100644
--- a/project/src/index.js
+++ b/project/src/index.js
@@ -105,7 +105,7 @@ url: ${window.location.href}
 hash: ${$fx.hash}
 

-hash: ${$fx.minter} +minter: ${$fx.minter}

params: From 98f585ac85aef6b227de34ac6f5560e54c1a915d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 13:27:03 +0200 Subject: [PATCH 13/15] fix: typo in hex conversion --- project/public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/public/index.html b/project/public/index.html index a8b398a..23de2df 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -95,7 +95,7 @@ random = BigInt( "0x" + Array.from(crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8)))) - .map((x) => x < 10 ? "0" + x : x.toString(16)) + .map((x) => x < 16 ? "0" + x : x.toString(16)) .join("") ) } while (random > range) From 059f38e7b962417ffff374145820e84d4bf344c8 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 15 Apr 2023 13:37:32 +0200 Subject: [PATCH 14/15] fix: update hex conversion - undoing previous megabrain blooper --- project/public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/public/index.html b/project/public/index.html index 23de2df..76ee38b 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -95,7 +95,7 @@ random = BigInt( "0x" + Array.from(crypto.getRandomValues(new Uint8Array(Math.ceil(bits / 8)))) - .map((x) => x < 16 ? "0" + x : x.toString(16)) + .map((x) => x.toString(16).padStart(2,"0")) .join("") ) } while (random > range) From 8dca39508126a956e387c2925348ce639cabf3b7 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 16 Jun 2023 15:36:34 +0200 Subject: [PATCH 15/15] run prettier --- .prettierrc.json | 6 + project/public/index.html | 977 ++++++++++++++++++++------------------ 2 files changed, 529 insertions(+), 454 deletions(-) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..0a379d5 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": false +} \ No newline at end of file diff --git a/project/public/index.html b/project/public/index.html index 01563fd..418e0aa 100644 --- a/project/public/index.html +++ b/project/public/index.html @@ -4,488 +4,557 @@ FXHASH project