├── .gitignore ├── Changelog.md ├── LICENSE ├── README.md ├── dist ├── bootstrap-maxlength.js └── bootstrap-maxlength.min.js ├── eslint.config.mjs ├── package-lock.json ├── package.json ├── src └── bootstrap-maxlength.js ├── test ├── basicInputTests.js ├── basicTextareaTests.js ├── optionsTests │ ├── Utf8Tests.js │ ├── ValidateTests.js │ ├── alwaysShowTests.js │ ├── customMaxAttributeTests.js │ ├── placementFunctionTests.js │ ├── placementTests.js │ └── twoCharLinebreakTests.js └── qunit.html └── travis.yml /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | node_modules/ 3 | dist/ 4 | .DS_Store -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | ### 2.0.0 4 | 5 | - Updated bootstrap 5.3.3 6 | - Updated jQuery 3.7.1 7 | - Updated qUnit 2.22 8 | 9 | ### 1.10.0 10 | 11 | ### 1.9.0 12 | 13 | - Add zIndex support by @ASKemp 14 | - Fixed file input counter (@djibe) 15 | - Update dependencies 16 | 17 | ### 1.8.0 18 | 19 | - Dropped Grunt (_Unmaintained_) 20 | - Moved project to **NodeJS** 21 | - Changed default parameters for **Bootstrap 4.4.1** and updated docs 22 | - Fixed : build files located in `/dist` folder 23 | - TODO : unit tests with qunit, travis builds 24 | 25 | ### 1.7.0 26 | 27 | - Restructured distribution files position from root folder to /dist folder 28 | 29 | ### 1.6.1 30 | 31 | - Added more tests around the functionalities of the plugin 32 | - Fixed issues around the **alwaysShow** option 33 | 34 | ### 1.6.0 35 | 36 | - Added new custom events: maxlength.reposition, maxlength.shown, maxlength.hidden. Thanks to dr-nick. 37 | - Bumped up required jQuery to 1.9.x 38 | - Added option `placement` for custom placement handler. Thanks to Kreegr 39 | - Extended `message` option. Now it can also be optionally a function. Thanks to Vincent Pizzo 40 | 41 | ### 1.5.7 42 | 43 | - Fixed issue with bower 44 | 45 | ### 1.5.6 46 | 47 | - Added over maxlength functionality with customMaxAttribute 48 | - Added twoCharLinebreak option 49 | 50 | ### 1.5.5 51 | 52 | - Implemented input event rather than keydown to improve usability 53 | - Fixed jshint, jscs errors 54 | 55 | ### 1.5.4 56 | 57 | - When an input with associated maxlength element is removed, maxlength is also removed. 58 | 59 | ### 1.5.3 60 | 61 | - Fixed #40, error on resize event. 62 | 63 | ### 1.5.2 64 | 65 | - Fixed #44 (pasted text in can cause it to go over the max length) 66 | 67 | ### 1.5.1 68 | 69 | - Added self protection of multiple focus events 70 | - Added back detection of window resizing 71 | 72 | ### 1.5.0 73 | 74 | - Removed window.resize event 75 | - Maxlength is created and destroyed each time 76 | - Fixed Doesn't update the limit after input's maxlength attribute was changed [#31](https://github.com/mimo84/bootstrap-maxlength/issues/31) 77 | - Added Gruntfile 78 | - Added qunit unit tests 79 | 80 | ### 1.4.2 81 | 82 | - Fixed issue with counting when the user moves with shift+tab keyboard shortcut. 83 | - Replaced the warningClass limitReachedClass options to use labels rather than badges for Bootstrap 3.0 better compatibility. 84 | 85 | ### 1.4.1 86 | 87 | - Added support for TAB key when the maxlength is reached. 88 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2013-2021 Maurizio Napoleoni; 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Bootstrap MaxLength](http://mimo84.github.com/bootstrap-maxlength/) [![Build Status](https://travis-ci.org/mimo84/bootstrap-maxlength.png?branch=master)](https://travis-ci.org/mimo84/bootstrap-maxlength) 2 | 3 | This plugin integrates by default with Twitter bootstrap using badges to display the maximum length of the field where the user is inserting text. 4 | This plugin uses the HTML5 attribute "maxlength" to work. 5 | 6 | The indicator badge shows up on focusing on the element, and disappears when the focus is lost. 7 | 8 | ## Configurable options 9 | 10 | * **alwaysShow**: if true the threshold will be ignored and the remaining length indication will be always showing up while typing or on focus on the input. Default: ```false```. 11 | * **threshold**: this is a number indicating how many chars are left to start displaying the indications. Default: ```0```. 12 | * **warningClass**: it's the class of the element with the indicator. Default is ```small form-text text-body-secondary ``` but can be changed to anything you'd like. 13 | * **limitReachedClass**: it's the class the element gets when the limit is reached. Default is ```small form-text text-danger``` and can be changed. 14 | * **limitExceededClass**: it's the class that the element gets when the limit is exceeded. The default is ```''``` In this case, the limitReachedClass setting is used. 15 | * **separator**: represents the separator between the number of typed chars and total number of available chars. Default is ``` / ```. 16 | * **preText**: is a string of text that can be outputted in front of the indicator. preText is empty by default. 17 | * **postText**: is a string outputted after the indicator. postText is empty by default. 18 | * **showMaxLength**: if false, will display just the number of typed characters, e.g. will not display the max length. Default: ```true```. 19 | * **showCharsTyped**: if false, will display just the remaining length, e.g. will display remaining length instead of number of typed characters. Default: ```true```. 20 | * **appendToParent**: appends the maxlength indicator badge to the parent of the input rather than to the body. Default: ```false```. 21 | * **message**: an alternative way to provide the message text, i.e. 'You have typed %charsTyped% chars, %charsRemaining% of %charsTotal% remaining'. %charsTyped%, %charsRemaining% and %charsTotal% will be replaced by the actual values. This overrides the options separator, preText, postText and showMaxLength. Alternatively you may supply a function that the current text and max length and returns the string to be displayed. For example, function(currentText, maxLength) { return '' + Math.ceil(currentText.length / 160) + ' SMS Message(s)'; } 22 | * **utf8**: if true the input will count using utf8 bytesize/encoding. For example: the '£' character is counted as two characters. Default: ```false```. 23 | * **showOnReady**: shows the badge as soon as it is added to the page, similar to alwaysShow. Default: ```false```. 24 | * **twoCharLinebreak**: count linebreak as 2 characters to match IE/Chrome textarea validation. Default: ```true```. 25 | * **customMaxAttribute**: String -- allows a custom attribute to display indicator without triggering native maxlength behaviour. Ignored if value greater than a native maxlength attribute. customMaxClass settings gets added when exceeded to allow user to implement form validation. Default is ```null```. 26 | * **customMaxClass**: Set the class to be added with 'customMaxAttribute'. The default is 'overmax'. 27 | * **validate**: If the browser doesn't support the maxlength attribute, attempt to type more than the indicated chars, will be prevented. Default: ```false```. 28 | * **allowOverMax**: Will allow the input to be over the customMaxLength. Useful in soft max situations. Default `false`. 29 | * **zIndex**: Will set the counter z-elevation. Useful to fix elevation in modals or dialogs. Default `1099`. 30 | * **placement**: Is a string, object, or function, to define where to output the counter. 31 | * Possible string values are: ```bottom```, ```left```, ```top```, ```right```, ```bottom-right```, ```top-right```, ```top-left```, ```bottom-left``` and ```centered-right```. Are also available : ```bottom-right-inside``` (*default option*, as in Google's Material Design), ```top-right-inside```, ```top-left-inside``` and ```bottom-left-inside```. 32 | * Custom placements can be passed as an object, with keys ```top```, ```right```, ```bottom```, ```left```, and ```position```. These are passed to $.fn.css. 33 | * A custom function may also be passed. This method is invoked with the {$element} Current Input, the {$element} MaxLength Indicator, and the Current Input's Position {bottom height left right top width}. 34 | 35 | ## Events 36 | 37 | * **maxlength.reposition** on an input element triggers re-placing of its indicator. Useful if textareas are resized by an external trigger. 38 | * **maxlength.shown** is triggered when the indicator is displayed. 39 | * **maxlength.hidden** is triggered when the indicator is removed from view. 40 | 41 | ## Examples 42 | 43 | Basic implementation: 44 | ```javascript 45 | $('[maxlength]').maxlength(); 46 | ``` 47 | 48 | Change the threshold value: 49 | ```javascript 50 | $('input.className').maxlength({ 51 | threshold: 20 52 | }); 53 | ``` 54 | 55 | An example with some of the configurable options: 56 | ```javascript 57 | $('input.className').maxlength({ 58 | alwaysShow: true, 59 | threshold: 10, 60 | warningClass: "label label-info", 61 | limitReachedClass: "label label-warning", 62 | placement: 'top', 63 | preText: 'used ', 64 | separator: ' of ', 65 | postText: ' chars.' 66 | }); 67 | ``` 68 | 69 | The same example using the message option: 70 | 71 | ```javascript 72 | $('input.className').maxlength({ 73 | alwaysShow: true, 74 | threshold: 10, 75 | warningClass: "label label-info", 76 | limitReachedClass: "label label-warning", 77 | placement: 'top', 78 | message: 'used %charsTyped% of %charsTotal% chars.' 79 | }); 80 | ``` 81 | 82 | An example allowing user to enter over max characters. __NOTE: you cannot have the maxlength attribute on the input element. You will need to provide the customMaxAttribute attribute__ 83 | 84 | Sample HTML element: 85 | ```html 86 | 87 | ``` 88 | 89 | ```javascript 90 | // Setup maxlength 91 | $('.form-control').maxlength({ 92 | alwaysShow: true, 93 | validate: false, 94 | allowOverMax: true, 95 | customMaxAttribute: "90" 96 | }); 97 | 98 | // validate form before submit 99 | $('form').on('submit', function (e) { 100 | $('.form-control').each( 101 | function () { 102 | if ($(this).hasClass('overmax')) { 103 | alert('prevent submit here'); 104 | e.preventDefault(); 105 | return false; 106 | } 107 | } 108 | ); 109 | }); 110 | ``` 111 | 112 | An example of triggering a `maxlength.reposition` event whenever an external autosize plugin resizes a textarea: 113 | ```javascript 114 | $('textarea').on('autosize:resized', function() { 115 | $(this).trigger('maxlength.reposition'); 116 | }); 117 | ``` 118 | -------------------------------------------------------------------------------- /dist/bootstrap-maxlength.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | "use strict"; 3 | if (!$.event.special.destroyed) { 4 | $.event.special.destroyed = { 5 | remove: function(o) { 6 | if (o.handler) { 7 | o.handler(); 8 | } 9 | } 10 | }; 11 | } 12 | $.fn.extend({ 13 | maxlength: function(options, callback) { 14 | var documentBody = $("body"), defaults = { 15 | showOnReady: false, 16 | alwaysShow: true, 17 | threshold: 0, 18 | warningClass: "small form-text text-body-secondary", 19 | limitReachedClass: "small form-text text-danger", 20 | limitExceededClass: "", 21 | separator: " / ", 22 | preText: "", 23 | postText: "", 24 | showMaxLength: true, 25 | placement: "bottom-right-inside", 26 | message: null, 27 | showCharsTyped: true, 28 | validate: false, 29 | utf8: false, 30 | appendToParent: false, 31 | twoCharLinebreak: true, 32 | customMaxAttribute: null, 33 | customMaxClass: "overmax", 34 | allowOverMax: false, 35 | zIndex: 1099 36 | }; 37 | if ($.isFunction(options) && !callback) { 38 | callback = options; 39 | options = {}; 40 | } 41 | options = $.extend(defaults, options); 42 | function utf8CharByteCount(character) { 43 | var c = character.charCodeAt(); 44 | return !c ? 0 : c < 128 ? 1 : c < 2048 ? 2 : 3; 45 | } 46 | function utf8Length(string) { 47 | return string.split("").map(utf8CharByteCount).concat(0).reduce((function(sum, val) { 48 | return sum + val; 49 | })); 50 | } 51 | function inputLength(input) { 52 | var text = input.val(); 53 | if (options.twoCharLinebreak) { 54 | text = text.replace(/\r(?!\n)|\n(?!\r)/g, "\r\n"); 55 | } else { 56 | text = text.replace(/(?:\r\n|\r|\n)/g, "\n"); 57 | } 58 | var currentLength = 0; 59 | if (options.utf8) { 60 | currentLength = utf8Length(text); 61 | } else { 62 | currentLength = text.length; 63 | } 64 | if (input.prop("type") === "file" && input.val() !== "") { 65 | currentLength -= 12; 66 | } 67 | return currentLength; 68 | } 69 | function truncateChars(input, maxlength) { 70 | var text = input.val(); 71 | if (options.twoCharLinebreak) { 72 | text = text.replace(/\r(?!\n)|\n(?!\r)/g, "\r\n"); 73 | if (text[text.length - 1] === "\n") { 74 | maxlength -= text.length % 2; 75 | } 76 | } 77 | if (options.utf8) { 78 | var indexedSize = text.split("").map(utf8CharByteCount); 79 | for (var removedBytes = 0, bytesPastMax = utf8Length(text) - maxlength; removedBytes < bytesPastMax; removedBytes += indexedSize.pop()) ; 80 | maxlength -= maxlength - indexedSize.length; 81 | } 82 | input.val(text.substr(0, maxlength)); 83 | } 84 | function charsLeftThreshold(input, threshold, maxlength) { 85 | var output = true; 86 | if (!options.alwaysShow && maxlength - inputLength(input) > threshold) { 87 | output = false; 88 | } 89 | return output; 90 | } 91 | function remainingChars(input, maxlength) { 92 | var length = maxlength - inputLength(input); 93 | return length; 94 | } 95 | function showRemaining(currentInput, indicator) { 96 | indicator.css({ 97 | display: "block" 98 | }); 99 | currentInput.trigger("maxlength.shown"); 100 | } 101 | function hideRemaining(currentInput, indicator) { 102 | if (options.alwaysShow) { 103 | return; 104 | } 105 | indicator.css({ 106 | display: "none" 107 | }); 108 | currentInput.trigger("maxlength.hidden"); 109 | } 110 | function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) { 111 | var output = ""; 112 | if (options.message) { 113 | if (typeof options.message === "function") { 114 | output = options.message(currentInputText, maxLengthThisInput); 115 | } else { 116 | output = options.message.replace("%charsTyped%", typedChars).replace("%charsRemaining%", maxLengthThisInput - typedChars).replace("%charsTotal%", maxLengthThisInput); 117 | } 118 | } else { 119 | if (options.preText) { 120 | output += options.preText; 121 | } 122 | if (!options.showCharsTyped) { 123 | output += maxLengthThisInput - typedChars; 124 | } else { 125 | output += typedChars; 126 | } 127 | if (options.showMaxLength) { 128 | output += options.separator + maxLengthThisInput; 129 | } 130 | if (options.postText) { 131 | output += options.postText; 132 | } 133 | } 134 | return output; 135 | } 136 | function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) { 137 | if (maxLengthIndicator) { 138 | maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, maxLengthCurrentInput - remaining)); 139 | if (remaining > 0) { 140 | if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) { 141 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass + " " + options.limitExceededClass).addClass(options.warningClass)); 142 | } else { 143 | hideRemaining(currentInput, maxLengthIndicator); 144 | } 145 | } else { 146 | if (!options.limitExceededClass) { 147 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass)); 148 | } else { 149 | if (remaining === 0) { 150 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass + " " + options.limitExceededClass).addClass(options.limitReachedClass)); 151 | } else { 152 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass + " " + options.limitReachedClass).addClass(options.limitExceededClass)); 153 | } 154 | } 155 | } 156 | } 157 | if (options.customMaxAttribute) { 158 | if (remaining < 0) { 159 | currentInput.addClass(options.customMaxClass); 160 | } else { 161 | currentInput.removeClass(options.customMaxClass); 162 | } 163 | } 164 | } 165 | function getPosition(currentInput) { 166 | var el = currentInput[0]; 167 | return $.extend({}, typeof el.getBoundingClientRect === "function" ? el.getBoundingClientRect() : { 168 | width: el.offsetWidth, 169 | height: el.offsetHeight 170 | }, currentInput.offset()); 171 | } 172 | function placeWithCSS(placement, maxLengthIndicator) { 173 | if (!placement || !maxLengthIndicator) { 174 | return; 175 | } 176 | var POSITION_KEYS = [ "top", "bottom", "left", "right", "position" ]; 177 | var cssPos = {}; 178 | $.each(POSITION_KEYS, (function(i, key) { 179 | var val = options.placement[key]; 180 | if (typeof val !== "undefined") { 181 | cssPos[key] = val; 182 | } 183 | })); 184 | maxLengthIndicator.css(cssPos); 185 | return; 186 | } 187 | function place(currentInput, maxLengthIndicator) { 188 | var pos = getPosition(currentInput); 189 | if ($.type(options.placement) === "function") { 190 | options.placement(currentInput, maxLengthIndicator, pos); 191 | return; 192 | } 193 | if ($.isPlainObject(options.placement)) { 194 | placeWithCSS(options.placement, maxLengthIndicator); 195 | return; 196 | } 197 | var inputOuter = currentInput.outerWidth(), outerWidth = maxLengthIndicator.outerWidth(), actualWidth = maxLengthIndicator.width(), actualHeight = maxLengthIndicator.height(); 198 | if (options.appendToParent) { 199 | pos.top -= currentInput.parent().offset().top; 200 | pos.left -= currentInput.parent().offset().left; 201 | } 202 | switch (options.placement) { 203 | case "bottom": 204 | maxLengthIndicator.css({ 205 | top: pos.top + pos.height, 206 | left: pos.left + pos.width / 2 - actualWidth / 2 207 | }); 208 | break; 209 | 210 | case "top": 211 | maxLengthIndicator.css({ 212 | top: pos.top - actualHeight, 213 | left: pos.left + pos.width / 2 - actualWidth / 2 214 | }); 215 | break; 216 | 217 | case "left": 218 | maxLengthIndicator.css({ 219 | top: pos.top + pos.height / 2 - actualHeight / 2, 220 | left: pos.left - actualWidth 221 | }); 222 | break; 223 | 224 | case "right": 225 | maxLengthIndicator.css({ 226 | top: pos.top + pos.height / 2 - actualHeight / 2, 227 | left: pos.left + pos.width 228 | }); 229 | break; 230 | 231 | case "bottom-right": 232 | maxLengthIndicator.css({ 233 | top: pos.top + pos.height, 234 | left: pos.left + pos.width 235 | }); 236 | break; 237 | 238 | case "top-right": 239 | maxLengthIndicator.css({ 240 | top: pos.top - actualHeight, 241 | left: pos.left + inputOuter 242 | }); 243 | break; 244 | 245 | case "top-left": 246 | maxLengthIndicator.css({ 247 | top: pos.top - actualHeight, 248 | left: pos.left - outerWidth 249 | }); 250 | break; 251 | 252 | case "bottom-left": 253 | maxLengthIndicator.css({ 254 | top: pos.top + currentInput.outerHeight(), 255 | left: pos.left - outerWidth 256 | }); 257 | break; 258 | 259 | case "centered-right": 260 | maxLengthIndicator.css({ 261 | top: pos.top + actualHeight / 2, 262 | left: pos.left + inputOuter - outerWidth - 3 263 | }); 264 | break; 265 | 266 | case "bottom-right-inside": 267 | maxLengthIndicator.css({ 268 | top: pos.top + pos.height, 269 | left: pos.left + pos.width - outerWidth 270 | }); 271 | break; 272 | 273 | case "top-right-inside": 274 | maxLengthIndicator.css({ 275 | top: pos.top - actualHeight, 276 | left: pos.left + inputOuter - outerWidth 277 | }); 278 | break; 279 | 280 | case "top-left-inside": 281 | maxLengthIndicator.css({ 282 | top: pos.top - actualHeight, 283 | left: pos.left 284 | }); 285 | break; 286 | 287 | case "bottom-left-inside": 288 | maxLengthIndicator.css({ 289 | top: pos.top + currentInput.outerHeight(), 290 | left: pos.left 291 | }); 292 | break; 293 | } 294 | } 295 | function getMaxLength(currentInput) { 296 | var max = currentInput.attr("maxlength") || options.customMaxAttribute; 297 | if (options.customMaxAttribute && !options.allowOverMax) { 298 | var custom = currentInput.attr(options.customMaxAttribute); 299 | if (!max || custom < max) { 300 | max = custom; 301 | } 302 | } 303 | if (!max) { 304 | max = currentInput.attr("size"); 305 | } 306 | return max; 307 | } 308 | return this.each((function() { 309 | var currentInput = $(this), maxLengthCurrentInput, maxLengthIndicator; 310 | $(window).resize((function() { 311 | if (maxLengthIndicator) { 312 | place(currentInput, maxLengthIndicator); 313 | } 314 | })); 315 | function firstInit() { 316 | var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, "0"); 317 | maxLengthCurrentInput = getMaxLength(currentInput); 318 | if (!maxLengthIndicator) { 319 | maxLengthIndicator = $('').css({ 320 | display: "none", 321 | position: "absolute", 322 | whiteSpace: "nowrap", 323 | zIndex: options.zIndex 324 | }).html(maxlengthContent); 325 | } 326 | if (currentInput.is("textarea")) { 327 | currentInput.data("maxlenghtsizex", currentInput.outerWidth()); 328 | currentInput.data("maxlenghtsizey", currentInput.outerHeight()); 329 | currentInput.mouseup((function() { 330 | if (currentInput.outerWidth() !== currentInput.data("maxlenghtsizex") || currentInput.outerHeight() !== currentInput.data("maxlenghtsizey")) { 331 | place(currentInput, maxLengthIndicator); 332 | } 333 | currentInput.data("maxlenghtsizex", currentInput.outerWidth()); 334 | currentInput.data("maxlenghtsizey", currentInput.outerHeight()); 335 | })); 336 | } 337 | if (options.appendToParent) { 338 | currentInput.parent().append(maxLengthIndicator); 339 | currentInput.parent().css("position", "relative"); 340 | } else { 341 | documentBody.append(maxLengthIndicator); 342 | } 343 | var remaining = remainingChars(currentInput, getMaxLength(currentInput)); 344 | manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 345 | place(currentInput, maxLengthIndicator); 346 | } 347 | if (options.showOnReady) { 348 | currentInput.ready((function() { 349 | firstInit(); 350 | })); 351 | } else { 352 | currentInput.focus((function() { 353 | firstInit(); 354 | })); 355 | } 356 | currentInput.on("maxlength.reposition", (function() { 357 | place(currentInput, maxLengthIndicator); 358 | })); 359 | currentInput.on("destroyed", (function() { 360 | if (maxLengthIndicator) { 361 | maxLengthIndicator.remove(); 362 | } 363 | })); 364 | currentInput.on("blur", (function() { 365 | if (maxLengthIndicator && !options.showOnReady) { 366 | maxLengthIndicator.remove(); 367 | } 368 | })); 369 | currentInput.on("input", (function() { 370 | var maxlength = getMaxLength(currentInput), remaining = remainingChars(currentInput, maxlength), output = true; 371 | if (options.validate && remaining < 0) { 372 | truncateChars(currentInput, maxlength); 373 | output = false; 374 | } else { 375 | manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 376 | } 377 | return output; 378 | })); 379 | })); 380 | } 381 | }); 382 | })(jQuery); -------------------------------------------------------------------------------- /dist/bootstrap-maxlength.min.js: -------------------------------------------------------------------------------- 1 | !function($){"use strict";$.event.special.destroyed||($.event.special.destroyed={remove:function(o){o.handler&&o.handler()}}),$.fn.extend({maxlength:function(options,callback){var documentBody=$("body");function utf8CharByteCount(character){var c=character.charCodeAt();return c?c<128?1:c<2048?2:3:0}function utf8Length(string){return string.split("").map(utf8CharByteCount).concat(0).reduce((function(sum,val){return sum+val}))}function inputLength(input){var text=input.val();text=options.twoCharLinebreak?text.replace(/\r(?!\n)|\n(?!\r)/g,"\r\n"):text.replace(/(?:\r\n|\r|\n)/g,"\n");var currentLength=0;return currentLength=options.utf8?utf8Length(text):text.length,"file"===input.prop("type")&&""!==input.val()&&(currentLength-=12),currentLength}function remainingChars(input,maxlength){return maxlength-inputLength(input)}function showRemaining(currentInput,indicator){indicator.css({display:"block"}),currentInput.trigger("maxlength.shown")}function updateMaxLengthHTML(currentInputText,maxLengthThisInput,typedChars){var output="";return options.message?output="function"==typeof options.message?options.message(currentInputText,maxLengthThisInput):options.message.replace("%charsTyped%",typedChars).replace("%charsRemaining%",maxLengthThisInput-typedChars).replace("%charsTotal%",maxLengthThisInput):(options.preText&&(output+=options.preText),options.showCharsTyped?output+=typedChars:output+=maxLengthThisInput-typedChars,options.showMaxLength&&(output+=options.separator+maxLengthThisInput),options.postText&&(output+=options.postText)),output}function manageRemainingVisibility(remaining,currentInput,maxLengthCurrentInput,maxLengthIndicator){var input,threshold,maxlength,output;maxLengthIndicator&&(maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(),maxLengthCurrentInput,maxLengthCurrentInput-remaining)),remaining>0?(input=currentInput,threshold=options.threshold,maxlength=maxLengthCurrentInput,output=!0,!options.alwaysShow&&maxlength-inputLength(input)>threshold&&(output=!1),output?showRemaining(currentInput,maxLengthIndicator.removeClass(options.limitReachedClass+" "+options.limitExceededClass).addClass(options.warningClass)):function(currentInput,indicator){options.alwaysShow||(indicator.css({display:"none"}),currentInput.trigger("maxlength.hidden"))}(currentInput,maxLengthIndicator)):options.limitExceededClass?showRemaining(currentInput,0===remaining?maxLengthIndicator.removeClass(options.warningClass+" "+options.limitExceededClass).addClass(options.limitReachedClass):maxLengthIndicator.removeClass(options.warningClass+" "+options.limitReachedClass).addClass(options.limitExceededClass)):showRemaining(currentInput,maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass))),options.customMaxAttribute&&(remaining<0?currentInput.addClass(options.customMaxClass):currentInput.removeClass(options.customMaxClass))}function place(currentInput,maxLengthIndicator){var pos=function(currentInput){var el=currentInput[0];return $.extend({},"function"==typeof el.getBoundingClientRect?el.getBoundingClientRect():{width:el.offsetWidth,height:el.offsetHeight},currentInput.offset())}(currentInput);if("function"!==$.type(options.placement))if($.isPlainObject(options.placement))!function(placement,maxLengthIndicator){if(placement&&maxLengthIndicator){var cssPos={};$.each(["top","bottom","left","right","position"],(function(i,key){var val=options.placement[key];void 0!==val&&(cssPos[key]=val)})),maxLengthIndicator.css(cssPos)}}(options.placement,maxLengthIndicator);else{var inputOuter=currentInput.outerWidth(),outerWidth=maxLengthIndicator.outerWidth(),actualWidth=maxLengthIndicator.width(),actualHeight=maxLengthIndicator.height();switch(options.appendToParent&&(pos.top-=currentInput.parent().offset().top,pos.left-=currentInput.parent().offset().left),options.placement){case"bottom":maxLengthIndicator.css({top:pos.top+pos.height,left:pos.left+pos.width/2-actualWidth/2});break;case"top":maxLengthIndicator.css({top:pos.top-actualHeight,left:pos.left+pos.width/2-actualWidth/2});break;case"left":maxLengthIndicator.css({top:pos.top+pos.height/2-actualHeight/2,left:pos.left-actualWidth});break;case"right":maxLengthIndicator.css({top:pos.top+pos.height/2-actualHeight/2,left:pos.left+pos.width});break;case"bottom-right":maxLengthIndicator.css({top:pos.top+pos.height,left:pos.left+pos.width});break;case"top-right":maxLengthIndicator.css({top:pos.top-actualHeight,left:pos.left+inputOuter});break;case"top-left":maxLengthIndicator.css({top:pos.top-actualHeight,left:pos.left-outerWidth});break;case"bottom-left":maxLengthIndicator.css({top:pos.top+currentInput.outerHeight(),left:pos.left-outerWidth});break;case"centered-right":maxLengthIndicator.css({top:pos.top+actualHeight/2,left:pos.left+inputOuter-outerWidth-3});break;case"bottom-right-inside":maxLengthIndicator.css({top:pos.top+pos.height,left:pos.left+pos.width-outerWidth});break;case"top-right-inside":maxLengthIndicator.css({top:pos.top-actualHeight,left:pos.left+inputOuter-outerWidth});break;case"top-left-inside":maxLengthIndicator.css({top:pos.top-actualHeight,left:pos.left});break;case"bottom-left-inside":maxLengthIndicator.css({top:pos.top+currentInput.outerHeight(),left:pos.left})}}else options.placement(currentInput,maxLengthIndicator,pos)}function getMaxLength(currentInput){var max=currentInput.attr("maxlength")||options.customMaxAttribute;if(options.customMaxAttribute&&!options.allowOverMax){var custom=currentInput.attr(options.customMaxAttribute);(!max||custom').css({display:"none",position:"absolute",whiteSpace:"nowrap",zIndex:options.zIndex}).html(maxlengthContent)),currentInput.is("textarea")&&(currentInput.data("maxlenghtsizex",currentInput.outerWidth()),currentInput.data("maxlenghtsizey",currentInput.outerHeight()),currentInput.mouseup((function(){currentInput.outerWidth()===currentInput.data("maxlenghtsizex")&¤tInput.outerHeight()===currentInput.data("maxlenghtsizey")||place(currentInput,maxLengthIndicator),currentInput.data("maxlenghtsizex",currentInput.outerWidth()),currentInput.data("maxlenghtsizey",currentInput.outerHeight())}))),options.appendToParent?(currentInput.parent().append(maxLengthIndicator),currentInput.parent().css("position","relative")):documentBody.append(maxLengthIndicator),manageRemainingVisibility(remainingChars(currentInput,getMaxLength(currentInput)),currentInput,maxLengthCurrentInput,maxLengthIndicator),place(currentInput,maxLengthIndicator)}$(window).resize((function(){maxLengthIndicator&&place(currentInput,maxLengthIndicator)})),options.showOnReady?currentInput.ready((function(){firstInit()})):currentInput.focus((function(){firstInit()})),currentInput.on("maxlength.reposition",(function(){place(currentInput,maxLengthIndicator)})),currentInput.on("destroyed",(function(){maxLengthIndicator&&maxLengthIndicator.remove()})),currentInput.on("blur",(function(){maxLengthIndicator&&!options.showOnReady&&maxLengthIndicator.remove()})),currentInput.on("input",(function(){var maxlength=getMaxLength(currentInput),remaining=remainingChars(currentInput,maxlength),output=!0;return options.validate&&remaining<0?(!function(input,maxlength){var text=input.val();if(options.twoCharLinebreak&&"\n"===(text=text.replace(/\r(?!\n)|\n(?!\r)/g,"\r\n"))[text.length-1]&&(maxlength-=text.length%2),options.utf8){for(var indexedSize=text.split("").map(utf8CharByteCount),removedBytes=0,bytesPastMax=utf8Length(text)-maxlength;removedBytes=16.0.0" 31 | }, 32 | "funding": { 33 | "url": "https://opencollective.com/eslint" 34 | }, 35 | "peerDependencies": { 36 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 37 | } 38 | }, 39 | "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { 40 | "version": "3.4.3", 41 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 42 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 43 | "dev": true, 44 | "engines": { 45 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 46 | }, 47 | "funding": { 48 | "url": "https://opencollective.com/eslint" 49 | } 50 | }, 51 | "node_modules/@eslint-community/regexpp": { 52 | "version": "4.12.1", 53 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 54 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 55 | "dev": true, 56 | "engines": { 57 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 58 | } 59 | }, 60 | "node_modules/@eslint/config-array": { 61 | "version": "0.18.0", 62 | "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", 63 | "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", 64 | "dev": true, 65 | "dependencies": { 66 | "@eslint/object-schema": "^2.1.4", 67 | "debug": "^4.3.1", 68 | "minimatch": "^3.1.2" 69 | }, 70 | "engines": { 71 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 72 | } 73 | }, 74 | "node_modules/@eslint/core": { 75 | "version": "0.7.0", 76 | "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", 77 | "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", 78 | "dev": true, 79 | "engines": { 80 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 81 | } 82 | }, 83 | "node_modules/@eslint/eslintrc": { 84 | "version": "3.1.0", 85 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", 86 | "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", 87 | "dev": true, 88 | "dependencies": { 89 | "ajv": "^6.12.4", 90 | "debug": "^4.3.2", 91 | "espree": "^10.0.1", 92 | "globals": "^14.0.0", 93 | "ignore": "^5.2.0", 94 | "import-fresh": "^3.2.1", 95 | "js-yaml": "^4.1.0", 96 | "minimatch": "^3.1.2", 97 | "strip-json-comments": "^3.1.1" 98 | }, 99 | "engines": { 100 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 101 | }, 102 | "funding": { 103 | "url": "https://opencollective.com/eslint" 104 | } 105 | }, 106 | "node_modules/@eslint/js": { 107 | "version": "9.13.0", 108 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", 109 | "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", 110 | "dev": true, 111 | "engines": { 112 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 113 | } 114 | }, 115 | "node_modules/@eslint/object-schema": { 116 | "version": "2.1.4", 117 | "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", 118 | "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", 119 | "dev": true, 120 | "engines": { 121 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 122 | } 123 | }, 124 | "node_modules/@eslint/plugin-kit": { 125 | "version": "0.2.2", 126 | "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", 127 | "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", 128 | "dev": true, 129 | "dependencies": { 130 | "levn": "^0.4.1" 131 | }, 132 | "engines": { 133 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 134 | } 135 | }, 136 | "node_modules/@humanfs/core": { 137 | "version": "0.19.1", 138 | "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", 139 | "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", 140 | "dev": true, 141 | "engines": { 142 | "node": ">=18.18.0" 143 | } 144 | }, 145 | "node_modules/@humanfs/node": { 146 | "version": "0.16.6", 147 | "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", 148 | "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", 149 | "dev": true, 150 | "dependencies": { 151 | "@humanfs/core": "^0.19.1", 152 | "@humanwhocodes/retry": "^0.3.0" 153 | }, 154 | "engines": { 155 | "node": ">=18.18.0" 156 | } 157 | }, 158 | "node_modules/@humanwhocodes/module-importer": { 159 | "version": "1.0.1", 160 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 161 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 162 | "dev": true, 163 | "engines": { 164 | "node": ">=12.22" 165 | }, 166 | "funding": { 167 | "type": "github", 168 | "url": "https://github.com/sponsors/nzakas" 169 | } 170 | }, 171 | "node_modules/@humanwhocodes/retry": { 172 | "version": "0.3.1", 173 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", 174 | "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", 175 | "dev": true, 176 | "engines": { 177 | "node": ">=18.18" 178 | }, 179 | "funding": { 180 | "type": "github", 181 | "url": "https://github.com/sponsors/nzakas" 182 | } 183 | }, 184 | "node_modules/@jridgewell/gen-mapping": { 185 | "version": "0.3.5", 186 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 187 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 188 | "dev": true, 189 | "dependencies": { 190 | "@jridgewell/set-array": "^1.2.1", 191 | "@jridgewell/sourcemap-codec": "^1.4.10", 192 | "@jridgewell/trace-mapping": "^0.3.24" 193 | }, 194 | "engines": { 195 | "node": ">=6.0.0" 196 | } 197 | }, 198 | "node_modules/@jridgewell/resolve-uri": { 199 | "version": "3.1.2", 200 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 201 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 202 | "dev": true, 203 | "engines": { 204 | "node": ">=6.0.0" 205 | } 206 | }, 207 | "node_modules/@jridgewell/set-array": { 208 | "version": "1.2.1", 209 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 210 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 211 | "dev": true, 212 | "engines": { 213 | "node": ">=6.0.0" 214 | } 215 | }, 216 | "node_modules/@jridgewell/source-map": { 217 | "version": "0.3.6", 218 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", 219 | "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", 220 | "dev": true, 221 | "dependencies": { 222 | "@jridgewell/gen-mapping": "^0.3.5", 223 | "@jridgewell/trace-mapping": "^0.3.25" 224 | } 225 | }, 226 | "node_modules/@jridgewell/sourcemap-codec": { 227 | "version": "1.5.0", 228 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 229 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 230 | "dev": true 231 | }, 232 | "node_modules/@jridgewell/trace-mapping": { 233 | "version": "0.3.25", 234 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 235 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 236 | "dev": true, 237 | "dependencies": { 238 | "@jridgewell/resolve-uri": "^3.1.0", 239 | "@jridgewell/sourcemap-codec": "^1.4.14" 240 | } 241 | }, 242 | "node_modules/@popperjs/core": { 243 | "version": "2.11.8", 244 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", 245 | "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", 246 | "peer": true, 247 | "funding": { 248 | "type": "opencollective", 249 | "url": "https://opencollective.com/popperjs" 250 | } 251 | }, 252 | "node_modules/@types/estree": { 253 | "version": "1.0.6", 254 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 255 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 256 | "dev": true 257 | }, 258 | "node_modules/@types/json-schema": { 259 | "version": "7.0.15", 260 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 261 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 262 | "dev": true 263 | }, 264 | "node_modules/acorn": { 265 | "version": "8.14.0", 266 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 267 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 268 | "dev": true, 269 | "bin": { 270 | "acorn": "bin/acorn" 271 | }, 272 | "engines": { 273 | "node": ">=0.4.0" 274 | } 275 | }, 276 | "node_modules/acorn-jsx": { 277 | "version": "5.3.2", 278 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 279 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 280 | "dev": true, 281 | "peerDependencies": { 282 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 283 | } 284 | }, 285 | "node_modules/ajv": { 286 | "version": "6.12.6", 287 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 288 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 289 | "dev": true, 290 | "dependencies": { 291 | "fast-deep-equal": "^3.1.1", 292 | "fast-json-stable-stringify": "^2.0.0", 293 | "json-schema-traverse": "^0.4.1", 294 | "uri-js": "^4.2.2" 295 | }, 296 | "funding": { 297 | "type": "github", 298 | "url": "https://github.com/sponsors/epoberezkin" 299 | } 300 | }, 301 | "node_modules/ansi-styles": { 302 | "version": "4.3.0", 303 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 304 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 305 | "dev": true, 306 | "dependencies": { 307 | "color-convert": "^2.0.1" 308 | }, 309 | "engines": { 310 | "node": ">=8" 311 | }, 312 | "funding": { 313 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 314 | } 315 | }, 316 | "node_modules/argparse": { 317 | "version": "2.0.1", 318 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 319 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 320 | "dev": true 321 | }, 322 | "node_modules/balanced-match": { 323 | "version": "1.0.2", 324 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 325 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 326 | "dev": true 327 | }, 328 | "node_modules/bootstrap": { 329 | "version": "5.3.3", 330 | "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", 331 | "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", 332 | "funding": [ 333 | { 334 | "type": "github", 335 | "url": "https://github.com/sponsors/twbs" 336 | }, 337 | { 338 | "type": "opencollective", 339 | "url": "https://opencollective.com/bootstrap" 340 | } 341 | ], 342 | "peerDependencies": { 343 | "@popperjs/core": "^2.11.8" 344 | } 345 | }, 346 | "node_modules/brace-expansion": { 347 | "version": "1.1.11", 348 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 349 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 350 | "dev": true, 351 | "dependencies": { 352 | "balanced-match": "^1.0.0", 353 | "concat-map": "0.0.1" 354 | } 355 | }, 356 | "node_modules/buffer-from": { 357 | "version": "1.1.2", 358 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 359 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 360 | "dev": true 361 | }, 362 | "node_modules/callsites": { 363 | "version": "3.1.0", 364 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 365 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 366 | "dev": true, 367 | "engines": { 368 | "node": ">=6" 369 | } 370 | }, 371 | "node_modules/chalk": { 372 | "version": "4.1.2", 373 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 374 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 375 | "dev": true, 376 | "dependencies": { 377 | "ansi-styles": "^4.1.0", 378 | "supports-color": "^7.1.0" 379 | }, 380 | "engines": { 381 | "node": ">=10" 382 | }, 383 | "funding": { 384 | "url": "https://github.com/chalk/chalk?sponsor=1" 385 | } 386 | }, 387 | "node_modules/color-convert": { 388 | "version": "2.0.1", 389 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 390 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 391 | "dev": true, 392 | "dependencies": { 393 | "color-name": "~1.1.4" 394 | }, 395 | "engines": { 396 | "node": ">=7.0.0" 397 | } 398 | }, 399 | "node_modules/color-name": { 400 | "version": "1.1.4", 401 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 402 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 403 | "dev": true 404 | }, 405 | "node_modules/commander": { 406 | "version": "2.20.3", 407 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 408 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 409 | "dev": true 410 | }, 411 | "node_modules/concat-map": { 412 | "version": "0.0.1", 413 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 414 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 415 | "dev": true 416 | }, 417 | "node_modules/cross-spawn": { 418 | "version": "7.0.3", 419 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 420 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 421 | "dev": true, 422 | "dependencies": { 423 | "path-key": "^3.1.0", 424 | "shebang-command": "^2.0.0", 425 | "which": "^2.0.1" 426 | }, 427 | "engines": { 428 | "node": ">= 8" 429 | } 430 | }, 431 | "node_modules/debug": { 432 | "version": "4.3.7", 433 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 434 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 435 | "dev": true, 436 | "dependencies": { 437 | "ms": "^2.1.3" 438 | }, 439 | "engines": { 440 | "node": ">=6.0" 441 | }, 442 | "peerDependenciesMeta": { 443 | "supports-color": { 444 | "optional": true 445 | } 446 | } 447 | }, 448 | "node_modules/deep-is": { 449 | "version": "0.1.4", 450 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 451 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 452 | "dev": true 453 | }, 454 | "node_modules/escape-string-regexp": { 455 | "version": "4.0.0", 456 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 457 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 458 | "dev": true, 459 | "engines": { 460 | "node": ">=10" 461 | }, 462 | "funding": { 463 | "url": "https://github.com/sponsors/sindresorhus" 464 | } 465 | }, 466 | "node_modules/eslint": { 467 | "version": "9.13.0", 468 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", 469 | "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", 470 | "dev": true, 471 | "dependencies": { 472 | "@eslint-community/eslint-utils": "^4.2.0", 473 | "@eslint-community/regexpp": "^4.11.0", 474 | "@eslint/config-array": "^0.18.0", 475 | "@eslint/core": "^0.7.0", 476 | "@eslint/eslintrc": "^3.1.0", 477 | "@eslint/js": "9.13.0", 478 | "@eslint/plugin-kit": "^0.2.0", 479 | "@humanfs/node": "^0.16.5", 480 | "@humanwhocodes/module-importer": "^1.0.1", 481 | "@humanwhocodes/retry": "^0.3.1", 482 | "@types/estree": "^1.0.6", 483 | "@types/json-schema": "^7.0.15", 484 | "ajv": "^6.12.4", 485 | "chalk": "^4.0.0", 486 | "cross-spawn": "^7.0.2", 487 | "debug": "^4.3.2", 488 | "escape-string-regexp": "^4.0.0", 489 | "eslint-scope": "^8.1.0", 490 | "eslint-visitor-keys": "^4.1.0", 491 | "espree": "^10.2.0", 492 | "esquery": "^1.5.0", 493 | "esutils": "^2.0.2", 494 | "fast-deep-equal": "^3.1.3", 495 | "file-entry-cache": "^8.0.0", 496 | "find-up": "^5.0.0", 497 | "glob-parent": "^6.0.2", 498 | "ignore": "^5.2.0", 499 | "imurmurhash": "^0.1.4", 500 | "is-glob": "^4.0.0", 501 | "json-stable-stringify-without-jsonify": "^1.0.1", 502 | "lodash.merge": "^4.6.2", 503 | "minimatch": "^3.1.2", 504 | "natural-compare": "^1.4.0", 505 | "optionator": "^0.9.3", 506 | "text-table": "^0.2.0" 507 | }, 508 | "bin": { 509 | "eslint": "bin/eslint.js" 510 | }, 511 | "engines": { 512 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 513 | }, 514 | "funding": { 515 | "url": "https://eslint.org/donate" 516 | }, 517 | "peerDependencies": { 518 | "jiti": "*" 519 | }, 520 | "peerDependenciesMeta": { 521 | "jiti": { 522 | "optional": true 523 | } 524 | } 525 | }, 526 | "node_modules/eslint-scope": { 527 | "version": "8.2.0", 528 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", 529 | "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", 530 | "dev": true, 531 | "dependencies": { 532 | "esrecurse": "^4.3.0", 533 | "estraverse": "^5.2.0" 534 | }, 535 | "engines": { 536 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 537 | }, 538 | "funding": { 539 | "url": "https://opencollective.com/eslint" 540 | } 541 | }, 542 | "node_modules/eslint-visitor-keys": { 543 | "version": "4.2.0", 544 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", 545 | "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", 546 | "dev": true, 547 | "engines": { 548 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 549 | }, 550 | "funding": { 551 | "url": "https://opencollective.com/eslint" 552 | } 553 | }, 554 | "node_modules/espree": { 555 | "version": "10.3.0", 556 | "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", 557 | "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", 558 | "dev": true, 559 | "dependencies": { 560 | "acorn": "^8.14.0", 561 | "acorn-jsx": "^5.3.2", 562 | "eslint-visitor-keys": "^4.2.0" 563 | }, 564 | "engines": { 565 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 566 | }, 567 | "funding": { 568 | "url": "https://opencollective.com/eslint" 569 | } 570 | }, 571 | "node_modules/esquery": { 572 | "version": "1.6.0", 573 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 574 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 575 | "dev": true, 576 | "dependencies": { 577 | "estraverse": "^5.1.0" 578 | }, 579 | "engines": { 580 | "node": ">=0.10" 581 | } 582 | }, 583 | "node_modules/esrecurse": { 584 | "version": "4.3.0", 585 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 586 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 587 | "dev": true, 588 | "dependencies": { 589 | "estraverse": "^5.2.0" 590 | }, 591 | "engines": { 592 | "node": ">=4.0" 593 | } 594 | }, 595 | "node_modules/estraverse": { 596 | "version": "5.3.0", 597 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 598 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 599 | "dev": true, 600 | "engines": { 601 | "node": ">=4.0" 602 | } 603 | }, 604 | "node_modules/esutils": { 605 | "version": "2.0.3", 606 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 607 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 608 | "dev": true, 609 | "engines": { 610 | "node": ">=0.10.0" 611 | } 612 | }, 613 | "node_modules/fast-deep-equal": { 614 | "version": "3.1.3", 615 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 616 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 617 | "dev": true 618 | }, 619 | "node_modules/fast-json-stable-stringify": { 620 | "version": "2.1.0", 621 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 622 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 623 | "dev": true 624 | }, 625 | "node_modules/fast-levenshtein": { 626 | "version": "2.0.6", 627 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 628 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 629 | "dev": true 630 | }, 631 | "node_modules/file-entry-cache": { 632 | "version": "8.0.0", 633 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", 634 | "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", 635 | "dev": true, 636 | "dependencies": { 637 | "flat-cache": "^4.0.0" 638 | }, 639 | "engines": { 640 | "node": ">=16.0.0" 641 | } 642 | }, 643 | "node_modules/find-up": { 644 | "version": "5.0.0", 645 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 646 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 647 | "dev": true, 648 | "dependencies": { 649 | "locate-path": "^6.0.0", 650 | "path-exists": "^4.0.0" 651 | }, 652 | "engines": { 653 | "node": ">=10" 654 | }, 655 | "funding": { 656 | "url": "https://github.com/sponsors/sindresorhus" 657 | } 658 | }, 659 | "node_modules/flat-cache": { 660 | "version": "4.0.1", 661 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", 662 | "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", 663 | "dev": true, 664 | "dependencies": { 665 | "flatted": "^3.2.9", 666 | "keyv": "^4.5.4" 667 | }, 668 | "engines": { 669 | "node": ">=16" 670 | } 671 | }, 672 | "node_modules/flatted": { 673 | "version": "3.3.1", 674 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", 675 | "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", 676 | "dev": true 677 | }, 678 | "node_modules/glob-parent": { 679 | "version": "6.0.2", 680 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 681 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 682 | "dev": true, 683 | "dependencies": { 684 | "is-glob": "^4.0.3" 685 | }, 686 | "engines": { 687 | "node": ">=10.13.0" 688 | } 689 | }, 690 | "node_modules/globals": { 691 | "version": "14.0.0", 692 | "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", 693 | "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", 694 | "dev": true, 695 | "engines": { 696 | "node": ">=18" 697 | }, 698 | "funding": { 699 | "url": "https://github.com/sponsors/sindresorhus" 700 | } 701 | }, 702 | "node_modules/globalyzer": { 703 | "version": "0.1.0", 704 | "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", 705 | "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==" 706 | }, 707 | "node_modules/globrex": { 708 | "version": "0.1.2", 709 | "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", 710 | "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" 711 | }, 712 | "node_modules/has-flag": { 713 | "version": "4.0.0", 714 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 715 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 716 | "dev": true, 717 | "engines": { 718 | "node": ">=8" 719 | } 720 | }, 721 | "node_modules/ignore": { 722 | "version": "5.3.2", 723 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 724 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 725 | "dev": true, 726 | "engines": { 727 | "node": ">= 4" 728 | } 729 | }, 730 | "node_modules/import-fresh": { 731 | "version": "3.3.0", 732 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 733 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 734 | "dev": true, 735 | "dependencies": { 736 | "parent-module": "^1.0.0", 737 | "resolve-from": "^4.0.0" 738 | }, 739 | "engines": { 740 | "node": ">=6" 741 | }, 742 | "funding": { 743 | "url": "https://github.com/sponsors/sindresorhus" 744 | } 745 | }, 746 | "node_modules/imurmurhash": { 747 | "version": "0.1.4", 748 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 749 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 750 | "dev": true, 751 | "engines": { 752 | "node": ">=0.8.19" 753 | } 754 | }, 755 | "node_modules/is-extglob": { 756 | "version": "2.1.1", 757 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 758 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 759 | "dev": true, 760 | "engines": { 761 | "node": ">=0.10.0" 762 | } 763 | }, 764 | "node_modules/is-glob": { 765 | "version": "4.0.3", 766 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 767 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 768 | "dev": true, 769 | "dependencies": { 770 | "is-extglob": "^2.1.1" 771 | }, 772 | "engines": { 773 | "node": ">=0.10.0" 774 | } 775 | }, 776 | "node_modules/isexe": { 777 | "version": "2.0.0", 778 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 779 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 780 | "dev": true 781 | }, 782 | "node_modules/jquery": { 783 | "version": "3.7.1", 784 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", 785 | "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" 786 | }, 787 | "node_modules/js-yaml": { 788 | "version": "4.1.0", 789 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 790 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 791 | "dev": true, 792 | "dependencies": { 793 | "argparse": "^2.0.1" 794 | }, 795 | "bin": { 796 | "js-yaml": "bin/js-yaml.js" 797 | } 798 | }, 799 | "node_modules/json-buffer": { 800 | "version": "3.0.1", 801 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 802 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 803 | "dev": true 804 | }, 805 | "node_modules/json-schema-traverse": { 806 | "version": "0.4.1", 807 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 808 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 809 | "dev": true 810 | }, 811 | "node_modules/json-stable-stringify-without-jsonify": { 812 | "version": "1.0.1", 813 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 814 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 815 | "dev": true 816 | }, 817 | "node_modules/keyv": { 818 | "version": "4.5.4", 819 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 820 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 821 | "dev": true, 822 | "dependencies": { 823 | "json-buffer": "3.0.1" 824 | } 825 | }, 826 | "node_modules/levn": { 827 | "version": "0.4.1", 828 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 829 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 830 | "dev": true, 831 | "dependencies": { 832 | "prelude-ls": "^1.2.1", 833 | "type-check": "~0.4.0" 834 | }, 835 | "engines": { 836 | "node": ">= 0.8.0" 837 | } 838 | }, 839 | "node_modules/locate-path": { 840 | "version": "6.0.0", 841 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 842 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 843 | "dev": true, 844 | "dependencies": { 845 | "p-locate": "^5.0.0" 846 | }, 847 | "engines": { 848 | "node": ">=10" 849 | }, 850 | "funding": { 851 | "url": "https://github.com/sponsors/sindresorhus" 852 | } 853 | }, 854 | "node_modules/lodash.merge": { 855 | "version": "4.6.2", 856 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 857 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 858 | "dev": true 859 | }, 860 | "node_modules/minimatch": { 861 | "version": "3.1.2", 862 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 863 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 864 | "dev": true, 865 | "dependencies": { 866 | "brace-expansion": "^1.1.7" 867 | }, 868 | "engines": { 869 | "node": "*" 870 | } 871 | }, 872 | "node_modules/ms": { 873 | "version": "2.1.3", 874 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 875 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 876 | "dev": true 877 | }, 878 | "node_modules/natural-compare": { 879 | "version": "1.4.0", 880 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 881 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 882 | "dev": true 883 | }, 884 | "node_modules/node-watch": { 885 | "version": "0.7.3", 886 | "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz", 887 | "integrity": "sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==", 888 | "engines": { 889 | "node": ">=6" 890 | } 891 | }, 892 | "node_modules/optionator": { 893 | "version": "0.9.4", 894 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", 895 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 896 | "dev": true, 897 | "dependencies": { 898 | "deep-is": "^0.1.3", 899 | "fast-levenshtein": "^2.0.6", 900 | "levn": "^0.4.1", 901 | "prelude-ls": "^1.2.1", 902 | "type-check": "^0.4.0", 903 | "word-wrap": "^1.2.5" 904 | }, 905 | "engines": { 906 | "node": ">= 0.8.0" 907 | } 908 | }, 909 | "node_modules/p-limit": { 910 | "version": "3.1.0", 911 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 912 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 913 | "dev": true, 914 | "dependencies": { 915 | "yocto-queue": "^0.1.0" 916 | }, 917 | "engines": { 918 | "node": ">=10" 919 | }, 920 | "funding": { 921 | "url": "https://github.com/sponsors/sindresorhus" 922 | } 923 | }, 924 | "node_modules/p-locate": { 925 | "version": "5.0.0", 926 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 927 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 928 | "dev": true, 929 | "dependencies": { 930 | "p-limit": "^3.0.2" 931 | }, 932 | "engines": { 933 | "node": ">=10" 934 | }, 935 | "funding": { 936 | "url": "https://github.com/sponsors/sindresorhus" 937 | } 938 | }, 939 | "node_modules/parent-module": { 940 | "version": "1.0.1", 941 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 942 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 943 | "dev": true, 944 | "dependencies": { 945 | "callsites": "^3.0.0" 946 | }, 947 | "engines": { 948 | "node": ">=6" 949 | } 950 | }, 951 | "node_modules/path-exists": { 952 | "version": "4.0.0", 953 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 954 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 955 | "dev": true, 956 | "engines": { 957 | "node": ">=8" 958 | } 959 | }, 960 | "node_modules/path-key": { 961 | "version": "3.1.1", 962 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 963 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 964 | "dev": true, 965 | "engines": { 966 | "node": ">=8" 967 | } 968 | }, 969 | "node_modules/prelude-ls": { 970 | "version": "1.2.1", 971 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 972 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 973 | "dev": true, 974 | "engines": { 975 | "node": ">= 0.8.0" 976 | } 977 | }, 978 | "node_modules/punycode": { 979 | "version": "2.3.1", 980 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 981 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 982 | "dev": true, 983 | "engines": { 984 | "node": ">=6" 985 | } 986 | }, 987 | "node_modules/qunit": { 988 | "version": "2.22.0", 989 | "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.22.0.tgz", 990 | "integrity": "sha512-wPYvAvpjTL3zlUeyCX75T8gfZfdVXZa8y1EVkGe/XZNORIsCH/WI2X8R2KlemT921X9EKSZUL6CLGSPC7Ks08g==", 991 | "dependencies": { 992 | "commander": "7.2.0", 993 | "node-watch": "0.7.3", 994 | "tiny-glob": "0.2.9" 995 | }, 996 | "bin": { 997 | "qunit": "bin/qunit.js" 998 | }, 999 | "engines": { 1000 | "node": ">=10" 1001 | } 1002 | }, 1003 | "node_modules/qunit/node_modules/commander": { 1004 | "version": "7.2.0", 1005 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 1006 | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 1007 | "engines": { 1008 | "node": ">= 10" 1009 | } 1010 | }, 1011 | "node_modules/resolve-from": { 1012 | "version": "4.0.0", 1013 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1014 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1015 | "dev": true, 1016 | "engines": { 1017 | "node": ">=4" 1018 | } 1019 | }, 1020 | "node_modules/shebang-command": { 1021 | "version": "2.0.0", 1022 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1023 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1024 | "dev": true, 1025 | "dependencies": { 1026 | "shebang-regex": "^3.0.0" 1027 | }, 1028 | "engines": { 1029 | "node": ">=8" 1030 | } 1031 | }, 1032 | "node_modules/shebang-regex": { 1033 | "version": "3.0.0", 1034 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1035 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1036 | "dev": true, 1037 | "engines": { 1038 | "node": ">=8" 1039 | } 1040 | }, 1041 | "node_modules/source-map": { 1042 | "version": "0.6.1", 1043 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1044 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1045 | "dev": true, 1046 | "engines": { 1047 | "node": ">=0.10.0" 1048 | } 1049 | }, 1050 | "node_modules/source-map-support": { 1051 | "version": "0.5.21", 1052 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1053 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1054 | "dev": true, 1055 | "dependencies": { 1056 | "buffer-from": "^1.0.0", 1057 | "source-map": "^0.6.0" 1058 | } 1059 | }, 1060 | "node_modules/strip-json-comments": { 1061 | "version": "3.1.1", 1062 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1063 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1064 | "dev": true, 1065 | "engines": { 1066 | "node": ">=8" 1067 | }, 1068 | "funding": { 1069 | "url": "https://github.com/sponsors/sindresorhus" 1070 | } 1071 | }, 1072 | "node_modules/supports-color": { 1073 | "version": "7.2.0", 1074 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1075 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1076 | "dev": true, 1077 | "dependencies": { 1078 | "has-flag": "^4.0.0" 1079 | }, 1080 | "engines": { 1081 | "node": ">=8" 1082 | } 1083 | }, 1084 | "node_modules/terser": { 1085 | "version": "5.36.0", 1086 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", 1087 | "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", 1088 | "dev": true, 1089 | "dependencies": { 1090 | "@jridgewell/source-map": "^0.3.3", 1091 | "acorn": "^8.8.2", 1092 | "commander": "^2.20.0", 1093 | "source-map-support": "~0.5.20" 1094 | }, 1095 | "bin": { 1096 | "terser": "bin/terser" 1097 | }, 1098 | "engines": { 1099 | "node": ">=10" 1100 | } 1101 | }, 1102 | "node_modules/text-table": { 1103 | "version": "0.2.0", 1104 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1105 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 1106 | "dev": true 1107 | }, 1108 | "node_modules/tiny-glob": { 1109 | "version": "0.2.9", 1110 | "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", 1111 | "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", 1112 | "dependencies": { 1113 | "globalyzer": "0.1.0", 1114 | "globrex": "^0.1.2" 1115 | } 1116 | }, 1117 | "node_modules/type-check": { 1118 | "version": "0.4.0", 1119 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1120 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1121 | "dev": true, 1122 | "dependencies": { 1123 | "prelude-ls": "^1.2.1" 1124 | }, 1125 | "engines": { 1126 | "node": ">= 0.8.0" 1127 | } 1128 | }, 1129 | "node_modules/uri-js": { 1130 | "version": "4.4.1", 1131 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1132 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1133 | "dev": true, 1134 | "dependencies": { 1135 | "punycode": "^2.1.0" 1136 | } 1137 | }, 1138 | "node_modules/which": { 1139 | "version": "2.0.2", 1140 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1141 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1142 | "dev": true, 1143 | "dependencies": { 1144 | "isexe": "^2.0.0" 1145 | }, 1146 | "bin": { 1147 | "node-which": "bin/node-which" 1148 | }, 1149 | "engines": { 1150 | "node": ">= 8" 1151 | } 1152 | }, 1153 | "node_modules/word-wrap": { 1154 | "version": "1.2.5", 1155 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 1156 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 1157 | "dev": true, 1158 | "engines": { 1159 | "node": ">=0.10.0" 1160 | } 1161 | }, 1162 | "node_modules/yocto-queue": { 1163 | "version": "0.1.0", 1164 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1165 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1166 | "dev": true, 1167 | "engines": { 1168 | "node": ">=10" 1169 | }, 1170 | "funding": { 1171 | "url": "https://github.com/sponsors/sindresorhus" 1172 | } 1173 | } 1174 | }, 1175 | "dependencies": { 1176 | "@eslint-community/eslint-utils": { 1177 | "version": "4.4.1", 1178 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", 1179 | "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", 1180 | "dev": true, 1181 | "requires": { 1182 | "eslint-visitor-keys": "^3.4.3" 1183 | }, 1184 | "dependencies": { 1185 | "eslint-visitor-keys": { 1186 | "version": "3.4.3", 1187 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 1188 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 1189 | "dev": true 1190 | } 1191 | } 1192 | }, 1193 | "@eslint-community/regexpp": { 1194 | "version": "4.12.1", 1195 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 1196 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 1197 | "dev": true 1198 | }, 1199 | "@eslint/config-array": { 1200 | "version": "0.18.0", 1201 | "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", 1202 | "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", 1203 | "dev": true, 1204 | "requires": { 1205 | "@eslint/object-schema": "^2.1.4", 1206 | "debug": "^4.3.1", 1207 | "minimatch": "^3.1.2" 1208 | } 1209 | }, 1210 | "@eslint/core": { 1211 | "version": "0.7.0", 1212 | "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", 1213 | "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", 1214 | "dev": true 1215 | }, 1216 | "@eslint/eslintrc": { 1217 | "version": "3.1.0", 1218 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", 1219 | "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", 1220 | "dev": true, 1221 | "requires": { 1222 | "ajv": "^6.12.4", 1223 | "debug": "^4.3.2", 1224 | "espree": "^10.0.1", 1225 | "globals": "^14.0.0", 1226 | "ignore": "^5.2.0", 1227 | "import-fresh": "^3.2.1", 1228 | "js-yaml": "^4.1.0", 1229 | "minimatch": "^3.1.2", 1230 | "strip-json-comments": "^3.1.1" 1231 | } 1232 | }, 1233 | "@eslint/js": { 1234 | "version": "9.13.0", 1235 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", 1236 | "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", 1237 | "dev": true 1238 | }, 1239 | "@eslint/object-schema": { 1240 | "version": "2.1.4", 1241 | "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", 1242 | "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", 1243 | "dev": true 1244 | }, 1245 | "@eslint/plugin-kit": { 1246 | "version": "0.2.2", 1247 | "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", 1248 | "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", 1249 | "dev": true, 1250 | "requires": { 1251 | "levn": "^0.4.1" 1252 | } 1253 | }, 1254 | "@humanfs/core": { 1255 | "version": "0.19.1", 1256 | "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", 1257 | "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", 1258 | "dev": true 1259 | }, 1260 | "@humanfs/node": { 1261 | "version": "0.16.6", 1262 | "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", 1263 | "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", 1264 | "dev": true, 1265 | "requires": { 1266 | "@humanfs/core": "^0.19.1", 1267 | "@humanwhocodes/retry": "^0.3.0" 1268 | } 1269 | }, 1270 | "@humanwhocodes/module-importer": { 1271 | "version": "1.0.1", 1272 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 1273 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 1274 | "dev": true 1275 | }, 1276 | "@humanwhocodes/retry": { 1277 | "version": "0.3.1", 1278 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", 1279 | "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", 1280 | "dev": true 1281 | }, 1282 | "@jridgewell/gen-mapping": { 1283 | "version": "0.3.5", 1284 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 1285 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 1286 | "dev": true, 1287 | "requires": { 1288 | "@jridgewell/set-array": "^1.2.1", 1289 | "@jridgewell/sourcemap-codec": "^1.4.10", 1290 | "@jridgewell/trace-mapping": "^0.3.24" 1291 | } 1292 | }, 1293 | "@jridgewell/resolve-uri": { 1294 | "version": "3.1.2", 1295 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 1296 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 1297 | "dev": true 1298 | }, 1299 | "@jridgewell/set-array": { 1300 | "version": "1.2.1", 1301 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 1302 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 1303 | "dev": true 1304 | }, 1305 | "@jridgewell/source-map": { 1306 | "version": "0.3.6", 1307 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", 1308 | "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", 1309 | "dev": true, 1310 | "requires": { 1311 | "@jridgewell/gen-mapping": "^0.3.5", 1312 | "@jridgewell/trace-mapping": "^0.3.25" 1313 | } 1314 | }, 1315 | "@jridgewell/sourcemap-codec": { 1316 | "version": "1.5.0", 1317 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 1318 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 1319 | "dev": true 1320 | }, 1321 | "@jridgewell/trace-mapping": { 1322 | "version": "0.3.25", 1323 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 1324 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 1325 | "dev": true, 1326 | "requires": { 1327 | "@jridgewell/resolve-uri": "^3.1.0", 1328 | "@jridgewell/sourcemap-codec": "^1.4.14" 1329 | } 1330 | }, 1331 | "@popperjs/core": { 1332 | "version": "2.11.8", 1333 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", 1334 | "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", 1335 | "peer": true 1336 | }, 1337 | "@types/estree": { 1338 | "version": "1.0.6", 1339 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 1340 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 1341 | "dev": true 1342 | }, 1343 | "@types/json-schema": { 1344 | "version": "7.0.15", 1345 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 1346 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 1347 | "dev": true 1348 | }, 1349 | "acorn": { 1350 | "version": "8.14.0", 1351 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 1352 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 1353 | "dev": true 1354 | }, 1355 | "acorn-jsx": { 1356 | "version": "5.3.2", 1357 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 1358 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 1359 | "dev": true, 1360 | "requires": {} 1361 | }, 1362 | "ajv": { 1363 | "version": "6.12.6", 1364 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 1365 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 1366 | "dev": true, 1367 | "requires": { 1368 | "fast-deep-equal": "^3.1.1", 1369 | "fast-json-stable-stringify": "^2.0.0", 1370 | "json-schema-traverse": "^0.4.1", 1371 | "uri-js": "^4.2.2" 1372 | } 1373 | }, 1374 | "ansi-styles": { 1375 | "version": "4.3.0", 1376 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1377 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1378 | "dev": true, 1379 | "requires": { 1380 | "color-convert": "^2.0.1" 1381 | } 1382 | }, 1383 | "argparse": { 1384 | "version": "2.0.1", 1385 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1386 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1387 | "dev": true 1388 | }, 1389 | "balanced-match": { 1390 | "version": "1.0.2", 1391 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1392 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1393 | "dev": true 1394 | }, 1395 | "bootstrap": { 1396 | "version": "5.3.3", 1397 | "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", 1398 | "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", 1399 | "requires": {} 1400 | }, 1401 | "brace-expansion": { 1402 | "version": "1.1.11", 1403 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1404 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1405 | "dev": true, 1406 | "requires": { 1407 | "balanced-match": "^1.0.0", 1408 | "concat-map": "0.0.1" 1409 | } 1410 | }, 1411 | "buffer-from": { 1412 | "version": "1.1.2", 1413 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 1414 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 1415 | "dev": true 1416 | }, 1417 | "callsites": { 1418 | "version": "3.1.0", 1419 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1420 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1421 | "dev": true 1422 | }, 1423 | "chalk": { 1424 | "version": "4.1.2", 1425 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1426 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1427 | "dev": true, 1428 | "requires": { 1429 | "ansi-styles": "^4.1.0", 1430 | "supports-color": "^7.1.0" 1431 | } 1432 | }, 1433 | "color-convert": { 1434 | "version": "2.0.1", 1435 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1436 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1437 | "dev": true, 1438 | "requires": { 1439 | "color-name": "~1.1.4" 1440 | } 1441 | }, 1442 | "color-name": { 1443 | "version": "1.1.4", 1444 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1445 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1446 | "dev": true 1447 | }, 1448 | "commander": { 1449 | "version": "2.20.3", 1450 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 1451 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 1452 | "dev": true 1453 | }, 1454 | "concat-map": { 1455 | "version": "0.0.1", 1456 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1457 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 1458 | "dev": true 1459 | }, 1460 | "cross-spawn": { 1461 | "version": "7.0.3", 1462 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1463 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1464 | "dev": true, 1465 | "requires": { 1466 | "path-key": "^3.1.0", 1467 | "shebang-command": "^2.0.0", 1468 | "which": "^2.0.1" 1469 | } 1470 | }, 1471 | "debug": { 1472 | "version": "4.3.7", 1473 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1474 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1475 | "dev": true, 1476 | "requires": { 1477 | "ms": "^2.1.3" 1478 | } 1479 | }, 1480 | "deep-is": { 1481 | "version": "0.1.4", 1482 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 1483 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 1484 | "dev": true 1485 | }, 1486 | "escape-string-regexp": { 1487 | "version": "4.0.0", 1488 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1489 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1490 | "dev": true 1491 | }, 1492 | "eslint": { 1493 | "version": "9.13.0", 1494 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", 1495 | "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", 1496 | "dev": true, 1497 | "requires": { 1498 | "@eslint-community/eslint-utils": "^4.2.0", 1499 | "@eslint-community/regexpp": "^4.11.0", 1500 | "@eslint/config-array": "^0.18.0", 1501 | "@eslint/core": "^0.7.0", 1502 | "@eslint/eslintrc": "^3.1.0", 1503 | "@eslint/js": "9.13.0", 1504 | "@eslint/plugin-kit": "^0.2.0", 1505 | "@humanfs/node": "^0.16.5", 1506 | "@humanwhocodes/module-importer": "^1.0.1", 1507 | "@humanwhocodes/retry": "^0.3.1", 1508 | "@types/estree": "^1.0.6", 1509 | "@types/json-schema": "^7.0.15", 1510 | "ajv": "^6.12.4", 1511 | "chalk": "^4.0.0", 1512 | "cross-spawn": "^7.0.2", 1513 | "debug": "^4.3.2", 1514 | "escape-string-regexp": "^4.0.0", 1515 | "eslint-scope": "^8.1.0", 1516 | "eslint-visitor-keys": "^4.1.0", 1517 | "espree": "^10.2.0", 1518 | "esquery": "^1.5.0", 1519 | "esutils": "^2.0.2", 1520 | "fast-deep-equal": "^3.1.3", 1521 | "file-entry-cache": "^8.0.0", 1522 | "find-up": "^5.0.0", 1523 | "glob-parent": "^6.0.2", 1524 | "ignore": "^5.2.0", 1525 | "imurmurhash": "^0.1.4", 1526 | "is-glob": "^4.0.0", 1527 | "json-stable-stringify-without-jsonify": "^1.0.1", 1528 | "lodash.merge": "^4.6.2", 1529 | "minimatch": "^3.1.2", 1530 | "natural-compare": "^1.4.0", 1531 | "optionator": "^0.9.3", 1532 | "text-table": "^0.2.0" 1533 | } 1534 | }, 1535 | "eslint-scope": { 1536 | "version": "8.2.0", 1537 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", 1538 | "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", 1539 | "dev": true, 1540 | "requires": { 1541 | "esrecurse": "^4.3.0", 1542 | "estraverse": "^5.2.0" 1543 | } 1544 | }, 1545 | "eslint-visitor-keys": { 1546 | "version": "4.2.0", 1547 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", 1548 | "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", 1549 | "dev": true 1550 | }, 1551 | "espree": { 1552 | "version": "10.3.0", 1553 | "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", 1554 | "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", 1555 | "dev": true, 1556 | "requires": { 1557 | "acorn": "^8.14.0", 1558 | "acorn-jsx": "^5.3.2", 1559 | "eslint-visitor-keys": "^4.2.0" 1560 | } 1561 | }, 1562 | "esquery": { 1563 | "version": "1.6.0", 1564 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 1565 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 1566 | "dev": true, 1567 | "requires": { 1568 | "estraverse": "^5.1.0" 1569 | } 1570 | }, 1571 | "esrecurse": { 1572 | "version": "4.3.0", 1573 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1574 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1575 | "dev": true, 1576 | "requires": { 1577 | "estraverse": "^5.2.0" 1578 | } 1579 | }, 1580 | "estraverse": { 1581 | "version": "5.3.0", 1582 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1583 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1584 | "dev": true 1585 | }, 1586 | "esutils": { 1587 | "version": "2.0.3", 1588 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1589 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1590 | "dev": true 1591 | }, 1592 | "fast-deep-equal": { 1593 | "version": "3.1.3", 1594 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1595 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1596 | "dev": true 1597 | }, 1598 | "fast-json-stable-stringify": { 1599 | "version": "2.1.0", 1600 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1601 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1602 | "dev": true 1603 | }, 1604 | "fast-levenshtein": { 1605 | "version": "2.0.6", 1606 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1607 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1608 | "dev": true 1609 | }, 1610 | "file-entry-cache": { 1611 | "version": "8.0.0", 1612 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", 1613 | "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", 1614 | "dev": true, 1615 | "requires": { 1616 | "flat-cache": "^4.0.0" 1617 | } 1618 | }, 1619 | "find-up": { 1620 | "version": "5.0.0", 1621 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1622 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1623 | "dev": true, 1624 | "requires": { 1625 | "locate-path": "^6.0.0", 1626 | "path-exists": "^4.0.0" 1627 | } 1628 | }, 1629 | "flat-cache": { 1630 | "version": "4.0.1", 1631 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", 1632 | "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", 1633 | "dev": true, 1634 | "requires": { 1635 | "flatted": "^3.2.9", 1636 | "keyv": "^4.5.4" 1637 | } 1638 | }, 1639 | "flatted": { 1640 | "version": "3.3.1", 1641 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", 1642 | "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", 1643 | "dev": true 1644 | }, 1645 | "glob-parent": { 1646 | "version": "6.0.2", 1647 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1648 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1649 | "dev": true, 1650 | "requires": { 1651 | "is-glob": "^4.0.3" 1652 | } 1653 | }, 1654 | "globals": { 1655 | "version": "14.0.0", 1656 | "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", 1657 | "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", 1658 | "dev": true 1659 | }, 1660 | "globalyzer": { 1661 | "version": "0.1.0", 1662 | "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", 1663 | "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==" 1664 | }, 1665 | "globrex": { 1666 | "version": "0.1.2", 1667 | "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", 1668 | "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" 1669 | }, 1670 | "has-flag": { 1671 | "version": "4.0.0", 1672 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1673 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1674 | "dev": true 1675 | }, 1676 | "ignore": { 1677 | "version": "5.3.2", 1678 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 1679 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 1680 | "dev": true 1681 | }, 1682 | "import-fresh": { 1683 | "version": "3.3.0", 1684 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1685 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1686 | "dev": true, 1687 | "requires": { 1688 | "parent-module": "^1.0.0", 1689 | "resolve-from": "^4.0.0" 1690 | } 1691 | }, 1692 | "imurmurhash": { 1693 | "version": "0.1.4", 1694 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1695 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1696 | "dev": true 1697 | }, 1698 | "is-extglob": { 1699 | "version": "2.1.1", 1700 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1701 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1702 | "dev": true 1703 | }, 1704 | "is-glob": { 1705 | "version": "4.0.3", 1706 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1707 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1708 | "dev": true, 1709 | "requires": { 1710 | "is-extglob": "^2.1.1" 1711 | } 1712 | }, 1713 | "isexe": { 1714 | "version": "2.0.0", 1715 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1716 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1717 | "dev": true 1718 | }, 1719 | "jquery": { 1720 | "version": "3.7.1", 1721 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", 1722 | "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" 1723 | }, 1724 | "js-yaml": { 1725 | "version": "4.1.0", 1726 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1727 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1728 | "dev": true, 1729 | "requires": { 1730 | "argparse": "^2.0.1" 1731 | } 1732 | }, 1733 | "json-buffer": { 1734 | "version": "3.0.1", 1735 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 1736 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1737 | "dev": true 1738 | }, 1739 | "json-schema-traverse": { 1740 | "version": "0.4.1", 1741 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1742 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1743 | "dev": true 1744 | }, 1745 | "json-stable-stringify-without-jsonify": { 1746 | "version": "1.0.1", 1747 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1748 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1749 | "dev": true 1750 | }, 1751 | "keyv": { 1752 | "version": "4.5.4", 1753 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 1754 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 1755 | "dev": true, 1756 | "requires": { 1757 | "json-buffer": "3.0.1" 1758 | } 1759 | }, 1760 | "levn": { 1761 | "version": "0.4.1", 1762 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1763 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1764 | "dev": true, 1765 | "requires": { 1766 | "prelude-ls": "^1.2.1", 1767 | "type-check": "~0.4.0" 1768 | } 1769 | }, 1770 | "locate-path": { 1771 | "version": "6.0.0", 1772 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1773 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1774 | "dev": true, 1775 | "requires": { 1776 | "p-locate": "^5.0.0" 1777 | } 1778 | }, 1779 | "lodash.merge": { 1780 | "version": "4.6.2", 1781 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1782 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1783 | "dev": true 1784 | }, 1785 | "minimatch": { 1786 | "version": "3.1.2", 1787 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1788 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1789 | "dev": true, 1790 | "requires": { 1791 | "brace-expansion": "^1.1.7" 1792 | } 1793 | }, 1794 | "ms": { 1795 | "version": "2.1.3", 1796 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1797 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1798 | "dev": true 1799 | }, 1800 | "natural-compare": { 1801 | "version": "1.4.0", 1802 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1803 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1804 | "dev": true 1805 | }, 1806 | "node-watch": { 1807 | "version": "0.7.3", 1808 | "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz", 1809 | "integrity": "sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==" 1810 | }, 1811 | "optionator": { 1812 | "version": "0.9.4", 1813 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", 1814 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 1815 | "dev": true, 1816 | "requires": { 1817 | "deep-is": "^0.1.3", 1818 | "fast-levenshtein": "^2.0.6", 1819 | "levn": "^0.4.1", 1820 | "prelude-ls": "^1.2.1", 1821 | "type-check": "^0.4.0", 1822 | "word-wrap": "^1.2.5" 1823 | } 1824 | }, 1825 | "p-limit": { 1826 | "version": "3.1.0", 1827 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1828 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1829 | "dev": true, 1830 | "requires": { 1831 | "yocto-queue": "^0.1.0" 1832 | } 1833 | }, 1834 | "p-locate": { 1835 | "version": "5.0.0", 1836 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1837 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1838 | "dev": true, 1839 | "requires": { 1840 | "p-limit": "^3.0.2" 1841 | } 1842 | }, 1843 | "parent-module": { 1844 | "version": "1.0.1", 1845 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1846 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1847 | "dev": true, 1848 | "requires": { 1849 | "callsites": "^3.0.0" 1850 | } 1851 | }, 1852 | "path-exists": { 1853 | "version": "4.0.0", 1854 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1855 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1856 | "dev": true 1857 | }, 1858 | "path-key": { 1859 | "version": "3.1.1", 1860 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1861 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1862 | "dev": true 1863 | }, 1864 | "prelude-ls": { 1865 | "version": "1.2.1", 1866 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1867 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1868 | "dev": true 1869 | }, 1870 | "punycode": { 1871 | "version": "2.3.1", 1872 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 1873 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1874 | "dev": true 1875 | }, 1876 | "qunit": { 1877 | "version": "2.22.0", 1878 | "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.22.0.tgz", 1879 | "integrity": "sha512-wPYvAvpjTL3zlUeyCX75T8gfZfdVXZa8y1EVkGe/XZNORIsCH/WI2X8R2KlemT921X9EKSZUL6CLGSPC7Ks08g==", 1880 | "requires": { 1881 | "commander": "7.2.0", 1882 | "node-watch": "0.7.3", 1883 | "tiny-glob": "0.2.9" 1884 | }, 1885 | "dependencies": { 1886 | "commander": { 1887 | "version": "7.2.0", 1888 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 1889 | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" 1890 | } 1891 | } 1892 | }, 1893 | "resolve-from": { 1894 | "version": "4.0.0", 1895 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1896 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1897 | "dev": true 1898 | }, 1899 | "shebang-command": { 1900 | "version": "2.0.0", 1901 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1902 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1903 | "dev": true, 1904 | "requires": { 1905 | "shebang-regex": "^3.0.0" 1906 | } 1907 | }, 1908 | "shebang-regex": { 1909 | "version": "3.0.0", 1910 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1911 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1912 | "dev": true 1913 | }, 1914 | "source-map": { 1915 | "version": "0.6.1", 1916 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1917 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1918 | "dev": true 1919 | }, 1920 | "source-map-support": { 1921 | "version": "0.5.21", 1922 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1923 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1924 | "dev": true, 1925 | "requires": { 1926 | "buffer-from": "^1.0.0", 1927 | "source-map": "^0.6.0" 1928 | } 1929 | }, 1930 | "strip-json-comments": { 1931 | "version": "3.1.1", 1932 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1933 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1934 | "dev": true 1935 | }, 1936 | "supports-color": { 1937 | "version": "7.2.0", 1938 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1939 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1940 | "dev": true, 1941 | "requires": { 1942 | "has-flag": "^4.0.0" 1943 | } 1944 | }, 1945 | "terser": { 1946 | "version": "5.36.0", 1947 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", 1948 | "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", 1949 | "dev": true, 1950 | "requires": { 1951 | "@jridgewell/source-map": "^0.3.3", 1952 | "acorn": "^8.8.2", 1953 | "commander": "^2.20.0", 1954 | "source-map-support": "~0.5.20" 1955 | } 1956 | }, 1957 | "text-table": { 1958 | "version": "0.2.0", 1959 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1960 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 1961 | "dev": true 1962 | }, 1963 | "tiny-glob": { 1964 | "version": "0.2.9", 1965 | "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", 1966 | "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", 1967 | "requires": { 1968 | "globalyzer": "0.1.0", 1969 | "globrex": "^0.1.2" 1970 | } 1971 | }, 1972 | "type-check": { 1973 | "version": "0.4.0", 1974 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1975 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1976 | "dev": true, 1977 | "requires": { 1978 | "prelude-ls": "^1.2.1" 1979 | } 1980 | }, 1981 | "uri-js": { 1982 | "version": "4.4.1", 1983 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1984 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1985 | "dev": true, 1986 | "requires": { 1987 | "punycode": "^2.1.0" 1988 | } 1989 | }, 1990 | "which": { 1991 | "version": "2.0.2", 1992 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1993 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1994 | "dev": true, 1995 | "requires": { 1996 | "isexe": "^2.0.0" 1997 | } 1998 | }, 1999 | "word-wrap": { 2000 | "version": "1.2.5", 2001 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 2002 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 2003 | "dev": true 2004 | }, 2005 | "yocto-queue": { 2006 | "version": "0.1.0", 2007 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2008 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2009 | "dev": true 2010 | } 2011 | } 2012 | } 2013 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-maxlength", 3 | "version": "2.0.0", 4 | "version_short": "2.0", 5 | "description": "A visual feedback indicator for the MaxLength attribute", 6 | "main": "dist/bootstrap-maxlength.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/mimo84/bootstrap-maxlength.git" 10 | }, 11 | "homepage": "https://github.com/mimo84/bootstrap-maxlength", 12 | "keywords": [ 13 | "form", 14 | "maxlength", 15 | "html5", 16 | "input", 17 | "feedback", 18 | "jquery-plugin", 19 | "jquery", 20 | "bootstrap", 21 | "bs" 22 | ], 23 | "author": "Maurizio Napoleoni @mimonap", 24 | "contributors": [ 25 | "Maurizio Napoleoni @mimonap", 26 | "djibe @djibe" 27 | ], 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/mimo84/bootstrap-maxlength/issues" 31 | }, 32 | "scripts": { 33 | "test": "eslint \"src/**\" --report-unused-disable-directives", 34 | "dist": "terser src/bootstrap-maxlength.js -o dist/bootstrap-maxlength.js --format beautify && terser src/bootstrap-maxlength.js -o dist/bootstrap-maxlength.min.js -c" 35 | }, 36 | "dependencies": { 37 | "bootstrap": "^5.3.3", 38 | "jquery": "^3.7.1", 39 | "qunit": "^2.22.0" 40 | }, 41 | "devDependencies": { 42 | "eslint": "^9.13.0", 43 | "terser": "^5.36.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/bootstrap-maxlength.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-maxlength.js v1.10.0 3 | * 4 | * Copyright (c) 2013-2021 Maurizio Napoleoni; 5 | * 6 | * Licensed under the terms of the MIT license. 7 | * See: https://github.com/mimo84/bootstrap-maxlength/blob/master/LICENSE 8 | * ========================================================== */ 9 | /*global jQuery*/ 10 | 11 | (function ($) { 12 | 'use strict'; 13 | /** 14 | * We need an event when the elements are destroyed 15 | * because if an input is removed, we have to remove the 16 | * maxlength object associated (if any). 17 | * From: 18 | * http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom 19 | */ 20 | if (!$.event.special.destroyed) { 21 | $.event.special.destroyed = { 22 | remove: function (o) { 23 | if (o.handler) { 24 | o.handler(); 25 | } 26 | } 27 | }; 28 | } 29 | 30 | 31 | $.fn.extend({ 32 | maxlength: function (options, callback) { 33 | var documentBody = $('body'), 34 | defaults = { 35 | showOnReady: false, // true to always show when indicator is ready 36 | alwaysShow: true, // if true the indicator it's always shown. 37 | threshold: 0, // Represents how many chars left are needed to show up the counter 38 | warningClass: 'small form-text text-body-secondary', 39 | limitReachedClass: 'small form-text text-danger', 40 | limitExceededClass: '', 41 | separator: ' / ', 42 | preText: '', 43 | postText: '', 44 | showMaxLength: true, 45 | placement: 'bottom-right-inside', 46 | message: null, // an alternative way to provide the message text 47 | showCharsTyped: true, // show the number of characters typed and not the number of characters remaining 48 | validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than the indicated chars, will be prevented. 49 | utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters. 50 | appendToParent: false, // append the indicator to the input field's parent instead of body 51 | twoCharLinebreak: true, // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage. 52 | customMaxAttribute: null, // null = use maxlength attribute and browser functionality, string = use specified attribute instead. 53 | customMaxClass: 'overmax', // Class to add to the input field when the maxlength is exceeded. 54 | allowOverMax: false, // Form submit validation is handled on your own. when maxlength has been exceeded 'overmax' class added to element 55 | zIndex: 1099 56 | }; 57 | 58 | if ($.isFunction(options) && !callback) { 59 | callback = options; 60 | options = {}; 61 | } 62 | options = $.extend(defaults, options); 63 | 64 | 65 | /** 66 | * Return the byte count of the specified character in UTF8 encoding. 67 | * Note: This won't cover UTF-8 characters that are 4 bytes long. 68 | * 69 | * @param input 70 | * @return {number} 71 | */ 72 | function utf8CharByteCount(character) { 73 | var c = character.charCodeAt(); 74 | // Not c then 0, else c < 128 then 1, else c < 2048 then 2, else 3 75 | return !c ? 0 : c < 128 ? 1 : c < 2048 ? 2 : 3; 76 | } 77 | 78 | /** 79 | * Return the length of the specified input in UTF8 encoding. 80 | * 81 | * @param input 82 | * @return {number} 83 | */ 84 | function utf8Length(string) { 85 | return string.split("") 86 | .map(utf8CharByteCount) 87 | // Prevent reduce from throwing an error if the string is empty. 88 | .concat(0) 89 | .reduce(function (sum, val) { 90 | return sum + val; 91 | }); 92 | } 93 | 94 | /** 95 | * Return the length of the specified input. 96 | * 97 | * @param input 98 | * @return {number} 99 | */ 100 | function inputLength(input) { 101 | var text = input.val(); 102 | 103 | if (options.twoCharLinebreak) { 104 | // Count all line breaks as 2 characters 105 | text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n'); 106 | } else { 107 | // Remove all double-character (\r\n) linebreaks, so they're counted only once. 108 | text = text.replace(/(?:\r\n|\r|\n)/g, '\n'); 109 | } 110 | 111 | var currentLength = 0; 112 | 113 | if (options.utf8) { 114 | currentLength = utf8Length(text); 115 | } else { 116 | currentLength = text.length; 117 | } 118 | 119 | // Remove "C:\fakepath\" from counter when using file input 120 | // Fix https://github.com/mimo84/bootstrap-maxlength/issues/146 121 | if (input.prop("type") === "file" && input.val() !== "") { 122 | currentLength -= 12; 123 | } 124 | 125 | return currentLength; 126 | } 127 | 128 | /** 129 | * Truncate the text of the specified input. 130 | * 131 | * @param input 132 | * @param limit 133 | */ 134 | function truncateChars(input, maxlength) { 135 | var text = input.val(); 136 | 137 | if (options.twoCharLinebreak) { 138 | text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n'); 139 | 140 | if (text[text.length - 1] === '\n') { 141 | maxlength -= text.length % 2; 142 | } 143 | } 144 | 145 | if (options.utf8) { 146 | var indexedSize = text.split("").map(utf8CharByteCount); 147 | for ( 148 | var removedBytes = 0, 149 | bytesPastMax = utf8Length(text) - maxlength; removedBytes < bytesPastMax; removedBytes += indexedSize.pop() 150 | ); 151 | maxlength -= (maxlength - indexedSize.length); 152 | } 153 | 154 | input.val(text.substr(0, maxlength)); 155 | } 156 | 157 | /** 158 | * Return true if the indicator should be showing up. 159 | * 160 | * @param input 161 | * @param threshold 162 | * @param maxlength 163 | * @return {number} 164 | */ 165 | function charsLeftThreshold(input, threshold, maxlength) { 166 | var output = true; 167 | if (!options.alwaysShow && (maxlength - inputLength(input) > threshold)) { 168 | output = false; 169 | } 170 | return output; 171 | } 172 | 173 | /** 174 | * Returns how many chars are left to complete the fill up of the form. 175 | * 176 | * @param input 177 | * @param maxlength 178 | * @return {number} 179 | */ 180 | function remainingChars(input, maxlength) { 181 | var length = maxlength - inputLength(input); 182 | return length; 183 | } 184 | 185 | /** 186 | * When called displays the indicator. 187 | * 188 | * @param indicator 189 | */ 190 | function showRemaining(currentInput, indicator) { 191 | indicator.css({ 192 | display: 'block' 193 | }); 194 | currentInput.trigger('maxlength.shown'); 195 | } 196 | 197 | /** 198 | * When called shows the indicator. 199 | * 200 | * @param indicator 201 | */ 202 | function hideRemaining(currentInput, indicator) { 203 | 204 | if (options.alwaysShow) { 205 | return; 206 | } 207 | 208 | indicator.css({ 209 | display: 'none' 210 | }); 211 | currentInput.trigger('maxlength.hidden'); 212 | } 213 | 214 | /** 215 | * This function updates the value in the indicator 216 | * 217 | * @param maxLengthThisInput 218 | * @param typedChars 219 | * @return String 220 | */ 221 | function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) { 222 | var output = ''; 223 | if (options.message) { 224 | if (typeof options.message === 'function') { 225 | output = options.message(currentInputText, maxLengthThisInput); 226 | } else { 227 | output = options.message.replace('%charsTyped%', typedChars) 228 | .replace('%charsRemaining%', maxLengthThisInput - typedChars) 229 | .replace('%charsTotal%', maxLengthThisInput); 230 | } 231 | } else { 232 | if (options.preText) { 233 | output += options.preText; 234 | } 235 | if (!options.showCharsTyped) { 236 | output += maxLengthThisInput - typedChars; 237 | } else { 238 | output += typedChars; 239 | } 240 | if (options.showMaxLength) { 241 | output += options.separator + maxLengthThisInput; 242 | } 243 | if (options.postText) { 244 | output += options.postText; 245 | } 246 | } 247 | return output; 248 | } 249 | 250 | /** 251 | * This function updates the value of the counter in the indicator. 252 | * Wants as parameters: the number of remaining chars, the element currently managed, 253 | * the maxLength for the current input and the indicator generated for it. 254 | * 255 | * @param remaining 256 | * @param currentInput 257 | * @param maxLengthCurrentInput 258 | * @param maxLengthIndicator 259 | */ 260 | function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) { 261 | if (maxLengthIndicator) { 262 | maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining))); 263 | 264 | if (remaining > 0) { 265 | if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) { 266 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass + ' ' + options.limitExceededClass).addClass(options.warningClass)); 267 | } else { 268 | hideRemaining(currentInput, maxLengthIndicator); 269 | } 270 | } else { 271 | if (!options.limitExceededClass) { 272 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass)); 273 | } else { 274 | if (remaining === 0) { 275 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass + ' ' + options.limitExceededClass).addClass(options.limitReachedClass)); 276 | } else { 277 | showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass + ' ' + options.limitReachedClass).addClass(options.limitExceededClass)); 278 | } 279 | } 280 | } 281 | } 282 | 283 | if (options.customMaxAttribute) { 284 | // class to use for form validation on custom maxlength attribute 285 | if (remaining < 0) { 286 | currentInput.addClass(options.customMaxClass); 287 | } else { 288 | currentInput.removeClass(options.customMaxClass); 289 | } 290 | } 291 | } 292 | 293 | /** 294 | * This function returns an object containing all the 295 | * informations about the position of the current input 296 | * 297 | * @param currentInput 298 | * @return object {bottom height left right top width} 299 | * 300 | */ 301 | function getPosition(currentInput) { 302 | var el = currentInput[0]; 303 | return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : { 304 | width: el.offsetWidth, 305 | height: el.offsetHeight 306 | }, currentInput.offset()); 307 | } 308 | 309 | /** 310 | * This function places the maxLengthIndicator based on placement config object. 311 | * 312 | * @param {object} placement 313 | * @param {$} maxLengthIndicator 314 | * @return null 315 | * 316 | */ 317 | function placeWithCSS(placement, maxLengthIndicator) { 318 | if (!placement || !maxLengthIndicator) { 319 | return; 320 | } 321 | 322 | var POSITION_KEYS = [ 323 | 'top', 324 | 'bottom', 325 | 'left', 326 | 'right', 327 | 'position' 328 | ]; 329 | 330 | var cssPos = {}; 331 | 332 | // filter css properties to position 333 | $.each(POSITION_KEYS, function (i, key) { 334 | var val = options.placement[key]; 335 | if (typeof val !== 'undefined') { 336 | cssPos[key] = val; 337 | } 338 | }); 339 | 340 | maxLengthIndicator.css(cssPos); 341 | 342 | return; 343 | } 344 | 345 | 346 | /** 347 | * This function places the maxLengthIndicator at the 348 | * top / bottom / left / right of the currentInput 349 | * 350 | * @param currentInput 351 | * @param maxLengthIndicator 352 | * @return null 353 | * 354 | */ 355 | function place(currentInput, maxLengthIndicator) { 356 | var pos = getPosition(currentInput); 357 | 358 | // Supports custom placement handler 359 | if ($.type(options.placement) === 'function') { 360 | options.placement(currentInput, maxLengthIndicator, pos); 361 | return; 362 | } 363 | 364 | // Supports custom placement via css positional properties 365 | if ($.isPlainObject(options.placement)) { 366 | placeWithCSS(options.placement, maxLengthIndicator); 367 | return; 368 | } 369 | 370 | var inputOuter = currentInput.outerWidth(), 371 | outerWidth = maxLengthIndicator.outerWidth(), 372 | actualWidth = maxLengthIndicator.width(), 373 | actualHeight = maxLengthIndicator.height(); 374 | 375 | // get the right position if the indicator is appended to the input's parent 376 | if (options.appendToParent) { 377 | pos.top -= currentInput.parent().offset().top; 378 | pos.left -= currentInput.parent().offset().left; 379 | } 380 | 381 | switch (options.placement) { 382 | case 'bottom': 383 | maxLengthIndicator.css({ 384 | top: pos.top + pos.height, 385 | left: pos.left + pos.width / 2 - actualWidth / 2 386 | }); 387 | break; 388 | case 'top': 389 | maxLengthIndicator.css({ 390 | top: pos.top - actualHeight, 391 | left: pos.left + pos.width / 2 - actualWidth / 2 392 | }); 393 | break; 394 | case 'left': 395 | maxLengthIndicator.css({ 396 | top: pos.top + pos.height / 2 - actualHeight / 2, 397 | left: pos.left - actualWidth 398 | }); 399 | break; 400 | case 'right': 401 | maxLengthIndicator.css({ 402 | top: pos.top + pos.height / 2 - actualHeight / 2, 403 | left: pos.left + pos.width 404 | }); 405 | break; 406 | case 'bottom-right': 407 | maxLengthIndicator.css({ 408 | top: pos.top + pos.height, 409 | left: pos.left + pos.width 410 | }); 411 | break; 412 | case 'top-right': 413 | maxLengthIndicator.css({ 414 | top: pos.top - actualHeight, 415 | left: pos.left + inputOuter 416 | }); 417 | break; 418 | case 'top-left': 419 | maxLengthIndicator.css({ 420 | top: pos.top - actualHeight, 421 | left: pos.left - outerWidth 422 | }); 423 | break; 424 | case 'bottom-left': 425 | maxLengthIndicator.css({ 426 | top: pos.top + currentInput.outerHeight(), 427 | left: pos.left - outerWidth 428 | }); 429 | break; 430 | case 'centered-right': 431 | maxLengthIndicator.css({ 432 | top: pos.top + (actualHeight / 2), 433 | left: pos.left + inputOuter - outerWidth - 3 434 | }); 435 | break; 436 | 437 | // Some more options for placements 438 | case 'bottom-right-inside': 439 | maxLengthIndicator.css({ 440 | top: pos.top + pos.height, 441 | left: pos.left + pos.width - outerWidth 442 | }); 443 | break; 444 | case 'top-right-inside': 445 | maxLengthIndicator.css({ 446 | top: pos.top - actualHeight, 447 | left: pos.left + inputOuter - outerWidth 448 | }); 449 | break; 450 | case 'top-left-inside': 451 | maxLengthIndicator.css({ 452 | top: pos.top - actualHeight, 453 | left: pos.left 454 | }); 455 | break; 456 | case 'bottom-left-inside': 457 | maxLengthIndicator.css({ 458 | top: pos.top + currentInput.outerHeight(), 459 | left: pos.left 460 | }); 461 | break; 462 | } 463 | } 464 | 465 | /** 466 | * This function retrieves the maximum length of currentInput 467 | * 468 | * @param currentInput 469 | * @return {number} 470 | * 471 | */ 472 | function getMaxLength(currentInput) { 473 | var max = currentInput.attr('maxlength') || options.customMaxAttribute; 474 | 475 | if (options.customMaxAttribute && !options.allowOverMax) { 476 | var custom = currentInput.attr(options.customMaxAttribute); 477 | if (!max || custom < max) { 478 | max = custom; 479 | } 480 | } 481 | 482 | if (!max) { 483 | max = currentInput.attr('size'); 484 | } 485 | return max; 486 | } 487 | 488 | return this.each(function () { 489 | 490 | var currentInput = $(this), 491 | maxLengthCurrentInput, 492 | maxLengthIndicator; 493 | 494 | $(window).resize(function () { 495 | if (maxLengthIndicator) { 496 | place(currentInput, maxLengthIndicator); 497 | } 498 | }); 499 | 500 | function firstInit() { 501 | var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0'); 502 | maxLengthCurrentInput = getMaxLength(currentInput); 503 | 504 | if (!maxLengthIndicator) { 505 | maxLengthIndicator = $('').css({ 506 | display: 'none', 507 | position: 'absolute', 508 | whiteSpace: 'nowrap', 509 | zIndex: options.zIndex 510 | }).html(maxlengthContent); 511 | } 512 | 513 | // We need to detect resizes if we are dealing with a textarea: 514 | if (currentInput.is('textarea')) { 515 | currentInput.data('maxlenghtsizex', currentInput.outerWidth()); 516 | currentInput.data('maxlenghtsizey', currentInput.outerHeight()); 517 | 518 | currentInput.mouseup(function () { 519 | if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) { 520 | place(currentInput, maxLengthIndicator); 521 | } 522 | 523 | currentInput.data('maxlenghtsizex', currentInput.outerWidth()); 524 | currentInput.data('maxlenghtsizey', currentInput.outerHeight()); 525 | }); 526 | } 527 | 528 | if (options.appendToParent) { 529 | currentInput.parent().append(maxLengthIndicator); 530 | currentInput.parent().css('position', 'relative'); 531 | } else { 532 | documentBody.append(maxLengthIndicator); 533 | } 534 | 535 | var remaining = remainingChars(currentInput, getMaxLength(currentInput)); 536 | manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 537 | place(currentInput, maxLengthIndicator); 538 | } 539 | 540 | if (options.showOnReady) { 541 | currentInput.ready(function () { 542 | firstInit(); 543 | }); 544 | } else { 545 | currentInput.focus(function () { 546 | firstInit(); 547 | }); 548 | } 549 | 550 | currentInput.on('maxlength.reposition', function () { 551 | place(currentInput, maxLengthIndicator); 552 | }); 553 | 554 | 555 | currentInput.on('destroyed', function () { 556 | if (maxLengthIndicator) { 557 | maxLengthIndicator.remove(); 558 | } 559 | }); 560 | 561 | currentInput.on('blur', function () { 562 | if (maxLengthIndicator && !options.showOnReady) { 563 | maxLengthIndicator.remove(); 564 | } 565 | }); 566 | 567 | currentInput.on('input', function () { 568 | var maxlength = getMaxLength(currentInput), 569 | remaining = remainingChars(currentInput, maxlength), 570 | output = true; 571 | 572 | if (options.validate && remaining < 0) { 573 | truncateChars(currentInput, maxlength); 574 | output = false; 575 | } else { 576 | manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 577 | } 578 | 579 | return output; 580 | }); 581 | }); 582 | } 583 | }); 584 | }(jQuery)); -------------------------------------------------------------------------------- /test/basicInputTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('maxlength', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength(); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Maxlength is displayed correctly', function (assert) { 20 | console.log($, maxlengthInput); 21 | maxlengthInput.focus(); 22 | assert.ok($('.bootstrap-maxlength').length, 'maxlength was inserted'); 23 | }); 24 | 25 | QUnit.test('Maxlength is visible on focus', function (assert) { 26 | maxlengthInput.focus(); 27 | assert.ok($('.bootstrap-maxlength').is(':visible'), 'Maxlength is visible'); 28 | }); 29 | 30 | QUnit.test('Maxlength is removed on blur', function (assert) { 31 | maxlengthInput.maxlength().focus().blur(); 32 | assert.ok(!$('.bootstrap-maxlength').length, 'Maxlength is removed on blur'); 33 | }); 34 | 35 | QUnit.test('Maxlength updates the maxlength', function (assert) { 36 | maxlengthInput.focus(); 37 | 38 | // Change the maxlength attribute 39 | maxlengthInput.blur().attr('maxlength', '142').focus(); 40 | 41 | assert.ok($('.bootstrap-maxlength').html() === '0 / 142', 'Maxlength updated the field'); 42 | 43 | }); 44 | 45 | QUnit.test('Removing an element with the maxlength removes the maxlength if any.', function (assert) { 46 | maxlengthInput.maxlength().focus(); 47 | maxlengthInput.remove(); 48 | assert.ok($('.bootstrap-maxlength').length === 0, 'Maxlength field removed with the input'); 49 | 50 | }); 51 | 52 | QUnit.test('The focus event is triggered multiple times without a blur', function (assert) { 53 | maxlengthInput.focus().focus().focus().focus(); 54 | assert.ok($('.bootstrap-maxlength').length === 1, 'Maxlength visualized only once after multiple focuses'); 55 | }); 56 | 57 | // QUnit.test('The default threshold is respected', function (assert) { 58 | // var content = 'Bootstrap'; 59 | // maxlengthInput.maxlength(); 60 | // assert.ok(content.length < 10, 'Initial content should be less of 10 letters'); 61 | // maxlengthInput.focus(); 62 | // maxlengthInput.val(content); 63 | // console.log(maxlengthInput); 64 | 65 | 66 | // assert.ok($('.bootstrap-maxlength.label.label-success').length === 1, 'Maxlength badge has the success label'); 67 | // assert.ok($('.bootstrap-maxlength.label.label-danger').length === 0, 'Maxlength badge do not have the danger label'); 68 | 69 | // var newContent = 'Bootstrap '; 70 | // assert.ok(newContent.length === 10, 'newContent should be of 10 letters'); 71 | // maxlengthInput.val(newContent); 72 | // maxlengthInput.focus(); 73 | // assert.ok($('.bootstrap-maxlength.label.label-danger').length === 1, 'Maxlength badge has the danger label'); 74 | // assert.ok($('.bootstrap-maxlength.label.label-success').length === 0, 'Maxlength badge do not have the success label'); 75 | // }); 76 | 77 | }); 78 | -------------------------------------------------------------------------------- /test/basicTextareaTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('textarea', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength(); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Newlines are counted twice', function (assert) { 20 | maxlengthInput.val('t\r\nt'); 21 | 22 | maxlengthInput.maxlength(); 23 | maxlengthInput.focus(); 24 | 25 | assert.ok($('.bootstrap-maxlength').html() === '4 / 10', 'Current length is: ' + $('.bootstrap-maxlength').html() + '. Expected 4 / 10.'); 26 | }); 27 | 28 | QUnit.test('Message can be a customizable function', function (assert) { 29 | $('.bootstrap-maxlength').remove(); 30 | $('#qunit-fixture').empty(); 31 | maxlengthInput = $('').appendTo('#qunit-fixture'); 32 | maxlengthInput.maxlength({ 33 | message: function (currentText, maxLength) { 34 | return '' + (currentText.length * 8) + ' Bytes / ' + (maxLength * 8) + ' Bytes'; 35 | } 36 | }); 37 | maxlengthInput.val('Test!'); 38 | maxlengthInput.focus(); 39 | 40 | assert.ok($('.bootstrap-maxlength').html() === '40 Bytes / 80 Bytes', 'Message override is not functioning properly'); 41 | }); 42 | 43 | QUnit.test('Message can be a customizable string', function (assert) { 44 | $('.bootstrap-maxlength').remove(); 45 | $('#qunit-fixture').empty(); 46 | maxlengthInput = $('').appendTo('#qunit-fixture'); 47 | maxlengthInput.maxlength({ 48 | message: 'You have typed %charsTyped% chars, %charsRemaining% of %charsTotal% remaining' 49 | }); 50 | maxlengthInput.val('Testing'); 51 | maxlengthInput.focus(); 52 | 53 | assert.ok($('.bootstrap-maxlength').html() === 'You have typed 7 chars, 3 of 10 remaining', 'Message override is not functioning properly'); 54 | }); 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /test/optionsTests/Utf8Tests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('utf8', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ utf8: true }); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Validate text length by byte', function (assert) { 20 | 21 | maxlengthInput 22 | .val('0°1°2°3°4°5°6°7°8°9°') // ° is two bytes each 23 | .maxlength({ utf8: true, validate: true }) 24 | .trigger('input'); 25 | 26 | var len = maxlengthInput.val().length; 27 | var msg = [ 28 | 'Current length', len, '/ 9.', 29 | 'Expected 6 / 9.' 30 | ].join(" "); 31 | assert.ok(len === 6, msg); 32 | }); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /test/optionsTests/ValidateTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('validate', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ validate: true }); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Text length by character', function (assert) { 20 | maxlengthInput 21 | .val('0°1°2°3°4°5°6°7°8°9°') 22 | .trigger('input'); 23 | 24 | var len = maxlengthInput.val().length; 25 | var msg = [ 26 | 'Current length', len, '/ 9.', 27 | 'Expected 9 / 9.' 28 | ].join(" "); 29 | assert.ok(len === 9, msg); 30 | }); 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /test/optionsTests/alwaysShowTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('alwaysShow', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ alwaysShow: true }); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('The badge is always visible', function (assert) { 20 | maxlengthInput.val('Hello World'); 21 | 22 | maxlengthInput.focus(); 23 | assert.ok($('.bootstrap-maxlength').is(':visible'), 'Maxlength is visible when input:focus'); 24 | 25 | maxlengthInput.blur(); 26 | assert.ok($('.bootstrap-maxlength').not(':visible'), 'Maxlength is not visible when input:not(:focus)'); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /test/optionsTests/customMaxAttributeTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('customMaxAttribute', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ customMaxAttribute: 'data-notifylength' }); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Allows over maxlength', function (assert) { 20 | maxlengthInput.val('this is over the custom maxlength'); 21 | maxlengthInput.focus(); 22 | 23 | assert.ok($('.bootstrap-maxlength').html() === '33 / 10', 'Current length is: ' + $('.bootstrap-maxlength').html() + '. Expected 26 / 10.'); 24 | }); 25 | 26 | QUnit.test('Adds overmax class to element', function (assert) { 27 | maxlengthInput.val('this is over the custom maxlength'); 28 | maxlengthInput.focus(); 29 | 30 | assert.ok(maxlengthInput.hasClass('overmax'), '"overmax" class added to element'); 31 | }); 32 | 33 | QUnit.test('Maxlength attribute remains', function (assert) { 34 | maxlengthInput.val('this is over the custom maxlength'); 35 | maxlengthInput.focus(); 36 | 37 | assert.ok(maxlengthInput.is('[maxlength]'), 'Maxlength attribute remains, but is ignored by this plugin.'); 38 | }); 39 | 40 | QUnit.module('redundant customMaxAttribute', { 41 | beforeEach: function () { 42 | maxlengthInput = $('') 43 | .appendTo('#qunit-fixture'); 44 | 45 | maxlengthInput.maxlength({ customMaxAttribute: 'data-notifylength' }); 46 | }, 47 | afterEach: function () { 48 | $('.bootstrap-maxlength').remove(); 49 | $('#qunit-fixture').empty(); 50 | } 51 | }); 52 | 53 | QUnit.test('custom maxlength attribute is ignored', function (assert) { 54 | maxlengthInput.val('this is over the native maxlength'); 55 | maxlengthInput.focus(); 56 | 57 | assert.ok($('.bootstrap-maxlength').html() === '33 / 10', 'Current length is: ' + $('.bootstrap-maxlength').html() + '. Expected 26 / 10.'); 58 | }); 59 | 60 | }); 61 | -------------------------------------------------------------------------------- /test/optionsTests/placementFunctionTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput, 5 | wasCalled, 6 | argsLength; 7 | 8 | QUnit.module('placement function option', { 9 | beforeEach: function () { 10 | wasCalled = false; 11 | maxlengthInput = $('') 12 | .appendTo('#qunit-fixture'); 13 | 14 | maxlengthInput.maxlength({ 15 | placement: function () { 16 | wasCalled = true; 17 | argsLength = arguments.length; 18 | } 19 | }); 20 | }, 21 | afterEach: function () { 22 | $('.bootstrap-maxlength').remove(); 23 | $('#qunit-fixture').empty(); 24 | } 25 | }); 26 | 27 | QUnit.test('Was called', function (assert) { 28 | maxlengthInput.focus(); 29 | assert.ok(wasCalled, 'Custom placement function was called'); 30 | }); 31 | QUnit.test('Was called with expected number of arguments', function (assert) { 32 | maxlengthInput.focus(); 33 | assert.ok(argsLength === 3, 'placement function option was called with expected number of arguments'); 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /test/optionsTests/placementTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('placement object option', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ 12 | placement: { 13 | top: '5px', 14 | left: '6px', 15 | bottom: '7px', 16 | right: '10px' 17 | } 18 | }); 19 | }, 20 | afterEach: function () { 21 | $('.bootstrap-maxlength').remove(); 22 | $('#qunit-fixture').empty(); 23 | } 24 | }); 25 | 26 | QUnit.test('css top placement from object placement option', function (assert) { 27 | maxlengthInput.focus(); 28 | assert.ok(window.getComputedStyle(document.querySelector('.bootstrap-maxlength')).top === '5px', 'maxlength has expected top style'); 29 | }); 30 | 31 | QUnit.test('css left placement from object placement option', function (assert) { 32 | maxlengthInput.focus(); 33 | assert.ok(window.getComputedStyle(document.querySelector('.bootstrap-maxlength')).left === '6px', 'maxlength has expected left style'); 34 | }); 35 | 36 | QUnit.test('css right placement from object placement option', function (assert) { 37 | maxlengthInput.focus(); 38 | assert.ok(window.getComputedStyle(document.querySelector('.bootstrap-maxlength')).right === '10px', 'maxlength has expected right style'); 39 | }); 40 | 41 | QUnit.test('css bottom placement from object placement option', function (assert) { 42 | maxlengthInput.focus(); 43 | assert.ok(window.getComputedStyle(document.querySelector('.bootstrap-maxlength')).bottom === '7px', 'maxlength has expected bottom style'); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/optionsTests/twoCharLinebreakTests.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 'use strict'; 3 | 4 | var maxlengthInput; 5 | 6 | QUnit.module('textarea', { 7 | beforeEach: function () { 8 | maxlengthInput = $('') 9 | .appendTo('#qunit-fixture'); 10 | 11 | maxlengthInput.maxlength({ twoCharLinebreak: false }); 12 | }, 13 | afterEach: function () { 14 | $('.bootstrap-maxlength').remove(); 15 | $('#qunit-fixture').empty(); 16 | } 17 | }); 18 | 19 | QUnit.test('Newlines are not counted twice', function (assert) { 20 | maxlengthInput.val('t\r\nt'); 21 | 22 | maxlengthInput.maxlength({ twoCharLinebreak: false }); 23 | maxlengthInput.focus(); 24 | 25 | assert.ok($('.bootstrap-maxlength').html() === '3 / 10', 'Current length is: ' + $('.bootstrap-maxlength').html() + '. Expected 3 / 10.'); 26 | 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /test/qunit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bootstap Maxlength Tests 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | before_script: 5 | - npm install --------------------------------------------------------------------------------