diff --git a/.eslintrc.js b/.eslintrc.js index 571093b..a3693d4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,11 +2,10 @@ module.exports = { root: true, extends: ["plugin:@foretagsplatsen/main"], parserOptions: { - ecmaVersion: 6, - sourceType: "module" + ecmaVersion: 2022, + sourceType: "module", }, rules: { - "quotes": ["error", "double"], "import/no-unused-modules": [ "error", { @@ -19,9 +18,9 @@ module.exports = { "**/.eslintrc.js", "webpack*", "src/router/optionalParameterSegment.js", - "src/router/staticSegment.js" + "src/router/staticSegment.js", ], }, - ] - } + ], + }, }; diff --git a/package.json b/package.json index 90a7deb..b712b9f 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "test": "jasmine-browser-runner runSpecs --config=jasmine-browser.json" }, "devDependencies": { - "@foretagsplatsen/eslint-plugin": "^3.0.0", + "@foretagsplatsen/eslint-plugin": "^4.0.1", "eslint": "^8.55.0", "jasmine": "^5.1.0", "jasmine-browser-runner": "^2.3.0", diff --git a/src/Widget2.js b/src/Widget2.js index 329b77a..82bbbca 100644 --- a/src/Widget2.js +++ b/src/Widget2.js @@ -1,9 +1,9 @@ import router from "./router.js"; -import {eventCategory} from "yaem"; +import { eventCategory } from "yaem"; import htmlCanvas from "./htmlCanvas.js"; import jQuery from "jquery"; -import {getCurrentWidget, withCurrentWidget} from "./currentWidget.js"; -import {newId} from "./idGenerator.js"; +import { getCurrentWidget, withCurrentWidget } from "./currentWidget.js"; +import { newId } from "./idGenerator.js"; /** * Base for all widgets. A widget can keep state in variables, contain logic and @@ -43,7 +43,7 @@ import {newId} from "./idGenerator.js"; * be generated and assigned. */ export default class Widget2 { - constructor({id} = {}) { + constructor({ id } = {}) { this._id = id || newId(); // When within an update transaction, do not update the widget @@ -90,14 +90,12 @@ export default class Widget2 { * of `_initializeSubwidgets()`). In particular, don't override * `constructor()`. */ - _initialize(spec) { - } + _initialize(spec) {} /** * Hook evaluated at the end of initialization. */ - _initializeSubwidgets(spec) { - } + _initializeSubwidgets(spec) {} // // Public @@ -262,7 +260,7 @@ export default class Widget2 { _createEvents() { let names = Array.prototype.slice.apply(arguments); - names.forEach(name => this._createEvent(name)); + names.forEach((name) => this._createEvent(name)); } // @@ -282,8 +280,7 @@ export default class Widget2 { /** * Widget specific dispose. */ - _dispose() { - } + _dispose() {} // // Render @@ -380,27 +377,23 @@ export default class Widget2 { * Hook evaluated before the widget is attached (or reattached due * to an update of rendering) to the DOM. */ - _willAttach() { - } + _willAttach() {} /** * Hook evaluated each time the widget is attached (or * reattached due to an update of rendering) to the DOM. */ - _didAttach() { - } + _didAttach() {} /** * Hook evaluated when a widget is detached from the DOM. */ - _willDetach() { - } + _willDetach() {} /** * Hook evaluated before widget update. */ - _willUpdate() { - } + _willUpdate() {} /** * Re-renders the widget and replace it in the DOM diff --git a/src/htmlCanvas.js b/src/htmlCanvas.js index a2f33c0..1372795 100644 --- a/src/htmlCanvas.js +++ b/src/htmlCanvas.js @@ -9,7 +9,8 @@ import classNames from "classnames"; /** @typedef {({}|string|renderer|widget|htmlTagBrush|*)} renderable */ // Supported HTML 'tags' -var tags = ("a abbr acronym address area article aside audio b bdi bdo big " + +var tags = ( + "a abbr acronym address area article aside audio b bdi bdo big " + "blockquote body br button canvas caption cite code col colgroup command " + "datalist dd del details dfn div dl dt em embed fieldset figcaption figure " + "footer form frame frameset h1 h2 h3 h4 h5 h6 hr head header hgroup html i " + @@ -17,9 +18,10 @@ var tags = ("a abbr acronym address area article aside audio b bdi bdo big " + "nav noscript object ol optgroup option output p param pre progress q rp rt" + "ruby samp script section select small source span strong style sub summary" + "sup table tbody td textarea tfoot th thead time title tr track tt ul var" + - "video wbr").split(" "); + "video wbr" +).split(" "); -var svgTags = ("svg circle path polygon rect text").split(" "); +var svgTags = "svg circle path polygon rect text".split(" "); // Supported HTML attributes var attributes = "href for id media rel src style title type".split(" "); @@ -27,10 +29,12 @@ var attributes = "href for id media rel src style title type".split(" "); var omitSymbol = {}; // Supported HTML events -var events = ("blur focus focusin focusout load resize scroll unload " + +var events = ( + "blur focus focusin focusout load resize scroll unload " + "click dblclick mousedown mouseup mousemove mouseover " + "mouseout mouseenter mouseleave change input select submit " + - "keydown keypress keyup error dragstart dragenter dragover dragleave drop dragend").split(" "); + "keydown keypress keyup error dragstart dragenter dragover dragleave drop dragend" +).split(" "); function HtmlCanvasConstructor(rootElement) { /** @@ -48,17 +52,17 @@ function HtmlCanvasConstructor(rootElement) { * @param {string} tagName Type of element (supported by document.createElement) * @param {renderable[]} [children] Renderable objects to append as children of brush. */ -HtmlCanvasConstructor.prototype.tag = function(tagName, children) { +HtmlCanvasConstructor.prototype.tag = function (tagName, children) { var tagBrush = htmlTagBrush({ tag: tagName, children: children }); this.root.appendBrush(tagBrush); return tagBrush; }; -HtmlCanvasConstructor.prototype.svgTag = function(tagName, children) { +HtmlCanvasConstructor.prototype.svgTag = function (tagName, children) { var tagBrush = htmlTagBrush({ tag: tagName, namespaceURI: "http://www.w3.org/2000/svg", - children: children + children: children, }); this.root.appendBrush(tagBrush); return tagBrush; @@ -72,8 +76,8 @@ HtmlCanvasConstructor.prototype.svgTag = function(tagName, children) { * html.strong("Important stuff"); * html.span(html.strong(userName), " signed in.") */ -tags.forEach(function(tagName) { - HtmlCanvasConstructor.prototype[tagName] = function() { +tags.forEach(function (tagName) { + HtmlCanvasConstructor.prototype[tagName] = function () { var args = Array.prototype.slice.call(arguments); return this.tag(tagName, args); }; @@ -82,8 +86,8 @@ tags.forEach(function(tagName) { /** * Tags builders for each supported SVG tag type. */ -svgTags.forEach(function(tagName) { - HtmlCanvasConstructor.prototype[tagName] = function() { +svgTags.forEach(function (tagName) { + HtmlCanvasConstructor.prototype[tagName] = function () { var args = Array.prototype.slice.call(arguments); return this.svgTag(tagName, args); }; @@ -95,7 +99,7 @@ svgTags.forEach(function(tagName) { * * @returns {{}} */ -HtmlCanvasConstructor.prototype.omit = function() { +HtmlCanvasConstructor.prototype.omit = function () { return omitSymbol; }; @@ -104,7 +108,7 @@ HtmlCanvasConstructor.prototype.omit = function() { * * @param anObject */ -HtmlCanvasConstructor.prototype.render = function() { +HtmlCanvasConstructor.prototype.render = function () { var args = Array.prototype.slice.call(arguments); this.root.render(args); }; @@ -112,7 +116,7 @@ HtmlCanvasConstructor.prototype.render = function() { /** * Append an unescaped HTML string to the root brush */ -HtmlCanvasConstructor.prototype.raw = function(htmlString) { +HtmlCanvasConstructor.prototype.raw = function (htmlString) { this.root.raw(htmlString); }; @@ -120,7 +124,7 @@ HtmlCanvasConstructor.prototype.raw = function(htmlString) { * Append an unescaped string replacing all spaces by * non-breaking spaces */ -HtmlCanvasConstructor.prototype.renderNonBreaking = function(htmlString) { +HtmlCanvasConstructor.prototype.renderNonBreaking = function (htmlString) { this.raw(htmlString.replace(/\s/g, " ")); }; @@ -172,9 +176,9 @@ function TagBrushConstructor(spec) { * * @type {HTMLElement} */ - this.element = spec.tag ? - this.createElement(spec.tag, spec.namespaceURI) : - this.getElement(spec.element); + this.element = spec.tag + ? this.createElement(spec.tag, spec.namespaceURI) + : this.getElement(spec.element); if (!this.element) { throw new Error("htmlTagBrush requires an element"); } @@ -198,7 +202,7 @@ var elementCache = {}; * @param {string} tagName * @returns {Element} */ -TagBrushConstructor.prototype.createElement = function(tagName, namespaceURI) { +TagBrushConstructor.prototype.createElement = function (tagName, namespaceURI) { if (namespaceURI) { return document.createElementNS(namespaceURI, tagName); } @@ -222,7 +226,7 @@ TagBrushConstructor.prototype.createElement = function(tagName, namespaceURI) { * * @param {renderable|renderable[]|{}} object */ -TagBrushConstructor.prototype.append = function(object) { +TagBrushConstructor.prototype.append = function (object) { if (object.appendToBrush) { object.appendToBrush(this); return; @@ -237,21 +241,21 @@ TagBrushConstructor.prototype.append = function(object) { throw new Error("Unsupported data type"); }; -omitSymbol.appendToBrush = function(brush) {}; +omitSymbol.appendToBrush = function (brush) {}; -String.prototype.appendToBrush = function(brush) { +String.prototype.appendToBrush = function (brush) { brush.appendString(this); }; -Function.prototype.appendToBrush = function(brush) { +Function.prototype.appendToBrush = function (brush) { brush.appendFunction(this); }; -Number.prototype.appendToBrush = function(brush) { +Number.prototype.appendToBrush = function (brush) { this.toString().appendToBrush(brush); }; -Array.prototype.appendToBrush = function(brush) { +Array.prototype.appendToBrush = function (brush) { var length = this.length; for (var i = length - 1; i >= 0; i--) { brush.append(this[length - i - 1]); @@ -264,7 +268,7 @@ Array.prototype.appendToBrush = function(brush) { * * @param {string|HTMLElement} child */ -TagBrushConstructor.prototype.appendChild = function(child) { +TagBrushConstructor.prototype.appendChild = function (child) { if (this.element.canHaveChildren !== false) { this.element.appendChild(child); } else { @@ -277,7 +281,7 @@ TagBrushConstructor.prototype.appendChild = function(child) { * * @param {htmlTagBrush} aTagBrush */ -TagBrushConstructor.prototype.appendBrush = function(aTagBrush) { +TagBrushConstructor.prototype.appendBrush = function (aTagBrush) { this.appendChild(aTagBrush.element); }; @@ -286,7 +290,7 @@ TagBrushConstructor.prototype.appendBrush = function(aTagBrush) { * * @param {string} string */ -TagBrushConstructor.prototype.appendString = function(string) { +TagBrushConstructor.prototype.appendString = function (string) { jQuery(this.element).append(document.createTextNode(string)); }; @@ -295,7 +299,7 @@ TagBrushConstructor.prototype.appendString = function(string) { * * @param {renderer} fn */ -TagBrushConstructor.prototype.appendFunction = function(fn) { +TagBrushConstructor.prototype.appendFunction = function (fn) { fn(new HtmlCanvasConstructor(this)); }; @@ -305,8 +309,7 @@ TagBrushConstructor.prototype.appendFunction = function(fn) { * @param {string|jQuery|HTMLElement|widget|htmlTagBrush} [object] * @returns {HTMLElement} */ -TagBrushConstructor.prototype.getElement = function(object) { - +TagBrushConstructor.prototype.getElement = function (object) { // Create a fragment if no object if (object === undefined || object === null) { return document.createDocumentFragment(); @@ -339,7 +342,7 @@ TagBrushConstructor.prototype.getElement = function(object) { * @param {renderable[]} arguments Any renderable objects * @returns {htmlTagBrush} */ -TagBrushConstructor.prototype.render = function() { +TagBrushConstructor.prototype.render = function () { var args = Array.prototype.slice.call(arguments); for (var i = 0; i < args.length; i++) { this.append(args[i]); @@ -353,7 +356,7 @@ TagBrushConstructor.prototype.render = function() { * * @param {htmlTagBrush} aTagBrush */ -TagBrushConstructor.prototype.appendToBrush = function(aTagBrush) { +TagBrushConstructor.prototype.appendToBrush = function (aTagBrush) { aTagBrush.appendBrush(this); }; @@ -362,7 +365,7 @@ TagBrushConstructor.prototype.appendToBrush = function(aTagBrush) { * * @param {string} htmlContents */ -TagBrushConstructor.prototype.html = function(htmlContents) { +TagBrushConstructor.prototype.html = function (htmlContents) { this.asJQuery().html(htmlContents); return this; }; @@ -372,7 +375,7 @@ TagBrushConstructor.prototype.html = function(htmlContents) { * * @param {string} htmlContents */ -TagBrushConstructor.prototype.raw = function(htmlContents) { +TagBrushConstructor.prototype.raw = function (htmlContents) { this.asJQuery().append(htmlContents); return this; }; @@ -381,7 +384,7 @@ TagBrushConstructor.prototype.raw = function(htmlContents) { * Append an unescaped string replacing all spaces by * non-breaking spaces */ -TagBrushConstructor.prototype.renderNonBreaking = function(htmlString) { +TagBrushConstructor.prototype.renderNonBreaking = function (htmlString) { this.raw(htmlString.replace(/\s/g, " ")); }; @@ -397,7 +400,7 @@ TagBrushConstructor.prototype.renderNonBreaking = function(htmlString) { * @param {function} callback A function to execute each time the event is triggered. * @returns {{}} */ -TagBrushConstructor.prototype.on = function(eventType, callback) { +TagBrushConstructor.prototype.on = function (eventType, callback) { this.asJQuery().bind(eventType, callback); return this; }; @@ -409,8 +412,8 @@ TagBrushConstructor.prototype.on = function(eventType, callback) { * aBrush.click(function() { .. }); * aBrush.blur(function() { .. }); */ -events.forEach(function(eventType) { - TagBrushConstructor.prototype[eventType] = function(callback) { +events.forEach(function (eventType) { + TagBrushConstructor.prototype[eventType] = function (callback) { return this.on(eventType, callback); }; }); @@ -421,7 +424,7 @@ events.forEach(function(eventType) { * @param value * @returns {{}} */ -TagBrushConstructor.prototype.setAttribute = function(key, value) { +TagBrushConstructor.prototype.setAttribute = function (key, value) { // Omit attribute if value is omit if (value === omitSymbol) { return this; @@ -439,8 +442,8 @@ TagBrushConstructor.prototype.setAttribute = function(key, value) { * aBrush.src("javascript:0"); * aBrush.href("#"); */ -attributes.forEach(function(attributeName) { - TagBrushConstructor.prototype[attributeName] = function(value) { +attributes.forEach(function (attributeName) { + TagBrushConstructor.prototype[attributeName] = function (value) { return this.setAttribute(attributeName, value); }; }); @@ -456,11 +459,10 @@ attributes.forEach(function(attributeName) { * @param {string} value * @returns {{}} */ -TagBrushConstructor.prototype.css = function(key, value) { +TagBrushConstructor.prototype.css = function (key, value) { if (typeof key === "string") { this.asJQuery().css(key, value); - } - else { + } else { this.asJQuery().css(key); // otherwise assume key is a map (object literal) } @@ -476,7 +478,7 @@ TagBrushConstructor.prototype.css = function(key, value) { * @param object * @returns {{}} */ -TagBrushConstructor.prototype.attr = function(object) { +TagBrushConstructor.prototype.attr = function (object) { for (var key in object) { if (Object.prototype.hasOwnProperty.call(object, key)) { this.addAttribute(key, object[key]); @@ -485,7 +487,7 @@ TagBrushConstructor.prototype.attr = function(object) { return this; }; -TagBrushConstructor.prototype.addAttribute = function(key, value) { +TagBrushConstructor.prototype.addAttribute = function (key, value) { if (!value) { return; } @@ -498,9 +500,7 @@ TagBrushConstructor.prototype.addAttribute = function(key, value) { // Attach functions if (typeof value === "function") { this.on(key, value); - } - - else if (key === "klass" || key === "class") { + } else if (key === "klass" || key === "class") { this.element.className = classNames(value); } else { this.setAttribute(key, value); @@ -514,7 +514,7 @@ TagBrushConstructor.prototype.addAttribute = function(key, value) { * `classNames` library * @returns {htmlTagBrush} */ -TagBrushConstructor.prototype.addClass = function(className) { +TagBrushConstructor.prototype.addClass = function (className) { this.asJQuery().addClass(classNames(className)); return this; }; @@ -526,7 +526,7 @@ TagBrushConstructor.prototype.addClass = function(className) { * `classNames` library * @returns {htmlTagBrush} */ -TagBrushConstructor.prototype.removeClass = function(className) { +TagBrushConstructor.prototype.removeClass = function (className) { this.asJQuery().removeClass(classNames(className)); return this; }; @@ -535,7 +535,7 @@ TagBrushConstructor.prototype.removeClass = function(className) { * Returns jQuery that match element. * @returns {jQuery} */ -TagBrushConstructor.prototype.asJQuery = function() { +TagBrushConstructor.prototype.asJQuery = function () { return jQuery(this.element); }; @@ -554,7 +554,6 @@ TagBrushConstructor.prototype.asJQuery = function() { * @returns {htmlTagBrush} */ function htmlTagBrush(spec) { - /** @typedef {{}} htmlTagBrush */ return new TagBrushConstructor(spec); } diff --git a/src/router.js b/src/router.js index 98bd27e..607bdf1 100644 --- a/src/router.js +++ b/src/router.js @@ -8,10 +8,10 @@ export default { url: url, route: route, router: router, - getRouter: function() { + getRouter: function () { return routerSingleton; }, - setRouter: function(newRouter) { + setRouter: function (newRouter) { routerSingleton = newRouter; - } + }, }; diff --git a/src/router/abstractSegment.js b/src/router/abstractSegment.js index 72cb2c2..36c62f2 100644 --- a/src/router/abstractSegment.js +++ b/src/router/abstractSegment.js @@ -10,9 +10,8 @@ import { object } from "klassified"; * @param my * @returns {abstractSegment} */ -const abstractSegment = object.subclass(function(that, my) { - - my.initialize = function(spec) { +const abstractSegment = object.subclass(function (that, my) { + my.initialize = function (spec) { my.super(spec); my.segmentString = spec.segmentString; my.options = spec.options || {}; @@ -28,7 +27,7 @@ const abstractSegment = object.subclass(function(that, my) { * @param {string} urlSegment * @returns {boolean} */ - that.match = function(urlSegment) { + that.match = function (urlSegment) { return false; }; @@ -38,7 +37,7 @@ const abstractSegment = object.subclass(function(that, my) { * @param {string} urlSegment * @returns {*} */ - that.getValue = function(urlSegment) { + that.getValue = function (urlSegment) { return my.segmentString; }; @@ -47,7 +46,7 @@ const abstractSegment = object.subclass(function(that, my) { * * @returns {boolean} */ - that.isParameter = function() { + that.isParameter = function () { return false; }; @@ -58,7 +57,7 @@ const abstractSegment = object.subclass(function(that, my) { * * @returns {boolean} */ - that.isOptional = function() { + that.isOptional = function () { return false; }; @@ -66,13 +65,13 @@ const abstractSegment = object.subclass(function(that, my) { * String representation for segment that can be used eg. when debugging. * @returns {*} */ - that.toString = function() { + that.toString = function () { return my.segmentString; }; }); -abstractSegment.class(function(that) { - that.match = function(segmentString) { +abstractSegment.class(function (that) { + that.match = function (segmentString) { return false; }; }); diff --git a/src/router/hashLocation.js b/src/router/hashLocation.js index d10fb54..7a56ad7 100644 --- a/src/router/hashLocation.js +++ b/src/router/hashLocation.js @@ -1,5 +1,5 @@ import jQuery from "jquery"; -import {eventCategory} from "yaem"; +import { eventCategory } from "yaem"; import url from "./url.js"; import { object } from "klassified"; @@ -30,8 +30,7 @@ var pollInterval = 25; * @param [my] * @returns {hashLocation} */ -const hashLocation = object.subclass(function(that, my) { - +const hashLocation = object.subclass(function (that, my) { var pollTimerId = null; my.currentHash = undefined; // last hash fragment @@ -56,7 +55,7 @@ const hashLocation = object.subclass(function(that, my) { * * @param {url|string} aUrl */ - that.setUrl = function(aUrl) { + that.setUrl = function (aUrl) { var aHash = urlToHash(aUrl); setWindowHash(aHash); setCurrentHash(aHash); @@ -67,7 +66,7 @@ const hashLocation = object.subclass(function(that, my) { * * @returns {url} */ - that.getUrl = function() { + that.getUrl = function () { return urlFromHash(getWindowHash()); }; @@ -77,7 +76,7 @@ const hashLocation = object.subclass(function(that, my) { * @param {string|url} aUrl * @returns {string} */ - that.linkToUrl = function(aUrl) { + that.linkToUrl = function (aUrl) { return urlToHash(aUrl); }; @@ -88,7 +87,7 @@ const hashLocation = object.subclass(function(that, my) { * @param {string|url} fallbackUrl * @returns {string} URL */ - that.back = function(fallbackUrl) { + that.back = function (fallbackUrl) { if (!that.isHistoryEmpty()) { my.history.pop(); setWindowHash(my.history.pop()); @@ -102,7 +101,7 @@ const hashLocation = object.subclass(function(that, my) { /** * Return `true` if the history is empty. */ - that.isHistoryEmpty = function() { + that.isHistoryEmpty = function () { return my.history.length <= 1; }; @@ -110,7 +109,7 @@ const hashLocation = object.subclass(function(that, my) { * Start listening for URL changes. If `hashchange` is supported by the browser * it will be used, otherwise a timer will poll for changes. */ - that.start = function() { + that.start = function () { that.stop(); my.currentHash = getWindowHash(); @@ -126,7 +125,7 @@ const hashLocation = object.subclass(function(that, my) { /** * Stop listening for location changes and unregister all bindings. */ - that.stop = function() { + that.stop = function () { if (pollTimerId) { clearInterval(pollTimerId); pollTimerId = null; @@ -148,14 +147,14 @@ const hashLocation = object.subclass(function(that, my) { function urlToHash(aUrl) { if (typeof aUrl === "string") { - aUrl = url({rawUrl: aUrl}); + aUrl = url({ rawUrl: aUrl }); } return "#!/" + aUrl.toString(); } function urlFromHash(aHash) { // Remove hash/hash-bang and any leading / - return url({rawUrl: aHash.replace(/^#!?[/]?/, "")}); + return url({ rawUrl: aHash.replace(/^#!?[/]?/, "") }); } function setCurrentHash(newHash) { diff --git a/src/router/optionalParameterSegment.js b/src/router/optionalParameterSegment.js index e0402aa..854ec97 100644 --- a/src/router/optionalParameterSegment.js +++ b/src/router/optionalParameterSegment.js @@ -7,9 +7,8 @@ import parameterSegment from "./parameterSegment.js"; * @param my * @returns {parameter} */ -const optionalParameterSegment = parameterSegment.subclass(function(that, my) { - - my.initialize = function(spec) { +const optionalParameterSegment = parameterSegment.subclass(function (that, my) { + my.initialize = function (spec) { my.super(spec); my.defaultValue = my.options.defaults && my.options.defaults[my.name]; }; @@ -24,17 +23,15 @@ const optionalParameterSegment = parameterSegment.subclass(function(that, my) { * @param {string} urlSegment * @returns {*} */ - that.getValue = function(urlSegment) { - return urlSegment === undefined ? - my.defaultValue : - urlSegment; + that.getValue = function (urlSegment) { + return urlSegment === undefined ? my.defaultValue : urlSegment; }; /** * Always true. * @returns {boolean} */ - that.isOptional = function() { + that.isOptional = function () { return true; }; @@ -42,18 +39,18 @@ const optionalParameterSegment = parameterSegment.subclass(function(that, my) { * String representation for segment that can be used eg. when debugging. * @returns {*} */ - that.toString = function() { + that.toString = function () { return "optional(" + that.getName() + ")"; }; }); -optionalParameterSegment.class(function(that) { +optionalParameterSegment.class(function (that) { /** * Match segment strings with a leading `?`. * @param {string} segmentString * @returns {boolean} */ - that.match = function(segmentString) { + that.match = function (segmentString) { return segmentString.substr(0, 1) === "?"; }; }); diff --git a/src/router/parameterSegment.js b/src/router/parameterSegment.js index 1056104..984ebb9 100644 --- a/src/router/parameterSegment.js +++ b/src/router/parameterSegment.js @@ -15,17 +15,17 @@ function parameterValidator(constraint) { // Match against RegExp if (constraint instanceof RegExp) { var exp = new RegExp(constraint); - return function(urlSegment) { + return function (urlSegment) { return exp.test(urlSegment); }; } // Match valid options in an array if (Object.prototype.toString.call(constraint) === "[object Array]") { - var options = constraint.map(function(option) { + var options = constraint.map(function (option) { return option.toLowerCase(); }); - return function(urlSegment) { + return function (urlSegment) { var val = urlSegment.toLowerCase(); return options.indexOf(val) !== -1; }; @@ -40,13 +40,16 @@ function parameterValidator(constraint) { * @param [my] * @returns {parameterSegment} */ -const parameterSegment = abstractSegment.subclass(function(that, my) { - - my.initialize = function(spec) { +const parameterSegment = abstractSegment.subclass(function (that, my) { + my.initialize = function (spec) { my.super(spec); my.name = my.segmentString.substr(1); // strip of the leading # - my.constraints = (my.options.constraints && my.options.constraints[my.name] && - [my.options.constraints[my.name]]) || []; + my.constraints = + (my.options.constraints && + my.options.constraints[my.name] && [ + my.options.constraints[my.name], + ]) || + []; my.validators = my.constraints.map(parameterValidator).filter(Boolean); }; @@ -59,7 +62,7 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * * @returns {string} */ - that.getName = function() { + that.getName = function () { return my.name; }; @@ -69,7 +72,7 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * @param {string} urlSegment * @returns {*} */ - that.getValue = function(urlSegment) { + that.getValue = function (urlSegment) { return urlSegment; }; @@ -78,7 +81,7 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * * @returns {boolean} */ - that.isParameter = function() { + that.isParameter = function () { return true; }; @@ -88,7 +91,7 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * @param {string} urlSegment * @returns {boolean|*} */ - that.match = function(urlSegment) { + that.match = function (urlSegment) { return urlSegment !== undefined && that.validate(urlSegment); }; @@ -98,8 +101,8 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * @param {string} urlSegment * @returns {boolean} */ - that.validate = function(urlSegment) { - return my.validators.every(function(validator) { + that.validate = function (urlSegment) { + return my.validators.every(function (validator) { return validator(urlSegment); }); }; @@ -108,19 +111,18 @@ const parameterSegment = abstractSegment.subclass(function(that, my) { * String representation for segment that can be used eg. when debugging. * @returns {*} */ - that.toString = function() { + that.toString = function () { return "param(" + that.getName() + ")"; }; }); -parameterSegment.class(function(that) { - +parameterSegment.class(function (that) { /** * Match segment strings with a leading `#`. * @param {string} segmentString * @returns {boolean} */ - that.match = function(segmentString) { + that.match = function (segmentString) { return segmentString.substr(0, 1) === "#"; }; }); diff --git a/src/router/route.js b/src/router/route.js index d9a218e..82a95fa 100644 --- a/src/router/route.js +++ b/src/router/route.js @@ -1,5 +1,5 @@ import routeFactory from "./routeFactory.js"; -import {eventCategory} from "yaem"; +import { eventCategory } from "yaem"; import routeMatchResult from "./routeMatchResult.js"; import url from "./url.js"; import { object } from "klassified"; @@ -56,20 +56,20 @@ import "jquery"; * @param {{}} my * @returns {route} */ -const route = object.subclass(function(that, my) { - +const route = object.subclass(function (that, my) { var segments; var ignoreTrailingSegments; var optionalSequences; - my.initialize = function(spec) { + my.initialize = function (spec) { my.super(); // Build segments from pattern segments = routeFactory(spec.pattern, spec.options); // Route match URL if all route segments match // but URL still contain trailing segments (default false) - ignoreTrailingSegments = (spec.options && spec.options.ignoreTrailingSegments) || false; + ignoreTrailingSegments = + (spec.options && spec.options.ignoreTrailingSegments) || false; // Array with all optional sequences, ie. all combinations // of optional parameters. Array must be ordered to match URL:s @@ -99,7 +99,7 @@ const route = object.subclass(function(that, my) { * @param {url} url * @returns {routeMatchResult} */ - that.matchUrl = function(url) { + that.matchUrl = function (url) { var match = findMatch(url); if (!match) { return routeMatchResult.routeNoMatchResult; @@ -119,12 +119,12 @@ const route = object.subclass(function(that, my) { * * @returns {string} URL string */ - that.expand = function(params) { + that.expand = function (params) { params = params || {}; // Try to expand route into URL var urlSegments = []; - segments.forEach(function(routeSegment) { + segments.forEach(function (routeSegment) { var urlSegment; if (routeSegment.isParameter()) { // Use supplied value for parameters @@ -135,8 +135,7 @@ const route = object.subclass(function(that, my) { } // Skip if no match and optional - if (urlSegment === undefined && - routeSegment.isOptional()) { + if (urlSegment === undefined && routeSegment.isOptional()) { return; } @@ -150,7 +149,7 @@ const route = object.subclass(function(that, my) { var query = {}; - Object.keys(params).forEach(function(param) { + Object.keys(params).forEach(function (param) { if (!that.hasParameter(param)) { query[param] = params[param]; // Handle array param values @@ -169,8 +168,8 @@ const route = object.subclass(function(that, my) { * @param {string} name * @returns {boolean} */ - that.hasParameter = function(name) { - return segments.some(function(segment) { + that.hasParameter = function (name) { + return segments.some(function (segment) { return segment.isParameter() && segment.getName() === name; }); }; @@ -180,7 +179,7 @@ const route = object.subclass(function(that, my) { * * @returns {string} */ - that.toString = function() { + that.toString = function () { return "route(" + segments.join("/") + ")"; }; @@ -204,7 +203,7 @@ const route = object.subclass(function(that, my) { } // All routeSegments much match corresponding URL segment - return sequence.every(function(routeSegment, index) { + return sequence.every(function (routeSegment, index) { var urlSegment = urlSegments[index]; return urlSegment !== undefined && routeSegment.match(urlSegment); }); @@ -226,7 +225,11 @@ const route = object.subclass(function(that, my) { // then optional sequences var sequenceIndex; - for (sequenceIndex = 0; sequenceIndex < optionalSequences.length; sequenceIndex++) { + for ( + sequenceIndex = 0; + sequenceIndex < optionalSequences.length; + sequenceIndex++ + ) { if (isMatch(urlSegments, optionalSequences[sequenceIndex])) { return optionalSequences[sequenceIndex]; } @@ -241,26 +244,30 @@ const route = object.subclass(function(that, my) { function ensureOptionalSequences() { // Find positions for optionals var optionalPositions = []; - segments.forEach(function(segment, index) { + segments.forEach(function (segment, index) { if (segment.isOptional()) { optionalPositions.push(index); } }); if (optionalPositions.length > 15) { - throw new Error("Too many optional arguments. \"" + optionalPositions.length + - "\" optionals would generate " + Math.pow(2, optionalPositions.length) + - " optional sequences."); + throw new Error( + 'Too many optional arguments. "' + + optionalPositions.length + + '" optionals would generate ' + + Math.pow(2, optionalPositions.length) + + " optional sequences.", + ); } // Generate possible sequences var possibleOptionalSequences = orderedSubsets(optionalPositions); - possibleOptionalSequences.forEach(function(sequence) { + possibleOptionalSequences.forEach(function (sequence) { // Clone segments array and remove optionals matching // indexes in index sequence var optionalSequence = segments.slice(); - sequence.forEach(function(optionalIndex, numRemoved) { + sequence.forEach(function (optionalIndex, numRemoved) { // Remove optional but take in to account that we have already // removed {numRemoved} from permutation. optionalSequence.splice(optionalIndex - numRemoved, 1); @@ -282,23 +289,26 @@ const route = object.subclass(function(that, my) { var urlSegments = url.getSegments(); var parameterValues = {}; - segments.forEach(function(routeSegment) { + segments.forEach(function (routeSegment) { if (!routeSegment.isParameter()) { return; } var matchedIndex = match.indexOf(routeSegment); if (matchedIndex >= 0) { - parameterValues[routeSegment.getName()] = routeSegment.getValue(urlSegments[matchedIndex]); + parameterValues[routeSegment.getName()] = routeSegment.getValue( + urlSegments[matchedIndex], + ); } else { - parameterValues[routeSegment.getName()] = routeSegment.getValue(); + parameterValues[routeSegment.getName()] = + routeSegment.getValue(); } }); return routeMatchResult({ route: that, url: url, - values: parameterValues + values: parameterValues, }); } }); diff --git a/src/router/routeFactory.js b/src/router/routeFactory.js index 8e2de30..dd93362 100644 --- a/src/router/routeFactory.js +++ b/src/router/routeFactory.js @@ -32,7 +32,7 @@ function routeFactory(pattern, options) { .map(Function.prototype.call, String.prototype.trim) .filter(Boolean); - var segmentArray = nonEmptySegmentStrings.map(function(segmentString) { + var segmentArray = nonEmptySegmentStrings.map(function (segmentString) { return segmentFactory(segmentString, options); }); @@ -57,7 +57,7 @@ function segmentFactory(segmentString, options) { if (segment.match(segmentString)) { return segment({ segmentString: segmentString, - options: options + options: options, }); } } diff --git a/src/router/routeMatchResult.js b/src/router/routeMatchResult.js index 566e000..c8d9912 100644 --- a/src/router/routeMatchResult.js +++ b/src/router/routeMatchResult.js @@ -10,15 +10,14 @@ import { object } from "klassified"; * * @returns {routeMatchResult} */ -const routeMatchResult = object.subclass(function(that, my) { - +const routeMatchResult = object.subclass(function (that, my) { var url; var route; var urlParameters; var routeParameters; var parameters; - my.initialize = function(spec) { + my.initialize = function (spec) { my.super(spec); url = spec.url; route = spec.route; @@ -37,7 +36,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {route} */ - that.getRoute = function() { + that.getRoute = function () { return route; }; @@ -46,7 +45,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {url} */ - that.getUrl = function() { + that.getUrl = function () { return url; }; @@ -55,7 +54,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {boolean} */ - that.isMatch = function() { + that.isMatch = function () { return true; }; @@ -64,7 +63,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {{}} */ - that.getRouteParameters = function() { + that.getRouteParameters = function () { return routeParameters; }; @@ -73,7 +72,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {{}} */ - that.getQueryParameters = function() { + that.getQueryParameters = function () { return url.getQuery(); }; @@ -82,7 +81,7 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {{}} */ - that.getParameters = function() { + that.getParameters = function () { return parameters; }; @@ -92,10 +91,12 @@ const routeMatchResult = object.subclass(function(that, my) { * * @returns {Array} */ - that.getActionArguments = function() { - var actionArguments = Object.keys(routeParameters).map(function(parameterName) { - return routeParameters[parameterName]; - }); + that.getActionArguments = function () { + var actionArguments = Object.keys(routeParameters).map( + function (parameterName) { + return routeParameters[parameterName]; + }, + ); actionArguments.push(url.getQuery()); return actionArguments; }; @@ -109,34 +110,42 @@ const routeMatchResult = object.subclass(function(that, my) { // Fill with route parameters for (var parameterName in routeParameters) { - if (Object.prototype.hasOwnProperty.call(routeParameters, parameterName)) { + if ( + Object.prototype.hasOwnProperty.call( + routeParameters, + parameterName, + ) + ) { allValues[parameterName] = routeParameters[parameterName]; } } // Fill with query parameters for (var queryParameterName in queryParameters) { - if (Object.prototype.hasOwnProperty.call(queryParameters, queryParameterName)) { - allValues[queryParameterName] = queryParameters[queryParameterName]; + if ( + Object.prototype.hasOwnProperty.call( + queryParameters, + queryParameterName, + ) + ) { + allValues[queryParameterName] = + queryParameters[queryParameterName]; } } return allValues; - } }); -routeMatchResult.class(function(that) { - +routeMatchResult.class(function (that) { /** * Result to use when match does not match url */ - that.routeNoMatchResult = (function() { - + that.routeNoMatchResult = (function () { /** @typedef {routeMatchResult} routeNoMatchResult */ var instance = that(); - instance.isMatch = function() { + instance.isMatch = function () { return false; }; diff --git a/src/router/router.js b/src/router/router.js index 9b296fe..10e5be2 100755 --- a/src/router/router.js +++ b/src/router/router.js @@ -1,4 +1,4 @@ -import {eventCategory} from "yaem"; +import { eventCategory } from "yaem"; import route from "./route.js"; import url from "./url.js"; import hashLocation from "./hashLocation.js"; @@ -33,9 +33,8 @@ function hashSingleton() { * * @returns {{}} */ -const router = object.subclass(function(that, my) { - - my.initialize = function(spec) { +const router = object.subclass(function (that, my) { + my.initialize = function (spec) { my.super(spec); my.location = spec.locationHandler || hashSingleton(); my.routeTable = []; @@ -43,7 +42,9 @@ const router = object.subclass(function(that, my) { my.defaultParameters = {}; // Listen for URL changes and resolve URL when changed - my.location.changed.register(function() { my.resolveUrl(); }); + my.location.changed.register(function () { + my.resolveUrl(); + }); }; // Events @@ -89,9 +90,9 @@ const router = object.subclass(function(that, my) { * * @param {url} [aUrl] A URL or current url as default */ - that.resolveUrl = function(aUrl) { + that.resolveUrl = function (aUrl) { if (typeof aUrl === "string") { - aUrl = url({rawUrl: aUrl}); + aUrl = url({ rawUrl: aUrl }); } my.resolveUrl(aUrl); @@ -143,16 +144,16 @@ const router = object.subclass(function(that, my) { * * @returns {route} */ - that.addRoute = function(routeSpec) { + that.addRoute = function (routeSpec) { routeSpec = routeSpec || {}; var newRoute = route({ pattern: routeSpec.pattern, - options: routeSpec + options: routeSpec, }); if (routeSpec.action) { - newRoute.matched.register(function(result) { + newRoute.matched.register(function (result) { routeSpec.action.apply(this, result.getActionArguments()); }); } @@ -173,7 +174,7 @@ const router = object.subclass(function(that, my) { * @param {function} predicate * @returns {route} Matched route or null if not matched */ - that.findRoute = function(predicate) { + that.findRoute = function (predicate) { var numRoutes = my.routeTable.length; for (var routeIndex = 0; routeIndex < numRoutes; routeIndex++) { var route = my.routeTable[routeIndex]; @@ -191,8 +192,8 @@ const router = object.subclass(function(that, my) { * @param {string} routeName * @returns {route} */ - that.getRouteByName = function(routeName) { - return that.findRoute(function(route) { + that.getRouteByName = function (routeName) { + return that.findRoute(function (route) { return route.name && route.name === routeName; }); }; @@ -202,7 +203,7 @@ const router = object.subclass(function(that, my) { * * @param route */ - that.removeRoute = function(route) { + that.removeRoute = function (route) { var index = my.routeTable.indexOf(route); if (index === -1) { throw new Error("Route not in route table"); @@ -214,7 +215,7 @@ const router = object.subclass(function(that, my) { /** * Removes all routes from routing table. */ - that.clear = function() { + that.clear = function () { my.routeTable = []; my.lastMatch = undefined; }; @@ -227,13 +228,13 @@ const router = object.subclass(function(that, my) { * * @returns {route} */ - that.pipeRoute = function(routeSpec, router) { + that.pipeRoute = function (routeSpec, router) { if (!routeSpec || !routeSpec.pattern) { throw new Error("Route pattern required"); } var aRoute = that.addRoute(routeSpec); - aRoute.matched.register(function(result) { + aRoute.matched.register(function (result) { router.resolveUrl(result.getUrl()); }); @@ -246,8 +247,8 @@ const router = object.subclass(function(that, my) { * @param {router} router * @returns {route} */ - that.pipeNotFound = function(router) { - return that.routeNotFound.register(function(aRawUrl) { + that.pipeNotFound = function (router) { + return that.routeNotFound.register(function (aRawUrl) { router.resolveUrl(aRawUrl); }); }; @@ -256,7 +257,7 @@ const router = object.subclass(function(that, my) { * Returns the current URL * @returns {url} */ - that.getUrl = function() { + that.getUrl = function () { return my.location.getUrl(); }; @@ -277,14 +278,16 @@ const router = object.subclass(function(that, my) { * * @returns {string} */ - that.linkTo = function(routeName, parameters, includeCurrentParameters) { + that.linkTo = function (routeName, parameters, includeCurrentParameters) { var route = that.getRouteByName(routeName); if (route) { - return my.location.linkToUrl(that.expand({ - routeName: route.name, - parameters: parameters, - excludeCurrentParameters: !includeCurrentParameters - })); + return my.location.linkToUrl( + that.expand({ + routeName: route.name, + parameters: parameters, + excludeCurrentParameters: !includeCurrentParameters, + }), + ); } // fallback to path (eg. /user/john) if route is not defined @@ -302,7 +305,7 @@ const router = object.subclass(function(that, my) { * @param {{}} query * @returns {string} */ - that.linkToPath = function(path, query) { + that.linkToPath = function (path, query) { return that.linkToUrl(url.build(path, query)); }; @@ -312,7 +315,7 @@ const router = object.subclass(function(that, my) { * @param {url} aUrl * @returns {string} */ - that.linkToUrl = function(aUrl) { + that.linkToUrl = function (aUrl) { return my.location.linkToUrl(aUrl); }; @@ -333,14 +336,20 @@ const router = object.subclass(function(that, my) { * * @returns {string} */ - that.redirectTo = function(routeName, parameters, includeCurrentParameters) { + that.redirectTo = function ( + routeName, + parameters, + includeCurrentParameters, + ) { var route = that.getRouteByName(routeName); if (route) { - return my.location.setUrl(that.expand({ - routeName: route.name, - parameters: parameters, - excludeCurrentParameters: !includeCurrentParameters - })); + return my.location.setUrl( + that.expand({ + routeName: route.name, + parameters: parameters, + excludeCurrentParameters: !includeCurrentParameters, + }), + ); } return that.redirectToPath(routeName, parameters); @@ -357,7 +366,7 @@ const router = object.subclass(function(that, my) { * @param {{}} query * @returns {string} */ - that.redirectToPath = function(path, query) { + that.redirectToPath = function (path, query) { return that.redirectToUrl(url.build(path, query)); }; @@ -367,7 +376,7 @@ const router = object.subclass(function(that, my) { * @param {url} aUrl * @returns {string} */ - that.redirectToUrl = function(aUrl) { + that.redirectToUrl = function (aUrl) { return my.location.setUrl(aUrl); }; @@ -377,7 +386,7 @@ const router = object.subclass(function(that, my) { * @param {string} path * @return {undefined} */ - that.redirectToLocationPath = function(path) { + that.redirectToLocationPath = function (path) { window.location.href = path.startsWith("/") ? path : "/" + path; }; @@ -386,14 +395,14 @@ const router = object.subclass(function(that, my) { * * @param {string} newLocation - The new URL. */ - that.setLocation = function(newLocation) { + that.setLocation = function (newLocation) { window.location = newLocation; }; /** * Reload the current URL, just like the "refresh" button. */ - that.reloadPage = function() { + that.reloadPage = function () { window.location.reload(); }; @@ -411,10 +420,11 @@ const router = object.subclass(function(that, my) { * * @returns {url} */ - that.expand = function(options) { + that.expand = function (options) { var routeName = options.routeName; var suppliedParameters = options.parameters || {}; - var excludeCurrentParameters = options.excludeCurrentParameters || false; + var excludeCurrentParameters = + options.excludeCurrentParameters || false; // Pick a template route var templateRoute; @@ -427,21 +437,24 @@ const router = object.subclass(function(that, my) { } // Merge current parameters with supplied parameters - var currentParameters = !excludeCurrentParameters ? that.getParameters() : {}; + var currentParameters = !excludeCurrentParameters + ? that.getParameters() + : {}; var allParameters = merge(currentParameters, suppliedParameters); // Fill with defaults if needed - Object.keys(my.defaultParameters).forEach(function(parameterName) { + Object.keys(my.defaultParameters).forEach(function (parameterName) { if (!(parameterName in allParameters)) { - allParameters[parameterName] = typeof my.defaultParameters[parameterName] === "function" ? - my.defaultParameters[parameterName]() : - my.defaultParameters[parameterName]; + allParameters[parameterName] = + typeof my.defaultParameters[parameterName] === "function" + ? my.defaultParameters[parameterName]() + : my.defaultParameters[parameterName]; } }); // Expand template route and construct URL var aRawUrl = templateRoute.expand(allParameters); - return url({rawUrl: aRawUrl}); + return url({ rawUrl: aRawUrl }); }; /** @@ -452,11 +465,13 @@ const router = object.subclass(function(that, my) { * * @returns {string} */ - that.linkToParameters = function(parameters, excludeCurrentParameters) { - return my.location.linkToUrl(that.expand({ - parameters: parameters, - excludeCurrentParameters: excludeCurrentParameters - })); + that.linkToParameters = function (parameters, excludeCurrentParameters) { + return my.location.linkToUrl( + that.expand({ + parameters: parameters, + excludeCurrentParameters: excludeCurrentParameters, + }), + ); }; /** @@ -467,11 +482,13 @@ const router = object.subclass(function(that, my) { * * @returns {string} */ - that.setParameters = function(parameters, excludeCurrentParameters) { - that.redirectToUrl(that.expand({ - parameters: parameters, - excludeCurrentParameters: excludeCurrentParameters - })); + that.setParameters = function (parameters, excludeCurrentParameters) { + that.redirectToUrl( + that.expand({ + parameters: parameters, + excludeCurrentParameters: excludeCurrentParameters, + }), + ); }; /** @@ -480,7 +497,7 @@ const router = object.subclass(function(that, my) { * * @returns {{}} Parameter values with parameter names as keys */ - that.getParameters = function() { + that.getParameters = function () { if (!my.lastMatch) { return my.location.getUrl().getQuery(); } @@ -494,12 +511,12 @@ const router = object.subclass(function(that, my) { * @param {string} parameterName * @returns {*} */ - that.getParameter = function(parameterName) { + that.getParameter = function (parameterName) { var parameters = that.getParameters(); return parameters[parameterName]; }; - that.setDefaultParameter = function(parameterName, value) { + that.setDefaultParameter = function (parameterName, value) { my.defaultParameters[parameterName] = value; }; @@ -510,14 +527,14 @@ const router = object.subclass(function(that, my) { * @param {string|url} aFallbackUrl * @returns {string} URL */ - that.back = function(aFallbackUrl) { + that.back = function (aFallbackUrl) { return my.location.back(aFallbackUrl); }; /** * Return `true` if the history is empty */ - that.isHistoryEmpty = function() { + that.isHistoryEmpty = function () { return my.location.isHistoryEmpty(); }; @@ -525,7 +542,7 @@ const router = object.subclass(function(that, my) { * Start listening for location changes and automatically * resolve new URLs (including the current) */ - that.start = function() { + that.start = function () { my.location.start(); my.resolveUrl(); // resolve current url }; @@ -533,7 +550,7 @@ const router = object.subclass(function(that, my) { /** * Stop listening for location changes. */ - that.stop = function() { + that.stop = function () { my.location.stop(); }; @@ -550,21 +567,23 @@ const router = object.subclass(function(that, my) { * * @param {url} [aUrl] A URL or current url as default */ - my.resolveUrl = function(aUrl) { + my.resolveUrl = function (aUrl) { var currentUrl = aUrl === undefined ? my.location.getUrl() : aUrl; that.onResolveUrl.trigger(currentUrl); var numMatched = 0; - my.routeTable.some(function(candidateRoute) { + my.routeTable.some(function (candidateRoute) { var result = currentUrl.matchRoute(candidateRoute); if (result.isMatch()) { my.lastMatch = result; numMatched++; that.routeMatched.trigger(result); - if (candidateRoute.fallThrough === undefined || - candidateRoute.fallThrough === false) { + if ( + candidateRoute.fallThrough === undefined || + candidateRoute.fallThrough === false + ) { return true; } } @@ -583,14 +602,16 @@ const router = object.subclass(function(that, my) { * * @param {route} route */ - my.addRoute = function(route) { + my.addRoute = function (route) { var routeIndex = my.routeTable.length; if (route.priority !== undefined) { do { --routeIndex; - } while (my.routeTable[routeIndex] && + } while ( + my.routeTable[routeIndex] && (my.routeTable[routeIndex].priority === undefined || - route.priority < my.routeTable[routeIndex].priority)); + route.priority < my.routeTable[routeIndex].priority) + ); routeIndex += 1; } my.routeTable.splice(routeIndex, 0, route); @@ -610,8 +631,8 @@ const router = object.subclass(function(that, my) { var objects = Array.prototype.slice.call(arguments); var target = {}; - objects.forEach(function(obj) { - Object.keys(obj).forEach(function(key) { + objects.forEach(function (obj) { + Object.keys(obj).forEach(function (key) { target[key] = obj[key]; }); }); diff --git a/src/router/staticSegment.js b/src/router/staticSegment.js index ccc4881..a09ff10 100644 --- a/src/router/staticSegment.js +++ b/src/router/staticSegment.js @@ -8,8 +8,7 @@ import abstractSegment from "./abstractSegment.js"; * @param [my] * @returns {segment} */ -const staticSegment = abstractSegment.subclass(function(that, my) { - +const staticSegment = abstractSegment.subclass(function (that, my) { /** * Static segment match if URL and route segment * strings are identical. @@ -17,21 +16,20 @@ const staticSegment = abstractSegment.subclass(function(that, my) { * @param {string} urlSegment * @returns {boolean} */ - that.match = function(urlSegment) { + that.match = function (urlSegment) { return that.getValue() === urlSegment; }; return that; }); -staticSegment.class(function(that) { - +staticSegment.class(function (that) { /** * Match all but parameter segment strings * @param {string} segmentString * @returns {boolean} */ - that.match = function(segmentString) { + that.match = function (segmentString) { return ["#", "?"].indexOf(segmentString[0]) === -1; }; }); diff --git a/src/router/url.js b/src/router/url.js index 2baf304..b63a6f4 100644 --- a/src/router/url.js +++ b/src/router/url.js @@ -18,14 +18,13 @@ var urlSeparator = "/"; * @param {string} rawUrl * @returns {url} */ -const url = object.subclass(function(that, my) { - +const url = object.subclass(function (that, my) { var rawUrl; var path; var query; var segments; - my.initialize = function(spec) { + my.initialize = function (spec) { my.super(spec); rawUrl = spec.rawUrl || ""; path = parsePath(rawUrl); @@ -41,21 +40,27 @@ const url = object.subclass(function(that, my) { * URL path * @returns {string} */ - that.getPath = function() { return path; }; + that.getPath = function () { + return path; + }; /** * Key/Value pairs parsed from query * * @returns {{}} */ - that.getQuery = function() { return query; }; + that.getQuery = function () { + return query; + }; /** * Segments in path parsed by splitting `path` by `urlSeparator` * * @returns {string[]} */ - that.getSegments = function() { return segments; }; + that.getSegments = function () { + return segments; + }; /** * Answers true if the route is a match for the receiver @@ -63,7 +68,7 @@ const url = object.subclass(function(that, my) { * @param route * @returns {boolean} */ - that.matchRoute = function(route) { + that.matchRoute = function (route) { return route.matchUrl(that); }; @@ -71,7 +76,7 @@ const url = object.subclass(function(that, my) { * Returns `rawUrl` * @returns {string} */ - that.toString = function() { + that.toString = function () { return rawUrl; }; }); @@ -87,19 +92,23 @@ const url = object.subclass(function(that, my) { * @param {{}} query * @returns {url} */ -url.build = function(path, query) { - if (typeof(path) === "undefined" || path === null || typeof path !== "string") { +url.build = function (path, query) { + if ( + typeof path === "undefined" || + path === null || + typeof path !== "string" + ) { throw "accepts only string paths"; } if (query) { var queryPart = decodeURIComponent(jQuery.param(query)); if (queryPart) { - return url({rawUrl: path + "?" + queryPart}); + return url({ rawUrl: path + "?" + queryPart }); } } - return url({rawUrl: path}); + return url({ rawUrl: path }); }; /** @@ -147,7 +156,7 @@ function parseQuery(rawUrl) { var query = {}; var pair; if (result && result.length >= 2) { - (result[1].split("&")).forEach(function(each) { + result[1].split("&").forEach(function (each) { pair = each.split("="); query[pair[0]] = pair[1]; }); diff --git a/src/test/.eslintrc.js b/src/test/.eslintrc.js index 391ba9a..f7759ec 100644 --- a/src/test/.eslintrc.js +++ b/src/test/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { rules: { - "import/no-unused-modules": "off" - } + "import/no-unused-modules": "off", + }, }; diff --git a/src/test/htmlCanvasTest.js b/src/test/htmlCanvasTest.js index 8f23bd5..460e391 100644 --- a/src/test/htmlCanvasTest.js +++ b/src/test/htmlCanvasTest.js @@ -2,7 +2,7 @@ import htmlCanvas from "../htmlCanvas.js"; import jQuery from "jquery"; function withCanvas(callback) { - $("BODY").append("
"); + $("BODY").append('
'); var sandbox = jQuery("#sandbox"); var html = htmlCanvas(sandbox); @@ -11,8 +11,7 @@ function withCanvas(callback) { sandbox.remove(); } -describe("htmlCanvas", function() { - +describe("htmlCanvas", function () { it("htmlCanvas library", () => { expect(htmlCanvas).toBeTruthy(); }); @@ -29,8 +28,9 @@ describe("htmlCanvas", function() { }); it("throws exception if jQuery dont match element", () => { - expect(() => { htmlCanvas("#notfound"); }) - .toThrowError("htmlTagBrush requires an element"); + expect(() => { + htmlCanvas("#notfound"); + }).toThrowError("htmlTagBrush requires an element"); }); it("can render HTML tags", () => { @@ -66,11 +66,14 @@ describe("htmlCanvas", function() { it("render object literal attributes", () => { withCanvas((html) => { // Arrange: a div with attributes - html.div({ - id: "test_div", - klass: "test_class", - "special_attribute": "test" - }, "content"); + html.div( + { + id: "test_div", + klass: "test_class", + special_attribute: "test", + }, + "content", + ); // Assert: that DIV was rendered var divEl = jQuery("#test_div"); @@ -89,10 +92,13 @@ describe("htmlCanvas", function() { it("when value is html.omit()", () => { withCanvas((html) => { // Arrange: a div with attributes - html.div({ - id: "test_div", - "special_attribute": html.omit() - }, "content"); + html.div( + { + id: "test_div", + special_attribute: html.omit(), + }, + "content", + ); // Assert: that DIV was rendered var divEl = jQuery("#test_div"); @@ -108,7 +114,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let attributeName = "data-test"; - let div = html.div({[attributeName]: undefined}); + let div = html.div({ [attributeName]: undefined }); expect(div.element.hasAttribute("data-test")).toBeFalse(); }); @@ -118,7 +124,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let attributeName = "data-test"; - let div = html.div({[attributeName]: null}); + let div = html.div({ [attributeName]: null }); expect(div.element.hasAttribute("data-test")).toBeFalse(); }); @@ -128,7 +134,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let attributeName = "data-test"; - let div = html.div({[attributeName]: false}); + let div = html.div({ [attributeName]: false }); expect(div.element.hasAttribute("data-test")).toBeFalse(); }); @@ -138,7 +144,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let attributeName = "data-test"; - let div = html.div({[attributeName]: ""}); + let div = html.div({ [attributeName]: "" }); expect(div.element.hasAttribute("data-test")).toBeFalse(); }); @@ -153,9 +159,11 @@ describe("htmlCanvas", function() { html.a( { id: "test_link", - click: () => { clicked = true; } + click: () => { + clicked = true; + }, }, - "Click me!" + "Click me!", ); // Assert: that link was rendered @@ -175,7 +183,11 @@ describe("htmlCanvas", function() { var clicked = false; // Arrange: a link with a click callback - html.a("Click me!").id("test_link").click(() => { clicked = true; }); + html.a("Click me!") + .id("test_link") + .click(() => { + clicked = true; + }); // Assert: that link was rendered var linkEl = jQuery("#test_link"); @@ -192,10 +204,9 @@ describe("htmlCanvas", function() { it("tags can be nested", () => { withCanvas((html) => { // Arrange: a inner and outer div with a span as inner child - html.div({"id": "outer_div"}, - html.div({"id": "inner_div"}, - html.span("Some text") - ) + html.div( + { id: "outer_div" }, + html.div({ id: "inner_div" }, html.span("Some text")), ); // Assert: that outer div rendered @@ -210,10 +221,12 @@ describe("htmlCanvas", function() { // Arrange: a inner and outer div with a span as inner child // where the child is omited based on a flag var hasSomeText = false; - html.div({"id": "outer_div"}, - html.div({"id": "inner_div"}, - hasSomeText ? html.span("Some text") : html.omit() - ) + html.div( + { id: "outer_div" }, + html.div( + { id: "inner_div" }, + hasSomeText ? html.span("Some text") : html.omit(), + ), ); // Assert: that outer div rendered @@ -251,13 +264,14 @@ describe("htmlCanvas", function() { it("can render arrays", () => { withCanvas((html) => { // Arrange a div with10 sub span supplied to DIV as an array - html.div($.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (num) => { - return html.span(num.toString()); - })).id("test_div"); + html.div( + $.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (num) => { + return html.span(num.toString()); + }), + ).id("test_div"); // Assert: expect(jQuery("#test_div > SPAN").length).toBe(10); - }); }); @@ -270,17 +284,18 @@ describe("htmlCanvas", function() { // Assert: expect(jQuery("#test_div > SPAN").length).toBe(2); - }); }); it("throws error if object to append is null or undefined", () => { withCanvas((html) => { - expect(() => { html.render(null); }) - .toThrowError(); + expect(() => { + html.render(null); + }).toThrowError(); - expect(() => { html.render(undefined); }) - .toThrowError(); + expect(() => { + html.render(undefined); + }).toThrowError(); }); }); @@ -292,7 +307,7 @@ describe("htmlCanvas", function() { } // and render a DIV with function as argument - html.div({id: "aDiv"}, htmlFn); + html.div({ id: "aDiv" }, htmlFn); // Assert expect(jQuery("#aDiv").get(0)).toBeTruthy(); @@ -323,7 +338,7 @@ describe("htmlCanvas", function() { it("rendering html strings not allowed by default", () => { withCanvas((html) => { // Arrange: - var htmlString = "
foo
"; + var htmlString = '
foo
'; // Act: render the string html.render(htmlString); @@ -352,7 +367,7 @@ describe("htmlCanvas", function() { var htmlString = "
hello
"; // Act: render the string - html.div({id: "not-escaped"}).html(htmlString); + html.div({ id: "not-escaped" }).html(htmlString); // Assert expect(jQuery("#not-escaped").html()).toBe(htmlString); @@ -375,7 +390,7 @@ describe("htmlCanvas", function() { var h1 = html.h1().setAttribute("id", "aHeading"); // Assert: id set - expect(h1.asJQuery().attr("id")).toBe(("aHeading")); + expect(h1.asJQuery().attr("id")).toBe("aHeading"); }); }); @@ -393,7 +408,7 @@ describe("htmlCanvas", function() { it("attr() get/set style", () => { withCanvas((html) => { // Arrange: a heading with id (set using map) - var h1 = html.h1().attr({id: "aHeading"}); + var h1 = html.h1().attr({ id: "aHeading" }); // Assert: that id is set expect(h1.asJQuery().attr("id")).toBe("aHeading"); @@ -421,7 +436,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let h1 = html.h1(); - h1.addClass(["foo", {disabled: () => false}, ["bar"]]); + h1.addClass(["foo", { disabled: () => false }, ["bar"]]); expect(h1.element.className).toEqual("foo disabled bar"); }); @@ -429,9 +444,9 @@ describe("htmlCanvas", function() { it("removeClass() with a complex argument", () => { withCanvas((html) => { - let h1 = html.h1({class: "foo baz disabled bar"}); + let h1 = html.h1({ class: "foo baz disabled bar" }); - h1.removeClass(["foo", {disabled: () => false}, ["bar"]]); + h1.removeClass(["foo", { disabled: () => false }, ["bar"]]); expect(h1.element.className).toEqual("baz"); }); @@ -465,62 +480,90 @@ describe("htmlCanvas", function() { withCanvas((html) => { let tag = html.svgTag("svg"); - expect(tag.element.namespaceURI).toEqual("http://www.w3.org/2000/svg"); + expect(tag.element.namespaceURI).toEqual( + "http://www.w3.org/2000/svg", + ); }); }); it("can render the svg-specific tags", () => { withCanvas((html) => { - ["svg", "circle", "path", "polygon", "rect", "text"].forEach((tagName) => { - let tag = html[tagName](); - - expect(tag.element.namespaceURI).toEqual("http://www.w3.org/2000/svg"); - expect(tag.element.tagName.toLowerCase()).toEqual(tagName); - }); + ["svg", "circle", "path", "polygon", "rect", "text"].forEach( + (tagName) => { + let tag = html[tagName](); + + expect(tag.element.namespaceURI).toEqual( + "http://www.w3.org/2000/svg", + ); + + expect(tag.element.tagName.toLowerCase()).toEqual( + tagName, + ); + }, + ); }); }); }); describe("class names", () => { it("assign a single class name", () => { - expectClassNamesToBecomeCSSClass({input: "foo", expectedOutput: "foo"}); + expectClassNamesToBecomeCSSClass({ + input: "foo", + expectedOutput: "foo", + }); }); it("assign 2 class names in a single string", () => { - expectClassNamesToBecomeCSSClass({input: "foo bar", expectedOutput: "foo bar"}); + expectClassNamesToBecomeCSSClass({ + input: "foo bar", + expectedOutput: "foo bar", + }); }); it("assign class names in an array", () => { - expectClassNamesToBecomeCSSClass({input: ["foo", "bar"], expectedOutput: "foo bar"}); + expectClassNamesToBecomeCSSClass({ + input: ["foo", "bar"], + expectedOutput: "foo bar", + }); }); it("assign class names in an object", () => { - expectClassNamesToBecomeCSSClass({input: {foo: true, bar: true}, expectedOutput: "foo bar"}); + expectClassNamesToBecomeCSSClass({ + input: { foo: true, bar: true }, + expectedOutput: "foo bar", + }); }); it("ignore class names in an object whose value is false", () => { - expectClassNamesToBecomeCSSClass({input: {foo: true, bar: false}, expectedOutput: "foo"}); + expectClassNamesToBecomeCSSClass({ + input: { foo: true, bar: false }, + expectedOutput: "foo", + }); }); it("assign class names in an object inside an array", () => { - expectClassNamesToBecomeCSSClass({input: [{foo: true}, {bar: false}], expectedOutput: "foo"}); + expectClassNamesToBecomeCSSClass({ + input: [{ foo: true }, { bar: false }], + expectedOutput: "foo", + }); }); it("assign class names in an array of mixed types", () => { expectClassNamesToBecomeCSSClass({ input: [ "foo", - {bar: true}, - {baz: false}, + { bar: true }, + { baz: false }, "yes no", - ["another-yes", "another-no"] + ["another-yes", "another-no"], ], - expectedOutput: "foo bar yes no another-yes another-no"}); + expectedOutput: "foo bar yes no another-yes another-no", + }); }); - function expectClassNamesToBecomeCSSClass({input, expectedOutput}) { + function expectClassNamesToBecomeCSSClass({ input, expectedOutput }) { withCanvas((html) => { - let tag = html.div({class: input}); + let tag = html.div({ class: input }); expect(tag.element.className).toEqual(expectedOutput); }); @@ -531,10 +574,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let rootRef = {}; - html.render( - {ref: rootRef}, - (html) => html.p("foo") - ); + html.render({ ref: rootRef }, (html) => html.p("foo")); expect(rootRef.current.innerHTML).toEqual("

foo

"); }); @@ -544,10 +584,7 @@ describe("htmlCanvas", function() { withCanvas((html) => { let rootRef = {}; - html.div( - {ref: rootRef}, - (html) => html.p("foo") - ); + html.div({ ref: rootRef }, (html) => html.p("foo")); expect(rootRef.current.outerHTML).toEqual("

foo

"); }); diff --git a/src/test/router/hashLocationTest.js b/src/test/router/hashLocationTest.js index 61af786..7a5e1df 100644 --- a/src/test/router/hashLocationTest.js +++ b/src/test/router/hashLocationTest.js @@ -11,7 +11,7 @@ function delayedSteps() { return; } var fn = steps.shift(); - setTimeout(function() { + setTimeout(function () { next(fn.apply(next, arguments)); }, 10); } @@ -28,9 +28,8 @@ function setHash(aHash) { var my; var hashLocation; -describe("hashLocation", function() { - - beforeEach(function() { +describe("hashLocation", function () { + beforeEach(function () { window.location.hash = ""; my = {}; @@ -38,7 +37,7 @@ describe("hashLocation", function() { jasmine.clock().install(); }); - afterEach(function() { + afterEach(function () { if (hashLocation) { hashLocation.stop(); } @@ -46,13 +45,13 @@ describe("hashLocation", function() { jasmine.clock().uninstall(); }); - it("hash defaults", function() { + it("hash defaults", function () { // Assert that defaults are correct expect(my.currentHash).toBe(undefined); expect(my.history.length).toBe(0); }); - it("start() initilize hash", function() { + it("start() initilize hash", function () { // Arrange: set a location hash window.location.hash = "#!/test"; @@ -65,7 +64,7 @@ describe("hashLocation", function() { expect(my.history[0]).toBe(my.currentHash); }); - it("start() resets hash", function() { + it("start() resets hash", function () { // Arrange: add some history hashLocation.start(); setHash("#!/a"); @@ -79,7 +78,7 @@ describe("hashLocation", function() { expect(my.history[0]).toBe(my.currentHash); }); - it("getUrl() returns location.hash minus hash-bang", function() { + it("getUrl() returns location.hash minus hash-bang", function () { // Arrange: set a location hash window.location.hash = "#!/test"; @@ -91,7 +90,7 @@ describe("hashLocation", function() { expect(currentUrl.toString()).toBe("test"); }); - it("setUrl() adds hash-bang", function() { + it("setUrl() adds hash-bang", function () { // Act: set url hashLocation.start(); hashLocation.setUrl("test"); @@ -100,7 +99,7 @@ describe("hashLocation", function() { expect(my.currentHash).toBe("#!/test"); }); - it("linkToUrl() return link for href:s", function() { + it("linkToUrl() return link for href:s", function () { // Act: create link to URL var link = hashLocation.linkToUrl("someurl"); @@ -108,7 +107,7 @@ describe("hashLocation", function() { expect(link).toBe("#!/someurl"); }); - it("setUrl() triggers change", function() { + it("setUrl() triggers change", function () { var anotherHashLocation = hashLocationModel(); var spy = jasmine.createSpy("changed event"); @@ -121,57 +120,57 @@ describe("hashLocation", function() { // Assert that "change" callback was executed with url expect(spy).toHaveBeenCalledWith({ - asymmetricMatch: function(actual) { + asymmetricMatch: function (actual) { return actual.toString() === "test"; - } + }, }); anotherHashLocation.stop(); }); - it("back()", function(callback) { + it("back()", function (callback) { delayedSteps( - function() { + function () { hashLocation.stop(); window.location.hash = ""; // start hash hashLocation.start(); }, - function() { + function () { hashLocation.setUrl("a"); }, - function() { + function () { hashLocation.setUrl("b"); }, - function() { + function () { expect(hashLocation.getUrl().toString()).toBe("b"); }, - function() { + function () { hashLocation.back(); }, - function() { + function () { expect(hashLocation.getUrl().toString()).toBe("a"); }, - function() { + function () { hashLocation.back(); }, - function() { + function () { expect(hashLocation.getUrl().toString()).toBe(""); }, - function() { + function () { hashLocation.back(); }, - function() { + function () { expect(hashLocation.getUrl().toString()).toBe(""); }, - function() { + function () { hashLocation.back("fallback"); }, - function() { + function () { expect(hashLocation.getUrl().toString()).toBe("fallback"); }, - function() { + function () { callback(); - } + }, ); jasmine.clock().tick(131); }); diff --git a/src/test/router/routeTest.js b/src/test/router/routeTest.js index f23f57d..6b52230 100644 --- a/src/test/router/routeTest.js +++ b/src/test/router/routeTest.js @@ -1,149 +1,190 @@ import router from "../../router.js"; function assertMatch(url, route, message) { - expect(router.url({rawUrl: url}).matchRoute(router.route({ pattern: route })).isMatch()).toBeTruthy(); + expect( + router + .url({ rawUrl: url }) + .matchRoute(router.route({ pattern: route })) + .isMatch(), + ).toBeTruthy(); } function assertNoMatch(url, route, message) { - expect(!router.url({rawUrl: url}).matchRoute(router.route({ pattern: route })).isMatch()).toBeTruthy(); + expect( + !router + .url({ rawUrl: url }) + .matchRoute(router.route({ pattern: route })) + .isMatch(), + ).toBeTruthy(); } -describe("route", function() { - +describe("route", function () { // MATCH tests - it("Empty route", function() { + it("Empty route", function () { var route = ""; assertMatch("", route, "Match empty"); assertMatch("/", route, "Match slash"); - assertMatch("//",route, "Ignore extra slash"); - assertMatch("?a=1&b=2",route, "Ignore query"); + assertMatch("//", route, "Ignore extra slash"); + assertMatch("?a=1&b=2", route, "Ignore query"); - assertNoMatch("value",route, "Don't match values"); + assertNoMatch("value", route, "Don't match values"); }); - it("Slash route", function() { + it("Slash route", function () { var route = "/"; assertMatch("", route, "Match empty"); assertMatch("/", route, "Match slash"); - assertMatch("//",route, "Ignore extra slash"); - assertMatch("?a=1&b=2",route, "Ignore query"); + assertMatch("//", route, "Ignore extra slash"); + assertMatch("?a=1&b=2", route, "Ignore query"); - assertNoMatch("value",route, "Don't match values"); + assertNoMatch("value", route, "Don't match values"); }); - it("Static route", function() { + it("Static route", function () { var route = "a/static/path"; - assertMatch("/a/static/path",route, "Match if all segments are equal"); - assertMatch("a/static/path",route, "Ignore leading slash"); - assertMatch("/a/static/path/",route, "Ignore trailing slash"); - assertMatch("/a//static///path/",route, "Ignore extra slash"); - assertMatch("/a/static/path?a=1&b=2",route, "Ignore query"); + assertMatch("/a/static/path", route, "Match if all segments are equal"); + assertMatch("a/static/path", route, "Ignore leading slash"); + assertMatch("/a/static/path/", route, "Ignore trailing slash"); + assertMatch("/a//static///path/", route, "Ignore extra slash"); + assertMatch("/a/static/path?a=1&b=2", route, "Ignore query"); assertNoMatch("", route, "Don't match empty"); - assertNoMatch("a/static/path/and/some/more",route, "Don't match if more segments than in route."); + assertNoMatch( + "a/static/path/and/some/more", + route, + "Don't match if more segments than in route.", + ); }); - it("Route ignore trailing slash on pattern", function() { + it("Route ignore trailing slash on pattern", function () { var route = "a/static/path/"; // <-- ends with a slash - assertMatch("/a/static/path",route, "Match if all segments are equal"); - assertMatch("a/static/path",route, "Ignore leading slash"); - assertMatch("/a/static/path/",route, "Ignore trailing slash"); - assertMatch("/a//static///path/",route, "Ignore extra slash"); - assertMatch("/a/static/path?a=1&b=2",route, "Ignore query"); - - assertNoMatch("",route, "Empty."); - assertNoMatch("a/static/path/and",route, "Don't match if more segments than in route."); + assertMatch("/a/static/path", route, "Match if all segments are equal"); + assertMatch("a/static/path", route, "Ignore leading slash"); + assertMatch("/a/static/path/", route, "Ignore trailing slash"); + assertMatch("/a//static///path/", route, "Ignore extra slash"); + assertMatch("/a/static/path?a=1&b=2", route, "Ignore query"); + + assertNoMatch("", route, "Empty."); + assertNoMatch( + "a/static/path/and", + route, + "Don't match if more segments than in route.", + ); }); - it("Parameter route", function() { + it("Parameter route", function () { var route = "a/#parameter/path"; // - assertMatch("/a/foo/path",route, "Match any segment value"); - assertMatch("a/bar/path",route, "Ignore leading slash"); - assertMatch("/a/bar/path/",route, "Ignore trailing slash"); - assertMatch("/a//bar///path/",route, "Ignore extra slash"); - assertMatch("/a/foo/path?a=1&b=2",route, "Ignore query"); - - assertNoMatch("",route, "Empty. One parameters expected"); - assertNoMatch("a/foo/path/and",route, "Don't match if more segments than in route."); - assertNoMatch("b/foo/path",route, "B does not match static a"); + assertMatch("/a/foo/path", route, "Match any segment value"); + assertMatch("a/bar/path", route, "Ignore leading slash"); + assertMatch("/a/bar/path/", route, "Ignore trailing slash"); + assertMatch("/a//bar///path/", route, "Ignore extra slash"); + assertMatch("/a/foo/path?a=1&b=2", route, "Ignore query"); + + assertNoMatch("", route, "Empty. One parameters expected"); + assertNoMatch( + "a/foo/path/and", + route, + "Don't match if more segments than in route.", + ); + assertNoMatch("b/foo/path", route, "B does not match static a"); }); - it("Multiple parameters route", function() { + it("Multiple parameters route", function () { var route = "#parameter/#parameter2"; // - assertMatch("foo/bar",route, "Match any segment values"); - assertMatch("a/bar/",route, "Ignore leading slash"); - assertMatch("/a/bar/",route, "Ignore trailing slash"); - assertMatch("/a//bar/",route, "Ignore extra slash"); - assertMatch("foo/bar?a=1&b=2",route, "Ignore query"); - - assertNoMatch("",route, "Empty. Two named parameters expected"); - assertNoMatch("/foo",route, "One segment. Two segments expected"); - assertNoMatch("a/foo/path/and",route, "Don't match if more segments than in route."); + assertMatch("foo/bar", route, "Match any segment values"); + assertMatch("a/bar/", route, "Ignore leading slash"); + assertMatch("/a/bar/", route, "Ignore trailing slash"); + assertMatch("/a//bar/", route, "Ignore extra slash"); + assertMatch("foo/bar?a=1&b=2", route, "Ignore query"); + + assertNoMatch("", route, "Empty. Two named parameters expected"); + assertNoMatch("/foo", route, "One segment. Two segments expected"); + assertNoMatch( + "a/foo/path/and", + route, + "Don't match if more segments than in route.", + ); }); - it("Optional Parameter route", function() { + it("Optional Parameter route", function () { var route = "a/?parameter/path"; // - assertMatch("/a/foo/path",route, "Match any segment value"); - assertMatch("/a/path",route, "Match URL without segment"); - assertMatch("a/bar/path",route, "Ignore leading slash"); - assertMatch("/a/bar/path/",route, "Ignore trailing slash"); - assertMatch("/a//bar///path/",route, "Ignore extra slash"); - assertMatch("/a/foo/path?a=1&b=2",route, "Ignore query"); - - assertNoMatch("",route, "Empty. Two segments expected"); - assertNoMatch("/a",route, "One segment. At least two expected"); - assertNoMatch("a/foo/path/and",route, "Don't match if more segments than in route."); - assertNoMatch("b/foo/path",route, "B does not match static a"); + assertMatch("/a/foo/path", route, "Match any segment value"); + assertMatch("/a/path", route, "Match URL without segment"); + assertMatch("a/bar/path", route, "Ignore leading slash"); + assertMatch("/a/bar/path/", route, "Ignore trailing slash"); + assertMatch("/a//bar///path/", route, "Ignore extra slash"); + assertMatch("/a/foo/path?a=1&b=2", route, "Ignore query"); + + assertNoMatch("", route, "Empty. Two segments expected"); + assertNoMatch("/a", route, "One segment. At least two expected"); + assertNoMatch( + "a/foo/path/and", + route, + "Don't match if more segments than in route.", + ); + assertNoMatch("b/foo/path", route, "B does not match static a"); }); - it("Multiple Optional Parameter route", function() { + it("Multiple Optional Parameter route", function () { var route = "?foo/world/?bar/hello"; - assertMatch("/foo/world/bar/hello",route, "Match if all segments"); - assertMatch("/world/bar/hello",route, "Match without first"); - assertMatch("/foo/world/hello",route, "Match without second"); - assertMatch("/world/hello",route, "Match without both"); - - assertMatch("foo/world/bar/hello",route, "Ignore leading slash"); - assertMatch("/foo/world/bar/hello/",route, "Ignore trailing slash"); - assertMatch("/foo///world/bar///hello",route, "Ignore extra slash"); - assertMatch("/foo/world/bar/hello?a=1&b=2",route, "Ignore query"); - - assertNoMatch("",route, "Empty. At least two segments expected"); - assertNoMatch("/foo/world/bar/hello/and",route, "Don't match if more segments than in route."); - assertNoMatch("/foo/b/bar/hello",route, "B does not match static world"); + assertMatch("/foo/world/bar/hello", route, "Match if all segments"); + assertMatch("/world/bar/hello", route, "Match without first"); + assertMatch("/foo/world/hello", route, "Match without second"); + assertMatch("/world/hello", route, "Match without both"); + + assertMatch("foo/world/bar/hello", route, "Ignore leading slash"); + assertMatch("/foo/world/bar/hello/", route, "Ignore trailing slash"); + assertMatch("/foo///world/bar///hello", route, "Ignore extra slash"); + assertMatch("/foo/world/bar/hello?a=1&b=2", route, "Ignore query"); + + assertNoMatch("", route, "Empty. At least two segments expected"); + assertNoMatch( + "/foo/world/bar/hello/and", + route, + "Don't match if more segments than in route.", + ); + assertNoMatch( + "/foo/b/bar/hello", + route, + "B does not match static world", + ); }); - it("Mixed Optional and Mandatory Parameter route", function() { + it("Mixed Optional and Mandatory Parameter route", function () { var route = "?foo/#bar/?bro"; - assertMatch("/foo/bar/bro",route, "Match if all segments"); - assertMatch("/foo/bar",route, "Match if two"); - assertMatch("/foo",route, "Match if one"); + assertMatch("/foo/bar/bro", route, "Match if all segments"); + assertMatch("/foo/bar", route, "Match if two"); + assertMatch("/foo", route, "Match if one"); - assertMatch("foo/bat/bro",route, "Ignore leading slash"); - assertMatch("/foo/bar/bro/",route, "Ignore trailing slash"); - assertMatch("/foo///bar/bro/",route, "Ignore extra slash"); - assertMatch("/foo/bar/bro?a=1&b=2",route, "Ignore query"); + assertMatch("foo/bat/bro", route, "Ignore leading slash"); + assertMatch("/foo/bar/bro/", route, "Ignore trailing slash"); + assertMatch("/foo///bar/bro/", route, "Ignore extra slash"); + assertMatch("/foo/bar/bro?a=1&b=2", route, "Ignore query"); assertNoMatch("", route, "No match if none"); - assertNoMatch("/",route, "No match if only slash"); - assertNoMatch("/foo/bar/bro/and",route, "Don't match if more segments than in route."); + assertNoMatch("/", route, "No match if only slash"); + assertNoMatch( + "/foo/bar/bro/and", + route, + "Don't match if more segments than in route.", + ); }); - // Parameter binding tests + // Parameter binding tests - it("Route match result", function() { + it("Route match result", function () { var route = router.route({ pattern: "#a/#b" }); - var url = router.url({rawUrl: "hello/world"}); + var url = router.url({ rawUrl: "hello/world" }); var result = url.matchRoute(route); @@ -155,28 +196,32 @@ describe("route", function() { expect(result.getRouteParameters().a).toBe("hello"); }); - it("Route match capture parameters", function() { - var result = router.url({rawUrl: "/hello/world"}).matchRoute(router.route({pattern: "#foo/#bar" })); + it("Route match capture parameters", function () { + var result = router + .url({ rawUrl: "/hello/world" }) + .matchRoute(router.route({ pattern: "#foo/#bar" })); var props = result.getRouteParameters(); expect(props).toBeTruthy(); expect(props.foo).toBe("hello"); expect(props.bar).toBe("world"); - }); - it("Route match capture parameters mixed with statics", function() { - var result = router.url({rawUrl: "/hello/static/world"}).matchRoute(router.route({ pattern: "#foo/static/#bar" })); + it("Route match capture parameters mixed with statics", function () { + var result = router + .url({ rawUrl: "/hello/static/world" }) + .matchRoute(router.route({ pattern: "#foo/static/#bar" })); var props = result.getRouteParameters(); expect(props).toBeTruthy(); expect(props.foo).toBe("hello"); expect(props.bar).toBe("world"); - }); - it("Route parameter capture optional parameters", function() { - var result = router.url({rawUrl: "/hello/world"}).matchRoute(router.route({ pattern: "?foo/?bar"})); + it("Route parameter capture optional parameters", function () { + var result = router + .url({ rawUrl: "/hello/world" }) + .matchRoute(router.route({ pattern: "?foo/?bar" })); var props = result.getRouteParameters(); expect(props).toBeTruthy(); @@ -184,35 +229,55 @@ describe("route", function() { expect(props.bar).toBe("world"); }); - it("Route parameter capture optional parameters mixed with parameters", function() { - var firstOptionalBothMatch = router.url({rawUrl: "hello/world"}).matchRoute(router.route({ pattern: "?foo/#bar"})).getRouteParameters(); + it("Route parameter capture optional parameters mixed with parameters", function () { + var firstOptionalBothMatch = router + .url({ rawUrl: "hello/world" }) + .matchRoute(router.route({ pattern: "?foo/#bar" })) + .getRouteParameters(); - expect(firstOptionalBothMatch).toEqual({ foo: "hello", bar : "world"}); + expect(firstOptionalBothMatch).toEqual({ foo: "hello", bar: "world" }); - var firstOptionalOneMatch = router.url({rawUrl: "/world"}).matchRoute(router.route({ pattern: "?foo/#bar"})).getRouteParameters(); + var firstOptionalOneMatch = router + .url({ rawUrl: "/world" }) + .matchRoute(router.route({ pattern: "?foo/#bar" })) + .getRouteParameters(); - expect(firstOptionalOneMatch).toEqual({ foo: undefined, bar : "world"}); + expect(firstOptionalOneMatch).toEqual({ foo: undefined, bar: "world" }); - var optionalInPath = router.url({rawUrl: "hello/world"}).matchRoute(router.route({ pattern: "#foo/?bar/#bro" })).getRouteParameters(); + var optionalInPath = router + .url({ rawUrl: "hello/world" }) + .matchRoute(router.route({ pattern: "#foo/?bar/#bro" })) + .getRouteParameters(); - expect(optionalInPath).toEqual({ foo: "hello", bar: undefined,bro : "world"}); + expect(optionalInPath).toEqual({ + foo: "hello", + bar: undefined, + bro: "world", + }); - var trailingOptionals = router.url({rawUrl: "hello/world"}).matchRoute(router.route({ pattern: "#foo/?bar/?bro" })).getRouteParameters(); + var trailingOptionals = router + .url({ rawUrl: "hello/world" }) + .matchRoute(router.route({ pattern: "#foo/?bar/?bro" })) + .getRouteParameters(); - expect(trailingOptionals).toEqual({ foo: "hello", bar : "world", bro: undefined}); + expect(trailingOptionals).toEqual({ + foo: "hello", + bar: "world", + bro: undefined, + }); }); - it("Route parameter can have defaults", function() { + it("Route parameter can have defaults", function () { var route = router.route({ pattern: "?foo/?bar", options: { defaults: { - bar: "world" - } - } + bar: "world", + }, + }, }); - var result = router.url({rawUrl: "/hello"}).matchRoute(route); + var result = router.url({ rawUrl: "/hello" }).matchRoute(route); var props = result.getRouteParameters(); expect(props).toBeTruthy(); @@ -220,173 +285,263 @@ describe("route", function() { expect(props.bar).toBe("world"); }); - // Query + // Query - it("Query", function() { - var query = router.url({rawUrl: "hello/world?a=1&b=2&c=3"}).getQuery(); + it("Query", function () { + var query = router + .url({ rawUrl: "hello/world?a=1&b=2&c=3" }) + .getQuery(); - expect(query).toEqual({a: "1", b:"2", c: "3"}); + expect(query).toEqual({ a: "1", b: "2", c: "3" }); }); - // Expand + // Expand - it("Expand parameters", function() { - var route = router.route({ pattern: "#a/test/#b"}); + it("Expand parameters", function () { + var route = router.route({ pattern: "#a/test/#b" }); - var url = route.expand({a : "hello", b: "world"}); + var url = route.expand({ a: "hello", b: "world" }); expect(url).toBe("hello/test/world"); }); - it("Route parameter expansion can handle arrays", function() { + it("Route parameter expansion can handle arrays", function () { var route = router.route({ - pattern: "foo/#bar" + pattern: "foo/#bar", }); - var url = route.expand({bar: ["a", "b"]}); + var url = route.expand({ bar: ["a", "b"] }); expect(url).toBe("foo/a,b"); }); - it("Route optional parameter expansion can handle arrays", function() { + it("Route optional parameter expansion can handle arrays", function () { var route = router.route({ - pattern: "foo" + pattern: "foo", }); - var url = route.expand({bar: ["a", "b"]}); + var url = route.expand({ bar: ["a", "b"] }); expect(url).toBe("foo?bar=a,b"); }); - it("Expand optionals", function() { - var route = router.route({ pattern: "#a/?c/#b/?d"}); + it("Expand optionals", function () { + var route = router.route({ pattern: "#a/?c/#b/?d" }); + + expect(route.expand({ a: "hello", b: "world", d: "d" })).toBe( + "hello/world/d", + ); - expect(route.expand({a : "hello", b: "world", d: "d"})).toBe("hello/world/d"); - expect(route.expand({a : "hello", b: "world" })).toBe("hello/world"); - expect(route.expand({a : "hello", b: "world", c: "c" })).toBe("hello/c/world"); + expect(route.expand({ a: "hello", b: "world" })).toBe("hello/world"); + expect(route.expand({ a: "hello", b: "world", c: "c" })).toBe( + "hello/c/world", + ); }); - it("Expand extra parameters to the query string", function() { - var route = router.route({ pattern: "#a/#b"}); + it("Expand extra parameters to the query string", function () { + var route = router.route({ pattern: "#a/#b" }); + + expect(route.expand({ a: "hello", b: "world", c: "foo" })).toBe( + "hello/world?c=foo", + ); - expect(route.expand({a : "hello", b: "world", c: "foo"})).toBe("hello/world?c=foo"); - expect(route.expand({a : "hello", b: "world", c: "foo", d: "bar" })).toBe("hello/world?c=foo&d=bar"); + expect( + route.expand({ a: "hello", b: "world", c: "foo", d: "bar" }), + ).toBe("hello/world?c=foo&d=bar"); }); - it("Expand throws not valid URL error", function() { + it("Expand throws not valid URL error", function () { var route = router.route({ pattern: "#a/#b" }); - expect(function() { route.expand({a : "hello"});}).toThrowError("Could not generate a valid URL"); + expect(function () { + route.expand({ a: "hello" }); + }).toThrowError("Could not generate a valid URL"); }); - // Constraints + // Constraints - it("Route with function constraint", function() { + it("Route with function constraint", function () { var aRoute = router.route({ pattern: "/hello/#foo/", options: { - constraints : { - foo: function(value) { + constraints: { + foo: function (value) { return value.length === 5; - } - } - } + }, + }, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: "/hello/world"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/hello/sweden"})).isMatch()).toBeTruthy(); + expect( + aRoute.matchUrl(router.url({ rawUrl: "/hello/world" })).isMatch(), + ).toBeTruthy(); + + expect( + !aRoute.matchUrl(router.url({ rawUrl: "/hello/sweden" })).isMatch(), + ).toBeTruthy(); }); - it("Route with array constraint", function() { + it("Route with array constraint", function () { var aRoute = router.route({ pattern: "hello/#foo", options: { - constraints : { - foo: ["world", "sweden"] - } - } + constraints: { + foo: ["world", "sweden"], + }, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: "/hello/world"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/hello/france"})).isMatch()).toBeTruthy(); + expect( + aRoute.matchUrl(router.url({ rawUrl: "/hello/world" })).isMatch(), + ).toBeTruthy(); + + expect( + !aRoute.matchUrl(router.url({ rawUrl: "/hello/france" })).isMatch(), + ).toBeTruthy(); }); - it("Route with RegExp constraint", function() { + it("Route with RegExp constraint", function () { var aRoute = router.route({ pattern: "hello/#foo", options: { - constraints : { - foo: /(^[a-z]+$)/ - } - } + constraints: { + foo: /(^[a-z]+$)/, + }, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: "/hello/world"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/hello/öland"})).isMatch()).toBeTruthy(); + expect( + aRoute.matchUrl(router.url({ rawUrl: "/hello/world" })).isMatch(), + ).toBeTruthy(); + + expect( + !aRoute.matchUrl(router.url({ rawUrl: "/hello/öland" })).isMatch(), + ).toBeTruthy(); }); - it("Route with mixed constraints", function() { + it("Route with mixed constraints", function () { var aRoute = router.route({ pattern: "#a/#b/#c", options: { - constraints : { - a: function(value) { + constraints: { + a: function (value) { return value.length > 5; }, b: ["nicolas", "Mikael"], - c: /(^[h-w]+$)/ - } - } + c: /(^[h-w]+$)/, + }, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: "/henrik/mikael/h"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/ben/mikael/1"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/henrik/dennis/1"})).isMatch()).toBeTruthy(); - expect(!aRoute.matchUrl(router.url({rawUrl: "/henrik/mikael/a"})).isMatch()).toBeTruthy(); + expect( + aRoute + .matchUrl(router.url({ rawUrl: "/henrik/mikael/h" })) + .isMatch(), + ).toBeTruthy(); + + expect( + !aRoute.matchUrl(router.url({ rawUrl: "/ben/mikael/1" })).isMatch(), + ).toBeTruthy(); + + expect( + !aRoute + .matchUrl(router.url({ rawUrl: "/henrik/dennis/1" })) + .isMatch(), + ).toBeTruthy(); + + expect( + !aRoute + .matchUrl(router.url({ rawUrl: "/henrik/mikael/a" })) + .isMatch(), + ).toBeTruthy(); }); - it("Route constraints on optional parameters", function() { + it("Route constraints on optional parameters", function () { var aRoute = router.route({ pattern: "?a/?b/?c", options: { - constraints : { - a: function(value) { + constraints: { + a: function (value) { return value.length > 5; }, b: ["nicolas", "micke"], - c: /(^[h-w]+$)/ - } - } + c: /(^[h-w]+$)/, + }, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: ""})).isMatch()).toBeTruthy(); - - expect(!aRoute.matchUrl(router.url({rawUrl: "ö"})).isMatch()).toBeTruthy(); - - expect(aRoute.matchUrl(router.url({rawUrl: "henrik/micke/h"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "henrik/micke/h"})).getRouteParameters()).toEqual({ a: "henrik", b: "micke", c: "h"}); - - expect(aRoute.matchUrl(router.url({rawUrl: "henrik/micke"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "henrik/micke"})).getRouteParameters()).toEqual({ a: "henrik", b: "micke", c: undefined}); - - expect(aRoute.matchUrl(router.url({rawUrl: "henrik"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "henrik"})).getRouteParameters()).toEqual({ a: "henrik", b: undefined, c: undefined}); - - expect(aRoute.matchUrl(router.url({rawUrl: "micke"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "micke"})).getRouteParameters()).toEqual({ a: undefined, b: "micke", c: undefined}); - - expect(aRoute.matchUrl(router.url({rawUrl: "h"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "h"})).getRouteParameters()).toEqual({ a: undefined, b: undefined, c: "h"}); + expect( + aRoute.matchUrl(router.url({ rawUrl: "" })).isMatch(), + ).toBeTruthy(); + + expect( + !aRoute.matchUrl(router.url({ rawUrl: "ö" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "henrik/micke/h" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute + .matchUrl(router.url({ rawUrl: "henrik/micke/h" })) + .getRouteParameters(), + ).toEqual({ a: "henrik", b: "micke", c: "h" }); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "henrik/micke" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute + .matchUrl(router.url({ rawUrl: "henrik/micke" })) + .getRouteParameters(), + ).toEqual({ a: "henrik", b: "micke", c: undefined }); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "henrik" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute + .matchUrl(router.url({ rawUrl: "henrik" })) + .getRouteParameters(), + ).toEqual({ a: "henrik", b: undefined, c: undefined }); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "micke" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute + .matchUrl(router.url({ rawUrl: "micke" })) + .getRouteParameters(), + ).toEqual({ a: undefined, b: "micke", c: undefined }); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "h" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute.matchUrl(router.url({ rawUrl: "h" })).getRouteParameters(), + ).toEqual({ a: undefined, b: undefined, c: "h" }); }); - it("Ignore trailing segments route option", function() { + it("Ignore trailing segments route option", function () { var aRoute = router.route({ pattern: "hello/#foo", options: { - ignoreTrailingSegments: true - } + ignoreTrailingSegments: true, + }, }); - expect(aRoute.matchUrl(router.url({rawUrl: "/hello/world"})).isMatch()).toBeTruthy(); - expect(aRoute.matchUrl(router.url({rawUrl: "/hello/world/and/some/extra"})).isMatch()).toBeTruthy(); + expect( + aRoute.matchUrl(router.url({ rawUrl: "/hello/world" })).isMatch(), + ).toBeTruthy(); + + expect( + aRoute + .matchUrl(router.url({ rawUrl: "/hello/world/and/some/extra" })) + .isMatch(), + ).toBeTruthy(); }); }); diff --git a/src/test/router/routerTest.js b/src/test/router/routerTest.js index 2c56a21..68092e3 100644 --- a/src/test/router/routerTest.js +++ b/src/test/router/routerTest.js @@ -8,7 +8,7 @@ function delayedSteps() { return; } var fn = steps.shift(); - setTimeout(function() { + setTimeout(function () { next(fn.apply(next, arguments)); }, 10); } @@ -19,9 +19,8 @@ function delayedSteps() { var my; var aRouter; -describe("router", function() { - - beforeEach(function() { +describe("router", function () { + beforeEach(function () { window.location.hash = ""; my = {}; @@ -29,51 +28,57 @@ describe("router", function() { jasmine.clock().install(); }); - afterEach(function() { + afterEach(function () { aRouter.stop(); aRouter.clear(); aRouter = null; jasmine.clock().uninstall(); }); - it("Router defaults", function() { + it("Router defaults", function () { // Assert that defaults are correct expect(my.routeTable.length).toBe(0); expect(my.lastMatch).toBe(undefined); }); - it("Router options", function() { + it("Router options", function () { // Arrange a router with options set var anotherMy = {}; - router({ - locationHandler: {isFake: true, changed: {register: function() {}}} - }, anotherMy); + router( + { + locationHandler: { + isFake: true, + changed: { register: function () {} }, + }, + }, + anotherMy, + ); // Assert that options where applied expect(anotherMy.location.isFake).toBeTruthy(); }); - it("Add route", function() { + it("Add route", function () { // Act: add a route - var route = aRouter.addRoute({pattern: "/users/"}); + var route = aRouter.addRoute({ pattern: "/users/" }); // Assert that route was added to route table expect(my.routeTable.length).toBe(1); expect(my.routeTable[0]).toBe(route); }); - it("Remove route", function() { + it("Remove route", function () { // Act: add and remove route - var route = aRouter.addRoute({pattern: "/users/"}); + var route = aRouter.addRoute({ pattern: "/users/" }); aRouter.removeRoute(route); // Assert that route was removed from route table expect(my.routeTable.length).toBe(0); }); - it("Named routes", function() { + it("Named routes", function () { // Arrange: a named route - var route = aRouter.addRoute({name: "users", pattern: "/users/"}); + var route = aRouter.addRoute({ name: "users", pattern: "/users/" }); // Act: lookup route by name var namedRoute = aRouter.getRouteByName("users"); @@ -82,16 +87,16 @@ describe("router", function() { expect(namedRoute).toBe(route); }); - it("Add routes with priority", function() { + it("Add routes with priority", function () { // Act: add routes with different priorities - var invoiceRoute = aRouter.addRoute({pattern: "/invoice/"}); - var ticketRoute = aRouter.addRoute({pattern: "/ticket/"}); - aRouter.addRoute({pattern: "/customer/", priority: 2}); + var invoiceRoute = aRouter.addRoute({ pattern: "/invoice/" }); + var ticketRoute = aRouter.addRoute({ pattern: "/ticket/" }); + aRouter.addRoute({ pattern: "/customer/", priority: 2 }); var orderRoute = aRouter.addRoute({ pattern: "/order/", - priority: 2 + priority: 2, }); - var userRoute = aRouter.addRoute({pattern: "/user/", priority: 1}); + var userRoute = aRouter.addRoute({ pattern: "/user/", priority: 1 }); // Assert that route was added to route table in correct order expect(my.routeTable.length).toBe(5); @@ -101,9 +106,9 @@ describe("router", function() { expect(my.routeTable[4]).toBe(ticketRoute); }); - it("resolveUrl executes route callback on match", function() { + it("resolveUrl executes route callback on match", function () { // Arrange: setup a route - var userRoute = aRouter.addRoute({pattern: "/user/"}); + var userRoute = aRouter.addRoute({ pattern: "/user/" }); var spy = jasmine.createSpy("matched event"); userRoute.on("matched", spy); @@ -116,7 +121,7 @@ describe("router", function() { expect(spy).toHaveBeenCalledTimes(1); }); - it("resolveUrl triggers resolveUrl event", function() { + it("resolveUrl triggers resolveUrl event", function () { var spy = jasmine.createSpy("resolveUrl event"); // listen for "resolveUrl event" on router @@ -129,12 +134,12 @@ describe("router", function() { expect(spy).toHaveBeenCalled(); }); - it("resolveUrl triggers routeMatched event", function(done) { + it("resolveUrl triggers routeMatched event", function (done) { // Arrange: setup a route - var userRoute = aRouter.addRoute({pattern: "/user/"}); + var userRoute = aRouter.addRoute({ pattern: "/user/" }); // listen for "matched event" on router - aRouter.on("routeMatched", function(result) { + aRouter.on("routeMatched", function (result) { // Assert that callback was executed expect(result).toBeTruthy(); expect(result.getRoute()).toEqual(userRoute); @@ -147,10 +152,10 @@ describe("router", function() { aRouter.resolveUrl("/user/"); }); - it("resolveUrl triggers routeNotFound event", function(done) { + it("resolveUrl triggers routeNotFound event", function (done) { // Arrange: setup no routes but // a lister for "notFound event" - aRouter.on("routeNotFound", function(url) { + aRouter.on("routeNotFound", function (url) { // Assert that callback was executed expect(url).toBeTruthy(); expect(url.toString()).toEqual("/user/"); @@ -163,13 +168,13 @@ describe("router", function() { aRouter.resolveUrl("/user/"); }); - it("resolveUrl executes action on match", function() { + it("resolveUrl executes action on match", function () { var spy = jasmine.createSpy("action"); // Arrange: setup a route aRouter.addRoute({ pattern: "/user/", - action: spy + action: spy, }); // Act: resolve a URL that match pattern @@ -179,119 +184,119 @@ describe("router", function() { expect(spy).toHaveBeenCalled(); }); - it("resolveUrl pass values to action", function(done) { + it("resolveUrl pass values to action", function (done) { // Arrange a route that have two mandatory parameters aRouter.addRoute({ pattern: "/user/#userid/order/#orderid", - action: function(userid, orderid) { + action: function (userid, orderid) { expect(userid === "john" && orderid === "1").toBeTruthy(); this.unbind(); // clean-up done(); // execute asserts - } + }, }); // Act: resolve a URL that match pattern aRouter.resolveUrl("/user/john/order/1"); }); - it("resolveUrl pass optional values to action", function(done) { + it("resolveUrl pass optional values to action", function (done) { // Arrange a route that have two mandatory parameters aRouter.addRoute({ pattern: "/user/?userid/order/?orderid", - action: function(userid, orderid) { + action: function (userid, orderid) { expect(userid).toBe(undefined); expect(orderid).toBe("1"); this.unbind(); // clean-up done(); // execute asserts - } + }, }); // Act: resolve a URL that match pattern aRouter.resolveUrl("/user/order/1"); }); - it("resolveUrl pass optional value defaults to action", function(done) { + it("resolveUrl pass optional value defaults to action", function (done) { // Arrange a route that have two optional parameters // with defaukts aRouter.addRoute({ pattern: "/user/?userid/order/?orderid", defaults: { userid: "bengan", - orderid: "skor" + orderid: "skor", }, - action: function(userid, orderid) { + action: function (userid, orderid) { expect(userid).toBe("bengan"); expect(orderid).toBe("1"); this.unbind(); // clean-up done(); // execute asserts - } + }, }); // Act: resolve a URL that match pattern aRouter.resolveUrl("/user/order/1"); }); - it("resolveUrl pass query as last argument to action", function(done) { + it("resolveUrl pass query as last argument to action", function (done) { // Arrange a route that have one parameter aRouter.addRoute({ pattern: "/user/#userid/order", - action: function(userid, query) { + action: function (userid, query) { // Assert: that parameters and query was passed ok expect(userid).toBe("john"); expect(query.filter).toBe("open"); expect(query.orderBy).toBe("date"); this.unbind(); // clean-up done(); // execute asserts - } + }, }); // Act: resolve a URL that match pattern aRouter.resolveUrl("/user/john/order/?filter=open&orderBy=date"); }); - it("resolveUrl continues if fallThrough", function(done) { + it("resolveUrl continues if fallThrough", function (done) { // Arrange a 3 routes, where first have fallThrough // set and the two other have not aRouter.addRoute({ fallThrough: true, pattern: "/user/", - action: function() { + action: function () { expect(true).toBeTruthy(); this.unbind(); // clean-up - } + }, }); aRouter.addRoute({ pattern: "/user/", - action: function() { + action: function () { expect(true).toBeTruthy(); this.unbind(); // clean-up done(); // execute asserts - } + }, }); aRouter.addRoute({ pattern: "/user/", - action: function() { + action: function () { expect(true).toBeTruthy(); this.unbind(); // clean-up - } + }, }); // Act: resolve a URL that match pattern aRouter.resolveUrl("/user/"); }); - it("Add route with constraints", function() { + it("Add route with constraints", function () { var action = jasmine.createSpy("action"); aRouter.addRoute({ pattern: "/user/#name/", constraints: { - name: ["nicolas", "Mikael"] + name: ["nicolas", "Mikael"], }, - action: action + action: action, }); aRouter.resolveUrl("/user/nicolas"); @@ -306,7 +311,7 @@ describe("router", function() { expect(action).toHaveBeenCalledTimes(1); }); - it("getUrl returns current location", function() { + it("getUrl returns current location", function () { // Act: change hash and get url window.location.hash = "#!/aPath"; var currentUrl = aRouter.getUrl(); @@ -315,12 +320,12 @@ describe("router", function() { expect(currentUrl.toString()).toBe("aPath"); }); - it("linkTo() creates links for href", function() { + it("linkTo() creates links for href", function () { expect(aRouter.linkTo("aPath")).toBe("#!/aPath"); expect(aRouter.linkTo("")).toBe("#!/"); }); - it("redirectTo() changes the current location to URL", function() { + it("redirectTo() changes the current location to URL", function () { aRouter.redirectTo("aPath"); expect(window.location.hash).toBe("#!/aPath"); @@ -330,13 +335,13 @@ describe("router", function() { expect(window.location.hash).toBe("#!/"); }); - it("Pipe notfound to another router", function() { + it("Pipe notfound to another router", function () { // Arrange another router with a route handler var anotherRouter = router(); var spy = jasmine.createSpy("action"); anotherRouter.addRoute({ pattern: "APathNotInDefaultRouterButInPipedRouter", - action: spy + action: spy, }); // Act: pipe to second router if not found in first @@ -348,17 +353,17 @@ describe("router", function() { anotherRouter.stop(); }); - it("Pipe route to another router", function() { + it("Pipe route to another router", function () { // Arrange another router with a route handler var anotherRouter = router(); var spy = jasmine.createSpy("action"); anotherRouter.addRoute({ pattern: "/a/b/#c", - action: spy + action: spy, }); // Act: pipe pattern tp second router - aRouter.pipeRoute({pattern: "a/#b/#c"}, anotherRouter); + aRouter.pipeRoute({ pattern: "a/#b/#c" }, anotherRouter); aRouter.resolveUrl("/a/b/c"); // Assert that second router matched the route @@ -366,58 +371,58 @@ describe("router", function() { anotherRouter.stop(); }); - it("back()", function(done) { + it("back()", function (done) { aRouter.stop(); window.location.hash = ""; // start path aRouter.start(); delayedSteps( - function() { + function () { aRouter.redirectTo("a"); }, - function() { + function () { aRouter.redirectTo("b"); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("b"); }, - function() { + function () { aRouter.back(); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("a"); }, - function() { + function () { aRouter.back(); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe(""); }, - function() { + function () { aRouter.back(); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe(""); }, - function() { + function () { aRouter.back("fallback"); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("fallback"); }, - done + done, ); jasmine.clock().tick(131); }); - it("Expand parameters for named route", function() { + it("Expand parameters for named route", function () { // Arrange: a named route - aRouter.addRoute({name: "user", pattern: "/user/#userId"}); + aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); // Act: get path from parameters var url = aRouter.expand({ routeName: "user", - parameters: {userId: "john", includeDetails: true} + parameters: { userId: "john", includeDetails: true }, }); // Assert that route parameters was injected in url and @@ -425,48 +430,50 @@ describe("router", function() { expect(url.toString()).toBe("user/john?includeDetails=true"); }); - it("Expand parameters for empty route", function() { + it("Expand parameters for empty route", function () { // Arrange: empty hash route window.location.hash = ""; // start path // Act: get path from parameters var url = aRouter.expand({ - parameters: {userId: "john", includeDetails: true} + parameters: { userId: "john", includeDetails: true }, }); // Assert that all parameters was set as query parameters expect(url.toString()).toBe("?userId=john&includeDetails=true"); }); - it("Expand parameters for current route", function() { + it("Expand parameters for current route", function () { // Arrange: a named route aRouter.addRoute({ name: "user", - pattern: "/user/#userId" + pattern: "/user/#userId", }); // and navigate to that route - aRouter.redirectTo("/user/john", {includeCompanies: true}); + aRouter.redirectTo("/user/john", { includeCompanies: true }); // Act: get path from parameters for current location var url = aRouter.expand({ - parameters: {includeDetails: true} + parameters: { includeDetails: true }, }); // Assert that route parameters was injected in url and // other parameters was set in query - expect(url.toString()).toBe("user/john?includeCompanies=true&includeDetails=true"); + expect(url.toString()).toBe( + "user/john?includeCompanies=true&includeDetails=true", + ); }); - it("LinkTo with default parameters", function() { + it("LinkTo with default parameters", function () { // Arrange: a route with non optional parameter #foo aRouter.addRoute({ name: "bar", - pattern: "/#foo/bar" + pattern: "/#foo/bar", }); // and a default parameter getter for #foo - aRouter.setDefaultParameter("foo", function() { + aRouter.setDefaultParameter("foo", function () { return "default"; }); @@ -477,12 +484,12 @@ describe("router", function() { expect(url.toString()).toBe("#!/default/bar"); }); - it("GetParameters from current URL", function() { + it("GetParameters from current URL", function () { // Arrange: a named route - aRouter.addRoute({name: "user", pattern: "/user/#userId"}); + aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); // and navigate to that route - aRouter.redirectTo("/user/john", {includeCompanies: true}); + aRouter.redirectTo("/user/john", { includeCompanies: true }); // Act: get parameters from URL var parameters = aRouter.getParameters(); @@ -490,20 +497,21 @@ describe("router", function() { // Assert that parameters contains both query and URL parameters expect(parameters).toEqual({ userId: "john", - includeCompanies: "true" + includeCompanies: "true", }); }); - it("GetParameter", function() { + it("GetParameter", function () { // Arrange: a named route - aRouter.addRoute({name: "user", pattern: "/user/#userId"}); + aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); // and navigate to that route - aRouter.redirectTo("/user/john", {includeCompanies: true}); + aRouter.redirectTo("/user/john", { includeCompanies: true }); // Act: get parameters from URL var userIdParameter = aRouter.getParameter("userId"); - var includeCompaniesParameter = aRouter.getParameter("includeCompanies"); + var includeCompaniesParameter = + aRouter.getParameter("includeCompanies"); var unknownParameter = aRouter.getParameter("unknown"); // Assert that parameters contains both query and URL parameters @@ -512,39 +520,41 @@ describe("router", function() { expect(unknownParameter).toBeUndefined(); }); - it("setParameters()", function(done) { + it("setParameters()", function (done) { aRouter.stop(); window.location.hash = ""; // start path aRouter.start(); - aRouter.addRoute({pattern: "a/#value"}); + aRouter.addRoute({ pattern: "a/#value" }); delayedSteps( - function() { - aRouter.redirectTo("a/b", {foo: "bar"}); + function () { + aRouter.redirectTo("a/b", { foo: "bar" }); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("a/b?foo=bar"); }, - function() { - aRouter.setParameters({value: "hello"}); + function () { + aRouter.setParameters({ value: "hello" }); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("a/hello?foo=bar"); }, - function() { - aRouter.setParameters({foo: "world"}); + function () { + aRouter.setParameters({ foo: "world" }); }, - function() { + function () { expect(aRouter.getUrl().toString()).toBe("a/hello?foo=world"); }, - function() { - aRouter.setParameters({extra: "fun"}); + function () { + aRouter.setParameters({ extra: "fun" }); }, - function() { - expect(aRouter.getUrl().toString()).toBe("a/hello?foo=world&extra=fun"); + function () { + expect(aRouter.getUrl().toString()).toBe( + "a/hello?foo=world&extra=fun", + ); }, - done + done, ); jasmine.clock().tick(131); }); diff --git a/src/test/widgetTest.js b/src/test/widgetTest.js index 7086ded..5282f5d 100644 --- a/src/test/widgetTest.js +++ b/src/test/widgetTest.js @@ -2,29 +2,29 @@ import widget from "../widget.js"; import htmlCanvas from "../htmlCanvas.js"; import jQuery from "jquery"; -var widgetSubclass = widget.subclass(function(that, my) { - that.renderContentOn = function(html) { +var widgetSubclass = widget.subclass(function (that, my) { + that.renderContentOn = function (html) { html.h1("Hello world"); }; }); function withWidget(callback) { - // create a widget + // create a widget var my = {}; var aWidget = widgetSubclass({}, my); aWidget.appendTo(jQuery("body")); - // execute test + // execute test callback(aWidget, my); - // clean-up : remove widget + // clean-up : remove widget aWidget.asJQuery().remove(); } function withCanvas(callback) { - $("BODY").append("
"); + $("BODY").append('
'); var sandbox = jQuery("#sandbox"); var html = htmlCanvas(sandbox); @@ -33,57 +33,56 @@ function withCanvas(callback) { sandbox.remove(); } - // actual tests +// actual tests -describe("function", function() { - - it("widgets are assigned unique identifiers", function() { - withWidget(function(aWidget) { +describe("function", function () { + it("widgets are assigned unique identifiers", function () { + withWidget(function (aWidget) { for (var i = 0; i < 1000; i++) { expect(widgetSubclass().id()).not.toEqual(aWidget.id()); } }); }); - it("widgets identifier set from spec", function() { - var aWidget = widgetSubclass({id: "anId"}); + it("widgets identifier set from spec", function () { + var aWidget = widgetSubclass({ id: "anId" }); expect(aWidget.id()).toBe("anId"); }); - it("widgets supports events", function() { - // Arrange: a widget with a public method - // that triggers an event when executed. - var aWidget = (function() { + it("widgets supports events", function () { + // Arrange: a widget with a public method + // that triggers an event when executed. + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); - that.aMethod = function() { + that.aMethod = function () { that.trigger("anEvent"); }; return that; })(); - // Assert: that callback is executed when - aWidget.register("anEvent", function() { + // Assert: that callback is executed when + aWidget.register("anEvent", function () { expect(true).toBeTruthy(); }); - // event is triggered + // event is triggered aWidget.aMethod(); }); - it("widgets supports event methods", function() { - // Arrange: a widget with a public method - // that triggers an event when executed. - var aWidget = (function() { + it("widgets supports event methods", function () { + // Arrange: a widget with a public method + // that triggers an event when executed. + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); that.anEvent = my.events.createEvent("anEvent"); - that.aMethod = function() { + that.aMethod = function () { that.trigger("anEvent"); }; @@ -92,23 +91,23 @@ describe("function", function() { var spy = jasmine.createSpy("callback"); - // Assert: that callback is executed when + // Assert: that callback is executed when aWidget.anEvent.register(spy); - // event is triggered + // event is triggered aWidget.aMethod(); expect(spy).toHaveBeenCalled(); }); - it("linkTo() creates links to paths in app", function() { + it("linkTo() creates links to paths in app", function () { var my = {}; // reference to protected methods using "my"; widgetSubclass({}, my); expect(my.linkTo("foo/bar")).toBe("#!/foo/bar"); }); - it("redirectTo() redirects to paths in app", function() { + it("redirectTo() redirects to paths in app", function () { var my = {}; // reference to protected methods using "my"; widgetSubclass({}, my); @@ -117,15 +116,15 @@ describe("function", function() { expect(window.location.hash).toBe(my.linkTo("foo/bar")); }); - it("Render", function() { - withWidget(function(aWidget) { + it("Render", function () { + withWidget(function (aWidget) { expect(jQuery("#" + aWidget.id()).get(0)).toBeTruthy(); }); }); - it("Update", function() { - withWidget(function(aWidget) { - aWidget.renderContentOn = function(html) { + it("Update", function () { + withWidget(function (aWidget) { + aWidget.renderContentOn = function (html) { html.div().id("foo"); }; @@ -135,8 +134,8 @@ describe("function", function() { }); }); - it("Remove", function() { - withWidget(function(aWidget, my) { + it("Remove", function () { + withWidget(function (aWidget, my) { var id = "#" + aWidget.id(); expect(jQuery(id).get(0)).toBeTruthy(); @@ -147,162 +146,163 @@ describe("function", function() { }); }); - it("Widgets can be appended a jQuery", function() { - withCanvas(function(html) { - // Arrange: a widget - var aWidget = (function() { + it("Widgets can be appended a jQuery", function () { + withCanvas(function (html) { + // Arrange: a widget + var aWidget = (function () { var that = widgetSubclass(); - that.renderContentOn = function(html) { + that.renderContentOn = function (html) { html.div("div").addClass("aDiv"); }; return that; })(); - // and a DIV with existing content + // and a DIV with existing content var divQuery = html.div(html.span("content")).id("aDiv").asJQuery(); - // Act: append widget to DIV + // Act: append widget to DIV aWidget.appendTo(divQuery); - // Assert: that widget was appended last to DIV + // Assert: that widget was appended last to DIV expect(divQuery.children().get(1).id).toBe(aWidget.id()); }); }); - it("Widgets can replace content of a jQuery", function() { - withCanvas(function(html) { - // Arrange: a widget - var aWidget = (function() { + it("Widgets can replace content of a jQuery", function () { + withCanvas(function (html) { + // Arrange: a widget + var aWidget = (function () { var that = widgetSubclass(); - that.renderContentOn = function(html) { + that.renderContentOn = function (html) { html.div("div").addClass("aDiv"); }; return that; })(); - // and a DIV with existing content + // and a DIV with existing content var divQuery = html.div(html.span("content")).id("aDiv").asJQuery(); - // Act: replace content with jQuery + // Act: replace content with jQuery aWidget.replace(divQuery); - // Assert: that widget was appended to DIV + // Assert: that widget was appended to DIV expect(divQuery.children().length).toBe(1); expect(divQuery.children().get(0).id).toBe(aWidget.id()); }); }); - it("Widgets can be appended to a HTML canvas", function() { - withCanvas(function(html) { - // Arrange: a widget - var aWidget = (function() { + it("Widgets can be appended to a HTML canvas", function () { + withCanvas(function (html) { + // Arrange: a widget + var aWidget = (function () { var that = widgetSubclass(); - that.renderContentOn = function(html) { + that.renderContentOn = function (html) { html.div("div").addClass("aDiv"); }; return that; })(); - // Act: append widget to canvas + // Act: append widget to canvas html.render(aWidget); - // Assert: that widget was rendered in canvas + // Assert: that widget was rendered in canvas expect(html.root.asJQuery().find(".aDiv").get(0)).toBeTruthy(); }); }); - it("isRendered()", function() { - withCanvas(function(html) { - // Arrange: a widget - var aWidget = (function() { + it("isRendered()", function () { + withCanvas(function (html) { + // Arrange: a widget + var aWidget = (function () { var that = widgetSubclass(); - that.renderContentOn = function(html) { + that.renderContentOn = function (html) { html.div("div").addClass("aDiv"); }; return that; })(); - // Assert: false before render + // Assert: false before render expect(!aWidget.isRendered()).toBeTruthy(); - // Act: render widget + // Act: render widget html.render(aWidget); - // Assert: true ehrn rendered + // Assert: true ehrn rendered expect(aWidget.isRendered()).toBeTruthy(); }); }); - it("renderRoot() can be overridden in widget", function() { - withCanvas(function(html) { - - // Arrange: a widget that renders it"s root as - // form instead of DIV - var aWidget = (function() { + it("renderRoot() can be overridden in widget", function () { + withCanvas(function (html) { + // Arrange: a widget that renders it"s root as + // form instead of DIV + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); - my.renderRootOn = function(html) { + my.renderRootOn = function (html) { return html.form().id(that.id()); }; return that; })(); - // Act: render widget + // Act: render widget html.render(aWidget); - // Assert: that form is rendered with id - expect(html.root.asJQuery().find("FORM").get(0).id).toBe(aWidget.id()); + // Assert: that form is rendered with id + expect(html.root.asJQuery().find("FORM").get(0).id).toBe( + aWidget.id(), + ); }); }); - it("willAttach() and didAttach() are called upon rendering", function() { - withCanvas(function(html) { - var aWidget = (function() { + it("willAttach() and didAttach() are called upon rendering", function () { + withCanvas(function (html) { + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); that.willAttachCalled = false; that.didAttachCalled = false; - my.willAttach = function() { + my.willAttach = function () { that.willAttachCalled = true; }; - my.didAttach = function() { + my.didAttach = function () { that.didAttachCalled = true; }; return that; })(); - // Act: render widget + // Act: render widget html.render(aWidget); - // Assert: that form is rendered with id + // Assert: that form is rendered with id expect(aWidget.willAttachCalled).toBeTruthy(); expect(aWidget.didAttachCalled).toBeTruthy(); }); }); - it("willUpdate() is not called when rendering", function() { - withCanvas(function(html) { - var aWidget = (function() { + it("willUpdate() is not called when rendering", function () { + withCanvas(function (html) { + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); that.willUpdateCalled = false; - my.willUpdate = function() { + my.willUpdate = function () { that.willUpdateCalled = true; }; @@ -315,15 +315,15 @@ describe("function", function() { }); }); - it("willUpdate() is called when updating", function() { - withCanvas(function(html) { - var aWidget = (function() { + it("willUpdate() is called when updating", function () { + withCanvas(function (html) { + var aWidget = (function () { var my = {}; var that = widgetSubclass({}, my); that.willUpdateCalled = false; - my.willUpdate = function() { + my.willUpdate = function () { that.willUpdateCalled = true; }; @@ -337,9 +337,9 @@ describe("function", function() { }); }); - it("widgets initialize their subwidgets", function() { + it("widgets initialize their subwidgets", function () { var spy = jasmine.createSpy("init"); - var mySubclass = widget.subclass(function(that, my) { + var mySubclass = widget.subclass(function (that, my) { my.initializeSubwidgets = spy; }); mySubclass(); @@ -347,16 +347,16 @@ describe("function", function() { expect(spy).toHaveBeenCalled(); }); - it("widgets initialize their subwidgets after themselves", function() { - // TODO: refactor when - // https://github.com/jasmine/jasmine/pull/1242 is merged + it("widgets initialize their subwidgets after themselves", function () { + // TODO: refactor when + // https://github.com/jasmine/jasmine/pull/1242 is merged var init = jasmine.createSpy("init"); var initSub = jasmine.createSpy("init sub"); - var mySubclass = widget.subclass(function(that, my) { + var mySubclass = widget.subclass(function (that, my) { my.initialize = init; - my.initializeSubwidgets = function() { + my.initializeSubwidgets = function () { expect(init).toHaveBeenCalled(); initSub(); }; @@ -367,8 +367,8 @@ describe("function", function() { expect(initSub).toHaveBeenCalled(); }); - it("widgets can create an event", function() { - withWidget(function(widget, my) { + it("widgets can create an event", function () { + withWidget(function (widget, my) { expect(widget.foo).toBeUndefined(); my.createEvent("foo"); @@ -376,8 +376,8 @@ describe("function", function() { }); }); - it("widgets can create events", function() { - withWidget(function(widget, my) { + it("widgets can create events", function () { + withWidget(function (widget, my) { expect(widget.foo).toBeUndefined(); expect(widget.bar).toBeUndefined(); my.createEvents("foo", "bar"); diff --git a/src/widget.js b/src/widget.js index 5a54e58..1568511 100644 --- a/src/widget.js +++ b/src/widget.js @@ -1,11 +1,11 @@ import { object } from "klassified"; import widgetExtensions from "./widget-extensions.js"; import router from "./router.js"; -import {eventCategory} from "yaem"; +import { eventCategory } from "yaem"; import htmlCanvas from "./htmlCanvas.js"; import jQuery from "jquery"; -import {getCurrentWidget, withCurrentWidget} from "./currentWidget.js"; -import {newId} from "./idGenerator.js"; +import { getCurrentWidget, withCurrentWidget } from "./currentWidget.js"; +import { newId } from "./idGenerator.js"; /** * Base for all widgets. A widget can keep state in variables, contain logic and @@ -46,15 +46,14 @@ import {newId} from "./idGenerator.js"; * * @returns {widget} */ -const widget = object.subclass(function(that, my) { - +const widget = object.subclass(function (that, my) { /** * Keep track of the rendered subwidgets */ var children; var id; - my.initialize = function(spec) { + my.initialize = function (spec) { my.super(spec); id = spec.id || newId(); // When within an update transaction, do not update the widget @@ -66,9 +65,9 @@ const widget = object.subclass(function(that, my) { * Hook evaluated at the end of widget initialization and * before any rendering. */ - my.initializeSubwidgets = function(spec) {}; + my.initializeSubwidgets = function (spec) {}; - my.postInitialize = function(spec) { + my.postInitialize = function (spec) { my.initializeSubwidgets(spec); }; @@ -87,7 +86,7 @@ const widget = object.subclass(function(that, my) { * * @returns {String} */ - that.getId = function() { + that.getId = function () { return id; }; @@ -103,8 +102,8 @@ const widget = object.subclass(function(that, my) { * this function. * */ - that.dispose = function() { - children.forEach(function(child) { + that.dispose = function () { + children.forEach(function (child) { child.dispose(); }); my.dispose(); @@ -117,8 +116,8 @@ const widget = object.subclass(function(that, my) { * DOM. The widegt and all its children will call `my.willDetach` in * turn. */ - that.willDetach = function() { - children.forEach(function(child) { + that.willDetach = function () { + children.forEach(function (child) { child.willDetach(); }); my.willDetach(); @@ -133,8 +132,8 @@ const widget = object.subclass(function(that, my) { * * @param aJQuery */ - that.appendTo = function(aJQuery) { - my.withAttachHooks(function() { + that.appendTo = function (aJQuery) { + my.withAttachHooks(function () { renderBasicOn(htmlCanvas(aJQuery)); }); }; @@ -145,8 +144,8 @@ const widget = object.subclass(function(that, my) { * * @param aJQuery */ - that.replace = function(aJQuery) { - my.withAttachHooks(function() { + that.replace = function (aJQuery) { + my.withAttachHooks(function () { var canvas = htmlCanvas(aJQuery); canvas.root.asJQuery().empty(); renderBasicOn(canvas); @@ -161,7 +160,7 @@ const widget = object.subclass(function(that, my) { * * @returns {*} */ - that.asJQuery = function() { + that.asJQuery = function () { return jQuery("#" + that.getId()); }; @@ -170,7 +169,7 @@ const widget = object.subclass(function(that, my) { * * @returns {boolean} */ - that.isRendered = function() { + that.isRendered = function () { return that.asJQuery().length > 0; }; @@ -183,8 +182,8 @@ const widget = object.subclass(function(that, my) { * * @param aTagBrush */ - that.appendToBrush = function(aTagBrush) { - my.withAttachHooks(function() { + that.appendToBrush = function (aTagBrush) { + my.withAttachHooks(function () { renderBasicOn(htmlCanvas(aTagBrush.asJQuery())); }); }; @@ -193,9 +192,9 @@ const widget = object.subclass(function(that, my) { * Trigger the `willAttach` event on the receiver and all * rendered subwidgets. */ - that.triggerWillAttach = function() { + that.triggerWillAttach = function () { my.willAttach(); - children.forEach(function(widget) { + children.forEach(function (widget) { widget.triggerWillAttach(); }); }; @@ -204,9 +203,9 @@ const widget = object.subclass(function(that, my) { * Trigger the `didAttach` event on the receiver and all * rendered subwidgets. */ - that.triggerDidAttach = function() { + that.triggerDidAttach = function () { my.didAttach(); - children.forEach(function(widget) { + children.forEach(function (widget) { widget.triggerDidAttach(); }); that.onAttach.trigger(); @@ -216,7 +215,7 @@ const widget = object.subclass(function(that, my) { * Evaluate `fn`, calling `willAttach` before and `didAttach` after * the evaluation. */ - my.withAttachHooks = function(fn) { + my.withAttachHooks = function (fn) { var inRendering = inRenderingLoop(); if (!inRendering) { that.triggerWillAttach(); @@ -230,14 +229,14 @@ const widget = object.subclass(function(that, my) { /** * Create and expose an event named `name`. */ - my.createEvent = function(name) { + my.createEvent = function (name) { that[name] = my.events.createEvent(); }; /** * Create and expose one event per string argument. */ - my.createEvents = function() { + my.createEvents = function () { var names = Array.prototype.slice.apply(arguments); names.forEach(my.createEvent); }; @@ -263,14 +262,14 @@ const widget = object.subclass(function(that, my) { * * @returns {String} */ - my.nextId = function() { + my.nextId = function () { return newId(); }; /** * Widget specific dispose. */ - my.dispose = function() {}; + my.dispose = function () {}; // Route / Controller extensions @@ -301,7 +300,7 @@ const widget = object.subclass(function(that, my) { * */ function renderBasicOn(html) { - my.withChildrenRegistration(function() { + my.withChildrenRegistration(function () { that.renderOn(html); }); } @@ -329,23 +328,23 @@ const widget = object.subclass(function(that, my) { * * @param html */ - that.renderOn = function(html) { + that.renderOn = function (html) { // Renders widget by wrapping `renderContentOn()` in a root element. my.renderRootOn(html).render(that.renderContentOn); }; - my.withChildrenRegistration = function(fn) { + my.withChildrenRegistration = function (fn) { var parent = getCurrentWidget(); if (parent) { parent.registerChild(that); } - withCurrentWidget(function() { + withCurrentWidget(function () { children = []; fn(); }, that); }; - that.registerChild = function(widget) { + that.registerChild = function (widget) { children.push(widget); }; @@ -357,7 +356,7 @@ const widget = object.subclass(function(that, my) { * @param html * @returns {htmlBrush} */ - my.renderRootOn = function(html) { + my.renderRootOn = function (html) { return html.tag("widgetjs-widget").id(id); }; @@ -375,7 +374,7 @@ const widget = object.subclass(function(that, my) { * * @param {htmlCanvas} html */ - that.renderContentOn = function(html) { + that.renderContentOn = function (html) { return my.subclassResponsibility(); }; @@ -383,55 +382,54 @@ const widget = object.subclass(function(that, my) { * Hook evaluated before the widget is attached (or reattached due * to an update of rendering) to the DOM. */ - my.willAttach = function() {}; + my.willAttach = function () {}; /** * Hook evaluated each time the widget is attached (or * reattached due to an update of rendering) to the DOM. */ - my.didAttach = function() {}; + my.didAttach = function () {}; /** * Hook evaluated when a widget is detached from the DOM. */ - my.willDetach = function() {}; + my.willDetach = function () {}; /** * Hook evaluated before widget update. */ - my.willUpdate = function() {}; + my.willUpdate = function () {}; /** * Re-renders the widget and replace it in the DOM */ - that.update = function() { + that.update = function () { if (my.inUpdateTransaction || !that.isRendered()) { return; } that.willDetach(); my.willUpdate(); - my.withAttachHooks(function() { + my.withAttachHooks(function () { // clear content of root that.asJQuery().empty(); // re-render content on root var html = htmlCanvas(that.asJQuery()); - my.withChildrenRegistration(function() { + my.withChildrenRegistration(function () { that.renderContentOn(html); }); }); }; - that.withinTransaction = function(fn, onDone) { + that.withinTransaction = function (fn, onDone) { if (my.inUpdateTransaction) { fn(); } else { try { my.inUpdateTransaction = true; fn(); - } - finally { + } finally { my.inUpdateTransaction = false; if (onDone) { onDone(); @@ -446,18 +444,20 @@ const widget = object.subclass(function(that, my) { * to `withUpdate` or `update` will result in updating the * widget only once. */ - that.withUpdate = function(fn) { + that.withUpdate = function (fn) { that.withinTransaction(fn, that.update); }; - that.withNoUpdate = function(fn) { + that.withNoUpdate = function (fn) { that.withinTransaction(fn); }; // Third party protected extensions** added to `my`. // See widget-extensions.js for (var extProperty in widgetExtensions) { - if (Object.prototype.hasOwnProperty.call(widgetExtensions, extProperty)) { + if ( + Object.prototype.hasOwnProperty.call(widgetExtensions, extProperty) + ) { my[extProperty] = widgetExtensions[extProperty]; } } diff --git a/src/widgetjs.js b/src/widgetjs.js index 6d6504a..97ce4ab 100644 --- a/src/widgetjs.js +++ b/src/widgetjs.js @@ -1,5 +1,5 @@ -export {default as htmlCanvas} from "./htmlCanvas.js"; -export {default as widget} from "./widget.js"; -export {default as Widget} from "./Widget2.js"; -export {default as ext} from "./widget-extensions.js"; -export {default as router} from "./router.js"; +export { default as htmlCanvas } from "./htmlCanvas.js"; +export { default as widget } from "./widget.js"; +export { default as Widget } from "./Widget2.js"; +export { default as ext } from "./widget-extensions.js"; +export { default as router } from "./router.js"; diff --git a/webpack.aliases.js b/webpack.aliases.js index 498933d..c91d716 100644 --- a/webpack.aliases.js +++ b/webpack.aliases.js @@ -1,5 +1,8 @@ const path = require("path"); module.exports = { - klassified: path.resolve(__dirname, "node_modules/klassified/src/klassified") + klassified: path.resolve( + __dirname, + "node_modules/klassified/src/klassified", + ), }; diff --git a/webpack.base.config.js b/webpack.base.config.js index d625bad..96f832a 100644 --- a/webpack.base.config.js +++ b/webpack.base.config.js @@ -9,22 +9,22 @@ let config = { path: path.resolve(__dirname, "dist"), filename: "widgetjs.js", libraryTarget: "umd", - library: "widgetjs" + library: "widgetjs", }, resolve: { modules: [path.resolve(__dirname, "js"), "node_modules"], - alias: aliases + alias: aliases, }, plugins: [ new webpack.ProvidePlugin({ - "$": "jquery", + $: "jquery", jQuery: "jquery", - "window.jQuery": "jquery" + "window.jQuery": "jquery", }), new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1 - }) - ] + maxChunks: 1, + }), + ], }; module.exports = config; diff --git a/yarn.lock b/yarn.lock index d1818a6..589c713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -44,15 +44,18 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.55.0.tgz#b721d52060f369aa259cf97392403cb9ce892ec6" integrity sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA== -"@foretagsplatsen/eslint-plugin@^3.0.0": - version "3.0.0" - resolved "https://npm.pkg.github.com/download/@foretagsplatsen/eslint-plugin/3.0.0/27fca7db450009df3a9672279a53d2576de1f074#27fca7db450009df3a9672279a53d2576de1f074" - integrity sha512-XoNBGFEFxX9tDdAtG0g/cs/UeYTqnRfNQkMBEtBo3uUVE2edxuP0d1QcZZJU4oPotFVI4nGfe9gmXSsH4ApspQ== +"@foretagsplatsen/eslint-plugin@^4.0.1": + version "4.0.1" + resolved "https://npm.pkg.github.com/download/@foretagsplatsen/eslint-plugin/4.0.1/6ca5a9c9d03ce84361c35860b161e1cabd4152ea#6ca5a9c9d03ce84361c35860b161e1cabd4152ea" + integrity sha512-4xVqJWzuwxy7rbxay7/l9AoYJruZTi0AC0hv+jQ/O/2UW+rA25qSekQRklNF5YLNujbP/3cB98eQnuvemr6usQ== dependencies: + eslint-config-prettier "^9.1.0" eslint-import-resolver-exports "^1.0.0-beta.5" eslint-plugin-import "^2.29.0" eslint-plugin-jasmine "^4.1.3" + eslint-plugin-prettier "^5.0.1" eslint-plugin-promise "^6.0.0" + prettier "^3.1.1" "@humanwhocodes/config-array@^0.11.13": version "0.11.13" @@ -133,12 +136,12 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -151,6 +154,18 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/utils@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" + integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.3.0" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.6.0" + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -493,6 +508,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +big-integer@^1.6.44: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -511,6 +531,13 @@ body-parser@1.20.1: type-is "~1.6.18" unpipe "1.0.0" +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -526,6 +553,13 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browserslist@^4.14.5: version "4.22.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" @@ -541,6 +575,13 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -686,6 +727,24 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" @@ -695,6 +754,11 @@ define-data-property@^1.0.1, define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" @@ -868,6 +932,11 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + eslint-import-resolver-exports@^1.0.0-beta.5: version "1.0.0-beta.5" resolved "https://registry.yarnpkg.com/eslint-import-resolver-exports/-/eslint-import-resolver-exports-1.0.0-beta.5.tgz#d603056ee168b3e84848cceef12824e470f47b31" @@ -919,6 +988,14 @@ eslint-plugin-jasmine@^4.1.3: resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-4.1.3.tgz#c4ced986a61dd5b180982bafe6da1cbac0941c52" integrity sha512-q8j8KnLH/4uwmPELFZvEyfEcuCuGxXScJaRdqHjOjz064GcfX6aoFbzy5VohZ5QYk2+WvoqMoqDSb9nRLf89GQ== +eslint-plugin-prettier@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz#a3b399f04378f79f066379f544e42d6b73f11515" + integrity sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.8.5" + eslint-plugin-promise@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" @@ -1037,6 +1114,36 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + express@^4.16.4: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -1079,6 +1186,22 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -1115,6 +1238,13 @@ filelist@^1.0.4: dependencies: minimatch "^5.0.1" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" @@ -1223,6 +1353,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-stream@^6.0.0, get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1231,6 +1366,13 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" @@ -1349,6 +1491,16 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -1462,6 +1614,16 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1472,13 +1634,20 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -1491,6 +1660,11 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" @@ -1518,6 +1692,16 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -1546,6 +1730,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -1750,11 +1941,24 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -1772,6 +1976,16 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1843,6 +2057,20 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + object-inspect@^1.13.1, object-inspect@^1.9.0: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" @@ -1905,6 +2133,30 @@ once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -1977,11 +2229,16 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -2005,6 +2262,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -2017,6 +2279,18 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -2141,6 +2415,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2298,6 +2579,11 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -2393,6 +2679,16 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -2417,6 +2713,14 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +synckit@^0.8.5: + version "0.8.6" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.6.tgz#b69b7fbce3917c2673cbdc0d87fb324db4a5b409" + integrity sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA== + dependencies: + "@pkgr/utils" "^2.4.2" + tslib "^2.6.2" + tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -2448,6 +2752,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + tmp@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -2455,6 +2764,13 @@ tmp@^0.2.1: dependencies: rimraf "^3.0.0" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -2470,6 +2786,11 @@ tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@^2.6.0, tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -2549,6 +2870,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + update-browserslist-db@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"