diff --git a/dist/opstring.js b/dist/opstring.js index e26f538..4849543 100644 --- a/dist/opstring.js +++ b/dist/opstring.js @@ -1,8 +1,8 @@ /**! * OpString * - * @version 0.4.0 + * @version 0.5.0 * @license MIT * @copyright meezwhite */ -export default class OpString{version="0.4.0";#e="";#t=[];#r={};#s={};#i={};#n;#o=!1;#a=!1;#h=1;#c=0;#l=1;#u=2;#g=0;#d=65535;#p=["sequence","operations","values","labels","maxSequenceLength","ignoreWarnings","strictMode"];constructor(e){try{this.#y("constructor",arguments),void 0!==e&&(void 0!==e.maxSequenceLength&&(this.#n=e.maxSequenceLength),"boolean"==typeof e.ignoreWarnings&&(this.#o=e.ignoreWarnings),"boolean"==typeof e.strictMode&&(this.#a=e.strictMode),void 0!==e.operations&&this.#f(e.operations),void 0!==e.values&&this.#m(e.values),void 0!==e.labels&&this.#b(e.labels),void 0!==e.sequence&&this.setSequence(e.sequence))}catch(e){this.#v(e)}}append(e,t){const r=this.#h;try{return this.#y("append",arguments),this.#t.push({id:r,operation:this.#C(e),values:this.#S(t)}),this.#h++,this.#q(),r}catch(e){this.#v(e)}return!1}insert(e,t,r){const s=this.#h;try{return this.#y("add",arguments),this.#t.splice(e,0,{id:s,operation:this.#C(t),values:this.#S(r)}),this.#h++,this.#q(),s}catch(e){this.#v(e)}return!1}prepend(e,t){const r=this.#h;try{return this.#y("prepend",arguments),this.#t.unshift({id:r,operation:this.#C(e),values:this.#S(t)}),this.#h++,this.#q(),r}catch(e){this.#v(e)}return!1}remove(e){try{this.#y("remove",arguments);const t=this.#t.findIndex((t=>t.id===e));if(-1===t)throw new ReferenceError(`Cannot remove operation with id ${e}, since not found.`);this.#t.splice(t,1),this.#q()}catch(e){return this.#v(e),!1}return!0}index(e){try{this.#y("index",arguments);const t=this.#t.findIndex((t=>t.id===e));if(-1!==t)return t;throw new ReferenceError(`Cannot find index of operation with id ${e}, since not found.`)}catch(e){this.#v(e)}}#C(e){return this.#w(e)===this.#l?e.charCodeAt(0):e}#S(e){return void 0!==e?e.map((e=>{const t=this.#w(e);return t===this.#l?e.charCodeAt(0):t===this.#u?e:null})):[]}#q(){let e="";for(let t=0;tt.includes(e)))),"object"==typeof e&&null!==e&&!Array.isArray(e)&&Object.keys(e).length>0&&r&&void 0!==e.constructor&&e.constructor.prototype.hasOwnProperty("isPrototypeOf")}#E(e){return e>=this.#g&&e<=this.#d}#L(e){return"number"==typeof e&&Number.isSafeInteger(e)&&e>0}#O(e){return!(void 0!==this.#n&&e.length>this.#n)}#v(e){e=`[${this.constructor.name}] ${e.name}: ${e.message}`,this.#a?console.error(e):this.#o||console.warn(e)}#y(e,t){let r;switch(e){case"constructor":if(void 0!==t[0]){if(!this.#$(t[0],this.#p)){const e=this.#p.slice(0,-1).map((e=>`'${e}'`)).join(", "),t=this.#p[this.#p.length-1];throw new TypeError(`The 'config' parameter, if defined, must be a non-empty plain object with valid 'config' properties; these are ${e} and '${t}'.`)}if(void 0!==t[0].sequence&&"string"!=typeof t[0].sequence)throw new TypeError("The 'config.sequence' property, if defined, must be a string.");if(void 0!==t[0].operations&&!this.#$(t[0].operations))throw new TypeError("The 'config.operations' property, if defined, must be a non-empty plain object.");if(void 0!==t[0].values&&!this.#$(t[0].values))throw new TypeError("The 'config.values' property, if defined, must be a non-empty plain object");if(void 0!==t[0].labels&&!this.#$(t[0].labels))throw new TypeError("The 'config.labels' property, if defined, must be a non-empty plain object");if(void 0!==t[0].maxSequenceLength&&!this.#L(t[0].maxSequenceLength))throw new TypeError("The 'config.maxSequenceLength' property, if defined, must be a positive safe integer.");if(void 0!==t[0].ignoreWarnings&&"boolean"!=typeof t[0].ignoreWarnings)throw new TypeError("The 'config.ignoreWarnings' property, if defined, must be a boolean.");if(void 0!==t[0].strictMode&&"boolean"!=typeof t[0].strictMode)throw new TypeError("The 'config.strictMode' property, if defined, must be a boolean.")}break;case"setSequence":if(r=this.#a?`Cannot ${e} to '${t[0]}'. The`:`Setting the sequence to '${t[0]}' despite exceeded length. The`,void 0!==t[0]&&"string"!=typeof t[0])throw new TypeError(`${r} sequence must be a string.`);if("string"==typeof t[0]&&!this.#O(t[0]))throw new RangeError(`${r} provided sequence exceeds the configured 'maxSequenceLength' of ${this.#n} characters.`);break;case"remove":if(!this.#L(t[0]))throw new TypeError(`Cannot remove operation with id '${t[0]}'. The id must be a positive safe integer.`);break;case"index":if(!this.#L(t[0]))throw new TypeError(`Cannot find index for operation with id '${t[0]}'. The id must be a positive safe integer.`);break;case"append":case"insert":case"prepend":case"registerOperation":case"registerValue":case"registerLabel":"insert"===e?t=[t[1],t[2],t[0]]:"registerLabel"===e&&(t=[t[1],t[0]]);const s=["append","insert","prepend"].includes(e);if(r=`Cannot ${e}${s?" operation":""} with symbol '${t[0]}'`,"insert"===e){const e="number"==typeof t[2];if(!e||e&&t[2]<0)throw new TypeError(`${r} at index '${t[2]}'. The index must be a non-negative integer.`)}else if("registerLabel"===e&&"string"!=typeof t[0])throw new TypeError(`${r}. The label must be a string.`);const i="symbol must be a string or an integer.",n="string symbol must consist of a single character.",o=`integer symbol must be within the range of ${this.#g} and ${this.#d}.`,a=this.#w(t[0]);if(a===this.#c)throw new TypeError(`${r}. The ${i}`);if(a===this.#l&&1!==t[0].length)throw new SyntaxError(`${r}. A ${n}`);if(a===this.#u&&!this.#E(t[0]))throw new RangeError(`${r}. An ${o}`);if(s&&void 0!==t[1]){const e=Array.isArray(t[1]);if(!e||e&&0===t[1].length)throw new TypeError(`${r}. The 'values' parameter must be an non-empty array.`);const s=` and values '${t[1]}'. The 'values' array contains an invalid symbol. Each `;for(let e=0;et.id===e));if(-1===t)throw new ReferenceError(`Cannot remove operation with id ${e}, since not found.`);this.#t.splice(t,1),this.#q()}catch(e){return this.#v(e),!1}return!0}index(e){try{this.#y("index",arguments);const t=this.#t.findIndex((t=>t.id===e));if(-1!==t)return t;throw new ReferenceError(`Cannot find index of operation with id ${e}, since not found.`)}catch(e){this.#v(e)}}#C(e){return this.#w(e)===this.#l?e.charCodeAt(0):e}#S(e){return void 0!==e?e.map((e=>{const t=this.#w(e);return t===this.#l?e.charCodeAt(0):t===this.#u?e:null})):[]}#q(){let e="";for(let t=0;tt.includes(e)))),"object"==typeof e&&null!==e&&!Array.isArray(e)&&Object.keys(e).length>0&&r&&void 0!==e.constructor&&e.constructor.prototype.hasOwnProperty("isPrototypeOf")}#E(e){return e>=this.#g&&e<=this.#d}#L(e){return"number"==typeof e&&Number.isSafeInteger(e)&&e>0}#I(e){return!(void 0!==this.#n&&e.length>this.#n)}#v(e){e=`[${this.constructor.name}] ${e.name}: ${e.message}`,this.#a?console.error(e):this.#o||console.warn(e)}#y(e,t){let r;switch(e){case"constructor":if(void 0!==t[0]){if(!this.#$(t[0],this.#p)){const e=this.#p.slice(0,-1).map((e=>`'${e}'`)).join(", "),t=this.#p[this.#p.length-1];throw new TypeError(`The 'config' parameter, if defined, must be a non-empty plain object with valid 'config' properties; these are ${e} and '${t}'.`)}if(void 0!==t[0].sequence&&"string"!=typeof t[0].sequence)throw new TypeError("The 'config.sequence' property, if defined, must be a string.");if(void 0!==t[0].operations&&!this.#$(t[0].operations))throw new TypeError("The 'config.operations' property, if defined, must be a non-empty plain object.");if(void 0!==t[0].values&&!this.#$(t[0].values))throw new TypeError("The 'config.values' property, if defined, must be a non-empty plain object");if(void 0!==t[0].labels&&!this.#$(t[0].labels))throw new TypeError("The 'config.labels' property, if defined, must be a non-empty plain object");if(void 0!==t[0].maxSequenceLength&&!this.#L(t[0].maxSequenceLength))throw new TypeError("The 'config.maxSequenceLength' property, if defined, must be a positive safe integer.");if(void 0!==t[0].ignoreWarnings&&"boolean"!=typeof t[0].ignoreWarnings)throw new TypeError("The 'config.ignoreWarnings' property, if defined, must be a boolean.");if(void 0!==t[0].strictMode&&"boolean"!=typeof t[0].strictMode)throw new TypeError("The 'config.strictMode' property, if defined, must be a boolean.")}break;case"setSequence":if(r=this.#a?`Cannot ${e} to '${t[0]}'. The`:`Setting the sequence to '${t[0]}' despite exceeded length. The`,void 0!==t[0]&&"string"!=typeof t[0])throw new TypeError(`${r} sequence must be a string.`);if("string"==typeof t[0]&&!this.#I(t[0]))throw new RangeError(`${r} provided sequence exceeds the configured 'maxSequenceLength' of ${this.#n} characters.`);break;case"remove":if(!this.#L(t[0]))throw new TypeError(`Cannot remove operation with id '${t[0]}'. The id must be a positive safe integer.`);break;case"index":if(!this.#L(t[0]))throw new TypeError(`Cannot find index for operation with id '${t[0]}'. The id must be a positive safe integer.`);break;case"append":case"insert":case"prepend":case"registerOperation":case"registerValue":case"registerLabel":"insert"===e?t=[t[1],t[2],t[0]]:"registerLabel"===e&&(t=[t[1],t[0]]);const s=["append","insert","prepend"].includes(e);if(r=`Cannot ${e}${s?" operation":""} with symbol '${t[0]}'`,"insert"===e){const e="number"==typeof t[2];if(!e||e&&t[2]<0)throw new TypeError(`${r} at index '${t[2]}'. The index must be a non-negative integer.`)}else if("registerLabel"===e&&"string"!=typeof t[0])throw new TypeError(`${r}. The label must be a string.`);const i="symbol must be a string or an integer.",n="string symbol must consist of a single character.",o=`integer symbol must be within the range of ${this.#g} and ${this.#d}.`,a=this.#w(t[0]);if(a===this.#c)throw new TypeError(`${r}. The ${i}`);if(a===this.#l&&1!==t[0].length)throw new SyntaxError(`${r}. A ${n}`);if(a===this.#u&&!this.#E(t[0]))throw new RangeError(`${r}. An ${o}`);if(s&&void 0!==t[1]){const e=Array.isArray(t[1]);if(!e||e&&0===t[1].length)throw new TypeError(`${r}. The 'values' parameter must be an non-empty array.`);const s=` and values '${t[1]}'. The 'values' array contains an invalid symbol. Each `;for(let e=0;e