@aref-shojaei/router 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- (()=>{"use strict";class t extends Error{constructor(t){super(t),this.name="Invalid argument error"}}class e{static#t="";static#e="";static#s;constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static setDocument(e){if("object"!=typeof e)throw new t("'document' must be a Document object!");this.#s=e}static _getDocument(){return this.#s}static setTitle(e){if("string"!=typeof e)throw new t("'title' must be a string!");this.#e=e,this.#i()}static getTitle(){return this.#e||this.#t}static setRootTitle(e){if("string"!=typeof e)throw new t("'value' must be a string!");this.#t=e,this.#i()}static getRootTitle(){return this.#t}static#i(){const t=this._getDocument();this.getTitle()?t.title=this.getTitle():t.title=this.getRootTitle()}}class s{constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static render(e,s={}){if("function"!=typeof e)throw new t("'template' must be a function!");try{return e(s)}catch(t){console.error("Error during template rendering: ",t)}}}class i{static#o=[];constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static findAll(e,s){if("string"!=typeof e)throw new t("'element' must be an HTMLElement object!");if("object"!=typeof s)throw new t("'document' must be a Document object!");const i=s.querySelectorAll(e);return this._setElements(i),this}static each(e){if("function"!=typeof e)throw new t("'callback' must be a function!");const s=this._getElements();this.#o.length&&s.forEach(e)}static _setElements(t){this.#o.push(...t)}static _getElements(){return this.#o}}class o{constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static onClick(e,s){if("object"!=typeof e)throw new t("'element' must be an HTMLElement object!");if("function"!=typeof s)throw new t("'callback' must be a function!");e.addEventListener("click",s)}}class r{title="";template;middlewares=[];meta={params:{},query:{}};constructor({title:t,template:e}){this.title=t??this.title,this.template=e}}class n{static _window;static _document;static _rootElement="#root";static _routes={};static _currentRoute="";static _routePrefix="";static _defaultRoute=new r({title:"404",template:()=>"404 | Page not found!"});constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static configure({window:e,document:s,selector:i}){if("object"!=typeof e)throw new t("'window' must be a Window object!");if("object"!=typeof s)throw new t("'document' must be a Document object!");if(i&&"string"!=typeof i)throw new t("'selector' must be a string!");i&&(this._rootElement=i),this._window=e,this._document=s}static#r(t){for(const e in this._routes){const s=new RegExp(`^${e.replace(/\{(\w+)\}/g,"(?<$1>[^/{}]+)")}$`);if(!s.test(t))continue;const{groups:i}=s.exec(t);return this.#n(e),this.#a(e,i),this._routes[e]}}static#n(t){const e={},{search:s}=location;if(!s.length)return!1;s.slice(1).split("&").forEach((t=>{const[s,i]=t.split("=");e[s]=i})),this._routes[t].meta.query={...e}}static#a(t,e){this._routes[t].meta.params={...e}}static _setRouteToURL(e){if("string"!=typeof e||!e.startsWith("/"))throw new t("'route' must be a string starting with \"/\"!");this._window.history.pushState({},"",e)}static#c(t){try{const{title:i,template:o,middlewares:r,meta:n}=this.#r(t)??this._defaultRoute;e.setTitle(i),this.#u(r),this._document.querySelector(this._rootElement).innerHTML=s.render(o,n)}catch(e){console.error("Error to inject route template:",t,e)}}static#l(){this._window.addEventListener("popstate",(t=>{const e=t.target.location.pathname;this.#c(e)}))}static#h(){const{pathname:t}=this._window.location;this.#c(t)}static#w(){i.findAll("a",this._document).each((t=>{o.onClick(t,(t=>{if(t.target.hasAttribute("data-link"))return!1;t.preventDefault();const e=t.target.getAttribute("href");this._setRouteToURL(e),this.#c(e)}))}))}static#u(t){try{t.length&&t.forEach((t=>t()))}catch(t){console.error("Error executing middleware:",t)}}static run(s=(()=>{})){if("function"!=typeof s)throw new t("'callback' must be a function!");e.setDocument(this._document),e.setRootTitle(this._document.title),this.#l(),this.#h(),this.#w(),s()}}window.Router=n,window.Route=class extends n{constructor(){throw new Error(`${new.target.name} class must not be called with "new" keyword!`)}static addRoute(e,s){if("string"!=typeof e)throw new t("'route' must be a string!");if("function"!=typeof s)throw new t("'callback' must be a function!");return this._routes[this._routePrefix+e]=new r({template:s}),this._currentRoute=e,this}static group(e,s){if("string"!=typeof e||!e.startsWith("/"))throw new t("'prefix' must be a string!");if("function"!=typeof s)throw new t("'callback' must be a function!");const i=this._routePrefix;return this._routePrefix=e,s(),this._routePrefix=i,this}static middleware(e){if(!Array.isArray(e))throw new t("'middlewares' must be an array!");if(this._routePrefix)for(const t in this._routes)t.startsWith(this._routePrefix)&&this._routes[t].middlewares.push(...e);else this._routes[this._routePrefix+this._currentRoute].middlewares.push(...e)}static title(e){if("string"!=typeof e)throw new t("'value' must be a string!");this._routes[this._routePrefix+this._currentRoute].title=e}static redirect(e){if("string"!=typeof e||!e.startsWith("/"))throw new t("'to' must be a string starting route with \"/\"!");this._setRouteToURL(e);const{template:i,meta:o}=this._routes[e]??this._defaultRoute;return s.render(i,o)}}})();
1
+ (()=>{"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(t){var i="function"==typeof Map?new Map:void 0;return e=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==i){if(i.has(t))return i.get(t);i.set(t,e)}function e(){return function(t,e,o){if(r())return Reflect.construct.apply(null,arguments);var i=[null];i.push.apply(i,e);var u=new(t.bind.apply(t,i));return o&&n(u,o.prototype),u}(t,arguments,o(this).constructor)}return e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n(e,t)},e(t)}function r(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(r=function(){return!!t})()}function n(t,e){return n=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},n(t,e)}function o(t){return o=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},o(t)}var i=function(e){function i(e){var n;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,i),(n=function(e,n,i){return n=o(n),function(e,r){if(r&&("object"==t(r)||"function"==typeof r))return r;if(void 0!==r)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(e)}(e,r()?Reflect.construct(n,i||[],o(e).constructor):n.apply(e,i))}(this,i,[e])).name="Invalid argument error",n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&n(t,e)}(i,e),u=i,Object.defineProperty(u,"prototype",{writable:!1}),u;var u}(e(Error));function u(t){return u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},u(t)}function c(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,a(n.key),n)}}function a(t){var e=function(t){if("object"!=u(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=u(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==u(e)?e:e+""}function l(t,e,r){if("function"==typeof t?t===e:t.has(e))return arguments.length<3?e:r;throw new TypeError("Private element is not present on this object")}var f=function(){function t(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new Error("".concat((this instanceof t?this.constructor:void 0).name,' class must not be called with "new" keyword!'))}return e=t,r=[{key:"setDocument",value:function(e){if("object"!==u(e))throw new i("'document' must be a Document object!");b._=l(t,this,e)}},{key:"_getDocument",value:function(){return l(t,this,b)._}},{key:"setTitle",value:function(e){if("string"!=typeof e)throw new i("'title' must be a string!");p._=l(t,this,e),l(t,this,s).call(this)}},{key:"getTitle",value:function(){return l(t,this,p)._||l(t,this,y)._}},{key:"setRootTitle",value:function(e){if("string"!=typeof e)throw new i("'value' must be a string!");y._=l(t,this,e),l(t,this,s).call(this)}},{key:"getRootTitle",value:function(){return l(t,this,y)._}}],null&&c(e.prototype,null),r&&c(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,r}();function s(){var t=this._getDocument();this.getTitle()?t.title=this.getTitle():t.title=this.getRootTitle()}var y={_:""},p={_:""},b={_:void 0};function m(t){return m="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},m(t)}function h(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,v(n.key),n)}}function v(t){var e=function(t){if("object"!=m(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=m(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==m(e)?e:e+""}var w=function(){return t=function t(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new Error("".concat((this instanceof t?this.constructor:void 0).name,' class must not be called with "new" keyword!'))},e=[{key:"render",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if("function"!=typeof t)throw new i("'template' must be a function!");try{return t(e)}catch(t){console.error("Error during template rendering: ",t)}}}],null&&h(t.prototype,null),e&&h(t,e),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,e}();function d(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}function g(t){return g="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},g(t)}function j(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,S(n.key),n)}}function S(t){var e=function(t){if("object"!=g(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=g(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==g(e)?e:e+""}function _(t,e,r){if("function"==typeof t?t===e:t.has(e))return arguments.length<3?e:r;throw new TypeError("Private element is not present on this object")}var P=function(){function t(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new Error("".concat((this instanceof t?this.constructor:void 0).name,' class must not be called with "new" keyword!'))}return e=t,r=[{key:"findAll",value:function(t,e){if("string"!=typeof t)throw new i("'element' must be an HTMLElement object!");if("object"!==g(e))throw new i("'document' must be a Document object!");var r=e.querySelectorAll(t);return this._setElements(r),this}},{key:"each",value:function(e){if("function"!=typeof e)throw new i("'callback' must be a function!");var r=this._getElements();_(t,this,O)._.length&&r.forEach(e)}},{key:"_setElements",value:function(e){var r;(r=_(t,this,O)._).push.apply(r,function(t){return function(t){if(Array.isArray(t))return d(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return d(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?d(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(e))}},{key:"_getElements",value:function(){return _(t,this,O)._}}],null&&j(e.prototype,null),r&&j(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,r}(),O={_:[]};function E(t){return E="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},E(t)}function k(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,T(n.key),n)}}function T(t){var e=function(t){if("object"!=E(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=E(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==E(e)?e:e+""}var A=function(){return t=function t(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new Error("".concat((this instanceof t?this.constructor:void 0).name,' class must not be called with "new" keyword!'))},e=[{key:"onClick",value:function(t,e){if("object"!==E(t))throw new i("'element' must be an HTMLElement object!");if("function"!=typeof e)throw new i("'callback' must be a function!");t.addEventListener("click",e)}}],null&&k(t.prototype,null),e&&k(t,e),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,e}();function R(t){return R="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},R(t)}function x(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,I(n.key),n)}}function C(t,e,r){return e&&x(t.prototype,e),r&&x(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t}function D(t,e,r){return(e=I(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function I(t){var e=function(t){if("object"!=R(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=R(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==R(e)?e:e+""}var L,M=C(function t(e){var r=e.title,n=e.template;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),D(this,"title",""),D(this,"template",void 0),D(this,"middlewares",[]),D(this,"meta",{params:{},query:{}}),this.title=null!=r?r:this.title,this.template=n});function U(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function W(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?U(Object(r),!0).forEach(function(e){B(t,e,r[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):U(Object(r)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))})}return t}function $(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}function q(t){return q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},q(t)}function H(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,F(n.key),n)}}function B(t,e,r){return(e=F(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function F(t){var e=function(t){if("object"!=q(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=q(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==q(e)?e:e+""}function z(t,e,r){if("function"==typeof t?t===e:t.has(e))return arguments.length<3?e:r;throw new TypeError("Private element is not present on this object")}var G=function(){function t(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new Error("".concat((this instanceof t?this.constructor:void 0).name,' class must not be called with "new" keyword!'))}return e=t,r=[{key:"configure",value:function(t){var e=t.window,r=t.document,n=t.selector;if("object"!==q(e))throw new i("'window' must be a Window object!");if("object"!==q(r))throw new i("'document' must be a Document object!");if(n&&"string"!=typeof n)throw new i("'selector' must be a string!");n&&(this._rootElement=n),this._window=e,this._document=r}},{key:"_setRouteToURL",value:function(t){if("string"!=typeof t||!t.startsWith("/"))throw new i("'route' must be a string starting with \"/\"!");this._window.history.pushState({},"",t)}},{key:"run",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){};if("function"!=typeof e)throw new i("'callback' must be a function!");f.setDocument(this._document),f.setRootTitle(this._document.title),z(t,this,V).call(this),z(t,this,X).call(this),z(t,this,Y).call(this),e()}}],null&&H(e.prototype,null),r&&H(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,r}();function J(t){for(var e in this._routes){var r=new RegExp("^".concat(e.replace(/\{(\w+)\}/g,"(?<$1>[^/{}]+)"),"$"));if(r.test(t)){var n=r.exec(t).groups;return z(L,this,K).call(this,e),z(L,this,N).call(this,e,n),this._routes[e]}}}function K(t){var e={},r=location.search;if(!r.length)return!1;r.slice(1).split("&").forEach(function(t){var r,n,o=(r=t.split("="),n=2,function(t){if(Array.isArray(t))return t}(r)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,u,c=[],a=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;a=!1}else for(;!(a=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);a=!0);}catch(t){l=!0,o=t}finally{try{if(!a&&null!=r.return&&(u=r.return(),Object(u)!==u))return}finally{if(l)throw o}}return c}}(r,n)||function(t,e){if(t){if("string"==typeof t)return $(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?$(t,e):void 0}}(r,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),i=o[0],u=o[1];e[i]=u}),this._routes[t].meta.query=W({},e)}function N(t,e){this._routes[t].meta.params=W({},e)}function Q(t){try{var e,r=null!==(e=z(L,this,J).call(this,t))&&void 0!==e?e:this._defaultRoute,n=r.title,o=r.template,i=r.middlewares,u=r.meta;f.setTitle(n),z(L,this,Z).call(this,i),this._document.querySelector(this._rootElement).innerHTML=w.render(o,u)}catch(e){console.error("Error to inject route template:",t,e)}}function V(){var t=this;this._window.addEventListener("popstate",function(e){var r=e.target.location.pathname;z(L,t,Q).call(t,r)})}function X(){var t=this._window.location.pathname;z(L,this,Q).call(this,t)}function Y(){var t=this;P.findAll("a",this._document).each(function(e){A.onClick(e,function(e){if(e.target.hasAttribute("data-link"))return!1;e.preventDefault();var r=e.target.getAttribute("href");t._setRouteToURL(r),z(L,t,Q).call(t,r)})})}function Z(t){try{t.length&&t.forEach(function(t){return t()})}catch(t){console.error("Error executing middleware:",t)}}function tt(t){return tt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},tt(t)}function et(t){return function(t){if(Array.isArray(t))return rt(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return rt(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?rt(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function rt(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}function nt(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,ot(n.key),n)}}function ot(t){var e=function(t){if("object"!=tt(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var r=e.call(t,"string");if("object"!=tt(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==tt(e)?e:e+""}function it(t,e){return it=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},it(t,e)}L=G,B(G,"_window",void 0),B(G,"_document",void 0),B(G,"_rootElement","#root"),B(G,"_routes",{}),B(G,"_currentRoute",""),B(G,"_routePrefix",""),B(G,"_defaultRoute",new M({title:"404",template:function(){return"404 | Page not found!"}}));var ut=function(t){function e(){throw function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),new Error("".concat((this instanceof e?this.constructor:void 0).name,' class must not be called with "new" keyword!'))}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&it(t,e)}(e,t),r=e,n=[{key:"add",value:function(t,e){if("string"!=typeof t)throw new i("'route' must be a string!");if("function"!=typeof e)throw new i("'callback' must be a function!");return this._routes[this._routePrefix+t]=new M({template:e}),this._currentRoute=t,this}},{key:"group",value:function(t,e){if("string"!=typeof t||!t.startsWith("/"))throw new i("'prefix' must be a string!");if("function"!=typeof e)throw new i("'callback' must be a function!");var r=this._routePrefix;return this._routePrefix=t,e(),this._routePrefix=r,this}},{key:"middleware",value:function(t){if(!Array.isArray(t))throw new i("'middlewares' must be an array!");var e;if(this._routePrefix)for(var r in this._routes){var n;r.startsWith(this._routePrefix)&&(n=this._routes[r].middlewares).push.apply(n,et(t))}else(e=this._routes[this._routePrefix+this._currentRoute].middlewares).push.apply(e,et(t))}},{key:"title",value:function(t){if("string"!=typeof t)throw new i("'value' must be a string!");this._routes[this._routePrefix+this._currentRoute].title=t}},{key:"redirect",value:function(t){var e;if("string"!=typeof t||!t.startsWith("/"))throw new i("'to' must be a string starting route with \"/\"!");this._setRouteToURL(t);var r=null!==(e=this._routes[t])&&void 0!==e?e:this._defaultRoute,n=r.template,o=r.meta;return w.render(n,o)}}],null&&nt(r.prototype,null),n&&nt(r,n),Object.defineProperty(r,"prototype",{writable:!1}),r;var r,n}(G);window.Route=ut,window.Router=G})();
@@ -1,26 +1,26 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>SPA | JavaScript</title>
8
- <link rel="stylesheet" href="/assets/css/styles.css">
9
- </head>
10
- <body>
11
- <h1>SPA Page</h1>
12
- <ul>
13
- <li><a href="/">Welcome</a></li>
14
- <li><a href="/users">Users</a></li>
15
- <li><a href="/blog">Blog</a></li>
16
- <li><a href="/test">404 | Not Found</a></li>
17
- <li><a href="/redirection">Redirection</a></li>
18
- <li><a href="https://github.com/ArefShojaei/Lite-PHP/" data-link>Github</a></li>
19
- </ul>
20
-
21
- <div id="root"></div>
22
-
23
- <script src="/assets/js/router.min.js"></script>
24
- <script src="/assets/js/app.js"></script>
25
- </body>
26
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>SPA | JavaScript</title>
8
+ <link rel="stylesheet" href="/assets/css/styles.css">
9
+ </head>
10
+ <body>
11
+ <h1>SPA Page</h1>
12
+ <ul>
13
+ <li><a href="/">Welcome</a></li>
14
+ <li><a href="/users">Users</a></li>
15
+ <li><a href="/blog">Blog</a></li>
16
+ <li><a href="/test">404 | Not Found</a></li>
17
+ <li><a href="/redirection">Redirection</a></li>
18
+ <li><a href="https://github.com/ArefShojaei" data-link>Github</a></li>
19
+ </ul>
20
+
21
+ <div id="root"></div>
22
+
23
+ <script src="/assets/js/router.min.js"></script>
24
+ <script src="/assets/js/app.js"></script>
25
+ </body>
26
+ </html>
package/example/server.js CHANGED
@@ -1,18 +1,18 @@
1
- const express = require('express');
2
- const path = require('path');
3
- const app = express()
4
- const PORT = 8000
5
-
6
- app.use(express.static(path.join(__dirname)))
7
-
8
- app.get("/", (req, res) => {
9
- try {
10
- const filePath = path.join(__dirname, "\\index.html")
11
-
12
- res.status(200).sendFile(filePath)
13
- } catch (error) {
14
- console.log(error);
15
- }
16
- })
17
-
1
+ const express = require("express");
2
+ const path = require("path");
3
+ const app = express()
4
+ const PORT = 8000
5
+
6
+ app.use(express.static(path.join(__dirname)))
7
+
8
+ app.get("*", (req, res) => {
9
+ try {
10
+ const filePath = path.join(__dirname, "index.html")
11
+
12
+ res.status(200).sendFile(filePath)
13
+ } catch (error) {
14
+ console.log(error);
15
+ }
16
+ })
17
+
18
18
  app.listen(PORT, () => console.log(`Server is running -> http://localhost:${PORT}`))
package/index.js CHANGED
@@ -1,5 +1,7 @@
1
- import Router from "./src/router.js";
2
- import Route from "./src/route.js";
3
-
4
-
1
+ import Router from "./src/router.js";
2
+ import Route from "./src/route.js";
3
+
4
+ window.Route = Route
5
+ window.Router = Router
6
+
5
7
  export { Router, Route }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aref-shojaei/router",
3
- "version": "1.0.1",
4
- "description": "JavaScript Router (SPA)",
3
+ "version": "1.1.0",
4
+ "description": "JavaScript Routing for Front-end (SPA)",
5
5
  "main": "index.js",
6
6
  "directories": {
7
7
  "test": "tests",
@@ -10,6 +10,8 @@
10
10
  "example": "example"
11
11
  },
12
12
  "scripts": {
13
+ "build": "webpack --mode=production",
14
+ "watch": "webpack --watch --mode=development",
13
15
  "test": "jest"
14
16
  },
15
17
  "jest": {
@@ -34,10 +36,14 @@
34
36
  },
35
37
  "homepage": "https://github.com/ArefShojaei/Router#readme",
36
38
  "devDependencies": {
39
+ "@babel/cli": "^7.28.6",
37
40
  "@babel/core": "^7.26.0",
38
41
  "@babel/preset-env": "^7.26.0",
39
42
  "babel-jest": "^29.7.0",
43
+ "babel-loader": "^10.0.0",
40
44
  "jest": "^29.7.0",
41
- "jsdom": "^25.0.1"
45
+ "jsdom": "^25.0.1",
46
+ "webpack": "^5.105.1",
47
+ "webpack-cli": "^6.0.1"
42
48
  }
43
- }
49
+ }
package/src/dto/route.js CHANGED
@@ -1,18 +1,14 @@
1
- export default class Route {
2
- title = ""
3
-
4
- template
5
-
6
- middlewares = []
7
-
8
- meta = {
9
- params : {},
10
- query : {},
11
- }
12
-
13
-
14
- constructor({ title, template }) {
15
- this.title = title ?? this.title
16
- this.template = template
17
- }
1
+ export default class Route {
2
+ title = ""
3
+ template
4
+ middlewares = []
5
+ meta = {
6
+ params : {},
7
+ query : {},
8
+ }
9
+
10
+ constructor({ title, template }) {
11
+ this.title = title ?? this.title
12
+ this.template = template
13
+ }
18
14
  }
package/src/exception.js CHANGED
@@ -1,6 +1,6 @@
1
- export class InvalidArgumentTypeError extends Error {
2
- constructor(message) {
3
- super(message)
4
- this.name = "Invalid argument error"
5
- }
1
+ export class InvalidArgumentTypeError extends Error {
2
+ constructor(message) {
3
+ super(message)
4
+ this.name = "Invalid argument error"
5
+ }
6
6
  }
package/src/page.js CHANGED
@@ -1,92 +1,92 @@
1
- import { InvalidArgumentTypeError } from "./exception.js"
2
-
3
- /**
4
- * @abstract
5
- */
6
- export default class Page {
7
- /**
8
- * Default page title
9
- */
10
- static #root = ""
11
-
12
- /**
13
- * Updated page title
14
- */
15
- static #title = ""
16
-
17
-
18
- static #document
19
-
20
-
21
- constructor() {
22
- throw new Error(`${new.target.name} class must not be called with \"new\" keyword!`)
23
- }
24
-
25
- /**
26
- * @param {Document} document
27
- */
28
- static setDocument(document) {
29
- if (typeof document !== "object") throw new InvalidArgumentTypeError("'document' must be a Document object!")
30
-
31
- this.#document = document
32
- }
33
-
34
- /**
35
- * @returns {Document}
36
- */
37
- static _getDocument() {
38
- return this.#document
39
- }
40
-
41
- /**
42
- * @param {string} value
43
- * @returns {void}
44
- */
45
- static setTitle(value) {
46
- if (typeof value !== "string") throw new InvalidArgumentTypeError("'title' must be a string!")
47
-
48
-
49
- this.#title = value
50
-
51
- this.#updateTitle()
52
- }
53
-
54
- /**
55
- * @param {string} value
56
- * @returns {void}
57
- */
58
- static getTitle() {
59
- return this.#title || this.#root
60
- }
61
-
62
- /**
63
- * @param {string} value
64
- * @returns {void}
65
- */
66
- static setRootTitle(value) {
67
- if (typeof value !== "string") throw new InvalidArgumentTypeError("'value' must be a string!")
68
-
69
-
70
- this.#root = value
71
-
72
- this.#updateTitle()
73
- }
74
-
75
- /**
76
- * @returns {string}
77
- */
78
- static getRootTitle() {
79
- return this.#root
80
- }
81
-
82
- /**
83
- * @returns {void}
84
- */
85
- static #updateTitle() {
86
- const document = this._getDocument()
87
-
88
- !this.getTitle()
89
- ? (document.title = this.getRootTitle())
90
- : (document.title = this.getTitle())
91
- }
1
+ import { InvalidArgumentTypeError } from "./exception.js"
2
+
3
+ /**
4
+ * @abstract
5
+ */
6
+ export default class Page {
7
+ /**
8
+ * Default page title
9
+ */
10
+ static #root = ""
11
+
12
+ /**
13
+ * Updated page title
14
+ */
15
+ static #title = ""
16
+
17
+
18
+ static #document
19
+
20
+
21
+ constructor() {
22
+ throw new Error(`${new.target.name} class must not be called with \"new\" keyword!`)
23
+ }
24
+
25
+ /**
26
+ * @param {Document} document
27
+ */
28
+ static setDocument(document) {
29
+ if (typeof document !== "object") throw new InvalidArgumentTypeError("'document' must be a Document object!")
30
+
31
+ this.#document = document
32
+ }
33
+
34
+ /**
35
+ * @returns {Document}
36
+ */
37
+ static _getDocument() {
38
+ return this.#document
39
+ }
40
+
41
+ /**
42
+ * @param {string} value
43
+ * @returns {void}
44
+ */
45
+ static setTitle(value) {
46
+ if (typeof value !== "string") throw new InvalidArgumentTypeError("'title' must be a string!")
47
+
48
+
49
+ this.#title = value
50
+
51
+ this.#updateTitle()
52
+ }
53
+
54
+ /**
55
+ * @param {string} value
56
+ * @returns {void}
57
+ */
58
+ static getTitle() {
59
+ return this.#title || this.#root
60
+ }
61
+
62
+ /**
63
+ * @param {string} value
64
+ * @returns {void}
65
+ */
66
+ static setRootTitle(value) {
67
+ if (typeof value !== "string") throw new InvalidArgumentTypeError("'value' must be a string!")
68
+
69
+
70
+ this.#root = value
71
+
72
+ this.#updateTitle()
73
+ }
74
+
75
+ /**
76
+ * @returns {string}
77
+ */
78
+ static getRootTitle() {
79
+ return this.#root
80
+ }
81
+
82
+ /**
83
+ * @returns {void}
84
+ */
85
+ static #updateTitle() {
86
+ const document = this._getDocument()
87
+
88
+ !this.getTitle()
89
+ ? (document.title = this.getRootTitle())
90
+ : (document.title = this.getTitle())
91
+ }
92
92
  }
package/src/route.js CHANGED
@@ -1,104 +1,104 @@
1
- import Router from "./router.js"
2
- import View from "./view.js";
3
- import { InvalidArgumentTypeError } from "./exception.js"
4
- import RouteDTO from "./dto/route.js"
5
-
6
-
7
- /**
8
- * @abstract
9
- */
10
- export default class Route extends Router {
11
- constructor() {
12
- throw new Error(`${new.target.name} class must not be called with \"new\" keyword!`)
13
- }
14
-
15
- /**
16
- * @param {string} route
17
- * @param {fucntion} callback
18
- * @returns {Route}
19
- */
20
- static addRoute(route, callback) {
21
- if (typeof route !== "string") throw new InvalidArgumentTypeError("'route' must be a string!")
22
-
23
- if (typeof callback !== "function") throw new InvalidArgumentTypeError("'callback' must be a function!")
24
-
25
-
26
- this._routes[this._routePrefix + route] = new RouteDTO({ template : callback })
27
-
28
- this._currentRoute = route;
29
-
30
- return this;
31
- }
32
-
33
- /**
34
- * @param {string} prefix
35
- * @param {function} callback
36
- * @returns {Route}
37
- */
38
- static group(prefix, callback) {
39
- if (typeof prefix !== "string" || !prefix.startsWith("/")) throw new InvalidArgumentTypeError("'prefix' must be a string!")
40
-
41
- if (typeof callback !== "function") throw new InvalidArgumentTypeError("'callback' must be a function!")
42
-
43
-
44
- const previousPrefix = this._routePrefix
45
-
46
- this._routePrefix = prefix;
47
-
48
- callback();
49
-
50
- this._routePrefix = previousPrefix
51
-
52
- return this;
53
- }
54
-
55
- /**
56
- * @param {array} middlewares
57
- * @returns {void}
58
- */
59
- static middleware(middlewares) {
60
- if (!Array.isArray(middlewares)) throw new InvalidArgumentTypeError("'middlewares' must be an array!")
61
-
62
- const isDefinedRoutePrefix = this._routePrefix ? true : false
63
-
64
- // Add middlewares to single route
65
- if (!isDefinedRoutePrefix) {
66
- this._routes[this._routePrefix + this._currentRoute]["middlewares"].push(...middlewares);
67
-
68
- return;
69
- }
70
-
71
- // Add middlewares to the group of routes
72
- for (const route in this._routes) {
73
- if (!route.startsWith(this._routePrefix)) continue;
74
-
75
- this._routes[route]["middlewares"].push(...middlewares);
76
- }
77
- }
78
-
79
- /**
80
- * Set route page title
81
- * @param {string} value
82
- * @returns {void}
83
- */
84
- static title(value) {
85
- if (typeof value !== "string") throw new InvalidArgumentTypeError("'value' must be a string!")
86
-
87
- this._routes[this._routePrefix + this._currentRoute]["title"] = value
88
- }
89
-
90
- /**
91
- * @param {string} to - Route pointer
92
- * @returns {string}
93
- */
94
- static redirect(to) {
95
- if (typeof to !== "string" || !to.startsWith("/")) throw new InvalidArgumentTypeError("'to' must be a string starting route with \"/\"!")
96
-
97
-
98
- this._setRouteToURL(to)
99
-
100
- const { template, meta } = this._routes[to] ?? this._defaultRoute;
101
-
102
- return View.render(template, meta)
103
- }
1
+ import Router from "./router.js"
2
+ import View from "./view.js";
3
+ import { InvalidArgumentTypeError } from "./exception.js"
4
+ import RouteDTO from "./dto/route.js"
5
+
6
+
7
+ /**
8
+ * @abstract
9
+ */
10
+ export default class Route extends Router {
11
+ constructor() {
12
+ throw new Error(`${new.target.name} class must not be called with \"new\" keyword!`)
13
+ }
14
+
15
+ /**
16
+ * @param {string} route
17
+ * @param {fucntion} callback
18
+ * @returns {Route}
19
+ */
20
+ static add(route, callback) {
21
+ if (typeof route !== "string") throw new InvalidArgumentTypeError("'route' must be a string!")
22
+
23
+ if (typeof callback !== "function") throw new InvalidArgumentTypeError("'callback' must be a function!")
24
+
25
+
26
+ this._routes[this._routePrefix + route] = new RouteDTO({ template : callback })
27
+
28
+ this._currentRoute = route;
29
+
30
+ return this;
31
+ }
32
+
33
+ /**
34
+ * @param {string} prefix
35
+ * @param {function} callback
36
+ * @returns {Route}
37
+ */
38
+ static group(prefix, callback) {
39
+ if (typeof prefix !== "string" || !prefix.startsWith("/")) throw new InvalidArgumentTypeError("'prefix' must be a string!")
40
+
41
+ if (typeof callback !== "function") throw new InvalidArgumentTypeError("'callback' must be a function!")
42
+
43
+
44
+ const previousPrefix = this._routePrefix
45
+
46
+ this._routePrefix = prefix;
47
+
48
+ callback();
49
+
50
+ this._routePrefix = previousPrefix
51
+
52
+ return this;
53
+ }
54
+
55
+ /**
56
+ * @param {array} middlewares
57
+ * @returns {void}
58
+ */
59
+ static middleware(middlewares) {
60
+ if (!Array.isArray(middlewares)) throw new InvalidArgumentTypeError("'middlewares' must be an array!")
61
+
62
+ const isDefinedRoutePrefix = this._routePrefix ? true : false
63
+
64
+ // Add middlewares to single route
65
+ if (!isDefinedRoutePrefix) {
66
+ this._routes[this._routePrefix + this._currentRoute]["middlewares"].push(...middlewares);
67
+
68
+ return;
69
+ }
70
+
71
+ // Add middlewares to the group of routes
72
+ for (const route in this._routes) {
73
+ if (!route.startsWith(this._routePrefix)) continue;
74
+
75
+ this._routes[route]["middlewares"].push(...middlewares);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Set route page title
81
+ * @param {string} value
82
+ * @returns {void}
83
+ */
84
+ static title(value) {
85
+ if (typeof value !== "string") throw new InvalidArgumentTypeError("'value' must be a string!")
86
+
87
+ this._routes[this._routePrefix + this._currentRoute]["title"] = value
88
+ }
89
+
90
+ /**
91
+ * @param {string} to - Route pointer
92
+ * @returns {string}
93
+ */
94
+ static redirect(to) {
95
+ if (typeof to !== "string" || !to.startsWith("/")) throw new InvalidArgumentTypeError("'to' must be a string starting route with \"/\"!")
96
+
97
+
98
+ this._setRouteToURL(to)
99
+
100
+ const { template, meta } = this._routes[to] ?? this._defaultRoute;
101
+
102
+ return View.render(template, meta)
103
+ }
104
104
  }