diff --git a/pos-module-user-invites/LICENSE b/pos-module-user-invites/LICENSE new file mode 100644 index 00000000..f8dcd169 --- /dev/null +++ b/pos-module-user-invites/LICENSE @@ -0,0 +1,20 @@ +Copyright platformOS and other contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/pos-module-user-invites/app/lib/hooks/hook_user_invites_current_profile.liquid b/pos-module-user-invites/app/lib/hooks/hook_user_invites_current_profile.liquid new file mode 100644 index 00000000..77c7b4a1 --- /dev/null +++ b/pos-module-user-invites/app/lib/hooks/hook_user_invites_current_profile.liquid @@ -0,0 +1,4 @@ +{% liquid + function profile = 'modules/user/helpers/current_profile' + return profile +%} diff --git a/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-easyMde.js b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-easyMde.js new file mode 100644 index 00000000..2b669e3e --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-easyMde.js @@ -0,0 +1,7 @@ +/** + * easymde v2.20.0 + * Copyright Jeroen Akkerman + * @link https://github.com/ionaru/easy-markdown-editor + * @license MIT + */ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).EasyMDE=e()}}((function(){return function e(t,n,i){function r(a,l){if(!n[a]){if(!t[a]){var s="function"==typeof require&&require;if(!l&&s)return s(a,!0);if(o)return o(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[a]={exports:{}};t[a][0].call(c.exports,(function(e){return r(t[a][1][e]||e)}),c,c.exports,e,t,n,i)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,n=/^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,i=/[*+-]\s/;function r(e,n){var i=n.line,r=0,o=0,a=t.exec(e.getLine(i)),l=a[1];do{var s=i+(r+=1),u=e.getLine(s),c=t.exec(u);if(c){var d=c[1],h=parseInt(a[3],10)+r-o,f=parseInt(c[3],10),p=f;if(l!==d||isNaN(f)){if(l.length>d.length)return;if(l.lengthf&&(p=h+1),e.replaceRange(u.replace(t,d+p+c[4]+c[5]),{line:s,ch:0},{line:s,ch:u.length})}}while(c)}e.commands.newlineAndIndentContinueMarkdownList=function(o){if(o.getOption("disableInput"))return e.Pass;for(var a=o.listSelections(),l=[],s=0;s\s*$/.test(p),x=!/>\s*$/.test(p);(v||x)&&o.replaceRange("",{line:u.line,ch:0},{line:u.line,ch:u.ch+1}),l[s]="\n"}else{var y=m[1],b=m[5],D=!(i.test(m[2])||m[2].indexOf(">")>=0),C=D?parseInt(m[3],10)+1+m[4]:m[2].replace("x"," ");l[s]="\n"+y+C+b,D&&r(o,u)}}o.replaceSelections(l)}})("object"==typeof n&&"object"==typeof t?e("../../lib/codemirror"):CodeMirror)},{"../../lib/codemirror":10}],7:[function(e,t,n){(function(e){"use strict";e.overlayMode=function(t,n,i){return{startState:function(){return{base:e.startState(t),overlay:e.startState(n),basePos:0,baseCur:null,overlayPos:0,overlayCur:null,streamSeen:null}},copyState:function(i){return{base:e.copyState(t,i.base),overlay:e.copyState(n,i.overlay),basePos:i.basePos,baseCur:null,overlayPos:i.overlayPos,overlayCur:null}},token:function(e,r){return(e!=r.streamSeen||Math.min(r.basePos,r.overlayPos)c);d++){var h=e.getLine(u++);l=null==l?h:l+"\n"+h}s*=2,t.lastIndex=n.ch;var f=t.exec(l);if(f){var p=l.slice(0,f.index).split("\n"),m=f[0].split("\n"),g=n.line+p.length-1,v=p[p.length-1].length;return{from:i(g,v),to:i(g+m.length-1,1==m.length?v+m[0].length:m[m.length-1].length),match:f}}}}function s(e,t,n){for(var i,r=0;r<=e.length;){t.lastIndex=r;var o=t.exec(e);if(!o)break;var a=o.index+o[0].length;if(a>e.length-n)break;(!i||a>i.index+i[0].length)&&(i=o),r=o.index+1}return i}function u(e,t,n){t=r(t,"g");for(var o=n.line,a=n.ch,l=e.firstLine();o>=l;o--,a=-1){var u=e.getLine(o),c=s(u,t,a<0?0:u.length-a);if(c)return{from:i(o,c.index),to:i(o,c.index+c[0].length),match:c}}}function c(e,t,n){if(!o(t))return u(e,t,n);t=r(t,"gm");for(var a,l=1,c=e.getLine(n.line).length-n.ch,d=n.line,h=e.firstLine();d>=h;){for(var f=0;f=h;f++){var p=e.getLine(d--);a=null==a?p:p+"\n"+a}l*=2;var m=s(a,t,c);if(m){var g=a.slice(0,m.index).split("\n"),v=m[0].split("\n"),x=d+g.length,y=g[g.length-1].length;return{from:i(x,y),to:i(x+v.length-1,1==v.length?y+v[0].length:v[v.length-1].length),match:m}}}}function d(e,t,n,i){if(e.length==t.length)return n;for(var r=0,o=n+Math.max(0,e.length-t.length);;){if(r==o)return r;var a=r+o>>1,l=i(e.slice(0,a)).length;if(l==n)return a;l>n?o=a:r=a+1}}function h(e,r,o,a){if(!r.length)return null;var l=a?t:n,s=l(r).split(/\r|\n\r?/);e:for(var u=o.line,c=o.ch,h=e.lastLine()+1-s.length;u<=h;u++,c=0){var f=e.getLine(u).slice(c),p=l(f);if(1==s.length){var m=p.indexOf(s[0]);if(-1==m)continue e;return o=d(f,p,m,l)+c,{from:i(u,d(f,p,m,l)+c),to:i(u,d(f,p,m+s[0].length,l)+c)}}var g=p.length-s[0].length;if(p.slice(g)==s[0]){for(var v=1;v=h;u--,c=-1){var f=e.getLine(u);c>-1&&(f=f.slice(0,c));var p=l(f);if(1==s.length){var m=p.lastIndexOf(s[0]);if(-1==m)continue e;return{from:i(u,d(f,p,m,l)),to:i(u,d(f,p,m+s[0].length,l))}}var g=s[s.length-1];if(p.slice(0,g.length)==g){var v=1;for(o=u-s.length+1;v(this.doc.getLine(n.line)||"").length&&(n.ch=0,n.line++)),0!=e.cmpPos(n,this.doc.clipPos(n))))return this.atOccurrence=!1;var r=this.matches(t,n);if(this.afterEmptyMatch=r&&0==e.cmpPos(r.from,r.to),r)return this.pos=r,this.atOccurrence=!0,this.pos.match||!0;var o=i(t?this.doc.firstLine():this.doc.lastLine()+1,0);return this.pos={from:o,to:o},this.atOccurrence=!1},from:function(){if(this.atOccurrence)return this.pos.from},to:function(){if(this.atOccurrence)return this.pos.to},replace:function(t,n){if(this.atOccurrence){var r=e.splitLines(t);this.doc.replaceRange(r,this.pos.from,this.pos.to,n),this.pos.to=i(this.pos.from.line+r.length-1,r[r.length-1].length+(1==r.length?this.pos.from.ch:0))}}},e.defineExtension("getSearchCursor",(function(e,t,n){return new p(this.doc,e,t,n)})),e.defineDocExtension("getSearchCursor",(function(e,t,n){return new p(this,e,t,n)})),e.defineExtension("selectMatches",(function(t,n){for(var i=[],r=this.getSearchCursor(t,this.getCursor("from"),n);r.findNext()&&!(e.cmpPos(r.to(),this.getCursor("to"))>0);)i.push({anchor:r.from(),head:r.to()});i.length&&this.setSelections(i,0)}))})("object"==typeof n&&"object"==typeof t?e("../../lib/codemirror"):CodeMirror)},{"../../lib/codemirror":10}],9:[function(e,t,n){(function(e){"use strict";function t(e){e.state.markedSelection&&e.operation((function(){!function(e){if(!e.somethingSelected())return a(e);if(e.listSelections().length>1)return l(e);var t=e.getCursor("start"),n=e.getCursor("end"),i=e.state.markedSelection;if(!i.length)return o(e,t,n);var s=i[0].find(),u=i[i.length-1].find();if(!s||!u||n.line-t.line<=8||r(t,u.to)>=0||r(n,s.from)<=0)return l(e);for(;r(t,s.from)>0;)i.shift().clear(),s=i[0].find();for(r(t,s.from)<0&&(s.to.line-t.line<8?(i.shift().clear(),o(e,t,s.to,0)):o(e,t,s.from,0));r(n,u.to)<0;)i.pop().clear(),u=i[i.length-1].find();r(n,u.to)>0&&(n.line-u.from.line<8?(i.pop().clear(),o(e,u.from,n)):o(e,u.to,n))}(e)}))}function n(e){e.state.markedSelection&&e.state.markedSelection.length&&e.operation((function(){a(e)}))}e.defineOption("styleSelectedText",!1,(function(i,r,o){var s=o&&o!=e.Init;r&&!s?(i.state.markedSelection=[],i.state.markedSelectionStyle="string"==typeof r?r:"CodeMirror-selectedtext",l(i),i.on("cursorActivity",t),i.on("change",n)):!r&&s&&(i.off("cursorActivity",t),i.off("change",n),a(i),i.state.markedSelection=i.state.markedSelectionStyle=null)}));var i=e.Pos,r=e.cmpPos;function o(e,t,n,o){if(0!=r(t,n))for(var a=e.state.markedSelection,l=e.state.markedSelectionStyle,s=t.line;;){var u=s==t.line?t:i(s,0),c=s+8,d=c>=n.line,h=d?n:i(c,0),f=e.markText(u,h,{className:l});if(null==o?a.push(f):a.splice(o++,0,f),d)break;s=c}}function a(e){for(var t=e.state.markedSelection,n=0;n2),v=/Android/.test(e),x=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=g||/Mac/.test(t),b=/\bCrOS\b/.test(e),D=/win/i.test(t),C=h&&e.match(/Version\/(\d*\.\d*)/);C&&(C=Number(C[1])),C&&C>=15&&(h=!1,s=!0);var w=y&&(u||h&&(null==C||C<12.11)),k=n||a&&l>=9;function S(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var F,A=function(e,t){var n=e.className,i=S(t).exec(n);if(i){var r=n.slice(i.index+i[0].length);e.className=n.slice(0,i.index)+(r?i[1]+r:"")}};function E(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function L(e,t){return E(e).appendChild(t)}function T(e,t,n,i){var r=document.createElement(e);if(n&&(r.className=n),i&&(r.style.cssText=i),"string"==typeof t)r.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return a+(t-o);a+=l-o,a+=n-a%n,o=l+1}}g?z=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:a&&(z=function(e){try{e.select()}catch(e){}});var j=function(){this.id=null,this.f=null,this.time=0,this.handler=P(this.onTimeout,this)};function q(e,t){for(var n=0;n=t)return i+Math.min(a,t-r);if(r+=o-i,i=o+1,(r+=n-r%n)>=t)return i}}var K=[""];function Z(e){for(;K.length<=e;)K.push(Y(K)+" ");return K[e]}function Y(e){return e[e.length-1]}function Q(e,t){for(var n=[],i=0;i"€"&&(e.toUpperCase()!=e.toLowerCase()||te.test(e))}function ie(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ne(e))||t.test(e):ne(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var oe=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ae(e){return e.charCodeAt(0)>=768&&oe.test(e)}function le(e,t,n){for(;(n<0?t>0:tn?-1:1;;){if(t==n)return t;var r=(t+n)/2,o=i<0?Math.ceil(r):Math.floor(r);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+i}}var ue=null;function ce(e,t,n){var i;ue=null;for(var r=0;rt)return r;o.to==t&&(o.from!=o.to&&"before"==n?i=r:ue=r),o.from==t&&(o.from!=o.to&&"before"!=n?i=r:ue=r)}return null!=i?i:ue}var de=function(){var e=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,t=/[stwN]/,n=/[LRr]/,i=/[Lb1n]/,r=/[1n]/;function o(e,t,n){this.level=e,this.from=t,this.to=n}return function(a,l){var s="ltr"==l?"L":"R";if(0==a.length||"ltr"==l&&!e.test(a))return!1;for(var u,c=a.length,d=[],h=0;h-1&&(i[t]=r.slice(0,o).concat(r.slice(o+1)))}}}function ve(e,t){var n=me(e,t);if(n.length)for(var i=Array.prototype.slice.call(arguments,2),r=0;r0}function De(e){e.prototype.on=function(e,t){pe(this,e,t)},e.prototype.off=function(e,t){ge(this,e,t)}}function Ce(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function we(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function ke(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Se(e){Ce(e),we(e)}function Fe(e){return e.target||e.srcElement}function Ae(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Ee,Le,Te=function(){if(a&&l<9)return!1;var e=T("div");return"draggable"in e||"dragDrop"in e}();function Me(e){if(null==Ee){var t=T("span","​");L(e,T("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Ee=t.offsetWidth<=1&&t.offsetHeight>2&&!(a&&l<8))}var n=Ee?T("span","​"):T("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}function Be(e){if(null!=Le)return Le;var t=L(e,document.createTextNode("AخA")),n=F(t,0,1).getBoundingClientRect(),i=F(t,1,2).getBoundingClientRect();return E(e),!(!n||n.left==n.right)&&(Le=i.right-n.right<3)}var Ne,Oe=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],i=e.length;t<=i;){var r=e.indexOf("\n",t);-1==r&&(r=e.length);var o=e.slice(t,"\r"==e.charAt(r-1)?r-1:r),a=o.indexOf("\r");-1!=a?(n.push(o.slice(0,a)),t+=a+1):(n.push(o),t=r+1)}return n}:function(e){return e.split(/\r\n?|\n/)},Ie=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},ze="oncopy"in(Ne=T("div"))||(Ne.setAttribute("oncopy","return;"),"function"==typeof Ne.oncopy),He=null;var Re={},Pe={};function _e(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Re[e]=t}function We(e){if("string"==typeof e&&Pe.hasOwnProperty(e))e=Pe[e];else if(e&&"string"==typeof e.name&&Pe.hasOwnProperty(e.name)){var t=Pe[e.name];"string"==typeof t&&(t={name:t}),(e=ee(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return We("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return We("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function je(e,t){t=We(t);var n=Re[t.name];if(!n)return je(e,"text/plain");var i=n(e,t);if(qe.hasOwnProperty(t.name)){var r=qe[t.name];for(var o in r)r.hasOwnProperty(o)&&(i.hasOwnProperty(o)&&(i["_"+o]=i[o]),i[o]=r[o])}if(i.name=t.name,t.helperType&&(i.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)i[a]=t.modeProps[a];return i}var qe={};function Ue(e,t){_(t,qe.hasOwnProperty(e)?qe[e]:qe[e]={})}function $e(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var i in t){var r=t[i];r instanceof Array&&(r=r.concat([])),n[i]=r}return n}function Ge(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function Ve(e,t,n){return!e.startState||e.startState(t,n)}var Xe=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Ke(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var i=0;;++i){var r=n.children[i],o=r.chunkSize();if(t=e.first&&tn?it(n,Ke(e,n).text.length):function(e,t){var n=e.ch;return null==n||n>t?it(e.line,t):n<0?it(e.line,0):e}(t,Ke(e,t.line).text.length)}function dt(e,t){for(var n=[],i=0;i=this.string.length},Xe.prototype.sol=function(){return this.pos==this.lineStart},Xe.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Xe.prototype.next=function(){if(this.post},Xe.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Xe.prototype.skipToEnd=function(){this.pos=this.string.length},Xe.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Xe.prototype.backUp=function(e){this.pos-=e},Xe.prototype.column=function(){return this.lastColumnPos0?null:(i&&!1!==t&&(this.pos+=i[0].length),i)}var r=function(e){return n?e.toLowerCase():e};if(r(this.string.substr(this.pos,e.length))==r(e))return!1!==t&&(this.pos+=e.length),!0},Xe.prototype.current=function(){return this.string.slice(this.start,this.pos)},Xe.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Xe.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Xe.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ht=function(e,t){this.state=e,this.lookAhead=t},ft=function(e,t,n,i){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=i||0,this.baseTokens=null,this.baseTokenPos=1};function pt(e,t,n,i){var r=[e.state.modeGen],o={};wt(e,t.text,e.doc.mode,n,(function(e,t){return r.push(e,t)}),o,i);for(var a=n.state,l=function(i){n.baseTokens=r;var l=e.state.overlays[i],s=1,u=0;n.state=!0,wt(e,t.text,l.mode,n,(function(e,t){for(var n=s;ue&&r.splice(s,1,e,r[s+1],i),s+=2,u=Math.min(e,i)}if(t)if(l.opaque)r.splice(n,s-n,e,"overlay "+t),s=n+2;else for(;ne.options.maxHighlightLength&&$e(e.doc.mode,i.state),o=pt(e,t,i);r&&(i.state=r),t.stateAfter=i.save(!r),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function gt(e,t,n){var i=e.doc,r=e.display;if(!i.mode.startState)return new ft(i,!0,t);var o=function(e,t,n){for(var i,r,o=e.doc,a=n?-1:t-(e.doc.mode.innerMode?1e3:100),l=t;l>a;--l){if(l<=o.first)return o.first;var s=Ke(o,l-1),u=s.stateAfter;if(u&&(!n||l+(u instanceof ht?u.lookAhead:0)<=o.modeFrontier))return l;var c=W(s.text,null,e.options.tabSize);(null==r||i>c)&&(r=l-1,i=c)}return r}(e,t,n),a=o>i.first&&Ke(i,o-1).stateAfter,l=a?ft.fromSaved(i,a,o):new ft(i,Ve(i.mode),o);return i.iter(o,t,(function(n){vt(e,n.text,l);var i=l.line;n.stateAfter=i==t-1||i%5==0||i>=r.viewFrom&&it.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ft.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ft.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ft.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ft.fromSaved=function(e,t,n){return t instanceof ht?new ft(e,$e(e.mode,t.state),n,t.lookAhead):new ft(e,$e(e.mode,t),n)},ft.prototype.save=function(e){var t=!1!==e?$e(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ht(t,this.maxLookAhead):t};var bt=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Dt(e,t,n,i){var r,o,a=e.doc,l=a.mode,s=Ke(a,(t=ct(a,t)).line),u=gt(e,t.line,n),c=new Xe(s.text,e.options.tabSize,u);for(i&&(o=[]);(i||c.pose.options.maxHighlightLength?(l=!1,a&&vt(e,t,i,d.pos),d.pos=t.length,s=null):s=Ct(yt(n,d,i.state,h),o),h){var f=h[0].name;f&&(s="m-"+(s?f+" "+s:f))}if(!l||c!=s){for(;u=t:o.to>t);(i||(i=[])).push(new Ft(a,o.from,l?null:o.to))}}return i}(n,r,a),s=function(e,t,n){var i;if(e)for(var r=0;r=t:o.to>t)||o.from==t&&"bookmark"==a.type&&(!n||o.marker.insertLeft)){var l=null==o.from||(a.inclusiveLeft?o.from<=t:o.from0&&l)for(var y=0;yt)&&(!n||It(n,o.marker)<0)&&(n=o.marker)}return n}function _t(e,t,n,i,r){var o=Ke(e,t),a=St&&o.markedSpans;if(a)for(var l=0;l=0&&d<=0||c<=0&&d>=0)&&(c<=0&&(s.marker.inclusiveRight&&r.inclusiveLeft?rt(u.to,n)>=0:rt(u.to,n)>0)||c>=0&&(s.marker.inclusiveRight&&r.inclusiveLeft?rt(u.from,i)<=0:rt(u.from,i)<0)))return!0}}}function Wt(e){for(var t;t=Ht(e);)e=t.find(-1,!0).line;return e}function jt(e,t){var n=Ke(e,t),i=Wt(n);return n==i?t:Je(i)}function qt(e,t){if(t>e.lastLine())return t;var n,i=Ke(e,t);if(!Ut(e,i))return t;for(;n=Rt(i);)i=n.find(1,!0).line;return Je(i)+1}function Ut(e,t){var n=St&&t.markedSpans;if(n)for(var i=void 0,r=0;rt.maxLineLength&&(t.maxLineLength=n,t.maxLine=e)}))}var Kt=function(e,t,n){this.text=e,Bt(this,t),this.height=n?n(this):1};function Zt(e){e.parent=null,Mt(e)}Kt.prototype.lineNo=function(){return Je(this)},De(Kt);var Yt={},Qt={};function Jt(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?Qt:Yt;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function en(e,t){var n=M("span",null,null,s?"padding-right: .1px":null),i={pre:M("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var r=0;r<=(t.rest?t.rest.length:0);r++){var o=r?t.rest[r-1]:t.line,a=void 0;i.pos=0,i.addToken=nn,Be(e.display.measure)&&(a=he(o,e.doc.direction))&&(i.addToken=rn(i.addToken,a)),i.map=[],an(o,i,mt(e,o,t!=e.display.externalMeasured&&Je(o))),o.styleClasses&&(o.styleClasses.bgClass&&(i.bgClass=I(o.styleClasses.bgClass,i.bgClass||"")),o.styleClasses.textClass&&(i.textClass=I(o.styleClasses.textClass,i.textClass||""))),0==i.map.length&&i.map.push(0,0,i.content.appendChild(Me(e.display.measure))),0==r?(t.measure.map=i.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(i.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(s){var l=i.content.lastChild;(/\bcm-tab\b/.test(l.className)||l.querySelector&&l.querySelector(".cm-tab"))&&(i.content.className="cm-tab-wrap-hack")}return ve(e,"renderLine",e,t.line,i.pre),i.pre.className&&(i.textClass=I(i.pre.className,i.textClass||"")),i}function tn(e){var t=T("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function nn(e,t,n,i,r,o,s){if(t){var u,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var n=t,i="",r=0;ru&&d.from<=u);h++);if(d.to>=c)return e(n,i,r,o,a,l,s);e(n,i.slice(0,d.to-u),r,o,null,l,s),o=null,i=i.slice(d.to-u),u=d.to}}}function on(e,t,n,i){var r=!i&&n.widgetNode;r&&e.map.push(e.pos,e.pos+t,r),!i&&e.cm.display.input.needsContentAttribute&&(r||(r=e.content.appendChild(document.createElement("span"))),r.setAttribute("cm-marker",n.id)),r&&(e.cm.display.input.setUneditable(r),e.content.appendChild(r)),e.pos+=t,e.trailingSpace=!1}function an(e,t,n){var i=e.markedSpans,r=e.text,o=0;if(i)for(var a,l,s,u,c,d,h,f=r.length,p=0,m=1,g="",v=0;;){if(v==p){s=u=c=l="",h=null,d=null,v=1/0;for(var x=[],y=void 0,b=0;bp||C.collapsed&&D.to==p&&D.from==p)){if(null!=D.to&&D.to!=p&&v>D.to&&(v=D.to,u=""),C.className&&(s+=" "+C.className),C.css&&(l=(l?l+";":"")+C.css),C.startStyle&&D.from==p&&(c+=" "+C.startStyle),C.endStyle&&D.to==v&&(y||(y=[])).push(C.endStyle,D.to),C.title&&((h||(h={})).title=C.title),C.attributes)for(var w in C.attributes)(h||(h={}))[w]=C.attributes[w];C.collapsed&&(!d||It(d.marker,C)<0)&&(d=D)}else D.from>p&&v>D.from&&(v=D.from)}if(y)for(var k=0;k=f)break;for(var F=Math.min(f,v);;){if(g){var A=p+g.length;if(!d){var E=A>F?g.slice(0,F-p):g;t.addToken(t,E,a?a+s:s,c,p+E.length==v?u:"",l,h)}if(A>=F){g=g.slice(F-p),p=F;break}p=A,c=""}g=r.slice(o,o=n[m++]),a=Jt(n[m++],t.cm.options)}}else for(var L=1;Ln)return{map:e.measure.maps[r],cache:e.measure.caches[r],before:!0}}}function Nn(e,t,n,i){return zn(e,In(e,t),n,i)}function On(e,t){if(t>=e.display.viewFrom&&t=n.lineN&&t2&&o.push((s.bottom+u.top)/2-n.top)}}o.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),o=function(e,t,n,i){var r,o=Pn(t.map,n,i),s=o.node,u=o.start,c=o.end,d=o.collapse;if(3==s.nodeType){for(var h=0;h<4;h++){for(;u&&ae(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c1}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,i=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*i,bottom:t.bottom*i}}(e.display.measure,r))}else{var f;u>0&&(d=i="right"),r=e.options.lineWrapping&&(f=s.getClientRects()).length>1?f["right"==i?f.length-1:0]:s.getBoundingClientRect()}if(a&&l<9&&!u&&(!r||!r.left&&!r.right)){var p=s.parentNode.getClientRects()[0];r=p?{left:p.left,right:p.left+li(e.display),top:p.top,bottom:p.bottom}:Rn}for(var m=r.top-t.rect.top,g=r.bottom-t.rect.top,v=(m+g)/2,x=t.view.measure.heights,y=0;yt)&&(r=(o=s-l)-1,t>=s&&(a="right")),null!=r){if(i=e[u+2],l==s&&n==(i.insertLeft?"left":"right")&&(a=n),"left"==n&&0==r)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)i=e[2+(u-=3)],a="left";if("right"==n&&r==s-l)for(;u=0&&(n=e[r]).left==n.right;r--);return n}function Wn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=i.text.length?(s=i.text.length,u="before"):s<=0&&(s=0,u="after"),!l)return a("before"==u?s-1:s,"before"==u);function c(e,t,n){return a(n?e-1:e,1==l[t].level!=n)}var d=ce(l,s,u),h=ue,f=c(s,d,"before"==u);return null!=h&&(f.other=c(s,h,"before"!=u)),f}function Yn(e,t){var n=0;t=ct(e.doc,t),e.options.lineWrapping||(n=li(e.display)*t.ch);var i=Ke(e.doc,t.line),r=Gt(i)+Fn(e.display);return{left:n,right:n,top:r,bottom:r+i.height}}function Qn(e,t,n,i,r){var o=it(e,t,n);return o.xRel=r,i&&(o.outside=i),o}function Jn(e,t,n){var i=e.doc;if((n+=e.display.viewOffset)<0)return Qn(i.first,0,null,-1,-1);var r=et(i,n),o=i.first+i.size-1;if(r>o)return Qn(i.first+i.size-1,Ke(i,o).text.length,null,1,1);t<0&&(t=0);for(var a=Ke(i,r);;){var l=ii(e,a,r,t,n),s=Pt(a,l.ch+(l.xRel>0||l.outside>0?1:0));if(!s)return l;var u=s.find(1);if(u.line==r)return u;a=Ke(i,r=u.line)}}function ei(e,t,n,i){i-=Gn(t);var r=t.text.length,o=se((function(t){return zn(e,n,t-1).bottom<=i}),r,0);return{begin:o,end:r=se((function(t){return zn(e,n,t).top>i}),o,r)}}function ti(e,t,n,i){return n||(n=In(e,t)),ei(e,t,n,Vn(e,t,zn(e,n,i),"line").top)}function ni(e,t,n,i){return!(e.bottom<=n)&&(e.top>n||(i?e.left:e.right)>t)}function ii(e,t,n,i,r){r-=Gt(t);var o=In(e,t),a=Gn(t),l=0,s=t.text.length,u=!0,c=he(t,e.doc.direction);if(c){var d=(e.options.lineWrapping?oi:ri)(e,t,n,o,c,i,r);l=(u=1!=d.level)?d.from:d.to-1,s=u?d.to:d.from-1}var h,f,p=null,m=null,g=se((function(t){var n=zn(e,o,t);return n.top+=a,n.bottom+=a,!!ni(n,i,r,!1)&&(n.top<=r&&n.left<=i&&(p=t,m=n),!0)}),l,s),v=!1;if(m){var x=i-m.left=b.bottom?1:0}return Qn(n,g=le(t.text,g,1),f,v,i-h)}function ri(e,t,n,i,r,o,a){var l=se((function(l){var s=r[l],u=1!=s.level;return ni(Zn(e,it(n,u?s.to:s.from,u?"before":"after"),"line",t,i),o,a,!0)}),0,r.length-1),s=r[l];if(l>0){var u=1!=s.level,c=Zn(e,it(n,u?s.from:s.to,u?"after":"before"),"line",t,i);ni(c,o,a,!0)&&c.top>a&&(s=r[l-1])}return s}function oi(e,t,n,i,r,o,a){var l=ei(e,t,i,a),s=l.begin,u=l.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,d=null,h=0;h=u||f.to<=s)){var p=zn(e,i,1!=f.level?Math.min(u,f.to)-1:Math.max(s,f.from)).right,m=pm)&&(c=f,d=m)}}return c||(c=r[r.length-1]),c.fromu&&(c={from:c.from,to:u,level:c.level}),c}function ai(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Hn){Hn=T("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Hn.appendChild(document.createTextNode("x")),Hn.appendChild(T("br"));Hn.appendChild(document.createTextNode("x"))}L(e.measure,Hn);var n=Hn.offsetHeight/50;return n>3&&(e.cachedTextHeight=n),E(e.measure),n||1}function li(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=T("span","xxxxxxxxxx"),n=T("pre",[t],"CodeMirror-line-like");L(e.measure,n);var i=t.getBoundingClientRect(),r=(i.right-i.left)/10;return r>2&&(e.cachedCharWidth=r),r||10}function si(e){for(var t=e.display,n={},i={},r=t.gutters.clientLeft,o=t.gutters.firstChild,a=0;o;o=o.nextSibling,++a){var l=e.display.gutterSpecs[a].className;n[l]=o.offsetLeft+o.clientLeft+r,i[l]=o.clientWidth}return{fixedPos:ui(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:i,wrapperWidth:t.wrapper.clientWidth}}function ui(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function ci(e){var t=ai(e.display),n=e.options.lineWrapping,i=n&&Math.max(5,e.display.scroller.clientWidth/li(e.display)-3);return function(r){if(Ut(e.doc,r))return 0;var o=0;if(r.widgets)for(var a=0;a0&&(s=Ke(e.doc,u.line).text).length==u.ch){var c=W(s,s.length,e.options.tabSize)-s.length;u=it(u.line,Math.max(0,Math.round((o-En(e.display).left)/li(e.display))-c))}return u}function fi(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,i=0;it)&&(r.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=r.viewTo)St&&jt(e.doc,t)r.viewFrom?gi(e):(r.viewFrom+=i,r.viewTo+=i);else if(t<=r.viewFrom&&n>=r.viewTo)gi(e);else if(t<=r.viewFrom){var o=vi(e,n,n+i,1);o?(r.view=r.view.slice(o.index),r.viewFrom=o.lineN,r.viewTo+=i):gi(e)}else if(n>=r.viewTo){var a=vi(e,t,t,-1);a?(r.view=r.view.slice(0,a.index),r.viewTo=a.lineN):gi(e)}else{var l=vi(e,t,t,-1),s=vi(e,n,n+i,1);l&&s?(r.view=r.view.slice(0,l.index).concat(sn(e,l.lineN,s.lineN)).concat(r.view.slice(s.index)),r.viewTo+=i):gi(e)}var u=r.externalMeasured;u&&(n=r.lineN&&t=i.viewTo)){var o=i.view[fi(e,t)];if(null!=o.node){var a=o.changes||(o.changes=[]);-1==q(a,n)&&a.push(n)}}}function gi(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function vi(e,t,n,i){var r,o=fi(e,t),a=e.display.view;if(!St||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var l=e.display.viewFrom,s=0;s0){if(o==a.length-1)return null;r=l+a[o].size-t,o++}else r=l-t;t+=r,n+=r}for(;jt(e.doc,n)!=n;){if(o==(i<0?0:a.length-1))return null;n+=i*a[o-(i<0?1:0)].size,o+=i}return{index:o,lineN:n}}function xi(e){for(var t=e.display.view,n=0,i=0;i=e.display.viewTo||s.to().line0?a:e.defaultCharWidth())+"px"}if(i.other){var l=n.appendChild(T("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));l.style.display="",l.style.left=i.other.left+"px",l.style.top=i.other.top+"px",l.style.height=.85*(i.other.bottom-i.other.top)+"px"}}function Ci(e,t){return e.top-t.top||e.left-t.left}function wi(e,t,n){var i=e.display,r=e.doc,o=document.createDocumentFragment(),a=En(e.display),l=a.left,s=Math.max(i.sizerWidth,Tn(e)-i.sizer.offsetLeft)-a.right,u="ltr"==r.direction;function c(e,t,n,i){t<0&&(t=0),t=Math.round(t),i=Math.round(i),o.appendChild(T("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?s-e:n)+"px;\n height: "+(i-t)+"px"))}function d(t,n,i){var o,a,d=Ke(r,t),h=d.text.length;function f(n,i){return Kn(e,it(t,n),"div",d,i)}function p(t,n,i){var r=ti(e,d,null,t),o="ltr"==n==("after"==i)?"left":"right";return f("after"==i?r.begin:r.end-(/\s/.test(d.text.charAt(r.end-1))?2:1),o)[o]}var m=he(d,r.direction);return function(e,t,n,i){if(!e)return i(t,n,"ltr",0);for(var r=!1,o=0;ot||t==n&&a.to==t)&&(i(Math.max(a.from,t),Math.min(a.to,n),1==a.level?"rtl":"ltr",o),r=!0)}r||i(t,n,"ltr")}(m,n||0,null==i?h:i,(function(e,t,r,d){var g="ltr"==r,v=f(e,g?"left":"right"),x=f(t-1,g?"right":"left"),y=null==n&&0==e,b=null==i&&t==h,D=0==d,C=!m||d==m.length-1;if(x.top-v.top<=3){var w=(u?b:y)&&C,k=(u?y:b)&&D?l:(g?v:x).left,S=w?s:(g?x:v).right;c(k,v.top,S-k,v.bottom)}else{var F,A,E,L;g?(F=u&&y&&D?l:v.left,A=u?s:p(e,r,"before"),E=u?l:p(t,r,"after"),L=u&&b&&C?s:x.right):(F=u?p(e,r,"before"):l,A=!u&&y&&D?s:v.right,E=!u&&b&&C?l:x.left,L=u?p(t,r,"after"):s),c(F,v.top,A-F,v.bottom),v.bottom0?t.blinker=setInterval((function(){e.hasFocus()||Ei(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"}),e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Si(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Ai(e))}function Fi(e){e.state.delayingBlurEvent=!0,setTimeout((function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&Ei(e))}),100)}function Ai(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ve(e,"focus",e,t),e.state.focused=!0,O(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),s&&setTimeout((function(){return e.display.input.reset(!0)}),20)),e.display.input.receivedFocus()),ki(e))}function Ei(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ve(e,"blur",e,t),e.state.focused=!1,A(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout((function(){e.state.focused||(e.display.shift=!1)}),150))}function Li(e){for(var t=e.display,n=t.lineDiv.offsetTop,i=Math.max(0,t.scroller.getBoundingClientRect().top),r=t.lineDiv.getBoundingClientRect().top,o=0,s=0;s.005||m<-.005)&&(re.display.sizerWidth){var v=Math.ceil(h/li(e.display));v>e.display.maxLineLength&&(e.display.maxLineLength=v,e.display.maxLine=u.line,e.display.maxLineChanged=!0)}}}Math.abs(o)>2&&(t.scroller.scrollTop+=o)}function Ti(e){if(e.widgets)for(var t=0;t=a&&(o=et(t,Gt(Ke(t,s))-e.wrapper.clientHeight),a=s)}return{from:o,to:Math.max(a,o+1)}}function Bi(e,t){var n=e.display,i=ai(e.display);t.top<0&&(t.top=0);var r=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=Mn(e),a={};t.bottom-t.top>o&&(t.bottom=t.top+o);var l=e.doc.height+An(n),s=t.topl-i;if(t.topr+o){var c=Math.min(t.top,(u?l:t.bottom)-o);c!=r&&(a.scrollTop=c)}var d=e.options.fixedGutter?0:n.gutters.offsetWidth,h=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-d,f=Tn(e)-n.gutters.offsetWidth,p=t.right-t.left>f;return p&&(t.right=t.left+f),t.left<10?a.scrollLeft=0:t.leftf+h-3&&(a.scrollLeft=t.right+(p?0:10)-f),a}function Ni(e,t){null!=t&&(zi(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Oi(e){zi(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Ii(e,t,n){null==t&&null==n||zi(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function zi(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Hi(e,Yn(e,t.from),Yn(e,t.to),t.margin))}function Hi(e,t,n,i){var r=Bi(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-i,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+i});Ii(e,r.scrollLeft,r.scrollTop)}function Ri(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||hr(e,{top:t}),Pi(e,t,!0),n&&hr(e),ar(e,100))}function Pi(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function _i(e,t,n,i){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!i||(e.doc.scrollLeft=t,mr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Wi(e){var t=e.display,n=t.gutters.offsetWidth,i=Math.round(e.doc.height+An(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:i,scrollHeight:i+Ln(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}var ji=function(e,t,n){this.cm=n;var i=this.vert=T("div",[T("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),r=this.horiz=T("div",[T("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");i.tabIndex=r.tabIndex=-1,e(i),e(r),pe(i,"scroll",(function(){i.clientHeight&&t(i.scrollTop,"vertical")})),pe(r,"scroll",(function(){r.clientWidth&&t(r.scrollLeft,"horizontal")})),this.checkedZeroWidth=!1,a&&l<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};ji.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,i=e.nativeBarWidth;if(n){this.vert.style.display="block",this.vert.style.bottom=t?i+"px":"0";var r=e.viewHeight-(t?i:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+r)+"px"}else this.vert.scrollTop=0,this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=n?i+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(n?i:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==i&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?i:0,bottom:t?i:0}},ji.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},ji.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},ji.prototype.zeroWidthHack=function(){var e=y&&!p?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.visibility=this.vert.style.visibility="hidden",this.disableHoriz=new j,this.disableVert=new j},ji.prototype.enableZeroWidthBar=function(e,t,n){e.style.visibility="",t.set(1e3,(function i(){var r=e.getBoundingClientRect();("vert"==n?document.elementFromPoint(r.right-1,(r.top+r.bottom)/2):document.elementFromPoint((r.right+r.left)/2,r.bottom-1))!=e?e.style.visibility="hidden":t.set(1e3,i)}))},ji.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var qi=function(){};function Ui(e,t){t||(t=Wi(e));var n=e.display.barWidth,i=e.display.barHeight;$i(e,t);for(var r=0;r<4&&n!=e.display.barWidth||i!=e.display.barHeight;r++)n!=e.display.barWidth&&e.options.lineWrapping&&Li(e),$i(e,Wi(e)),n=e.display.barWidth,i=e.display.barHeight}function $i(e,t){var n=e.display,i=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=i.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=i.bottom)+"px",n.heightForcer.style.borderBottom=i.bottom+"px solid transparent",i.right&&i.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=i.bottom+"px",n.scrollbarFiller.style.width=i.right+"px"):n.scrollbarFiller.style.display="",i.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=i.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}qi.prototype.update=function(){return{bottom:0,right:0}},qi.prototype.setScrollLeft=function(){},qi.prototype.setScrollTop=function(){},qi.prototype.clear=function(){};var Gi={native:ji,null:qi};function Vi(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&A(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Gi[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),pe(t,"mousedown",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute("cm-not-content","true")}),(function(t,n){"horizontal"==n?_i(e,t):Ri(e,t)}),e),e.display.scrollbars.addClass&&O(e.display.wrapper,e.display.scrollbars.addClass)}var Xi=0;function Ki(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Xi,markArrays:null},t=e.curOp,un?un.ops.push(t):t.ownsGroup=un={ops:[t],delayedCallbacks:[]}}function Zi(e){var t=e.curOp;t&&function(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new sr(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Qi(e){e.updatedDisplay=e.mustUpdate&&cr(e.cm,e.update)}function Ji(e){var t=e.cm,n=t.display;e.updatedDisplay&&Li(t),e.barMeasure=Wi(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Nn(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Ln(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Tn(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}function er(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft1&&(a=!0)),null!=u.scrollLeft&&(_i(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-d)>1&&(a=!0)),!a)break}return r}(t,ct(i,e.scrollToPos.from),ct(i,e.scrollToPos.to),e.scrollToPos.margin);!function(e,t){if(!xe(e,"scrollCursorIntoView")){var n=e.display,i=n.sizer.getBoundingClientRect(),r=null,o=n.wrapper.ownerDocument;if(t.top+i.top<0?r=!0:t.bottom+i.top>(o.defaultView.innerHeight||o.documentElement.clientHeight)&&(r=!1),null!=r&&!m){var a=T("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-Fn(e.display))+"px;\n height: "+(t.bottom-t.top+Ln(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(a),a.scrollIntoView(r),e.display.lineSpace.removeChild(a)}}}(t,r)}var o=e.maybeHiddenMarkers,a=e.maybeUnhiddenMarkers;if(o)for(var l=0;l=e.display.viewTo)){var n=+new Date+e.options.workTime,i=gt(e,t.highlightFrontier),r=[];t.iter(i.line,Math.min(t.first+t.size,e.display.viewTo+500),(function(o){if(i.line>=e.display.viewFrom){var a=o.styles,l=o.text.length>e.options.maxHighlightLength?$e(t.mode,i.state):null,s=pt(e,o,i,!0);l&&(i.state=l),o.styles=s.styles;var u=o.styleClasses,c=s.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var d=!a||a.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),h=0;!d&&hn)return ar(e,e.options.workDelay),!0})),t.highlightFrontier=i.line,t.modeFrontier=Math.max(t.modeFrontier,i.line),r.length&&nr(e,(function(){for(var t=0;t=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==xi(e))return!1;gr(e)&&(gi(e),t.dims=si(e));var r=i.first+i.size,o=Math.max(t.visible.from-e.options.viewportMargin,i.first),a=Math.min(r,t.visible.to+e.options.viewportMargin);n.viewFroma&&n.viewTo-a<20&&(a=Math.min(r,n.viewTo)),St&&(o=jt(e.doc,o),a=qt(e.doc,a));var l=o!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;!function(e,t,n){var i=e.display;0==i.view.length||t>=i.viewTo||n<=i.viewFrom?(i.view=sn(e,t,n),i.viewFrom=t):(i.viewFrom>t?i.view=sn(e,t,i.viewFrom).concat(i.view):i.viewFromn&&(i.view=i.view.slice(0,fi(e,n)))),i.viewTo=n}(e,o,a),n.viewOffset=Gt(Ke(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var u=xi(e);if(!l&&0==u&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var c=ur(e);return u>4&&(n.lineDiv.style.display="none"),function(e,t,n){var i=e.display,r=e.options.lineNumbers,o=i.lineDiv,a=o.firstChild;function l(t){var n=t.nextSibling;return s&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),n}for(var u=i.view,c=i.viewFrom,d=0;d-1&&(f=!1),fn(e,h,c,n)),f&&(E(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(nt(e.options,c)))),a=h.node.nextSibling}else{var p=bn(e,h,c,n);o.insertBefore(p,a)}c+=h.size}for(;a;)a=l(a)}(e,n.updateLineNumbers,t.dims),u>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,function(e){if(e&&e.activeElt&&e.activeElt!=N(e.activeElt.ownerDocument)&&(e.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(e.activeElt.nodeName)&&e.anchorNode&&B(document.body,e.anchorNode)&&B(document.body,e.focusNode))){var t=e.activeElt.ownerDocument,n=t.defaultView.getSelection(),i=t.createRange();i.setEnd(e.anchorNode,e.anchorOffset),i.collapse(!1),n.removeAllRanges(),n.addRange(i),n.extend(e.focusNode,e.focusOffset)}}(c),E(n.cursorDiv),E(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,l&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,ar(e,400)),n.updateLineNumbers=null,!0}function dr(e,t){for(var n=t.viewport,i=!0;;i=!1){if(i&&e.options.lineWrapping&&t.oldDisplayWidth!=Tn(e))i&&(t.visible=Mi(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+An(e.display)-Mn(e),n.top)}),t.visible=Mi(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!cr(e,t))break;Li(e);var r=Wi(e);yi(e),Ui(e,r),pr(e,r),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function hr(e,t){var n=new sr(e,t);if(cr(e,n)){Li(e),dr(e,n);var i=Wi(e);yi(e),Ui(e,i),pr(e,i),n.finish()}}function fr(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px",dn(e,"gutterChanged",e)}function pr(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Ln(e)+"px"}function mr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var i=ui(t)-t.scroller.scrollLeft+e.doc.scrollLeft,r=t.gutters.offsetWidth,o=i+"px",a=0;a=105&&(o.wrapper.style.clipPath="inset(0px)"),o.wrapper.setAttribute("translate","no"),a&&l<8&&(o.gutters.style.zIndex=-1,o.scroller.style.paddingRight=0),s||n&&x||(o.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(o.wrapper):e(o.wrapper)),o.viewFrom=o.viewTo=t.first,o.reportedViewFrom=o.reportedViewTo=t.first,o.view=[],o.renderedView=null,o.externalMeasured=null,o.viewOffset=0,o.lastWrapHeight=o.lastWrapWidth=0,o.updateLineNumbers=null,o.nativeBarWidth=o.barHeight=o.barWidth=0,o.scrollbarsClipped=!1,o.lineNumWidth=o.lineNumInnerWidth=o.lineNumChars=null,o.alignWidgets=!1,o.cachedCharWidth=o.cachedTextHeight=o.cachedPaddingH=null,o.maxLine=null,o.maxLineLength=0,o.maxLineChanged=!1,o.wheelDX=o.wheelDY=o.wheelStartX=o.wheelStartY=null,o.shift=!1,o.selForContextMenu=null,o.activeTouch=null,o.gutterSpecs=vr(r.gutters,r.lineNumbers),xr(o),i.init(o)}sr.prototype.signal=function(e,t){be(e,t)&&this.events.push(arguments)},sr.prototype.finish=function(){for(var e=0;eu.clientWidth,p=u.scrollHeight>u.clientHeight;if(r&&f||o&&p){if(o&&y&&s)e:for(var m=t.target,g=l.view;m!=u;m=m.parentNode)for(var v=0;v=0&&rt(e,i.to())<=0)return n}return-1};var Ar=function(e,t){this.anchor=e,this.head=t};function Er(e,t,n){var i=e&&e.options.selectionsMayTouch,r=t[n];t.sort((function(e,t){return rt(e.from(),t.from())})),n=q(t,r);for(var o=1;o0:s>=0){var u=st(l.from(),a.from()),c=lt(l.to(),a.to()),d=l.empty()?a.from()==a.head:l.from()==l.head;o<=n&&--n,t.splice(--o,2,new Ar(d?c:u,d?u:c))}}return new Fr(t,n)}function Lr(e,t){return new Fr([new Ar(e,t||e)],0)}function Tr(e){return e.text?it(e.from.line+e.text.length-1,Y(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function Mr(e,t){if(rt(e,t.from)<0)return e;if(rt(e,t.to)<=0)return Tr(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,i=e.ch;return e.line==t.to.line&&(i+=Tr(t).ch-t.to.ch),it(n,i)}function Br(e,t){for(var n=[],i=0;i1&&e.remove(l.line+1,p-1),e.insert(l.line+1,v)}dn(e,"change",e,t)}function Rr(e,t,n){!function e(i,r,o){if(i.linked)for(var a=0;al-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(qr(e.done),Y(e.done)):e.done.length&&!Y(e.done).ranges?Y(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),Y(e.done)):void 0}(r,r.lastOp==i)))a=Y(o.changes),0==rt(t.from,t.to)&&0==rt(t.from,a.to)?a.to=Tr(t):o.changes.push(jr(e,t));else{var s=Y(r.done);for(s&&s.ranges||Gr(e.sel,r.done),o={changes:[jr(e,t)],generation:r.generation},r.done.push(o);r.done.length>r.undoDepth;)r.done.shift(),r.done[0].ranges||r.done.shift()}r.done.push(n),r.generation=++r.maxGeneration,r.lastModTime=r.lastSelTime=l,r.lastOp=r.lastSelOp=i,r.lastOrigin=r.lastSelOrigin=t.origin,a||ve(e,"historyAdded")}function $r(e,t,n,i){var r=e.history,o=i&&i.origin;n==r.lastSelOp||o&&r.lastSelOrigin==o&&(r.lastModTime==r.lastSelTime&&r.lastOrigin==o||function(e,t,n,i){var r=t.charAt(0);return"*"==r||"+"==r&&n.ranges.length==i.ranges.length&&n.somethingSelected()==i.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,Y(r.done),t))?r.done[r.done.length-1]=t:Gr(t,r.done),r.lastSelTime=+new Date,r.lastSelOrigin=o,r.lastSelOp=n,i&&!1!==i.clearRedo&&qr(r.undone)}function Gr(e,t){var n=Y(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Vr(e,t,n,i){var r=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,n),Math.min(e.first+e.size,i),(function(n){n.markedSpans&&((r||(r=t["spans_"+e.id]={}))[o]=n.markedSpans),++o}))}function Xr(e){if(!e)return null;for(var t,n=0;n-1&&(Y(l)[d]=u[d],delete u[d])}}}return i}function Yr(e,t,n,i){if(i){var r=e.anchor;if(n){var o=rt(t,r)<0;o!=rt(n,r)<0?(r=t,t=n):o!=rt(t,n)<0&&(t=n)}return new Ar(r,t)}return new Ar(n||t,t)}function Qr(e,t,n,i,r){null==r&&(r=e.cm&&(e.cm.display.shift||e.extend)),io(e,new Fr([Yr(e.sel.primary(),t,n,r)],0),i)}function Jr(e,t,n){for(var i=[],r=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:l.to>t.ch))){if(r&&(ve(s,"beforeCursorEnter"),s.explicitlyCleared)){if(o.markedSpans){--a;continue}break}if(!s.atomic)continue;if(n){var d=s.find(i<0?1:-1),h=void 0;if((i<0?c:u)&&(d=co(e,d,-i,d&&d.line==t.line?o:null)),d&&d.line==t.line&&(h=rt(d,n))&&(i<0?h<0:h>0))return so(e,d,t,i,r)}var f=s.find(i<0?-1:1);return(i<0?u:c)&&(f=co(e,f,i,f.line==t.line?o:null)),f?so(e,f,t,i,r):null}}return t}function uo(e,t,n,i,r){var o=i||1,a=so(e,t,n,o,r)||!r&&so(e,t,n,o,!0)||so(e,t,n,-o,r)||!r&&so(e,t,n,-o,!0);return a||(e.cantEdit=!0,it(e.first,0))}function co(e,t,n,i){return n<0&&0==t.ch?t.line>e.first?ct(e,it(t.line-1)):null:n>0&&t.ch==(i||Ke(e,t.line)).text.length?t.line0)){var c=[s,1],d=rt(u.from,l.from),h=rt(u.to,l.to);(d<0||!a.inclusiveLeft&&!d)&&c.push({from:u.from,to:l.from}),(h>0||!a.inclusiveRight&&!h)&&c.push({from:l.to,to:u.to}),r.splice.apply(r,c),s+=c.length-3}}return r}(e,t.from,t.to);if(i)for(var r=i.length-1;r>=0;--r)mo(e,{from:i[r].from,to:i[r].to,text:r?[""]:t.text,origin:t.origin});else mo(e,t)}}function mo(e,t){if(1!=t.text.length||""!=t.text[0]||0!=rt(t.from,t.to)){var n=Br(e,t);Ur(e,t,n,e.cm?e.cm.curOp.id:NaN),xo(e,t,n,Lt(e,t));var i=[];Rr(e,(function(e,n){n||-1!=q(i,e.history)||(Co(e.history,t),i.push(e.history)),xo(e,t,null,Lt(e,t))}))}}function go(e,t,n){var i=e.cm&&e.cm.state.suppressEdits;if(!i||n){for(var r,o=e.history,a=e.sel,l="undo"==t?o.done:o.undone,s="undo"==t?o.undone:o.done,u=0;u=0;--f){var p=h(f);if(p)return p.v}}}}function vo(e,t){if(0!=t&&(e.first+=t,e.sel=new Fr(Q(e.sel.ranges,(function(e){return new Ar(it(e.anchor.line+t,e.anchor.ch),it(e.head.line+t,e.head.ch))})),e.sel.primIndex),e.cm)){pi(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,i=n.viewFrom;ie.lastLine())){if(t.from.lineo&&(t={from:t.from,to:it(o,Ke(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ze(e,t.from,t.to),n||(n=Br(e,t)),e.cm?function(e,t,n){var i=e.doc,r=e.display,o=t.from,a=t.to,l=!1,s=o.line;e.options.lineWrapping||(s=Je(Wt(Ke(i,o.line))),i.iter(s,a.line+1,(function(e){if(e==r.maxLine)return l=!0,!0})));i.sel.contains(t.from,t.to)>-1&&ye(e);Hr(i,t,n,ci(e)),e.options.lineWrapping||(i.iter(s,o.line+t.text.length,(function(e){var t=Vt(e);t>r.maxLineLength&&(r.maxLine=e,r.maxLineLength=t,r.maxLineChanged=!0,l=!1)})),l&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontiern;i--){var r=Ke(e,i).stateAfter;if(r&&(!(r instanceof ht)||i+r.lookAhead1||!(this.children[0]instanceof ko))){var l=[];this.collapse(l),this.children=[new ko(l)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=r.lines.length%25+25,l=a;l10);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var i=0;i0||0==a&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=M("span",[o.replacedWith],"CodeMirror-widget"),i.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),i.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(_t(e,t.line,t,n,o)||t.line!=n.line&&_t(e,n.line,t,n,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");St=!0}o.addToHistory&&Ur(e,{from:t,to:n,origin:"markText"},e.sel,NaN);var l,s=t.line,u=e.cm;if(e.iter(s,n.line+1,(function(i){u&&o.collapsed&&!u.options.lineWrapping&&Wt(i)==u.display.maxLine&&(l=!0),o.collapsed&&s!=t.line&&Qe(i,0),function(e,t,n){var i=n&&window.WeakSet&&(n.markedSpans||(n.markedSpans=new WeakSet));i&&e.markedSpans&&i.has(e.markedSpans)?e.markedSpans.push(t):(e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],i&&i.add(e.markedSpans)),t.marker.attachLine(e)}(i,new Ft(o,s==t.line?t.ch:null,s==n.line?n.ch:null),e.cm&&e.cm.curOp),++s})),o.collapsed&&e.iter(t.line,n.line+1,(function(t){Ut(e,t)&&Qe(t,0)})),o.clearOnEnter&&pe(o,"beforeCursorEnter",(function(){return o.clear()})),o.readOnly&&(kt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++Eo,o.atomic=!0),u){if(l&&(u.curOp.updateMaxLine=!0),o.collapsed)pi(u,t.line,n.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=n.line;c++)mi(u,c,"text");o.atomic&&ao(u.doc),dn(u,"markerAdded",u,o)}return o}Lo.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Ki(e),be(this,"clear")){var n=this.find();n&&dn(this,"clear",n.from,n.to)}for(var i=null,r=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=i&&e&&this.collapsed&&pi(e,i,r+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&ao(e.doc)),e&&dn(e,"markerCleared",e,this,i,r),t&&Zi(e),this.parent&&this.parent.clear()}},Lo.prototype.find=function(e,t){var n,i;null==e&&"bookmark"==this.type&&(e=1);for(var r=0;r=0;s--)po(this,i[s]);l?no(this,l):this.cm&&Oi(this.cm)})),undo:or((function(){go(this,"undo")})),redo:or((function(){go(this,"redo")})),undoSelection:or((function(){go(this,"undo",!0)})),redoSelection:or((function(){go(this,"redo",!0)})),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,i=0;i=e.ch)&&t.push(r.marker.parent||r.marker)}return t},findMarks:function(e,t,n){e=ct(this,e),t=ct(this,t);var i=[],r=e.line;return this.iter(e.line,t.line+1,(function(o){var a=o.markedSpans;if(a)for(var l=0;l=s.to||null==s.from&&r!=e.line||null!=s.from&&r==t.line&&s.from>=t.ch||n&&!n(s.marker)||i.push(s.marker.parent||s.marker)}++r})),i},getAllMarks:function(){var e=[];return this.iter((function(t){var n=t.markedSpans;if(n)for(var i=0;ie)return t=e,!0;e-=o,++n})),ct(this,it(n,t))},indexFromPos:function(e){var t=(e=ct(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout((function(){return t.display.input.focus()}),20);try{var d=e.dataTransfer.getData("Text");if(d){var h;if(t.state.draggingText&&!t.state.draggingText.copy&&(h=t.listSelections()),ro(t.doc,Lr(n,n)),h)for(var f=0;f=0;t--)yo(e.doc,"",i[t].from,i[t].to,"+delete");Oi(e)}))}function na(e,t,n){var i=le(e.text,t+n,n);return i<0||i>e.text.length?null:i}function ia(e,t,n){var i=na(e,t.ch,n);return null==i?null:new it(t.line,i,n<0?"after":"before")}function ra(e,t,n,i,r){if(e){"rtl"==t.doc.direction&&(r=-r);var o=he(n,t.doc.direction);if(o){var a,l=r<0?Y(o):o[0],s=r<0==(1==l.level)?"after":"before";if(l.level>0||"rtl"==t.doc.direction){var u=In(t,n);a=r<0?n.text.length-1:0;var c=zn(t,u,a).top;a=se((function(e){return zn(t,u,e).top==c}),r<0==(1==l.level)?l.from:l.to-1,a),"before"==s&&(a=na(n,a,1))}else a=r<0?l.to:l.from;return new it(i,a,s)}}return new it(i,r<0?n.text.length:0,r<0?"before":"after")}Vo.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Vo.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Vo.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Vo.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Vo.default=y?Vo.macDefault:Vo.pcDefault;var oa={selectAll:ho,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),$)},killLine:function(e){return ta(e,(function(t){if(t.empty()){var n=Ke(e.doc,t.head.line).text.length;return t.head.ch==n&&t.head.line0)r=new it(r.line,r.ch+1),e.replaceRange(o.charAt(r.ch-1)+o.charAt(r.ch-2),it(r.line,r.ch-2),r,"+transpose");else if(r.line>e.doc.first){var a=Ke(e.doc,r.line-1).text;a&&(r=new it(r.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),it(r.line-1,a.length-1),r,"+transpose"))}n.push(new Ar(r,r))}e.setSelections(n)}))},newlineAndIndent:function(e){return nr(e,(function(){for(var t=e.listSelections(),n=t.length-1;n>=0;n--)e.replaceRange(e.doc.lineSeparator(),t[n].anchor,t[n].head,"+input");t=e.listSelections();for(var i=0;i-1&&(rt((r=u.ranges[r]).from(),t)<0||t.xRel>0)&&(rt(r.to(),t)>0||t.xRel<0)?function(e,t,n,i){var r=e.display,o=!1,u=ir(e,(function(t){s&&(r.scroller.draggable=!1),e.state.draggingText=!1,e.state.delayingBlurEvent&&(e.hasFocus()?e.state.delayingBlurEvent=!1:Fi(e)),ge(r.wrapper.ownerDocument,"mouseup",u),ge(r.wrapper.ownerDocument,"mousemove",c),ge(r.scroller,"dragstart",d),ge(r.scroller,"drop",u),o||(Ce(t),i.addNew||Qr(e.doc,n,null,null,i.extend),s&&!f||a&&9==l?setTimeout((function(){r.wrapper.ownerDocument.body.focus({preventScroll:!0}),r.input.focus()}),20):r.input.focus())})),c=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},d=function(){return o=!0};s&&(r.scroller.draggable=!0);e.state.draggingText=u,u.copy=!i.moveOnDrag,pe(r.wrapper.ownerDocument,"mouseup",u),pe(r.wrapper.ownerDocument,"mousemove",c),pe(r.scroller,"dragstart",d),pe(r.scroller,"drop",u),e.state.delayingBlurEvent=!0,setTimeout((function(){return r.input.focus()}),20),r.scroller.dragDrop&&r.scroller.dragDrop()}(e,i,t,o):function(e,t,n,i){a&&Fi(e);var r=e.display,o=e.doc;Ce(t);var l,s,u=o.sel,c=u.ranges;i.addNew&&!i.extend?(s=o.sel.contains(n),l=s>-1?c[s]:new Ar(n,n)):(l=o.sel.primary(),s=o.sel.primIndex);if("rectangle"==i.unit)i.addNew||(l=new Ar(n,n)),n=hi(e,t,!0,!0),s=-1;else{var d=Da(e,n,i.unit);l=i.extend?Yr(l,d.anchor,d.head,i.extend):d}i.addNew?-1==s?(s=c.length,io(o,Er(e,c.concat([l]),s),{scroll:!1,origin:"*mouse"})):c.length>1&&c[s].empty()&&"char"==i.unit&&!i.extend?(io(o,Er(e,c.slice(0,s).concat(c.slice(s+1)),0),{scroll:!1,origin:"*mouse"}),u=o.sel):eo(o,s,l,G):(s=0,io(o,new Fr([l],0),G),u=o.sel);var h=n;function f(t){if(0!=rt(h,t))if(h=t,"rectangle"==i.unit){for(var r=[],a=e.options.tabSize,c=W(Ke(o,n.line).text,n.ch,a),d=W(Ke(o,t.line).text,t.ch,a),f=Math.min(c,d),p=Math.max(c,d),m=Math.min(n.line,t.line),g=Math.min(e.lastLine(),Math.max(n.line,t.line));m<=g;m++){var v=Ke(o,m).text,x=X(v,f,a);f==p?r.push(new Ar(it(m,x),it(m,x))):v.length>x&&r.push(new Ar(it(m,x),it(m,X(v,p,a))))}r.length||r.push(new Ar(n,n)),io(o,Er(e,u.ranges.slice(0,s).concat(r),s),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var y,b=l,D=Da(e,t,i.unit),C=b.anchor;rt(D.anchor,C)>0?(y=D.head,C=st(b.from(),D.anchor)):(y=D.anchor,C=lt(b.to(),D.head));var w=u.ranges.slice(0);w[s]=function(e,t){var n=t.anchor,i=t.head,r=Ke(e.doc,n.line);if(0==rt(n,i)&&n.sticky==i.sticky)return t;var o=he(r);if(!o)return t;var a=ce(o,n.ch,n.sticky),l=o[a];if(l.from!=n.ch&&l.to!=n.ch)return t;var s,u=a+(l.from==n.ch==(1!=l.level)?0:1);if(0==u||u==o.length)return t;if(i.line!=n.line)s=(i.line-n.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ce(o,i.ch,i.sticky),d=c-a||(i.ch-n.ch)*(1==l.level?-1:1);s=c==u-1||c==u?d<0:d>0}var h=o[u+(s?-1:0)],f=s==(1==h.level),p=f?h.from:h.to,m=f?"after":"before";return n.ch==p&&n.sticky==m?t:new Ar(new it(n.line,p,m),i)}(e,new Ar(ct(o,C),y)),io(o,Er(e,w,s),G)}}var p=r.wrapper.getBoundingClientRect(),m=0;function g(t){var n=++m,a=hi(e,t,!0,"rectangle"==i.unit);if(a)if(0!=rt(a,h)){e.curOp.focus=N(H(e)),f(a);var l=Mi(r,o);(a.line>=l.to||a.linep.bottom?20:0;s&&setTimeout(ir(e,(function(){m==n&&(r.scroller.scrollTop+=s,g(t))})),50)}}function v(t){e.state.selectingText=!1,m=1/0,t&&(Ce(t),r.input.focus()),ge(r.wrapper.ownerDocument,"mousemove",x),ge(r.wrapper.ownerDocument,"mouseup",y),o.history.lastSelOrigin=null}var x=ir(e,(function(e){0!==e.buttons&&Ae(e)?g(e):v(e)})),y=ir(e,v);e.state.selectingText=y,pe(r.wrapper.ownerDocument,"mousemove",x),pe(r.wrapper.ownerDocument,"mouseup",y)}(e,i,t,o)}(t,i,o,e):Fe(e)==n.scroller&&Ce(e):2==r?(i&&Qr(t.doc,i),setTimeout((function(){return n.input.focus()}),20)):3==r&&(k?t.display.input.onContextMenu(e):Fi(t)))}}function Da(e,t,n){if("char"==n)return new Ar(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new Ar(it(t.line,0),ct(e.doc,it(t.line+1,0)));var i=n(e,t);return new Ar(i.from,i.to)}function Ca(e,t,n,i){var r,o;if(t.touches)r=t.touches[0].clientX,o=t.touches[0].clientY;else try{r=t.clientX,o=t.clientY}catch(e){return!1}if(r>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;i&&Ce(t);var a=e.display,l=a.lineDiv.getBoundingClientRect();if(o>l.bottom||!be(e,n))return ke(t);o-=l.top-a.viewOffset;for(var s=0;s=r)return ve(e,n,e,et(e.doc,o),e.display.gutterSpecs[s].className,t),ke(t)}}function wa(e,t){return Ca(e,t,"gutterClick",!0)}function ka(e,t){Sn(e.display,t)||function(e,t){if(!be(e,"gutterContextMenu"))return!1;return Ca(e,t,"gutterContextMenu",!1)}(e,t)||xe(e,t,"contextmenu")||k||e.display.input.onContextMenu(t)}function Sa(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),qn(e)}ya.prototype.compare=function(e,t,n){return this.time+400>e&&0==rt(t,this.pos)&&n==this.button};var Fa={toString:function(){return"CodeMirror.Init"}},Aa={},Ea={};function La(e,t,n){if(!t!=!(n&&n!=Fa)){var i=e.display.dragFunctions,r=t?pe:ge;r(e.display.scroller,"dragstart",i.start),r(e.display.scroller,"dragenter",i.enter),r(e.display.scroller,"dragover",i.over),r(e.display.scroller,"dragleave",i.leave),r(e.display.scroller,"drop",i.drop)}}function Ta(e){e.options.lineWrapping?(O(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(A(e.display.wrapper,"CodeMirror-wrap"),Xt(e)),di(e),pi(e),qn(e),setTimeout((function(){return Ui(e)}),100)}function Ma(e,t){var n=this;if(!(this instanceof Ma))return new Ma(e,t);this.options=t=t?_(t):{},_(Aa,t,!1);var i=t.value;"string"==typeof i?i=new Io(i,t.mode,null,t.lineSeparator,t.direction):t.mode&&(i.modeOption=t.mode),this.doc=i;var r=new Ma.inputStyles[t.inputStyle](this),o=this.display=new br(e,i,r,t);for(var u in o.wrapper.CodeMirror=this,Sa(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Vi(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new j,keySeq:null,specialChars:null},t.autofocus&&!x&&o.input.focus(),a&&l<11&&setTimeout((function(){return n.display.input.reset(!0)}),20),function(e){var t=e.display;pe(t.scroller,"mousedown",ir(e,ba)),pe(t.scroller,"dblclick",a&&l<11?ir(e,(function(t){if(!xe(e,t)){var n=hi(e,t);if(n&&!wa(e,t)&&!Sn(e.display,t)){Ce(t);var i=e.findWordAt(n);Qr(e.doc,i.anchor,i.head)}}})):function(t){return xe(e,t)||Ce(t)});pe(t.scroller,"contextmenu",(function(t){return ka(e,t)})),pe(t.input.getField(),"contextmenu",(function(n){t.scroller.contains(n.target)||ka(e,n)}));var n,i={end:0};function r(){t.activeTouch&&(n=setTimeout((function(){return t.activeTouch=null}),1e3),(i=t.activeTouch).end=+new Date)}function o(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}function s(e,t){if(null==t.left)return!0;var n=t.left-e.left,i=t.top-e.top;return n*n+i*i>400}pe(t.scroller,"touchstart",(function(r){if(!xe(e,r)&&!o(r)&&!wa(e,r)){t.input.ensurePolled(),clearTimeout(n);var a=+new Date;t.activeTouch={start:a,moved:!1,prev:a-i.end<=300?i:null},1==r.touches.length&&(t.activeTouch.left=r.touches[0].pageX,t.activeTouch.top=r.touches[0].pageY)}})),pe(t.scroller,"touchmove",(function(){t.activeTouch&&(t.activeTouch.moved=!0)})),pe(t.scroller,"touchend",(function(n){var i=t.activeTouch;if(i&&!Sn(t,n)&&null!=i.left&&!i.moved&&new Date-i.start<300){var o,a=e.coordsChar(t.activeTouch,"page");o=!i.prev||s(i,i.prev)?new Ar(a,a):!i.prev.prev||s(i,i.prev.prev)?e.findWordAt(a):new Ar(it(a.line,0),ct(e.doc,it(a.line+1,0))),e.setSelection(o.anchor,o.head),e.focus(),Ce(n)}r()})),pe(t.scroller,"touchcancel",r),pe(t.scroller,"scroll",(function(){t.scroller.clientHeight&&(Ri(e,t.scroller.scrollTop),_i(e,t.scroller.scrollLeft,!0),ve(e,"scroll",e))})),pe(t.scroller,"mousewheel",(function(t){return Sr(e,t)})),pe(t.scroller,"DOMMouseScroll",(function(t){return Sr(e,t)})),pe(t.wrapper,"scroll",(function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0})),t.dragFunctions={enter:function(t){xe(e,t)||Se(t)},over:function(t){xe(e,t)||(!function(e,t){var n=hi(e,t);if(n){var i=document.createDocumentFragment();Di(e,n,i),e.display.dragCursor||(e.display.dragCursor=T("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),L(e.display.dragCursor,i)}}(e,t),Se(t))},start:function(t){return function(e,t){if(a&&(!e.state.draggingText||+new Date-zo<100))Se(t);else if(!xe(e,t)&&!Sn(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!f)){var n=T("img",null,null,"position: fixed; left: 0; top: 0;");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",h&&(n.width=n.height=1,e.display.wrapper.appendChild(n),n._top=n.offsetTop),t.dataTransfer.setDragImage(n,0,0),h&&n.parentNode.removeChild(n)}}(e,t)},drop:ir(e,Ho),leave:function(t){xe(e,t)||Ro(e)}};var u=t.input.getField();pe(u,"keyup",(function(t){return ma.call(e,t)})),pe(u,"keydown",ir(e,pa)),pe(u,"keypress",ir(e,ga)),pe(u,"focus",(function(t){return Ai(e,t)})),pe(u,"blur",(function(t){return Ei(e,t)}))}(this),Wo(),Ki(this),this.curOp.forceUpdate=!0,Pr(this,i),t.autofocus&&!x||this.hasFocus()?setTimeout((function(){n.hasFocus()&&!n.state.focused&&Ai(n)}),20):Ei(this),Ea)Ea.hasOwnProperty(u)&&Ea[u](this,t[u],Fa);gr(this),t.finishInit&&t.finishInit(this);for(var c=0;c150)){if(!i)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?W(Ke(o,t-1).text,null,a):0:"add"==n?u=s+e.options.indentUnit:"subtract"==n?u=s-e.options.indentUnit:"number"==typeof n&&(u=s+n),u=Math.max(0,u);var d="",h=0;if(e.options.indentWithTabs)for(var f=Math.floor(u/a);f;--f)h+=a,d+="\t";if(ha,s=Oe(t),u=null;if(l&&i.ranges.length>1)if(Oa&&Oa.text.join("\n")==t){if(i.ranges.length%Oa.text.length==0){u=[];for(var c=0;c=0;h--){var f=i.ranges[h],p=f.from(),m=f.to();f.empty()&&(n&&n>0?p=it(p.line,p.ch-n):e.state.overwrite&&!l?m=it(m.line,Math.min(Ke(o,m.line).text.length,m.ch+Y(s).length)):l&&Oa&&Oa.lineWise&&Oa.text.join("\n")==s.join("\n")&&(p=m=it(p.line,0)));var g={from:p,to:m,text:u?u[h%u.length]:s,origin:r||(l?"paste":e.state.cutIncoming>a?"cut":"+input")};po(e.doc,g),dn(e,"inputRead",e,g)}t&&!l&&Ra(e,t),Oi(e),e.curOp.updateInput<2&&(e.curOp.updateInput=d),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Ha(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");if(n)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||!t.hasFocus()||nr(t,(function(){return za(t,n,0,null,"paste")})),!0}function Ra(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,i=n.ranges.length-1;i>=0;i--){var r=n.ranges[i];if(!(r.head.ch>100||i&&n.ranges[i-1].head.line==r.head.line)){var o=e.getModeAt(r.head),a=!1;if(o.electricChars){for(var l=0;l-1){a=Na(e,r.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Ke(e.doc,r.head.line).text.slice(0,r.head.ch))&&(a=Na(e,r.head.line,"smart"));a&&dn(e,"electricInput",e,r.head.line)}}}function Pa(e){for(var t=[],n=[],i=0;i0?0:-1));if(isNaN(c))a=null;else{var d=n>0?c>=55296&&c<56320:c>=56320&&c<57343;a=new it(t.line,Math.max(0,Math.min(l.text.length,t.ch+n*(d?2:1))),-n)}}else a=r?function(e,t,n,i){var r=he(t,e.doc.direction);if(!r)return ia(t,n,i);n.ch>=t.text.length?(n.ch=t.text.length,n.sticky="before"):n.ch<=0&&(n.ch=0,n.sticky="after");var o=ce(r,n.ch,n.sticky),a=r[o];if("ltr"==e.doc.direction&&a.level%2==0&&(i>0?a.to>n.ch:a.from=a.from&&h>=c.begin)){var f=d?"before":"after";return new it(n.line,h,f)}}var p=function(e,t,i){for(var o=function(e,t){return t?new it(n.line,s(e,1),"before"):new it(n.line,e,"after")};e>=0&&e0==(1!=a.level),u=l?i.begin:s(i.end,-1);if(a.from<=u&&u0?c.end:s(c.begin,-1);return null==g||i>0&&g==t.text.length||!(m=p(i>0?0:r.length-1,i,u(g)))?null:m}(e.cm,l,t,n):ia(l,t,n);if(null==a){if(o||(u=t.line+s)=e.first+e.size||(t=new it(u,t.ch,t.sticky),!(l=Ke(e,u))))return!1;t=ra(r,e.cm,l,t.line,s)}else t=a;return!0}if("char"==i||"codepoint"==i)u();else if("column"==i)u(!0);else if("word"==i||"group"==i)for(var c=null,d="group"==i,h=e.cm&&e.cm.getHelper(t,"wordChars"),f=!0;!(n<0)||u(!f);f=!1){var p=l.text.charAt(t.ch)||"\n",m=ie(p,h)?"w":d&&"\n"==p?"n":!d||/\s/.test(p)?null:"p";if(!d||f||m||(m="s"),c&&c!=m){n<0&&(n=1,u(),t.sticky="after");break}if(m&&(c=m),n>0&&!u(!f))break}var g=uo(e,t,o,a,!0);return ot(o,g)&&(g.hitSide=!0),g}function qa(e,t,n,i){var r,o,a=e.doc,l=t.left;if("page"==i){var s=Math.min(e.display.wrapper.clientHeight,R(e).innerHeight||a(e).documentElement.clientHeight),u=Math.max(s-.5*ai(e.display),3);r=(n>0?t.bottom:t.top)+n*u}else"line"==i&&(r=n>0?t.bottom+3:t.top-3);for(;(o=Jn(e,l,r)).outside;){if(n<0?r<=0:r>=a.height){o.hitSide=!0;break}r+=5*n}return o}var Ua=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new j,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function $a(e,t){var n=On(e,t.line);if(!n||n.hidden)return null;var i=Ke(e.doc,t.line),r=Bn(n,i,t.line),o=he(i,e.doc.direction),a="left";o&&(a=ce(o,t.ch)%2?"right":"left");var l=Pn(r.map,t.ch,a);return l.offset="right"==l.collapse?l.end:l.start,l}function Ga(e,t){return t&&(e.bad=!0),e}function Va(e,t,n){var i;if(t==e.display.lineDiv){if(!(i=e.display.lineDiv.childNodes[n]))return Ga(e.clipPos(it(e.display.viewTo-1)),!0);t=null,n=0}else for(i=t;;i=i.parentNode){if(!i||i==e.display.lineDiv)return null;if(i.parentNode&&i.parentNode==e.display.lineDiv)break}for(var r=0;r=t.display.viewTo||o.line=t.display.viewFrom&&$a(t,r)||{node:s[0].measure.map[2],offset:0},c=o.linei.firstLine()&&(a=it(a.line-1,Ke(i.doc,a.line-1).length)),l.ch==Ke(i.doc,l.line).text.length&&l.liner.viewTo-1)return!1;a.line==r.viewFrom||0==(e=fi(i,a.line))?(t=Je(r.view[0].line),n=r.view[0].node):(t=Je(r.view[e].line),n=r.view[e-1].node.nextSibling);var s,u,c=fi(i,l.line);if(c==r.view.length-1?(s=r.viewTo-1,u=r.lineDiv.lastChild):(s=Je(r.view[c+1].line)-1,u=r.view[c+1].node.previousSibling),!n)return!1;for(var d=i.doc.splitLines(function(e,t,n,i,r){var o="",a=!1,l=e.doc.lineSeparator(),s=!1;function u(e){return function(t){return t.id==e}}function c(){a&&(o+=l,s&&(o+=l),a=s=!1)}function d(e){e&&(c(),o+=e)}function h(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void d(n);var o,f=t.getAttribute("cm-marker");if(f){var p=e.findMarks(it(i,0),it(r+1,0),u(+f));return void(p.length&&(o=p[0].find(0))&&d(Ze(e.doc,o.from,o.to).join(l)))}if("false"==t.getAttribute("contenteditable"))return;var m=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;m&&c();for(var g=0;g1&&h.length>1;)if(Y(d)==Y(h))d.pop(),h.pop(),s--;else{if(d[0]!=h[0])break;d.shift(),h.shift(),t++}for(var f=0,p=0,m=d[0],g=h[0],v=Math.min(m.length,g.length);fa.ch&&x.charCodeAt(x.length-p-1)==y.charCodeAt(y.length-p-1);)f--,p++;d[d.length-1]=x.slice(0,x.length-p).replace(/^\u200b+/,""),d[0]=d[0].slice(f).replace(/\u200b+$/,"");var D=it(t,f),C=it(s,h.length?Y(h).length-p:0);return d.length>1||d[0]||rt(D,C)?(yo(i.doc,d,D,C,"+input"),!0):void 0},Ua.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ua.prototype.reset=function(){this.forceCompositionEnd()},Ua.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ua.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout((function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()}),80))},Ua.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||nr(this.cm,(function(){return pi(e.cm)}))},Ua.prototype.setUneditable=function(e){e.contentEditable="false"},Ua.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||ir(this.cm,za)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ua.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ua.prototype.onContextMenu=function(){},Ua.prototype.resetPosition=function(){},Ua.prototype.needsContentAttribute=!0;var Ka=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new j,this.hasSelection=!1,this.composing=null,this.resetting=!1};Ka.prototype.init=function(e){var t=this,n=this,i=this.cm;this.createField(e);var r=this.textarea;function o(e){if(!xe(i,e)){if(i.somethingSelected())Ia({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=Pa(i);Ia({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,$):(n.prevInput="",r.value=t.text.join("\n"),z(r))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(r.style.width="0px"),pe(r,"input",(function(){a&&l>=9&&t.hasSelection&&(t.hasSelection=null),n.poll()})),pe(r,"paste",(function(e){xe(i,e)||Ha(e,i)||(i.state.pasteIncoming=+new Date,n.fastPoll())})),pe(r,"cut",o),pe(r,"copy",o),pe(e.scroller,"paste",(function(t){if(!Sn(e,t)&&!xe(i,t)){if(!r.dispatchEvent)return i.state.pasteIncoming=+new Date,void n.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,r.dispatchEvent(o)}})),pe(e.lineSpace,"selectstart",(function(t){Sn(e,t)||Ce(t)})),pe(r,"compositionstart",(function(){var e=i.getCursor("from");n.composing&&n.composing.range.clear(),n.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}})),pe(r,"compositionend",(function(){n.composing&&(n.poll(),n.composing.range.clear(),n.composing=null)}))},Ka.prototype.createField=function(e){this.wrapper=Wa(),this.textarea=this.wrapper.firstChild;var t=this.cm.options;_a(this.textarea,t.spellcheck,t.autocorrect,t.autocapitalize)},Ka.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},Ka.prototype.prepareSelection=function(){var e=this.cm,t=e.display,n=e.doc,i=bi(e);if(e.options.moveInputWithCursor){var r=Zn(e,n.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();i.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,r.top+a.top-o.top)),i.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,r.left+a.left-o.left))}return i},Ka.prototype.showSelection=function(e){var t=this.cm.display;L(t.cursorDiv,e.cursors),L(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Ka.prototype.reset=function(e){if(!(this.contextMenuPending||this.composing&&e)){var t=this.cm;if(this.resetting=!0,t.somethingSelected()){this.prevInput="";var n=t.getSelection();this.textarea.value=n,t.state.focused&&z(this.textarea),a&&l>=9&&(this.hasSelection=n)}else e||(this.prevInput=this.textarea.value="",a&&l>=9&&(this.hasSelection=null));this.resetting=!1}},Ka.prototype.getField=function(){return this.textarea},Ka.prototype.supportsTouch=function(){return!1},Ka.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!x||N(this.textarea.ownerDocument)!=this.textarea))try{this.textarea.focus()}catch(e){}},Ka.prototype.blur=function(){this.textarea.blur()},Ka.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Ka.prototype.receivedFocus=function(){this.slowPoll()},Ka.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,(function(){e.poll(),e.cm.state.focused&&e.slowPoll()}))},Ka.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,(function n(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,n))}))},Ka.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,i=this.prevInput;if(this.contextMenuPending||this.resetting||!t.state.focused||Ie(n)&&!i&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var r=n.value;if(r==i&&!t.somethingSelected())return!1;if(a&&l>=9&&this.hasSelection===r||y&&/[\uf700-\uf7ff]/.test(r))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=r.charCodeAt(0);if(8203!=o||i||(i="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var s=0,u=Math.min(i.length,r.length);s1e3||r.indexOf("\n")>-1?n.value=e.prevInput="":e.prevInput=r,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))})),!0},Ka.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Ka.prototype.onKeyPress=function(){a&&l>=9&&(this.hasSelection=null),this.fastPoll()},Ka.prototype.onContextMenu=function(e){var t=this,n=t.cm,i=n.display,r=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=hi(n,e),u=i.scroller.scrollTop;if(o&&!h){n.options.resetSelectionOnContextMenu&&-1==n.doc.sel.contains(o)&&ir(n,io)(n.doc,Lr(o),$);var c,d=r.style.cssText,f=t.wrapper.style.cssText,p=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",r.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-p.top-5)+"px; left: "+(e.clientX-p.left-5)+"px;\n z-index: 1000; background: "+(a?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",s&&(c=r.ownerDocument.defaultView.scrollY),i.input.focus(),s&&r.ownerDocument.defaultView.scrollTo(null,c),i.input.reset(),n.somethingSelected()||(r.value=t.prevInput=" "),t.contextMenuPending=v,i.selForContextMenu=n.doc.sel,clearTimeout(i.detectingSelectAll),a&&l>=9&&g(),k){Se(e);var m=function(){ge(window,"mouseup",m),setTimeout(v,20)};pe(window,"mouseup",m)}else setTimeout(v,50)}function g(){if(null!=r.selectionStart){var e=n.somethingSelected(),o="​"+(e?r.value:"");r.value="⇚",r.value=o,t.prevInput=e?"":"​",r.selectionStart=1,r.selectionEnd=o.length,i.selForContextMenu=n.doc.sel}}function v(){if(t.contextMenuPending==v&&(t.contextMenuPending=!1,t.wrapper.style.cssText=f,r.style.cssText=d,a&&l<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=u),null!=r.selectionStart)){(!a||a&&l<9)&&g();var e=0,o=function(){i.selForContextMenu==n.doc.sel&&0==r.selectionStart&&r.selectionEnd>0&&"​"==t.prevInput?ir(n,ho)(n):e++<10?i.detectingSelectAll=setTimeout(o,500):(i.selForContextMenu=null,i.input.reset())};i.detectingSelectAll=setTimeout(o,200)}}},Ka.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},Ka.prototype.setUneditable=function(){},Ka.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function n(n,i,r,o){e.defaults[n]=i,r&&(t[n]=o?function(e,t,n){n!=Fa&&r(e,t,n)}:r)}e.defineOption=n,e.Init=Fa,n("value","",(function(e,t){return e.setValue(t)}),!0),n("mode",null,(function(e,t){e.doc.modeOption=t,Or(e)}),!0),n("indentUnit",2,Or,!0),n("indentWithTabs",!1),n("smartIndent",!0),n("tabSize",4,(function(e){Ir(e),qn(e),pi(e)}),!0),n("lineSeparator",null,(function(e,t){if(e.doc.lineSep=t,t){var n=[],i=e.doc.first;e.doc.iter((function(e){for(var r=0;;){var o=e.text.indexOf(t,r);if(-1==o)break;r=o+t.length,n.push(it(i,o))}i++}));for(var r=n.length-1;r>=0;r--)yo(e.doc,t,n[r],it(n[r].line,n[r].ch+t.length))}})),n("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g,(function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=Fa&&e.refresh()})),n("specialCharPlaceholder",tn,(function(e){return e.refresh()}),!0),n("electricChars",!0),n("inputStyle",x?"contenteditable":"textarea",(function(){throw new Error("inputStyle can not (yet) be changed in a running editor")}),!0),n("spellcheck",!1,(function(e,t){return e.getInputField().spellcheck=t}),!0),n("autocorrect",!1,(function(e,t){return e.getInputField().autocorrect=t}),!0),n("autocapitalize",!1,(function(e,t){return e.getInputField().autocapitalize=t}),!0),n("rtlMoveVisually",!D),n("wholeLineUpdateBefore",!0),n("theme","default",(function(e){Sa(e),yr(e)}),!0),n("keyMap","default",(function(e,t,n){var i=ea(t),r=n!=Fa&&ea(n);r&&r.detach&&r.detach(e,i),i.attach&&i.attach(e,r||null)})),n("extraKeys",null),n("configureMouse",null),n("lineWrapping",!1,Ta,!0),n("gutters",[],(function(e,t){e.display.gutterSpecs=vr(t,e.options.lineNumbers),yr(e)}),!0),n("fixedGutter",!0,(function(e,t){e.display.gutters.style.left=t?ui(e.display)+"px":"0",e.refresh()}),!0),n("coverGutterNextToScrollbar",!1,(function(e){return Ui(e)}),!0),n("scrollbarStyle","native",(function(e){Vi(e),Ui(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)}),!0),n("lineNumbers",!1,(function(e,t){e.display.gutterSpecs=vr(e.options.gutters,t),yr(e)}),!0),n("firstLineNumber",1,yr,!0),n("lineNumberFormatter",(function(e){return e}),yr,!0),n("showCursorWhenSelecting",!1,yi,!0),n("resetSelectionOnContextMenu",!0),n("lineWiseCopyCut",!0),n("pasteLinesPerSelection",!0),n("selectionsMayTouch",!1),n("readOnly",!1,(function(e,t){"nocursor"==t&&(Ei(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)})),n("screenReaderLabel",null,(function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)})),n("disableInput",!1,(function(e,t){t||e.display.input.reset()}),!0),n("dragDrop",!0,La),n("allowDropFileTypes",null),n("cursorBlinkRate",530),n("cursorScrollMargin",0),n("cursorHeight",1,yi,!0),n("singleCursorHeightPerLine",!0,yi,!0),n("workTime",100),n("workDelay",100),n("flattenSpans",!0,Ir,!0),n("addModeClass",!1,Ir,!0),n("pollInterval",100),n("undoDepth",200,(function(e,t){return e.doc.history.undoDepth=t})),n("historyEventDelay",1250),n("viewportMargin",10,(function(e){return e.refresh()}),!0),n("maxHighlightLength",1e4,Ir,!0),n("moveInputWithCursor",!0,(function(e,t){t||e.display.input.resetPosition()})),n("tabindex",null,(function(e,t){return e.display.input.getField().tabIndex=t||""})),n("autofocus",null),n("direction","ltr",(function(e,t){return e.doc.setDirection(t)}),!0),n("phrases",null)}(Ma),function(e){var t=e.optionHandlers,n=e.helpers={};e.prototype={constructor:e,focus:function(){R(this).focus(),this.display.input.focus()},setOption:function(e,n){var i=this.options,r=i[e];i[e]==n&&"mode"!=e||(i[e]=n,t.hasOwnProperty(e)&&ir(this,t[e])(this,n,r),ve(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](ea(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;nn&&(Na(this,r.head.line,e,!0),n=r.head.line,i==this.doc.sel.primIndex&&Oi(this));else{var o=r.from(),a=r.to(),l=Math.max(n,o.line);n=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var s=l;s0&&eo(this.doc,i,new Ar(o,u[i].to()),$)}}})),getTokenAt:function(e,t){return Dt(this,e,t)},getLineTokens:function(e,t){return Dt(this,it(e),t,!0)},getTokenTypeAt:function(e){e=ct(this.doc,e);var t,n=mt(this,Ke(this.doc,e.line)),i=0,r=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var a=i+r>>1;if((a?n[2*a-1]:0)>=o)r=a;else{if(!(n[2*a+1]o&&(e=o,r=!0),i=Ke(this.doc,e)}else i=e;return Vn(this,i,{top:0,left:0},t||"page",n||r).top+(r?this.doc.height-Gt(i):0)},defaultTextHeight:function(){return ai(this.display)},defaultCharWidth:function(){return li(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,i,r){var o,a,l,s=this.display,u=(e=Zn(this,ct(this.doc,e))).bottom,c=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),s.sizer.appendChild(t),"over"==i)u=e.top;else if("above"==i||"near"==i){var d=Math.max(s.wrapper.clientHeight,this.doc.height),h=Math.max(s.sizer.clientWidth,s.lineSpace.clientWidth);("above"==i||e.bottom+t.offsetHeight>d)&&e.top>t.offsetHeight?u=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=d&&(u=e.bottom),c+t.offsetWidth>h&&(c=h-t.offsetWidth)}t.style.top=u+"px",t.style.left=t.style.right="","right"==r?(c=s.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==r?c=0:"middle"==r&&(c=(s.sizer.clientWidth-t.offsetWidth)/2),t.style.left=c+"px"),n&&(o=this,a={left:c,top:u,right:c+t.offsetWidth,bottom:u+t.offsetHeight},null!=(l=Bi(o,a)).scrollTop&&Ri(o,l.scrollTop),null!=l.scrollLeft&&_i(o,l.scrollLeft))},triggerOnKeyDown:rr(pa),triggerOnKeyPress:rr(ga),triggerOnKeyUp:ma,triggerOnMouseDown:rr(ba),execCommand:function(e){if(oa.hasOwnProperty(e))return oa[e].call(null,this)},triggerElectric:rr((function(e){Ra(this,e)})),findPosH:function(e,t,n,i){var r=1;t<0&&(r=-1,t=-t);for(var o=ct(this.doc,e),a=0;a0&&a(t.charAt(n-1));)--n;for(;i.5||this.options.lineWrapping)&&di(this),ve(this,"refresh",this)})),swapDoc:rr((function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Pr(this,e),qn(this),this.display.input.reset(),Ii(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,dn(this,"swapDoc",this,t),t})),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},De(e),e.registerHelper=function(t,i,r){n.hasOwnProperty(t)||(n[t]=e[t]={_global:[]}),n[t][i]=r},e.registerGlobalHelper=function(t,i,r,o){e.registerHelper(t,i,o),n[t]._global.push({pred:r,val:o})}}(Ma);var Za="iter insert remove copy getEditor constructor".split(" ");for(var Ya in Io.prototype)Io.prototype.hasOwnProperty(Ya)&&q(Za,Ya)<0&&(Ma.prototype[Ya]=function(e){return function(){return e.apply(this.doc,arguments)}}(Io.prototype[Ya]));return De(Io),Ma.inputStyles={textarea:Ka,contenteditable:Ua},Ma.defineMode=function(e){Ma.defaults.mode||"null"==e||(Ma.defaults.mode=e),_e.apply(this,arguments)},Ma.defineMIME=function(e,t){Pe[e]=t},Ma.defineMode("null",(function(){return{token:function(e){return e.skipToEnd()}}})),Ma.defineMIME("text/plain","null"),Ma.defineExtension=function(e,t){Ma.prototype[e]=t},Ma.defineDocExtension=function(e,t){Io.prototype[e]=t},Ma.fromTextArea=function(e,t){if((t=t?_(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=N(e.ownerDocument);t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}function i(){e.value=l.getValue()}var r;if(e.form&&(pe(e.form,"submit",i),!t.leaveSubmitMethodAlone)){var o=e.form;r=o.submit;try{var a=o.submit=function(){i(),o.submit=r,o.submit(),o.submit=a}}catch(e){}}t.finishInit=function(n){n.save=i,n.getTextArea=function(){return e},n.toTextArea=function(){n.toTextArea=isNaN,i(),e.parentNode.removeChild(n.getWrapperElement()),e.style.display="",e.form&&(ge(e.form,"submit",i),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=r))}},e.style.display="none";var l=Ma((function(t){return e.parentNode.insertBefore(t,e.nextSibling)}),t);return l},function(e){e.off=ge,e.on=pe,e.wheelEventPixels=kr,e.Doc=Io,e.splitLines=Oe,e.countColumn=W,e.findColumn=X,e.isWordChar=ne,e.Pass=U,e.signal=ve,e.Line=Kt,e.changeEnd=Tr,e.scrollbarModel=Gi,e.Pos=it,e.cmpPos=rt,e.modes=Re,e.mimeModes=Pe,e.resolveMode=We,e.getMode=je,e.modeExtensions=qe,e.extendMode=Ue,e.copyState=$e,e.startState=Ve,e.innerMode=Ge,e.commands=oa,e.keyMap=Vo,e.keyName=Jo,e.isModifierKey=Yo,e.lookupKey=Zo,e.normalizeKeyMap=Ko,e.StringStream=Xe,e.SharedTextMarker=Mo,e.TextMarker=Lo,e.LineWidget=Fo,e.e_preventDefault=Ce,e.e_stopPropagation=we,e.e_stop=Se,e.addClass=O,e.contains=B,e.rmClass=A,e.keyNames=qo}(Ma),Ma.version="5.65.15",Ma}))},{}],11:[function(e,t,n){var i;i=function(e){"use strict";var t=/^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i;e.defineMode("gfm",(function(n,i){var r=0,o={startState:function(){return{code:!1,codeBlock:!1,ateSpace:!1}},copyState:function(e){return{code:e.code,codeBlock:e.codeBlock,ateSpace:e.ateSpace}},token:function(e,n){if(n.combineTokens=null,n.codeBlock)return e.match(/^```+/)?(n.codeBlock=!1,null):(e.skipToEnd(),null);if(e.sol()&&(n.code=!1),e.sol()&&e.match(/^```+/))return e.skipToEnd(),n.codeBlock=!0,null;if("`"===e.peek()){e.next();var o=e.pos;e.eatWhile("`");var a=1+e.pos-o;return n.code?a===r&&(n.code=!1):(r=a,n.code=!0),null}if(n.code)return e.next(),null;if(e.eatSpace())return n.ateSpace=!0,null;if((e.sol()||n.ateSpace)&&(n.ateSpace=!1,!1!==i.gitHubSpice)){if(e.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?=.{0,6}\d)(?:[a-f0-9]{7,40}\b)/))return n.combineTokens=!0,"link";if(e.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/))return n.combineTokens=!0,"link"}return e.match(t)&&"]("!=e.string.slice(e.start-2,e.start)&&(0==e.start||/\W/.test(e.string.charAt(e.start-1)))?(n.combineTokens=!0,"link"):(e.next(),null)},blankLine:function(e){return e.code=!1,null}},a={taskLists:!0,strikethrough:!0,emoji:!0};for(var l in i)a[l]=i[l];return a.name="markdown",e.overlayMode(e.getMode(n,a),o)}),"markdown"),e.defineMIME("text/x-gfm","gfm")},"object"==typeof n&&"object"==typeof t?i(e("../../lib/codemirror"),e("../markdown/markdown"),e("../../addon/mode/overlay")):i(CodeMirror)},{"../../addon/mode/overlay":7,"../../lib/codemirror":10,"../markdown/markdown":12}],12:[function(e,t,n){var i;i=function(e){"use strict";e.defineMode("markdown",(function(t,n){var i=e.getMode(t,"text/html"),r="null"==i.name;void 0===n.highlightFormatting&&(n.highlightFormatting=!1),void 0===n.maxBlockquoteDepth&&(n.maxBlockquoteDepth=0),void 0===n.taskLists&&(n.taskLists=!1),void 0===n.strikethrough&&(n.strikethrough=!1),void 0===n.emoji&&(n.emoji=!1),void 0===n.fencedCodeBlockHighlighting&&(n.fencedCodeBlockHighlighting=!0),void 0===n.fencedCodeBlockDefaultMode&&(n.fencedCodeBlockDefaultMode="text/plain"),void 0===n.xml&&(n.xml=!0),void 0===n.tokenTypeOverrides&&(n.tokenTypeOverrides={});var o={header:"header",code:"comment",quote:"quote",list1:"variable-2",list2:"variable-3",list3:"keyword",hr:"hr",image:"image",imageAltText:"image-alt-text",imageMarker:"image-marker",formatting:"formatting",linkInline:"link",linkEmail:"link",linkText:"link",linkHref:"string",em:"em",strong:"strong",strikethrough:"strikethrough",emoji:"builtin"};for(var a in o)o.hasOwnProperty(a)&&n.tokenTypeOverrides[a]&&(o[a]=n.tokenTypeOverrides[a]);var l=/^([*\-_])(?:\s*\1){2,}\s*$/,s=/^(?:[*\-+]|^[0-9]+([.)]))\s+/,u=/^\[(x| )\](?=\s)/i,c=n.allowAtxHeaderWithoutSpace?/^(#+)/:/^(#+)(?: |$)/,d=/^ {0,3}(?:\={1,}|-{2,})\s*$/,h=/^[^#!\[\]*_\\<>` "'(~:]+/,f=/^(~~~+|```+)[ \t]*([\w\/+#-]*)[^\n`]*$/,p=/^\s*\[[^\]]+?\]:.*$/,m=/[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/;function g(e,t,n){return t.f=t.inline=n,n(e,t)}function v(e,t,n){return t.f=t.block=n,n(e,t)}function x(t){if(t.linkTitle=!1,t.linkHref=!1,t.linkText=!1,t.em=!1,t.strong=!1,t.strikethrough=!1,t.quote=0,t.indentedCode=!1,t.f==b){var n=r;if(!n){var o=e.innerMode(i,t.htmlState);n="xml"==o.mode.name&&null===o.state.tagStart&&!o.state.context&&o.state.tokenize.isInText}n&&(t.f=k,t.block=y,t.htmlState=null)}return t.trailingSpace=0,t.trailingSpaceNewLine=!1,t.prevLine=t.thisLine,t.thisLine={stream:null},null}function y(i,r){var a,h=i.column()===r.indentation,m=!(a=r.prevLine.stream)||!/\S/.test(a.string),v=r.indentedCode,x=r.prevLine.hr,y=!1!==r.list,b=(r.listStack[r.listStack.length-1]||0)+3;r.indentedCode=!1;var w=r.indentation;if(null===r.indentationDiff&&(r.indentationDiff=r.indentation,y)){for(r.list=null;w=4&&(v||r.prevLine.fencedCodeEnd||r.prevLine.header||m))return i.skipToEnd(),r.indentedCode=!0,o.code;if(i.eatSpace())return null;if(h&&r.indentation<=b&&(F=i.match(c))&&F[1].length<=6)return r.quote=0,r.header=F[1].length,r.thisLine.header=!0,n.highlightFormatting&&(r.formatting="header"),r.f=r.inline,C(r);if(r.indentation<=b&&i.eat(">"))return r.quote=h?1:r.quote+1,n.highlightFormatting&&(r.formatting="quote"),i.eatSpace(),C(r);if(!S&&!r.setext&&h&&r.indentation<=b&&(F=i.match(s))){var A=F[1]?"ol":"ul";return r.indentation=w+i.current().length,r.list=!0,r.quote=0,r.listStack.push(r.indentation),r.em=!1,r.strong=!1,r.code=!1,r.strikethrough=!1,n.taskLists&&i.match(u,!1)&&(r.taskList=!0),r.f=r.inline,n.highlightFormatting&&(r.formatting=["list","list-"+A]),C(r)}return h&&r.indentation<=b&&(F=i.match(f,!0))?(r.quote=0,r.fencedEndRE=new RegExp(F[1]+"+ *$"),r.localMode=n.fencedCodeBlockHighlighting&&function(n){if(e.findModeByName){var i=e.findModeByName(n);i&&(n=i.mime||i.mimes[0])}var r=e.getMode(t,n);return"null"==r.name?null:r}(F[2]||n.fencedCodeBlockDefaultMode),r.localMode&&(r.localState=e.startState(r.localMode)),r.f=r.block=D,n.highlightFormatting&&(r.formatting="code-block"),r.code=-1,C(r)):r.setext||!(k&&y||r.quote||!1!==r.list||r.code||S||p.test(i.string))&&(F=i.lookAhead(1))&&(F=F.match(d))?(r.setext?(r.header=r.setext,r.setext=0,i.skipToEnd(),n.highlightFormatting&&(r.formatting="header")):(r.header="="==F[0].charAt(0)?1:2,r.setext=r.header),r.thisLine.header=!0,r.f=r.inline,C(r)):S?(i.skipToEnd(),r.hr=!0,r.thisLine.hr=!0,o.hr):"["===i.peek()?g(i,r,E):g(i,r,r.inline)}function b(t,n){var o=i.token(t,n.htmlState);if(!r){var a=e.innerMode(i,n.htmlState);("xml"==a.mode.name&&null===a.state.tagStart&&!a.state.context&&a.state.tokenize.isInText||n.md_inside&&t.current().indexOf(">")>-1)&&(n.f=k,n.block=y,n.htmlState=null)}return o}function D(e,t){var i,r=t.listStack[t.listStack.length-1]||0,a=t.indentation=e.quote?t.push(o.formatting+"-"+e.formatting[i]+"-"+e.quote):t.push("error"))}if(e.taskOpen)return t.push("meta"),t.length?t.join(" "):null;if(e.taskClosed)return t.push("property"),t.length?t.join(" "):null;if(e.linkHref?t.push(o.linkHref,"url"):(e.strong&&t.push(o.strong),e.em&&t.push(o.em),e.strikethrough&&t.push(o.strikethrough),e.emoji&&t.push(o.emoji),e.linkText&&t.push(o.linkText),e.code&&t.push(o.code),e.image&&t.push(o.image),e.imageAltText&&t.push(o.imageAltText,"link"),e.imageMarker&&t.push(o.imageMarker)),e.header&&t.push(o.header,o.header+"-"+e.header),e.quote&&(t.push(o.quote),!n.maxBlockquoteDepth||n.maxBlockquoteDepth>=e.quote?t.push(o.quote+"-"+e.quote):t.push(o.quote+"-"+n.maxBlockquoteDepth)),!1!==e.list){var r=(e.listStack.length-1)%3;r?1===r?t.push(o.list2):t.push(o.list3):t.push(o.list1)}return e.trailingSpaceNewLine?t.push("trailing-space-new-line"):e.trailingSpace&&t.push("trailing-space-"+(e.trailingSpace%2?"a":"b")),t.length?t.join(" "):null}function w(e,t){if(e.match(h,!0))return C(t)}function k(t,r){var a=r.text(t,r);if(void 0!==a)return a;if(r.list)return r.list=null,C(r);if(r.taskList)return" "===t.match(u,!0)[1]?r.taskOpen=!0:r.taskClosed=!0,n.highlightFormatting&&(r.formatting="task"),r.taskList=!1,C(r);if(r.taskOpen=!1,r.taskClosed=!1,r.header&&t.match(/^#+$/,!0))return n.highlightFormatting&&(r.formatting="header"),C(r);var l=t.next();if(r.linkTitle){r.linkTitle=!1;var s=l;"("===l&&(s=")");var c="^\\s*(?:[^"+(s=(s+"").replace(/([.?*+^\[\]\\(){}|-])/g,"\\$1"))+"\\\\]+|\\\\\\\\|\\\\.)"+s;if(t.match(new RegExp(c),!0))return o.linkHref}if("`"===l){var d=r.formatting;n.highlightFormatting&&(r.formatting="code"),t.eatWhile("`");var h=t.current().length;if(0!=r.code||r.quote&&1!=h){if(h==r.code){var f=C(r);return r.code=0,f}return r.formatting=d,C(r)}return r.code=h,C(r)}if(r.code)return C(r);if("\\"===l&&(t.next(),n.highlightFormatting)){var p=C(r),g=o.formatting+"-escape";return p?p+" "+g:g}if("!"===l&&t.match(/\[[^\]]*\] ?(?:\(|\[)/,!1))return r.imageMarker=!0,r.image=!0,n.highlightFormatting&&(r.formatting="image"),C(r);if("["===l&&r.imageMarker&&t.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/,!1))return r.imageMarker=!1,r.imageAltText=!0,n.highlightFormatting&&(r.formatting="image"),C(r);if("]"===l&&r.imageAltText){n.highlightFormatting&&(r.formatting="image");var p=C(r);return r.imageAltText=!1,r.image=!1,r.inline=r.f=F,p}if("["===l&&!r.image)return r.linkText&&t.match(/^.*?\]/)||(r.linkText=!0,n.highlightFormatting&&(r.formatting="link")),C(r);if("]"===l&&r.linkText){n.highlightFormatting&&(r.formatting="link");var p=C(r);return r.linkText=!1,r.inline=r.f=t.match(/\(.*?\)| ?\[.*?\]/,!1)?F:k,p}if("<"===l&&t.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/,!1))return r.f=r.inline=S,n.highlightFormatting&&(r.formatting="link"),(p=C(r))?p+=" ":p="",p+o.linkInline;if("<"===l&&t.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/,!1))return r.f=r.inline=S,n.highlightFormatting&&(r.formatting="link"),(p=C(r))?p+=" ":p="",p+o.linkEmail;if(n.xml&&"<"===l&&t.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i,!1)){var x=t.string.indexOf(">",t.pos);if(-1!=x){var y=t.string.substring(t.start,x);/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(y)&&(r.md_inside=!0)}return t.backUp(1),r.htmlState=e.startState(i),v(t,r,b)}if(n.xml&&"<"===l&&t.match(/^\/\w*?>/))return r.md_inside=!1,"tag";if("*"===l||"_"===l){for(var D=1,w=1==t.pos?" ":t.string.charAt(t.pos-2);D<3&&t.eat(l);)D++;var A=t.peek()||" ",E=!/\s/.test(A)&&(!m.test(A)||/\s/.test(w)||m.test(w)),L=!/\s/.test(w)&&(!m.test(w)||/\s/.test(A)||m.test(A)),T=null,M=null;if(D%2&&(r.em||!E||"*"!==l&&L&&!m.test(w)?r.em!=l||!L||"*"!==l&&E&&!m.test(A)||(T=!1):T=!0),D>1&&(r.strong||!E||"*"!==l&&L&&!m.test(w)?r.strong!=l||!L||"*"!==l&&E&&!m.test(A)||(M=!1):M=!0),null!=M||null!=T)return n.highlightFormatting&&(r.formatting=null==T?"strong":null==M?"em":"strong em"),!0===T&&(r.em=l),!0===M&&(r.strong=l),f=C(r),!1===T&&(r.em=!1),!1===M&&(r.strong=!1),f}else if(" "===l&&(t.eat("*")||t.eat("_"))){if(" "===t.peek())return C(r);t.backUp(1)}if(n.strikethrough)if("~"===l&&t.eatWhile(l)){if(r.strikethrough)return n.highlightFormatting&&(r.formatting="strikethrough"),f=C(r),r.strikethrough=!1,f;if(t.match(/^[^\s]/,!1))return r.strikethrough=!0,n.highlightFormatting&&(r.formatting="strikethrough"),C(r)}else if(" "===l&&t.match("~~",!0)){if(" "===t.peek())return C(r);t.backUp(2)}if(n.emoji&&":"===l&&t.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)){r.emoji=!0,n.highlightFormatting&&(r.formatting="emoji");var B=C(r);return r.emoji=!1,B}return" "===l&&(t.match(/^ +$/,!1)?r.trailingSpace++:r.trailingSpace&&(r.trailingSpaceNewLine=!0)),C(r)}function S(e,t){if(">"===e.next()){t.f=t.inline=k,n.highlightFormatting&&(t.formatting="link");var i=C(t);return i?i+=" ":i="",i+o.linkInline}return e.match(/^[^>]+/,!0),o.linkInline}function F(e,t){if(e.eatSpace())return null;var i,r=e.next();return"("===r||"["===r?(t.f=t.inline=(i="("===r?")":"]",function(e,t){if(e.next()===i){t.f=t.inline=k,n.highlightFormatting&&(t.formatting="link-string");var r=C(t);return t.linkHref=!1,r}return e.match(A[i]),t.linkHref=!0,C(t)}),n.highlightFormatting&&(t.formatting="link-string"),t.linkHref=!0,C(t)):"error"}var A={")":/^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,"]":/^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/};function E(e,t){return e.match(/^([^\]\\]|\\.)*\]:/,!1)?(t.f=L,e.next(),n.highlightFormatting&&(t.formatting="link"),t.linkText=!0,C(t)):g(e,t,k)}function L(e,t){if(e.match("]:",!0)){t.f=t.inline=T,n.highlightFormatting&&(t.formatting="link");var i=C(t);return t.linkText=!1,i}return e.match(/^([^\]\\]|\\.)+/,!0),o.linkText}function T(e,t){return e.eatSpace()?null:(e.match(/^[^\s]+/,!0),void 0===e.peek()?t.linkTitle=!0:e.match(/^(?:\s+(?:"(?:[^"\\]|\\.)+"|'(?:[^'\\]|\\.)+'|\((?:[^)\\]|\\.)+\)))?/,!0),t.f=t.inline=k,o.linkHref+" url")}var M={startState:function(){return{f:y,prevLine:{stream:null},thisLine:{stream:null},block:y,htmlState:null,indentation:0,inline:k,text:w,formatting:!1,linkText:!1,linkHref:!1,linkTitle:!1,code:0,em:!1,strong:!1,header:0,setext:0,hr:!1,taskList:!1,list:!1,listStack:[],quote:0,trailingSpace:0,trailingSpaceNewLine:!1,strikethrough:!1,emoji:!1,fencedEndRE:null}},copyState:function(t){return{f:t.f,prevLine:t.prevLine,thisLine:t.thisLine,block:t.block,htmlState:t.htmlState&&e.copyState(i,t.htmlState),indentation:t.indentation,localMode:t.localMode,localState:t.localMode?e.copyState(t.localMode,t.localState):null,inline:t.inline,text:t.text,formatting:!1,linkText:t.linkText,linkTitle:t.linkTitle,linkHref:t.linkHref,code:t.code,em:t.em,strong:t.strong,strikethrough:t.strikethrough,emoji:t.emoji,header:t.header,setext:t.setext,hr:t.hr,taskList:t.taskList,list:t.list,listStack:t.listStack.slice(0),quote:t.quote,indentedCode:t.indentedCode,trailingSpace:t.trailingSpace,trailingSpaceNewLine:t.trailingSpaceNewLine,md_inside:t.md_inside,fencedEndRE:t.fencedEndRE}},token:function(e,t){if(t.formatting=!1,e!=t.thisLine.stream){if(t.header=0,t.hr=!1,e.match(/^\s*$/,!0))return x(t),null;if(t.prevLine=t.thisLine,t.thisLine={stream:e},t.taskList=!1,t.trailingSpace=0,t.trailingSpaceNewLine=!1,!t.localState&&(t.f=t.block,t.f!=b)){var n=e.match(/^\s*/,!0)[0].replace(/\t/g," ").length;if(t.indentation=n,t.indentationDiff=null,n>0)return null}}return t.f(e,t)},innerMode:function(e){return e.block==b?{state:e.htmlState,mode:i}:e.localState?{state:e.localState,mode:e.localMode}:{state:e,mode:M}},indent:function(t,n,r){return t.block==b&&i.indent?i.indent(t.htmlState,n,r):t.localState&&t.localMode.indent?t.localMode.indent(t.localState,n,r):e.Pass},blankLine:x,getType:C,blockCommentStart:"\x3c!--",blockCommentEnd:"--\x3e",closeBrackets:"()[]{}''\"\"``",fold:"markdown"};return M}),"xml"),e.defineMIME("text/markdown","markdown"),e.defineMIME("text/x-markdown","markdown")},"object"==typeof n&&"object"==typeof t?i(e("../../lib/codemirror"),e("../xml/xml"),e("../meta")):i(CodeMirror)},{"../../lib/codemirror":10,"../meta":13,"../xml/xml":14}],13:[function(e,t,n){(function(e){"use strict";e.modeInfo=[{name:"APL",mime:"text/apl",mode:"apl",ext:["dyalog","apl"]},{name:"PGP",mimes:["application/pgp","application/pgp-encrypted","application/pgp-keys","application/pgp-signature"],mode:"asciiarmor",ext:["asc","pgp","sig"]},{name:"ASN.1",mime:"text/x-ttcn-asn",mode:"asn.1",ext:["asn","asn1"]},{name:"Asterisk",mime:"text/x-asterisk",mode:"asterisk",file:/^extensions\.conf$/i},{name:"Brainfuck",mime:"text/x-brainfuck",mode:"brainfuck",ext:["b","bf"]},{name:"C",mime:"text/x-csrc",mode:"clike",ext:["c","h","ino"]},{name:"C++",mime:"text/x-c++src",mode:"clike",ext:["cpp","c++","cc","cxx","hpp","h++","hh","hxx"],alias:["cpp"]},{name:"Cobol",mime:"text/x-cobol",mode:"cobol",ext:["cob","cpy","cbl"]},{name:"C#",mime:"text/x-csharp",mode:"clike",ext:["cs"],alias:["csharp","cs"]},{name:"Clojure",mime:"text/x-clojure",mode:"clojure",ext:["clj","cljc","cljx"]},{name:"ClojureScript",mime:"text/x-clojurescript",mode:"clojure",ext:["cljs"]},{name:"Closure Stylesheets (GSS)",mime:"text/x-gss",mode:"css",ext:["gss"]},{name:"CMake",mime:"text/x-cmake",mode:"cmake",ext:["cmake","cmake.in"],file:/^CMakeLists\.txt$/},{name:"CoffeeScript",mimes:["application/vnd.coffeescript","text/coffeescript","text/x-coffeescript"],mode:"coffeescript",ext:["coffee"],alias:["coffee","coffee-script"]},{name:"Common Lisp",mime:"text/x-common-lisp",mode:"commonlisp",ext:["cl","lisp","el"],alias:["lisp"]},{name:"Cypher",mime:"application/x-cypher-query",mode:"cypher",ext:["cyp","cypher"]},{name:"Cython",mime:"text/x-cython",mode:"python",ext:["pyx","pxd","pxi"]},{name:"Crystal",mime:"text/x-crystal",mode:"crystal",ext:["cr"]},{name:"CSS",mime:"text/css",mode:"css",ext:["css"]},{name:"CQL",mime:"text/x-cassandra",mode:"sql",ext:["cql"]},{name:"D",mime:"text/x-d",mode:"d",ext:["d"]},{name:"Dart",mimes:["application/dart","text/x-dart"],mode:"dart",ext:["dart"]},{name:"diff",mime:"text/x-diff",mode:"diff",ext:["diff","patch"]},{name:"Django",mime:"text/x-django",mode:"django"},{name:"Dockerfile",mime:"text/x-dockerfile",mode:"dockerfile",file:/^Dockerfile$/},{name:"DTD",mime:"application/xml-dtd",mode:"dtd",ext:["dtd"]},{name:"Dylan",mime:"text/x-dylan",mode:"dylan",ext:["dylan","dyl","intr"]},{name:"EBNF",mime:"text/x-ebnf",mode:"ebnf"},{name:"ECL",mime:"text/x-ecl",mode:"ecl",ext:["ecl"]},{name:"edn",mime:"application/edn",mode:"clojure",ext:["edn"]},{name:"Eiffel",mime:"text/x-eiffel",mode:"eiffel",ext:["e"]},{name:"Elm",mime:"text/x-elm",mode:"elm",ext:["elm"]},{name:"Embedded JavaScript",mime:"application/x-ejs",mode:"htmlembedded",ext:["ejs"]},{name:"Embedded Ruby",mime:"application/x-erb",mode:"htmlembedded",ext:["erb"]},{name:"Erlang",mime:"text/x-erlang",mode:"erlang",ext:["erl"]},{name:"Esper",mime:"text/x-esper",mode:"sql"},{name:"Factor",mime:"text/x-factor",mode:"factor",ext:["factor"]},{name:"FCL",mime:"text/x-fcl",mode:"fcl"},{name:"Forth",mime:"text/x-forth",mode:"forth",ext:["forth","fth","4th"]},{name:"Fortran",mime:"text/x-fortran",mode:"fortran",ext:["f","for","f77","f90","f95"]},{name:"F#",mime:"text/x-fsharp",mode:"mllike",ext:["fs"],alias:["fsharp"]},{name:"Gas",mime:"text/x-gas",mode:"gas",ext:["s"]},{name:"Gherkin",mime:"text/x-feature",mode:"gherkin",ext:["feature"]},{name:"GitHub Flavored Markdown",mime:"text/x-gfm",mode:"gfm",file:/^(readme|contributing|history)\.md$/i},{name:"Go",mime:"text/x-go",mode:"go",ext:["go"]},{name:"Groovy",mime:"text/x-groovy",mode:"groovy",ext:["groovy","gradle"],file:/^Jenkinsfile$/},{name:"HAML",mime:"text/x-haml",mode:"haml",ext:["haml"]},{name:"Haskell",mime:"text/x-haskell",mode:"haskell",ext:["hs"]},{name:"Haskell (Literate)",mime:"text/x-literate-haskell",mode:"haskell-literate",ext:["lhs"]},{name:"Haxe",mime:"text/x-haxe",mode:"haxe",ext:["hx"]},{name:"HXML",mime:"text/x-hxml",mode:"haxe",ext:["hxml"]},{name:"ASP.NET",mime:"application/x-aspx",mode:"htmlembedded",ext:["aspx"],alias:["asp","aspx"]},{name:"HTML",mime:"text/html",mode:"htmlmixed",ext:["html","htm","handlebars","hbs"],alias:["xhtml"]},{name:"HTTP",mime:"message/http",mode:"http"},{name:"IDL",mime:"text/x-idl",mode:"idl",ext:["pro"]},{name:"Pug",mime:"text/x-pug",mode:"pug",ext:["jade","pug"],alias:["jade"]},{name:"Java",mime:"text/x-java",mode:"clike",ext:["java"]},{name:"Java Server Pages",mime:"application/x-jsp",mode:"htmlembedded",ext:["jsp"],alias:["jsp"]},{name:"JavaScript",mimes:["text/javascript","text/ecmascript","application/javascript","application/x-javascript","application/ecmascript"],mode:"javascript",ext:["js"],alias:["ecmascript","js","node"]},{name:"JSON",mimes:["application/json","application/x-json"],mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"JSON-LD",mime:"application/ld+json",mode:"javascript",ext:["jsonld"],alias:["jsonld"]},{name:"JSX",mime:"text/jsx",mode:"jsx",ext:["jsx"]},{name:"Jinja2",mime:"text/jinja2",mode:"jinja2",ext:["j2","jinja","jinja2"]},{name:"Julia",mime:"text/x-julia",mode:"julia",ext:["jl"],alias:["jl"]},{name:"Kotlin",mime:"text/x-kotlin",mode:"clike",ext:["kt"]},{name:"LESS",mime:"text/x-less",mode:"css",ext:["less"]},{name:"LiveScript",mime:"text/x-livescript",mode:"livescript",ext:["ls"],alias:["ls"]},{name:"Lua",mime:"text/x-lua",mode:"lua",ext:["lua"]},{name:"Markdown",mime:"text/x-markdown",mode:"markdown",ext:["markdown","md","mkd"]},{name:"mIRC",mime:"text/mirc",mode:"mirc"},{name:"MariaDB SQL",mime:"text/x-mariadb",mode:"sql"},{name:"Mathematica",mime:"text/x-mathematica",mode:"mathematica",ext:["m","nb","wl","wls"]},{name:"Modelica",mime:"text/x-modelica",mode:"modelica",ext:["mo"]},{name:"MUMPS",mime:"text/x-mumps",mode:"mumps",ext:["mps"]},{name:"MS SQL",mime:"text/x-mssql",mode:"sql"},{name:"mbox",mime:"application/mbox",mode:"mbox",ext:["mbox"]},{name:"MySQL",mime:"text/x-mysql",mode:"sql"},{name:"Nginx",mime:"text/x-nginx-conf",mode:"nginx",file:/nginx.*\.conf$/i},{name:"NSIS",mime:"text/x-nsis",mode:"nsis",ext:["nsh","nsi"]},{name:"NTriples",mimes:["application/n-triples","application/n-quads","text/n-triples"],mode:"ntriples",ext:["nt","nq"]},{name:"Objective-C",mime:"text/x-objectivec",mode:"clike",ext:["m"],alias:["objective-c","objc"]},{name:"Objective-C++",mime:"text/x-objectivec++",mode:"clike",ext:["mm"],alias:["objective-c++","objc++"]},{name:"OCaml",mime:"text/x-ocaml",mode:"mllike",ext:["ml","mli","mll","mly"]},{name:"Octave",mime:"text/x-octave",mode:"octave",ext:["m"]},{name:"Oz",mime:"text/x-oz",mode:"oz",ext:["oz"]},{name:"Pascal",mime:"text/x-pascal",mode:"pascal",ext:["p","pas"]},{name:"PEG.js",mime:"null",mode:"pegjs",ext:["jsonld"]},{name:"Perl",mime:"text/x-perl",mode:"perl",ext:["pl","pm"]},{name:"PHP",mimes:["text/x-php","application/x-httpd-php","application/x-httpd-php-open"],mode:"php",ext:["php","php3","php4","php5","php7","phtml"]},{name:"Pig",mime:"text/x-pig",mode:"pig",ext:["pig"]},{name:"Plain Text",mime:"text/plain",mode:"null",ext:["txt","text","conf","def","list","log"]},{name:"PLSQL",mime:"text/x-plsql",mode:"sql",ext:["pls"]},{name:"PostgreSQL",mime:"text/x-pgsql",mode:"sql"},{name:"PowerShell",mime:"application/x-powershell",mode:"powershell",ext:["ps1","psd1","psm1"]},{name:"Properties files",mime:"text/x-properties",mode:"properties",ext:["properties","ini","in"],alias:["ini","properties"]},{name:"ProtoBuf",mime:"text/x-protobuf",mode:"protobuf",ext:["proto"]},{name:"Python",mime:"text/x-python",mode:"python",ext:["BUILD","bzl","py","pyw"],file:/^(BUCK|BUILD)$/},{name:"Puppet",mime:"text/x-puppet",mode:"puppet",ext:["pp"]},{name:"Q",mime:"text/x-q",mode:"q",ext:["q"]},{name:"R",mime:"text/x-rsrc",mode:"r",ext:["r","R"],alias:["rscript"]},{name:"reStructuredText",mime:"text/x-rst",mode:"rst",ext:["rst"],alias:["rst"]},{name:"RPM Changes",mime:"text/x-rpm-changes",mode:"rpm"},{name:"RPM Spec",mime:"text/x-rpm-spec",mode:"rpm",ext:["spec"]},{name:"Ruby",mime:"text/x-ruby",mode:"ruby",ext:["rb"],alias:["jruby","macruby","rake","rb","rbx"]},{name:"Rust",mime:"text/x-rustsrc",mode:"rust",ext:["rs"]},{name:"SAS",mime:"text/x-sas",mode:"sas",ext:["sas"]},{name:"Sass",mime:"text/x-sass",mode:"sass",ext:["sass"]},{name:"Scala",mime:"text/x-scala",mode:"clike",ext:["scala"]},{name:"Scheme",mime:"text/x-scheme",mode:"scheme",ext:["scm","ss"]},{name:"SCSS",mime:"text/x-scss",mode:"css",ext:["scss"]},{name:"Shell",mimes:["text/x-sh","application/x-sh"],mode:"shell",ext:["sh","ksh","bash"],alias:["bash","sh","zsh"],file:/^PKGBUILD$/},{name:"Sieve",mime:"application/sieve",mode:"sieve",ext:["siv","sieve"]},{name:"Slim",mimes:["text/x-slim","application/x-slim"],mode:"slim",ext:["slim"]},{name:"Smalltalk",mime:"text/x-stsrc",mode:"smalltalk",ext:["st"]},{name:"Smarty",mime:"text/x-smarty",mode:"smarty",ext:["tpl"]},{name:"Solr",mime:"text/x-solr",mode:"solr"},{name:"SML",mime:"text/x-sml",mode:"mllike",ext:["sml","sig","fun","smackspec"]},{name:"Soy",mime:"text/x-soy",mode:"soy",ext:["soy"],alias:["closure template"]},{name:"SPARQL",mime:"application/sparql-query",mode:"sparql",ext:["rq","sparql"],alias:["sparul"]},{name:"Spreadsheet",mime:"text/x-spreadsheet",mode:"spreadsheet",alias:["excel","formula"]},{name:"SQL",mime:"text/x-sql",mode:"sql",ext:["sql"]},{name:"SQLite",mime:"text/x-sqlite",mode:"sql"},{name:"Squirrel",mime:"text/x-squirrel",mode:"clike",ext:["nut"]},{name:"Stylus",mime:"text/x-styl",mode:"stylus",ext:["styl"]},{name:"Swift",mime:"text/x-swift",mode:"swift",ext:["swift"]},{name:"sTeX",mime:"text/x-stex",mode:"stex"},{name:"LaTeX",mime:"text/x-latex",mode:"stex",ext:["text","ltx","tex"],alias:["tex"]},{name:"SystemVerilog",mime:"text/x-systemverilog",mode:"verilog",ext:["v","sv","svh"]},{name:"Tcl",mime:"text/x-tcl",mode:"tcl",ext:["tcl"]},{name:"Textile",mime:"text/x-textile",mode:"textile",ext:["textile"]},{name:"TiddlyWiki",mime:"text/x-tiddlywiki",mode:"tiddlywiki"},{name:"Tiki wiki",mime:"text/tiki",mode:"tiki"},{name:"TOML",mime:"text/x-toml",mode:"toml",ext:["toml"]},{name:"Tornado",mime:"text/x-tornado",mode:"tornado"},{name:"troff",mime:"text/troff",mode:"troff",ext:["1","2","3","4","5","6","7","8","9"]},{name:"TTCN",mime:"text/x-ttcn",mode:"ttcn",ext:["ttcn","ttcn3","ttcnpp"]},{name:"TTCN_CFG",mime:"text/x-ttcn-cfg",mode:"ttcn-cfg",ext:["cfg"]},{name:"Turtle",mime:"text/turtle",mode:"turtle",ext:["ttl"]},{name:"TypeScript",mime:"application/typescript",mode:"javascript",ext:["ts"],alias:["ts"]},{name:"TypeScript-JSX",mime:"text/typescript-jsx",mode:"jsx",ext:["tsx"],alias:["tsx"]},{name:"Twig",mime:"text/x-twig",mode:"twig"},{name:"Web IDL",mime:"text/x-webidl",mode:"webidl",ext:["webidl"]},{name:"VB.NET",mime:"text/x-vb",mode:"vb",ext:["vb"]},{name:"VBScript",mime:"text/vbscript",mode:"vbscript",ext:["vbs"]},{name:"Velocity",mime:"text/velocity",mode:"velocity",ext:["vtl"]},{name:"Verilog",mime:"text/x-verilog",mode:"verilog",ext:["v"]},{name:"VHDL",mime:"text/x-vhdl",mode:"vhdl",ext:["vhd","vhdl"]},{name:"Vue.js Component",mimes:["script/x-vue","text/x-vue"],mode:"vue",ext:["vue"]},{name:"XML",mimes:["application/xml","text/xml"],mode:"xml",ext:["xml","xsl","xsd","svg"],alias:["rss","wsdl","xsd"]},{name:"XQuery",mime:"application/xquery",mode:"xquery",ext:["xy","xquery"]},{name:"Yacas",mime:"text/x-yacas",mode:"yacas",ext:["ys"]},{name:"YAML",mimes:["text/x-yaml","text/yaml"],mode:"yaml",ext:["yaml","yml"],alias:["yml"]},{name:"Z80",mime:"text/x-z80",mode:"z80",ext:["z80"]},{name:"mscgen",mime:"text/x-mscgen",mode:"mscgen",ext:["mscgen","mscin","msc"]},{name:"xu",mime:"text/x-xu",mode:"mscgen",ext:["xu"]},{name:"msgenny",mime:"text/x-msgenny",mode:"mscgen",ext:["msgenny"]},{name:"WebAssembly",mime:"text/webassembly",mode:"wast",ext:["wat","wast"]}];for(var t=0;t-1&&t.substring(r+1,t.length);if(o)return e.findModeByExtension(o)},e.findModeByName=function(t){t=t.toLowerCase();for(var n=0;n")):null:e.match("--")?n(f("comment","--\x3e")):e.match("DOCTYPE",!0,!0)?(e.eatWhile(/[\w\._\-]/),n(p(1))):null:e.eat("?")?(e.eatWhile(/[\w\._\-]/),t.tokenize=f("meta","?>"),"meta"):(o=e.eat("/")?"closeTag":"openTag",t.tokenize=h,"tag bracket"):"&"==i?(e.eat("#")?e.eat("x")?e.eatWhile(/[a-fA-F\d]/)&&e.eat(";"):e.eatWhile(/[\d]/)&&e.eat(";"):e.eatWhile(/[\w\.\-:]/)&&e.eat(";"))?"atom":"error":(e.eatWhile(/[^&<]/),null)}function h(e,t){var n,i,r=e.next();if(">"==r||"/"==r&&e.eat(">"))return t.tokenize=d,o=">"==r?"endTag":"selfcloseTag","tag bracket";if("="==r)return o="equals",null;if("<"==r){t.tokenize=d,t.state=y,t.tagName=t.tagStart=null;var a=t.tokenize(e,t);return a?a+" tag error":"tag error"}return/[\'\"]/.test(r)?(t.tokenize=(n=r,i=function(e,t){for(;!e.eol();)if(e.next()==n){t.tokenize=h;break}return"string"},i.isInAttribute=!0,i),t.stringStartCol=e.column(),t.tokenize(e,t)):(e.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/),"word")}function f(e,t){return function(n,i){for(;!n.eol();){if(n.match(t)){i.tokenize=d;break}n.next()}return e}}function p(e){return function(t,n){for(var i;null!=(i=t.next());){if("<"==i)return n.tokenize=p(e+1),n.tokenize(t,n);if(">"==i){if(1==e){n.tokenize=d;break}return n.tokenize=p(e-1),n.tokenize(t,n)}}return"meta"}}function m(e){return e&&e.toLowerCase()}function g(e,t,n){this.prev=e.context,this.tagName=t||"",this.indent=e.indented,this.startOfLine=n,(s.doNotIndent.hasOwnProperty(t)||e.context&&e.context.noIndent)&&(this.noIndent=!0)}function v(e){e.context&&(e.context=e.context.prev)}function x(e,t){for(var n;;){if(!e.context)return;if(n=e.context.tagName,!s.contextGrabbers.hasOwnProperty(m(n))||!s.contextGrabbers[m(n)].hasOwnProperty(m(t)))return;v(e)}}function y(e,t,n){return"openTag"==e?(n.tagStart=t.column(),b):"closeTag"==e?D:y}function b(e,t,n){return"word"==e?(n.tagName=t.current(),a="tag",k):s.allowMissingTagName&&"endTag"==e?(a="tag bracket",k(e,0,n)):(a="error",b)}function D(e,t,n){if("word"==e){var i=t.current();return n.context&&n.context.tagName!=i&&s.implicitlyClosed.hasOwnProperty(m(n.context.tagName))&&v(n),n.context&&n.context.tagName==i||!1===s.matchClosing?(a="tag",C):(a="tag error",w)}return s.allowMissingTagName&&"endTag"==e?(a="tag bracket",C(e,0,n)):(a="error",w)}function C(e,t,n){return"endTag"!=e?(a="error",C):(v(n),y)}function w(e,t,n){return a="error",C(e,0,n)}function k(e,t,n){if("word"==e)return a="attribute",S;if("endTag"==e||"selfcloseTag"==e){var i=n.tagName,r=n.tagStart;return n.tagName=n.tagStart=null,"selfcloseTag"==e||s.autoSelfClosers.hasOwnProperty(m(i))?x(n,i):(x(n,i),n.context=new g(n,i,r==n.indented)),y}return a="error",k}function S(e,t,n){return"equals"==e?F:(s.allowMissing||(a="error"),k(e,0,n))}function F(e,t,n){return"string"==e?A:"word"==e&&s.allowUnquoted?(a="string",k):(a="error",k(e,0,n))}function A(e,t,n){return"string"==e?A:k(e,0,n)}return d.isInText=!0,{startState:function(e){var t={tokenize:d,state:y,indented:e||0,tagName:null,tagStart:null,context:null};return null!=e&&(t.baseIndent=e),t},token:function(e,t){if(!t.tagName&&e.sol()&&(t.indented=e.indentation()),e.eatSpace())return null;o=null;var n=t.tokenize(e,t);return(n||o)&&"comment"!=n&&(a=null,t.state=t.state(o||n,e,t),a&&(n="error"==a?n+" error":a)),n},indent:function(t,n,i){var r=t.context;if(t.tokenize.isInAttribute)return t.tagStart==t.indented?t.stringStartCol+1:t.indented+l;if(r&&r.noIndent)return e.Pass;if(t.tokenize!=h&&t.tokenize!=d)return i?i.match(/^(\s*)/)[0].length:0;if(t.tagName)return!1!==s.multilineTagIndentPastTag?t.tagStart+t.tagName.length+2:t.tagStart+l*(s.multilineTagIndentFactor||1);if(s.alignCDATA&&/$/,blockCommentStart:"\x3c!--",blockCommentEnd:"--\x3e",configuration:s.htmlMode?"html":"xml",helperType:s.htmlMode?"html":"xml",skipAttribute:function(e){e.state==F&&(e.state=k)},xmlCurrentTag:function(e){return e.tagName?{name:e.tagName,close:"closeTag"==e.type}:null},xmlCurrentContext:function(e){for(var t=[],n=e.context;n;n=n.prev)t.push(n.tagName);return t.reverse()}}})),e.defineMIME("text/xml","xml"),e.defineMIME("application/xml","xml"),e.mimeModes.hasOwnProperty("text/html")||e.defineMIME("text/html",{name:"xml",htmlMode:!0})})("object"==typeof n&&"object"==typeof t?e("../../lib/codemirror"):CodeMirror)},{"../../lib/codemirror":10}],15:[function(e,t,n){!function(e,i){"object"==typeof n&&void 0!==t?i(n):i((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,i=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return{async:!1,baseUrl:null,breaks:!1,extensions:null,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1}}e.defaults={async:!1,baseUrl:null,breaks:!1,extensions:null,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1};var o=/[&<>"']/,a=/[&<>"']/g,l=/[<>"']|&(?!#?\w+;)/,s=/[<>"']|&(?!#?\w+;)/g,u={"&":"&","<":"<",">":">",'"':""","'":"'"},c=function(e){return u[e]};function d(e,t){if(t){if(o.test(e))return e.replace(a,c)}else if(l.test(e))return e.replace(s,c);return e}var h=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function f(e){return e.replace(h,(function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""}))}var p=/(^|[^\[])\^/g;function m(e,t){e="string"==typeof e?e:e.source,t=t||"";var n={replace:function(t,i){return i=(i=i.source||i).replace(p,"$1"),e=e.replace(t,i),n},getRegex:function(){return new RegExp(e,t)}};return n}var g=/[^\w:]/g,v=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function x(e,t,n){if(e){var i;try{i=decodeURIComponent(f(n)).replace(g,"").toLowerCase()}catch(e){return null}if(0===i.indexOf("javascript:")||0===i.indexOf("vbscript:")||0===i.indexOf("data:"))return null}t&&!v.test(n)&&(n=function(e,t){y[" "+e]||(b.test(e)?y[" "+e]=e+"/":y[" "+e]=F(e,"/",!0));var n=-1===(e=y[" "+e]).indexOf(":");return"//"===t.substring(0,2)?n?t:e.replace(D,"$1")+t:"/"===t.charAt(0)?n?t:e.replace(C,"$1")+t:e+t}(t,n));try{n=encodeURI(n).replace(/%25/g,"%")}catch(e){return null}return n}var y={},b=/^[^:]+:\/*[^/]*$/,D=/^([^:]+:)[\s\S]*$/,C=/^([^:]+:\/*[^/]*)[\s\S]*$/;var w={exec:function(){}};function k(e){for(var t,n,i=1;i=0&&"\\"===n[r];)i=!i;return i?"|":" |"})).split(/ \|/),i=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),n.length>t)n.splice(t);else for(;n.length1;)1&t&&(n+=e),t>>=1,e+=e;return n+e}function L(e,t,n,i){var r=t.href,o=t.title?d(t.title):null,a=e[1].replace(/\\([\[\]])/g,"$1");if("!"!==e[0].charAt(0)){i.state.inLink=!0;var l={type:"link",raw:n,href:r,title:o,text:a,tokens:i.inlineTokens(a)};return i.state.inLink=!1,l}return{type:"image",raw:n,href:r,title:o,text:d(a)}}var T=function(){function t(t){this.options=t||e.defaults}var n=t.prototype;return n.space=function(e){var t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}},n.code=function(e){var t=this.rules.block.code.exec(e);if(t){var n=t[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:F(n,"\n")}}},n.fences=function(e){var t=this.rules.block.fences.exec(e);if(t){var n=t[0],i=function(e,t){var n=e.match(/^(\s+)(?:```)/);if(null===n)return t;var i=n[1];return t.split("\n").map((function(e){var t=e.match(/^\s+/);return null===t?e:t[0].length>=i.length?e.slice(i.length):e})).join("\n")}(n,t[3]||"");return{type:"code",raw:n,lang:t[2]?t[2].trim():t[2],text:i}}},n.heading=function(e){var t=this.rules.block.heading.exec(e);if(t){var n=t[2].trim();if(/#$/.test(n)){var i=F(n,"#");this.options.pedantic?n=i.trim():i&&!/ $/.test(i)||(n=i.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}},n.hr=function(e){var t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[0]}},n.blockquote=function(e){var t=this.rules.block.blockquote.exec(e);if(t){var n=t[0].replace(/^ *>[ \t]?/gm,"");return{type:"blockquote",raw:t[0],tokens:this.lexer.blockTokens(n,[]),text:n}}},n.list=function(e){var t=this.rules.block.list.exec(e);if(t){var n,r,o,a,l,s,u,c,d,h,f,p,m=t[1].trim(),g=m.length>1,v={type:"list",raw:"",ordered:g,start:g?+m.slice(0,-1):"",loose:!1,items:[]};m=g?"\\d{1,9}\\"+m.slice(-1):"\\"+m,this.options.pedantic&&(m=g?m:"[*+-]");for(var x=new RegExp("^( {0,3}"+m+")((?:[\t ][^\\n]*)?(?:\\n|$))");e&&(p=!1,t=x.exec(e))&&!this.rules.block.hr.test(e);){if(n=t[0],e=e.substring(n.length),c=t[2].split("\n",1)[0],d=e.split("\n",1)[0],this.options.pedantic?(a=2,f=c.trimLeft()):(a=(a=t[2].search(/[^ ]/))>4?1:a,f=c.slice(a),a+=t[1].length),s=!1,!c&&/^ *$/.test(d)&&(n+=d+"\n",e=e.substring(d.length+1),p=!0),!p)for(var y=new RegExp("^ {0,"+Math.min(3,a-1)+"}(?:[*+-]|\\d{1,9}[.)])((?: [^\\n]*)?(?:\\n|$))"),b=new RegExp("^ {0,"+Math.min(3,a-1)+"}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)"),D=new RegExp("^ {0,"+Math.min(3,a-1)+"}(?:```|~~~)"),C=new RegExp("^ {0,"+Math.min(3,a-1)+"}#");e&&(c=h=e.split("\n",1)[0],this.options.pedantic&&(c=c.replace(/^ {1,4}(?=( {4})*[^ ])/g," ")),!D.test(c))&&!C.test(c)&&!y.test(c)&&!b.test(e);){if(c.search(/[^ ]/)>=a||!c.trim())f+="\n"+c.slice(a);else{if(s)break;f+="\n"+c}s||c.trim()||(s=!0),n+=h+"\n",e=e.substring(h.length+1)}v.loose||(u?v.loose=!0:/\n *\n *$/.test(n)&&(u=!0)),this.options.gfm&&(r=/^\[[ xX]\] /.exec(f))&&(o="[ ] "!==r[0],f=f.replace(/^\[[ xX]\] +/,"")),v.items.push({type:"list_item",raw:n,task:!!r,checked:o,loose:!1,text:f}),v.raw+=n}v.items[v.items.length-1].raw=n.trimRight(),v.items[v.items.length-1].text=f.trimRight(),v.raw=v.raw.trimRight();var w=v.items.length;for(l=0;l1)return!0}return!1}));!v.loose&&k.length&&S&&(v.loose=!0,v.items[l].loose=!0)}return v}},n.html=function(e){var t=this.rules.block.html.exec(e);if(t){var n={type:"html",raw:t[0],pre:!this.options.sanitizer&&("pre"===t[1]||"script"===t[1]||"style"===t[1]),text:t[0]};if(this.options.sanitize){var i=this.options.sanitizer?this.options.sanitizer(t[0]):d(t[0]);n.type="paragraph",n.text=i,n.tokens=this.lexer.inline(i)}return n}},n.def=function(e){var t=this.rules.block.def.exec(e);if(t)return t[3]&&(t[3]=t[3].substring(1,t[3].length-1)),{type:"def",tag:t[1].toLowerCase().replace(/\s+/g," "),raw:t[0],href:t[2],title:t[3]}},n.table=function(e){var t=this.rules.block.table.exec(e);if(t){var n={type:"table",header:S(t[1]).map((function(e){return{text:e}})),align:t[2].replace(/^ *|\| *$/g,"").split(/ *\| */),rows:t[3]&&t[3].trim()?t[3].replace(/\n[ \t]*$/,"").split("\n"):[]};if(n.header.length===n.align.length){n.raw=t[0];var i,r,o,a,l=n.align.length;for(i=0;i/i.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:this.options.sanitize?"text":"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(t[0]):d(t[0]):t[0]}},n.link=function(e){var t=this.rules.inline.link.exec(e);if(t){var n=t[2].trim();if(!this.options.pedantic&&/^$/.test(n))return;var i=F(n.slice(0,-1),"\\");if((n.length-i.length)%2==0)return}else{var r=function(e,t){if(-1===e.indexOf(t[1]))return-1;for(var n=e.length,i=0,r=0;r-1){var o=(0===t[0].indexOf("!")?5:4)+t[1].length+r;t[2]=t[2].substring(0,r),t[0]=t[0].substring(0,o).trim(),t[3]=""}}var a=t[2],l="";if(this.options.pedantic){var s=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(a);s&&(a=s[1],l=s[3])}else l=t[3]?t[3].slice(1,-1):"";return a=a.trim(),/^$/.test(n)?a.slice(1):a.slice(1,-1)),L(t,{href:a?a.replace(this.rules.inline._escapes,"$1"):a,title:l?l.replace(this.rules.inline._escapes,"$1"):l},t[0],this.lexer)}},n.reflink=function(e,t){var n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){var i=(n[2]||n[1]).replace(/\s+/g," ");if(!(i=t[i.toLowerCase()])||!i.href){var r=n[0].charAt(0);return{type:"text",raw:r,text:r}}return L(n,i,n[0],this.lexer)}},n.emStrong=function(e,t,n){void 0===n&&(n="");var i=this.rules.inline.emStrong.lDelim.exec(e);if(i&&(!i[3]||!n.match(/(?:[0-9A-Za-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/))){var r=i[1]||i[2]||"";if(!r||r&&(""===n||this.rules.inline.punctuation.exec(n))){var o,a,l=i[0].length-1,s=l,u=0,c="*"===i[0][0]?this.rules.inline.emStrong.rDelimAst:this.rules.inline.emStrong.rDelimUnd;for(c.lastIndex=0,t=t.slice(-1*e.length+l);null!=(i=c.exec(t));)if(o=i[1]||i[2]||i[3]||i[4]||i[5]||i[6])if(a=o.length,i[3]||i[4])s+=a;else if(!((i[5]||i[6])&&l%3)||(l+a)%3){if(!((s-=a)>0)){if(a=Math.min(a,a+s+u),Math.min(l,a)%2){var d=e.slice(1,l+i.index+a);return{type:"em",raw:e.slice(0,l+i.index+a+1),text:d,tokens:this.lexer.inlineTokens(d)}}var h=e.slice(2,l+i.index+a-1);return{type:"strong",raw:e.slice(0,l+i.index+a+1),text:h,tokens:this.lexer.inlineTokens(h)}}}else u+=a}}},n.codespan=function(e){var t=this.rules.inline.code.exec(e);if(t){var n=t[2].replace(/\n/g," "),i=/[^ ]/.test(n),r=/^ /.test(n)&&/ $/.test(n);return i&&r&&(n=n.substring(1,n.length-1)),n=d(n,!0),{type:"codespan",raw:t[0],text:n}}},n.br=function(e){var t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}},n.del=function(e){var t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}},n.autolink=function(e,t){var n,i,r=this.rules.inline.autolink.exec(e);if(r)return i="@"===r[2]?"mailto:"+(n=d(this.options.mangle?t(r[1]):r[1])):n=d(r[1]),{type:"link",raw:r[0],text:n,href:i,tokens:[{type:"text",raw:n,text:n}]}},n.url=function(e,t){var n;if(n=this.rules.inline.url.exec(e)){var i,r;if("@"===n[2])r="mailto:"+(i=d(this.options.mangle?t(n[0]):n[0]));else{var o;do{o=n[0],n[0]=this.rules.inline._backpedal.exec(n[0])[0]}while(o!==n[0]);i=d(n[0]),r="www."===n[1]?"http://"+i:i}return{type:"link",raw:n[0],text:i,href:r,tokens:[{type:"text",raw:i,text:i}]}}},n.inlineText=function(e,t){var n,i=this.rules.inline.text.exec(e);if(i)return n=this.lexer.state.inRawBlock?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):d(i[0]):i[0]:d(this.options.smartypants?t(i[0]):i[0]),{type:"text",raw:i[0],text:n}},t}(),M={newline:/^(?: *(?:\n|$))+/,code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,hr:/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,html:"^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))",def:/^ {0,3}\[(label)\]: *(?:\n *)?]+)>?(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,table:w,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\.|[^\[\]\\])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/};M.def=m(M.def).replace("label",M._label).replace("title",M._title).getRegex(),M.bullet=/(?:[*+-]|\d{1,9}[.)])/,M.listItemStart=m(/^( *)(bull) */).replace("bull",M.bullet).getRegex(),M.list=m(M.list).replace(/bull/g,M.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+M.def.source+")").getRegex(),M._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",M._comment=/|$)/,M.html=m(M.html,"i").replace("comment",M._comment).replace("tag",M._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),M.paragraph=m(M._paragraph).replace("hr",M.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",M._tag).getRegex(),M.blockquote=m(M.blockquote).replace("paragraph",M.paragraph).getRegex(),M.normal=k({},M),M.gfm=k({},M.normal,{table:"^ *([^\\n ].*\\|.*)\\n {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),M.gfm.table=m(M.gfm.table).replace("hr",M.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",M._tag).getRegex(),M.gfm.paragraph=m(M._paragraph).replace("hr",M.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("table",M.gfm.table).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",M._tag).getRegex(),M.pedantic=k({},M.normal,{html:m("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",M._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:w,paragraph:m(M.normal._paragraph).replace("hr",M.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",M.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});var B={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:w,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(ref)\]/,nolink:/^!?\[(ref)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",emStrong:{lDelim:/^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,rDelimAst:/^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[^*]+(?=[^*])|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,rDelimUnd:/^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:w,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\.5&&(n="x"+n.toString(16)),i+="&#"+n+";";return i}B._punctuation="!\"#$%&'()+\\-.,/:;<=>?@\\[\\]`^{|}~",B.punctuation=m(B.punctuation).replace(/punctuation/g,B._punctuation).getRegex(),B.blockSkip=/\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g,B.escapedEmSt=/\\\*|\\_/g,B._comment=m(M._comment).replace("(?:--\x3e|$)","--\x3e").getRegex(),B.emStrong.lDelim=m(B.emStrong.lDelim).replace(/punct/g,B._punctuation).getRegex(),B.emStrong.rDelimAst=m(B.emStrong.rDelimAst,"g").replace(/punct/g,B._punctuation).getRegex(),B.emStrong.rDelimUnd=m(B.emStrong.rDelimUnd,"g").replace(/punct/g,B._punctuation).getRegex(),B._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,B._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,B._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,B.autolink=m(B.autolink).replace("scheme",B._scheme).replace("email",B._email).getRegex(),B._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,B.tag=m(B.tag).replace("comment",B._comment).replace("attribute",B._attribute).getRegex(),B._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,B._href=/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/,B._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,B.link=m(B.link).replace("label",B._label).replace("href",B._href).replace("title",B._title).getRegex(),B.reflink=m(B.reflink).replace("label",B._label).replace("ref",M._label).getRegex(),B.nolink=m(B.nolink).replace("ref",M._label).getRegex(),B.reflinkSearch=m(B.reflinkSearch,"g").replace("reflink",B.reflink).replace("nolink",B.nolink).getRegex(),B.normal=k({},B),B.pedantic=k({},B.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:m(/^!?\[(label)\]\((.*?)\)/).replace("label",B._label).getRegex(),reflink:m(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",B._label).getRegex()}),B.gfm=k({},B.normal,{escape:m(B.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),!(i=t[t.length-1])||"paragraph"!==i.type&&"text"!==i.type?t.push(n):(i.raw+="\n"+n.raw,i.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=i.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),!(i=t[t.length-1])||"paragraph"!==i.type&&"text"!==i.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(i.raw+="\n"+n.raw,i.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=i.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else if(r=e,this.options.extensions&&this.options.extensions.startBlock&&function(){var t=1/0,n=e.slice(1),i=void 0;a.options.extensions.startBlock.forEach((function(e){"number"==typeof(i=e.call({lexer:this},n))&&i>=0&&(t=Math.min(t,i))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}(),this.state.top&&(n=this.tokenizer.paragraph(r)))i=t[t.length-1],o&&"paragraph"===i.type?(i.raw+="\n"+n.raw,i.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=i.text):t.push(n),o=r.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),(i=t[t.length-1])&&"text"===i.type?(i.raw+="\n"+n.raw,i.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=i.text):t.push(n);else if(e){var l="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(l);break}throw new Error(l)}return this.state.top=!0,t},a.inline=function(e,t){return void 0===t&&(t=[]),this.inlineQueue.push({src:e,tokens:t}),t},a.inlineTokens=function(e,t){var n,i,r,o=this;void 0===t&&(t=[]);var a,l,s,u=e;if(this.tokens.links){var c=Object.keys(this.tokens.links);if(c.length>0)for(;null!=(a=this.tokenizer.rules.inline.reflinkSearch.exec(u));)c.includes(a[0].slice(a[0].lastIndexOf("[")+1,-1))&&(u=u.slice(0,a.index)+"["+E("a",a[0].length-2)+"]"+u.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(a=this.tokenizer.rules.inline.blockSkip.exec(u));)u=u.slice(0,a.index)+"["+E("a",a[0].length-2)+"]"+u.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(a=this.tokenizer.rules.inline.escapedEmSt.exec(u));)u=u.slice(0,a.index)+"++"+u.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);for(;e;)if(l||(s=""),l=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((function(i){return!!(n=i.call({lexer:o},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)}))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),(i=t[t.length-1])&&"text"===n.type&&"text"===i.type?(i.raw+=n.raw,i.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),(i=t[t.length-1])&&"text"===n.type&&"text"===i.type?(i.raw+=n.raw,i.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,u,s))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e,O))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e,O))){if(r=e,this.options.extensions&&this.options.extensions.startInline&&function(){var t=1/0,n=e.slice(1),i=void 0;o.options.extensions.startInline.forEach((function(e){"number"==typeof(i=e.call({lexer:this},n))&&i>=0&&(t=Math.min(t,i))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}(),n=this.tokenizer.inlineText(r,N))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(s=n.raw.slice(-1)),l=!0,(i=t[t.length-1])&&"text"===i.type?(i.raw+=n.raw,i.text+=n.text):t.push(n);else if(e){var d="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(d);break}throw new Error(d)}}else e=e.substring(n.raw.length),t.push(n);return t},i=n,o=[{key:"rules",get:function(){return{block:M,inline:B}}}],(r=null)&&t(i.prototype,r),o&&t(i,o),Object.defineProperty(i,"prototype",{writable:!1}),n}(),z=function(){function t(t){this.options=t||e.defaults}var n=t.prototype;return n.code=function(e,t,n){var i=(t||"").match(/\S*/)[0];if(this.options.highlight){var r=this.options.highlight(e,i);null!=r&&r!==e&&(n=!0,e=r)}return e=e.replace(/\n$/,"")+"\n",i?'
'+(n?e:d(e,!0))+"
\n":"
"+(n?e:d(e,!0))+"
\n"},n.blockquote=function(e){return"
\n"+e+"
\n"},n.html=function(e){return e},n.heading=function(e,t,n,i){return this.options.headerIds?"'+e+"\n":""+e+"\n"},n.hr=function(){return this.options.xhtml?"
\n":"
\n"},n.list=function(e,t,n){var i=t?"ol":"ul";return"<"+i+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},n.listitem=function(e){return"
  • "+e+"
  • \n"},n.checkbox=function(e){return" "},n.paragraph=function(e){return"

    "+e+"

    \n"},n.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},n.tablerow=function(e){return"\n"+e+"\n"},n.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},n.strong=function(e){return""+e+""},n.em=function(e){return""+e+""},n.codespan=function(e){return""+e+""},n.br=function(){return this.options.xhtml?"
    ":"
    "},n.del=function(e){return""+e+""},n.link=function(e,t,n){if(null===(e=x(this.options.sanitize,this.options.baseUrl,e)))return n;var i='"},n.image=function(e,t,n){if(null===(e=x(this.options.sanitize,this.options.baseUrl,e)))return n;var i=''+n+'":">"},n.text=function(e){return e},t}(),H=function(){function e(){}var t=e.prototype;return t.strong=function(e){return e},t.em=function(e){return e},t.codespan=function(e){return e},t.del=function(e){return e},t.html=function(e){return e},t.text=function(e){return e},t.link=function(e,t,n){return""+n},t.image=function(e,t,n){return""+n},t.br=function(){return""},e}(),R=function(){function e(){this.seen={}}var t=e.prototype;return t.serialize=function(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")},t.getNextSafeSlug=function(e,t){var n=e,i=0;if(this.seen.hasOwnProperty(n)){i=this.seen[e];do{n=e+"-"+ ++i}while(this.seen.hasOwnProperty(n))}return t||(this.seen[e]=i,this.seen[n]=0),n},t.slug=function(e,t){void 0===t&&(t={});var n=this.serialize(e);return this.getNextSafeSlug(n,t.dryrun)},e}(),P=function(){function t(t){this.options=t||e.defaults,this.options.renderer=this.options.renderer||new z,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new H,this.slugger=new R}t.parse=function(e,n){return new t(n).parse(e)},t.parseInline=function(e,n){return new t(n).parseInline(e)};var n=t.prototype;return n.parse=function(e,t){void 0===t&&(t=!0);var n,i,r,o,a,l,s,u,c,d,h,p,m,g,v,x,y,b,D,C="",w=e.length;for(n=0;n0&&"paragraph"===v.tokens[0].type?(v.tokens[0].text=b+" "+v.tokens[0].text,v.tokens[0].tokens&&v.tokens[0].tokens.length>0&&"text"===v.tokens[0].tokens[0].type&&(v.tokens[0].tokens[0].text=b+" "+v.tokens[0].tokens[0].text)):v.tokens.unshift({type:"text",text:b}):g+=b),g+=this.parse(v.tokens,m),c+=this.renderer.listitem(g,y,x);C+=this.renderer.list(c,h,p);continue;case"html":C+=this.renderer.html(d.text);continue;case"paragraph":C+=this.renderer.paragraph(this.parseInline(d.tokens));continue;case"text":for(c=d.tokens?this.parseInline(d.tokens):d.text;n+1An error occurred:

    "+d(e.message+"",!0)+"
    ";throw e}try{var s=I.lex(e,t);if(t.walkTokens){if(t.async)return Promise.all(_.walkTokens(s,t.walkTokens)).then((function(){return P.parse(s,t)})).catch(l);_.walkTokens(s,t.walkTokens)}return P.parse(s,t)}catch(e){l(e)}}_.options=_.setOptions=function(t){var n;return k(_.defaults,t),n=_.defaults,e.defaults=n,_},_.getDefaults=r,_.defaults=e.defaults,_.use=function(){for(var e=arguments.length,t=new Array(e),n=0;nAn error occurred:

    "+d(e.message+"",!0)+"
    ";throw e}},_.Parser=P,_.parser=P.parse,_.Renderer=z,_.TextRenderer=H,_.Lexer=I,_.lexer=I.lex,_.Tokenizer=T,_.Slugger=R,_.parse=_;var W=_.options,j=_.setOptions,q=_.use,U=_.walkTokens,$=_.parseInline,G=_,V=P.parse,X=I.lex;e.Lexer=I,e.Parser=P,e.Renderer=z,e.Slugger=R,e.TextRenderer=H,e.Tokenizer=T,e.getDefaults=r,e.lexer=X,e.marked=_,e.options=W,e.parse=G,e.parseInline=$,e.parser=V,e.setOptions=j,e.use=q,e.walkTokens=U,Object.defineProperty(e,"__esModule",{value:!0})}))},{}],16:[function(e,t,n){(function(n){(function(){var i;!function(){"use strict";(i=function(e,t,i,r){r=r||{},this.dictionary=null,this.rules={},this.dictionaryTable={},this.compoundRules=[],this.compoundRuleCodes={},this.replacementTable=[],this.flags=r.flags||{},this.memoized={},this.loaded=!1;var o,a,l,s,u,c=this;function d(e,t){var n=c._readFile(e,null,r.asyncLoad);r.asyncLoad?n.then((function(e){t(e)})):t(n)}function h(e){t=e,i&&p()}function f(e){i=e,t&&p()}function p(){for(c.rules=c._parseAFF(t),c.compoundRuleCodes={},a=0,s=c.compoundRules.length;a0&&(b.continuationClasses=x),"."!==y&&(b.match="SFX"===d?new RegExp(y+"$"):new RegExp("^"+y)),"0"!=m&&(b.remove="SFX"===d?new RegExp(m+"$"):m),p.push(b)}s[h]={type:d,combineable:"Y"==f,entries:p},r+=n}else if("COMPOUNDRULE"===d){for(o=r+1,l=r+1+(n=parseInt(c[1],10));o0&&(null===n[e]&&(n[e]=[]),n[e].push(t))}for(var r=1,o=t.length;r1){var u=this.parseRuleCodes(l[1]);"NEEDAFFIX"in this.flags&&-1!=u.indexOf(this.flags.NEEDAFFIX)||i(s,u);for(var c=0,d=u.length;c=this.flags.COMPOUNDMIN)for(t=0,n=this.compoundRules.length;t1&&c[1][1]!==c[1][0]&&(o=c[0]+c[1][1]+c[1][0]+c[1].substring(2),t&&!l.check(o)||(o in a?a[o]+=1:a[o]=1)),c[1]){var d=c[1].substring(0,1).toUpperCase()===c[1].substring(0,1)?"uppercase":"lowercase";for(i=0;ii?1:t[0].localeCompare(e[0])})).reverse();var u=[],c="lowercase";e.toUpperCase()===e?c="uppercase":e.substr(0,1).toUpperCase()+e.substr(1).toLowerCase()===e&&(c="capitalized");var d=t;for(n=0;n)+?/g),s={toggleBold:x,toggleItalic:y,drawLink:O,toggleHeadingSmaller:w,toggleHeadingBigger:k,drawImage:I,toggleBlockquote:C,toggleOrderedList:B,toggleUnorderedList:M,toggleCodeBlock:D,togglePreview:U,toggleStrikethrough:b,toggleHeading1:S,toggleHeading2:F,toggleHeading3:A,toggleHeading4:E,toggleHeading5:L,toggleHeading6:T,cleanBlock:N,drawTable:P,drawHorizontalRule:_,undo:W,redo:j,toggleSideBySide:q,toggleFullScreen:v},u={toggleBold:"Cmd-B",toggleItalic:"Cmd-I",drawLink:"Cmd-K",toggleHeadingSmaller:"Cmd-H",toggleHeadingBigger:"Shift-Cmd-H",toggleHeading1:"Ctrl+Alt+1",toggleHeading2:"Ctrl+Alt+2",toggleHeading3:"Ctrl+Alt+3",toggleHeading4:"Ctrl+Alt+4",toggleHeading5:"Ctrl+Alt+5",toggleHeading6:"Ctrl+Alt+6",cleanBlock:"Cmd-E",drawImage:"Cmd-Alt-I",toggleBlockquote:"Cmd-'",toggleOrderedList:"Cmd-Alt-L",toggleUnorderedList:"Cmd-L",toggleCodeBlock:"Cmd-Alt-C",togglePreview:"Cmd-P",toggleSideBySide:"F9",toggleFullScreen:"F11"},c=function(){var e,t=!1;return e=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(e.substr(0,4)))&&(t=!0),t};function d(e){return e=a?e.replace("Ctrl","Cmd"):e.replace("Cmd","Ctrl")}function h(e,t,n,i){var r=f(e,!1,t,n,"button",i);r.classList.add("easymde-dropdown"),r.onclick=function(){r.focus()};var o=document.createElement("div");o.className="easymde-dropdown-content";for(var a=0;a0){for(var g=document.createElement("i"),v=0;v=0&&!n(h=s.getLineHandle(o));o--);var g,v,x,y,b=i(s.getTokenAt({line:o,ch:1})).fencedChars;n(s.getLineHandle(u.line))?(g="",v=u.line):n(s.getLineHandle(u.line-1))?(g="",v=u.line-1):(g=b+"\n",v=u.line),n(s.getLineHandle(c.line))?(x="",y=c.line,0===c.ch&&(y+=1)):0!==c.ch&&n(s.getLineHandle(c.line+1))?(x="",y=c.line+1):(x=b+"\n",y=c.line+1),0===c.ch&&(y-=1),s.operation((function(){s.replaceRange(x,{line:y,ch:0},{line:y+(x?0:1),ch:0}),s.replaceRange(g,{line:v,ch:0},{line:v+(g?0:1),ch:0})})),s.setSelection({line:v+(g?1:0),ch:0},{line:y+(g?1:-1),ch:0}),s.focus()}else{var D=u.line;if(n(s.getLineHandle(u.line))&&("fenced"===r(s,u.line+1)?(o=u.line,D=u.line+1):(a=u.line,D=u.line-1)),void 0===o)for(o=D;o>=0&&!n(h=s.getLineHandle(o));o--);if(void 0===a)for(l=s.lineCount(),a=D;a=0;o--)if(!(h=s.getLineHandle(o)).text.match(/^\s*$/)&&"indented"!==r(s,o,h)){o+=1;break}for(l=s.lineCount(),a=u.line;a ]+|[0-9]+(.|\)))[ ]*/,""),e.replaceRange(t,{line:r,ch:0},{line:r,ch:99999999999999})}(e.codemirror)}function O(e){var t=e.options,n="https://";if(t.promptURLs){var i=prompt(t.promptTexts.link,n);if(!i)return!1;n=z(i)}X(e,"link",t.insertTexts.link,n)}function I(e){var t=e.options,n="https://";if(t.promptURLs){var i=prompt(t.promptTexts.image,n);if(!i)return!1;n=z(i)}X(e,"image",t.insertTexts.image,n)}function z(e){return encodeURI(e).replace(/([\\()])/g,"\\$1")}function H(e){e.openBrowseFileWindow()}function R(e,t){var n=e.codemirror,i=m(n),r=e.options,o=t.substr(t.lastIndexOf("/")+1),a=o.substring(o.lastIndexOf(".")+1).replace(/\?.*$/,"").toLowerCase();if(["png","jpg","jpeg","gif","svg","apng","avif","webp"].includes(a))$(n,i.image,r.insertTexts.uploadedImage,t);else{var l=r.insertTexts.link;l[0]="["+o,$(n,i.link,l,t)}e.updateStatusBar("upload-image",e.options.imageTexts.sbOnUploaded.replace("#image_name#",o)),setTimeout((function(){e.updateStatusBar("upload-image",e.options.imageTexts.sbInit)}),1e3)}function P(e){var t=e.codemirror,n=m(t),i=e.options;$(t,n.table,i.insertTexts.table)}function _(e){var t=e.codemirror,n=m(t),i=e.options;$(t,n.image,i.insertTexts.horizontalRule)}function W(e){var t=e.codemirror;t.undo(),t.focus()}function j(e){var t=e.codemirror;t.redo(),t.focus()}function q(e){var t=e.codemirror,n=t.getWrapperElement(),i=n.nextSibling,r=e.toolbarElements&&e.toolbarElements["side-by-side"],o=!1,a=n.parentNode;i.classList.contains("editor-preview-active-side")?(!1===e.options.sideBySideFullscreen&&a.classList.remove("sided--no-fullscreen"),i.classList.remove("editor-preview-active-side"),r&&r.classList.remove("active"),n.classList.remove("CodeMirror-sided")):(setTimeout((function(){t.getOption("fullScreen")||(!1===e.options.sideBySideFullscreen?a.classList.add("sided--no-fullscreen"):v(e)),i.classList.add("editor-preview-active-side")}),1),r&&r.classList.add("active"),n.classList.add("CodeMirror-sided"),o=!0);var l=n.lastChild;if(l.classList.contains("editor-preview-active")){l.classList.remove("editor-preview-active");var s=e.toolbarElements.preview,u=e.toolbar_div;s.classList.remove("active"),u.classList.remove("disabled-for-preview")}if(t.sideBySideRenderingFunction||(t.sideBySideRenderingFunction=function(){var t=e.options.previewRender(e.value(),i);null!=t&&(i.innerHTML=t)}),o){var c=e.options.previewRender(e.value(),i);null!=c&&(i.innerHTML=c),t.on("update",t.sideBySideRenderingFunction)}else t.off("update",t.sideBySideRenderingFunction);t.refresh()}function U(e){var t=e.codemirror,n=t.getWrapperElement(),i=e.toolbar_div,r=!!e.options.toolbar&&e.toolbarElements.preview,o=n.lastChild;if(t.getWrapperElement().nextSibling.classList.contains("editor-preview-active-side")&&q(e),!o||!o.classList.contains("editor-preview-full")){if((o=document.createElement("div")).className="editor-preview-full",e.options.previewClass)if(Array.isArray(e.options.previewClass))for(var a=0;a\s+/,"unordered-list":i,"ordered-list":i},u=function(e,t,o){var a=i.exec(t),l=function(e,t){return{quote:">","unordered-list":n,"ordered-list":"%%i."}[e].replace("%%i",t)}(e,c);return null!==a?(function(e,t){var i=new RegExp({quote:">","unordered-list":"\\"+n,"ordered-list":"\\d+."}[e]);return t&&i.test(t)}(e,a[2])&&(l=""),t=a[1]+l+a[3]+t.replace(r,"").replace(s[e],"$1")):0==o&&(t=l+" "+t),t},c=1,d=a.line;d<=l.line;d++)!function(n){var i=e.getLine(n);o[t]?i=i.replace(s[t],"$1"):("unordered-list"==t&&(i=u("ordered-list",i,!0)),i=u(t,i,!1),c+=1),e.replaceRange(i,{line:n,ch:0},{line:n,ch:99999999999999})}(d);e.focus()}}function X(e,t,n,i){if(e.codemirror&&!e.isPreviewActive()){var r=e.codemirror,o=m(r)[t];if(o){var a=r.getCursor("start"),l=r.getCursor("end"),s=r.getLine(a.line),u=s.slice(0,a.ch),c=s.slice(a.ch);"link"==t?u=u.replace(/(.*)[^!]\[/,"$1"):"image"==t&&(u=u.replace(/(.*)!\[$/,"$1")),c=c.replace(/]\(.*?\)/,""),r.replaceRange(u+c,{line:a.line,ch:0},{line:a.line,ch:99999999999999}),a.ch-=n[0].length,a!==l&&(l.ch-=n[0].length),r.setSelection(a,l),r.focus()}else $(r,o,n,i)}}function K(e,t,n,i){if(e.codemirror&&!e.isPreviewActive()){i=void 0===i?n:i;var r,o=e.codemirror,a=m(o),l=n,s=i,u=o.getCursor("start"),c=o.getCursor("end");a[t]?(l=(r=o.getLine(u.line)).slice(0,u.ch),s=r.slice(u.ch),"bold"==t?(l=l.replace(/(\*\*|__)(?![\s\S]*(\*\*|__))/,""),s=s.replace(/(\*\*|__)/,"")):"italic"==t?(l=l.replace(/(\*|_)(?![\s\S]*(\*|_))/,""),s=s.replace(/(\*|_)/,"")):"strikethrough"==t&&(l=l.replace(/(\*\*|~~)(?![\s\S]*(\*\*|~~))/,""),s=s.replace(/(\*\*|~~)/,"")),o.replaceRange(l+s,{line:u.line,ch:0},{line:u.line,ch:99999999999999}),"bold"==t||"strikethrough"==t?(u.ch-=2,u!==c&&(c.ch-=2)):"italic"==t&&(u.ch-=1,u!==c&&(c.ch-=1))):(r=o.getSelection(),"bold"==t?r=(r=r.split("**").join("")).split("__").join(""):"italic"==t?r=(r=r.split("*").join("")).split("_").join(""):"strikethrough"==t&&(r=r.split("~~").join("")),o.replaceSelection(l+r+s),u.ch+=n.length,c.ch=u.ch+r.length),o.setSelection(u,c),o.focus()}}function Z(e,t){if(Math.abs(e)<1024)return""+e+t[0];var n=0;do{e/=1024,++n}while(Math.abs(e)>=1024&&n=19968?n+=t[i].length:n+=1;return n}var ee={bold:"fa fa-bold",italic:"fa fa-italic",strikethrough:"fa fa-strikethrough",heading:"fa fa-header fa-heading","heading-smaller":"fa fa-header fa-heading header-smaller","heading-bigger":"fa fa-header fa-heading header-bigger","heading-1":"fa fa-header fa-heading header-1","heading-2":"fa fa-header fa-heading header-2","heading-3":"fa fa-header fa-heading header-3",code:"fa fa-code",quote:"fa fa-quote-left","ordered-list":"fa fa-list-ol","unordered-list":"fa fa-list-ul","clean-block":"fa fa-eraser",link:"fa fa-link",image:"fa fa-image","upload-image":"fa fa-image",table:"fa fa-table","horizontal-rule":"fa fa-minus",preview:"fa fa-eye","side-by-side":"fa fa-columns",fullscreen:"fa fa-arrows-alt",guide:"fa fa-question-circle",undo:"fa fa-undo",redo:"fa fa-repeat fa-redo"},te={bold:{name:"bold",action:x,className:ee.bold,title:"Bold",default:!0},italic:{name:"italic",action:y,className:ee.italic,title:"Italic",default:!0},strikethrough:{name:"strikethrough",action:b,className:ee.strikethrough,title:"Strikethrough"},heading:{name:"heading",action:w,className:ee.heading,title:"Heading",default:!0},"heading-smaller":{name:"heading-smaller",action:w,className:ee["heading-smaller"],title:"Smaller Heading"},"heading-bigger":{name:"heading-bigger",action:k,className:ee["heading-bigger"],title:"Bigger Heading"},"heading-1":{name:"heading-1",action:S,className:ee["heading-1"],title:"Big Heading"},"heading-2":{name:"heading-2",action:F,className:ee["heading-2"],title:"Medium Heading"},"heading-3":{name:"heading-3",action:A,className:ee["heading-3"],title:"Small Heading"},"separator-1":{name:"separator-1"},code:{name:"code",action:D,className:ee.code,title:"Code"},quote:{name:"quote",action:C,className:ee.quote,title:"Quote",default:!0},"unordered-list":{name:"unordered-list",action:M,className:ee["unordered-list"],title:"Generic List",default:!0},"ordered-list":{name:"ordered-list",action:B,className:ee["ordered-list"],title:"Numbered List",default:!0},"clean-block":{name:"clean-block",action:N,className:ee["clean-block"],title:"Clean block"},"separator-2":{name:"separator-2"},link:{name:"link",action:O,className:ee.link,title:"Create Link",default:!0},image:{name:"image",action:I,className:ee.image,title:"Insert Image",default:!0},"upload-image":{name:"upload-image",action:H,className:ee["upload-image"],title:"Import an image"},table:{name:"table",action:P,className:ee.table,title:"Insert Table"},"horizontal-rule":{name:"horizontal-rule",action:_,className:ee["horizontal-rule"],title:"Insert Horizontal Line"},"separator-3":{name:"separator-3"},preview:{name:"preview",action:U,className:ee.preview,noDisable:!0,title:"Toggle Preview",default:!0},"side-by-side":{name:"side-by-side",action:q,className:ee["side-by-side"],noDisable:!0,noMobile:!0,title:"Toggle Side by Side",default:!0},fullscreen:{name:"fullscreen",action:v,className:ee.fullscreen,noDisable:!0,noMobile:!0,title:"Toggle Fullscreen",default:!0},"separator-4":{name:"separator-4"},guide:{name:"guide",action:"https://www.markdownguide.org/basic-syntax/",className:ee.guide,noDisable:!0,title:"Markdown Guide",default:!0},"separator-5":{name:"separator-5"},undo:{name:"undo",action:W,className:ee.undo,noDisable:!0,title:"Undo"},redo:{name:"redo",action:j,className:ee.redo,noDisable:!0,title:"Redo"}},ne={link:["[","](#url#)"],image:["![","](#url#)"],uploadedImage:["![](#url#)",""],table:["","\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n"],horizontalRule:["","\n\n-----\n\n"]},ie={link:"URL for the link:",image:"URL of the image:"},re={locale:"en-US",format:{hour:"2-digit",minute:"2-digit"}},oe={bold:"**",code:"```",italic:"*"},ae={sbInit:"Attach files by drag and dropping or pasting from clipboard.",sbOnDragEnter:"Drop image to upload it.",sbOnDrop:"Uploading image #images_names#...",sbProgress:"Uploading #file_name#: #progress#%",sbOnUploaded:"Uploaded #image_name#",sizeUnits:" B, KB, MB"},le={noFileGiven:"You must select a file.",typeNotAllowed:"This image type is not allowed.",fileTooLarge:"Image #image_name# is too big (#image_size#).\nMaximum file size is #image_max_size#.",importError:"Something went wrong when uploading the image #image_name#."};function se(e){(e=e||{}).parent=this;var t=!0;if(!1===e.autoDownloadFontAwesome&&(t=!1),!0!==e.autoDownloadFontAwesome)for(var n=document.styleSheets,i=0;i-1&&(t=!1);if(t){var r=document.createElement("link");r.rel="stylesheet",r.href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css",document.getElementsByTagName("head")[0].appendChild(r)}if(e.element)this.element=e.element;else if(null===e.element)return void console.log("EasyMDE: Error. No element was found.");if(void 0===e.toolbar)for(var o in e.toolbar=[],te)Object.prototype.hasOwnProperty.call(te,o)&&(-1!=o.indexOf("separator-")&&e.toolbar.push("|"),(!0===te[o].default||e.showIcons&&e.showIcons.constructor===Array&&-1!=e.showIcons.indexOf(o))&&e.toolbar.push(o));if(Object.prototype.hasOwnProperty.call(e,"previewClass")||(e.previewClass="editor-preview"),Object.prototype.hasOwnProperty.call(e,"status")||(e.status=["autosave","lines","words","cursor"],e.uploadImage&&e.status.unshift("upload-image")),e.previewRender||(e.previewRender=function(e){return this.parent.markdown(e)}),e.parsingConfig=Q({highlightFormatting:!0},e.parsingConfig||{}),e.insertTexts=Q({},ne,e.insertTexts||{}),e.promptTexts=Q({},ie,e.promptTexts||{}),e.blockStyles=Q({},oe,e.blockStyles||{}),null!=e.autosave&&(e.autosave.timeFormat=Q({},re,e.autosave.timeFormat||{})),e.iconClassMap=Q({},ee,e.iconClassMap||{}),e.shortcuts=Q({},u,e.shortcuts||{}),e.maxHeight=e.maxHeight||void 0,e.direction=e.direction||"ltr",void 0!==e.maxHeight?e.minHeight=e.maxHeight:e.minHeight=e.minHeight||"300px",e.errorCallback=e.errorCallback||function(e){alert(e)},e.uploadImage=e.uploadImage||!1,e.imageMaxSize=e.imageMaxSize||2097152,e.imageAccept=e.imageAccept||"image/png, image/jpeg, image/gif, image/avif",e.imageTexts=Q({},ae,e.imageTexts||{}),e.errorMessages=Q({},le,e.errorMessages||{}),e.imagePathAbsolute=e.imagePathAbsolute||!1,e.imageCSRFName=e.imageCSRFName||"csrfmiddlewaretoken",e.imageCSRFHeader=e.imageCSRFHeader||!1,e.imageInputName=e.imageInputName||"image",null!=e.autosave&&null!=e.autosave.unique_id&&""!=e.autosave.unique_id&&(e.autosave.uniqueId=e.autosave.unique_id),e.overlayMode&&void 0===e.overlayMode.combine&&(e.overlayMode.combine=!0),this.options=e,this.render(),!e.initialValue||this.options.autosave&&!0===this.options.autosave.foundSavedValue||this.value(e.initialValue),e.uploadImage){var a=this;this.codemirror.on("dragenter",(function(e,t){a.updateStatusBar("upload-image",a.options.imageTexts.sbOnDragEnter),t.stopPropagation(),t.preventDefault()})),this.codemirror.on("dragend",(function(e,t){a.updateStatusBar("upload-image",a.options.imageTexts.sbInit),t.stopPropagation(),t.preventDefault()})),this.codemirror.on("dragleave",(function(e,t){a.updateStatusBar("upload-image",a.options.imageTexts.sbInit),t.stopPropagation(),t.preventDefault()})),this.codemirror.on("dragover",(function(e,t){a.updateStatusBar("upload-image",a.options.imageTexts.sbOnDragEnter),t.stopPropagation(),t.preventDefault()})),this.codemirror.on("drop",(function(t,n){n.stopPropagation(),n.preventDefault(),e.imageUploadFunction?a.uploadImagesUsingCustomFunction(e.imageUploadFunction,n.dataTransfer.files):a.uploadImages(n.dataTransfer.files)})),this.codemirror.on("paste",(function(t,n){e.imageUploadFunction?a.uploadImagesUsingCustomFunction(e.imageUploadFunction,n.clipboardData.files):a.uploadImages(n.clipboardData.files)}))}}function ue(){if("object"!=typeof localStorage)return!1;try{localStorage.setItem("smde_localStorage",1),localStorage.removeItem("smde_localStorage")}catch(e){return!1}return!0}se.prototype.uploadImages=function(e,t,n){if(0!==e.length){for(var i=[],r=0;r$/,' target="_blank">');e=e.replace(n,i)}}return e}(i))}},se.prototype.render=function(e){if(e||(e=this.element||document.getElementsByTagName("textarea")[0]),!this._rendered||this._rendered!==e){this.element=e;var t,n,o=this.options,a=this,l={};for(var u in o.shortcuts)null!==o.shortcuts[u]&&null!==s[u]&&function(e){l[d(o.shortcuts[e])]=function(){var t=s[e];"function"==typeof t?t(a):"string"==typeof t&&window.open(t,"_blank")}}(u);if(l.Enter="newlineAndIndentContinueMarkdownList",l.Tab="tabAndIndentMarkdownList",l["Shift-Tab"]="shiftTabAndUnindentMarkdownList",l.Esc=function(e){e.getOption("fullScreen")&&v(a)},this.documentOnKeyDown=function(e){27==(e=e||window.event).keyCode&&a.codemirror.getOption("fullScreen")&&v(a)},document.addEventListener("keydown",this.documentOnKeyDown,!1),o.overlayMode?(i.defineMode("overlay-mode",(function(e){return i.overlayMode(i.getMode(e,!1!==o.spellChecker?"spell-checker":"gfm"),o.overlayMode.mode,o.overlayMode.combine)})),t="overlay-mode",(n=o.parsingConfig).gitHubSpice=!1):((t=o.parsingConfig).name="gfm",t.gitHubSpice=!1),!1!==o.spellChecker&&(t="spell-checker",(n=o.parsingConfig).name="gfm",n.gitHubSpice=!1,"function"==typeof o.spellChecker?o.spellChecker({codeMirrorInstance:i}):r({codeMirrorInstance:i})),this.codemirror=i.fromTextArea(e,{mode:t,backdrop:n,theme:null!=o.theme?o.theme:"easymde",tabSize:null!=o.tabSize?o.tabSize:2,indentUnit:null!=o.tabSize?o.tabSize:2,indentWithTabs:!1!==o.indentWithTabs,lineNumbers:!0===o.lineNumbers,autofocus:!0===o.autofocus,extraKeys:l,direction:o.direction,lineWrapping:!1!==o.lineWrapping,allowDropFileTypes:["text/plain"],placeholder:o.placeholder||e.getAttribute("placeholder")||"",styleSelectedText:null!=o.styleSelectedText?o.styleSelectedText:!c(),scrollbarStyle:null!=o.scrollbarStyle?o.scrollbarStyle:"native",configureMouse:function(e,t,n){return{addNew:!1}},inputStyle:null!=o.inputStyle?o.inputStyle:c()?"contenteditable":"textarea",spellcheck:null==o.nativeSpellcheck||o.nativeSpellcheck,autoRefresh:null!=o.autoRefresh&&o.autoRefresh}),this.codemirror.getScrollerElement().style.minHeight=o.minHeight,void 0!==o.maxHeight&&(this.codemirror.getScrollerElement().style.height=o.maxHeight),!0===o.forceSync){var h=this.codemirror;h.on("change",(function(){h.save()}))}this.gui={};var f=document.createElement("div");f.classList.add("EasyMDEContainer"),f.setAttribute("role","application");var p=this.codemirror.getWrapperElement();p.parentNode.insertBefore(f,p),f.appendChild(p),!1!==o.toolbar&&(this.gui.toolbar=this.createToolbar()),!1!==o.status&&(this.gui.statusbar=this.createStatusbar()),null!=o.autosave&&!0===o.autosave.enabled&&(this.autosave(),this.codemirror.on("change",(function(){clearTimeout(a._autosave_timeout),a._autosave_timeout=setTimeout((function(){a.autosave()}),a.options.autosave.submit_delay||a.options.autosave.delay||1e3)})));var m=this;this.codemirror.on("update",(function(){o.previewImagesInEditor&&f.querySelectorAll(".cm-image-marker").forEach((function(e){var t=e.parentElement;if(t.innerText.match(/^!\[.*?\]\(.*\)/g)&&!t.hasAttribute("data-img-src")){var n=t.innerText.match(/!\[.*?\]\((.*?)\)/);if(window.EMDEimagesCache||(window.EMDEimagesCache={}),n&&n.length>=2){var i=n[1];if(o.imagesPreviewHandler){var r=o.imagesPreviewHandler(n[1]);"string"==typeof r&&(i=r)}if(window.EMDEimagesCache[i])x(t,window.EMDEimagesCache[i]);else{window.EMDEimagesCache[i]={};var a=document.createElement("img");a.onload=function(){window.EMDEimagesCache[i]={naturalWidth:a.naturalWidth,naturalHeight:a.naturalHeight,url:i},x(t,window.EMDEimagesCache[i])},a.src=i}}}}))})),this.gui.sideBySide=this.createSideBySide(),this._rendered=this.element,(!0===o.autofocus||e.autofocus)&&this.codemirror.focus();var g=this.codemirror;setTimeout(function(){g.refresh()}.bind(g),0)}function x(e,t){var n,i,r=new URL(t.url,document.baseURI).href;e.setAttribute("data-img-src",r),e.setAttribute("style","--bg-image:url("+r+");--width:"+t.naturalWidth+"px;--height:"+(n=t.naturalWidth,i=t.naturalHeight,nthis.options.imageMaxSize)r(o(this.options.errorMessages.fileTooLarge));else{var a=new FormData;a.append("image",e),i.options.imageCSRFToken&&!i.options.imageCSRFHeader&&a.append(i.options.imageCSRFName,i.options.imageCSRFToken);var l=new XMLHttpRequest;l.upload.onprogress=function(t){if(t.lengthComputable){var n=""+Math.round(100*t.loaded/t.total);i.updateStatusBar("upload-image",i.options.imageTexts.sbProgress.replace("#file_name#",e.name).replace("#progress#",n))}},l.open("POST",this.options.imageUploadEndpoint),i.options.imageCSRFToken&&i.options.imageCSRFHeader&&l.setRequestHeader(i.options.imageCSRFName,i.options.imageCSRFToken),l.onload=function(){try{var e=JSON.parse(this.responseText)}catch(e){return console.error("EasyMDE: The server did not return a valid json."),void r(o(i.options.errorMessages.importError))}200===this.status&&e&&!e.error&&e.data&&e.data.filePath?t((i.options.imagePathAbsolute?"":window.location.origin+"/")+e.data.filePath):e.error&&e.error in i.options.errorMessages?r(o(i.options.errorMessages[e.error])):e.error?r(o(e.error)):(console.error("EasyMDE: Received an unexpected response after uploading the image."+this.status+" ("+this.statusText+")"),r(o(i.options.errorMessages.importError)))},l.onerror=function(e){console.error("EasyMDE: An unexpected error occurred when trying to upload the image."+e.target.status+" ("+e.target.statusText+")"),r(i.options.errorMessages.importError)},l.send(a)}},se.prototype.uploadImageUsingCustomFunction=function(e,t){var n=this;e.apply(this,[t,function(e){R(n,e)},function(e){var i=function(e){var i=n.options.imageTexts.sizeUnits.split(",");return e.replace("#image_name#",t.name).replace("#image_size#",Z(t.size,i)).replace("#image_max_size#",Z(n.options.imageMaxSize,i))}(e);n.updateStatusBar("upload-image",i),setTimeout((function(){n.updateStatusBar("upload-image",n.options.imageTexts.sbInit)}),1e4),n.options.errorCallback(i)}])},se.prototype.setPreviewMaxHeight=function(){var e=this.codemirror.getWrapperElement(),t=e.nextSibling,n=parseInt(window.getComputedStyle(e).paddingTop),i=parseInt(window.getComputedStyle(e).borderTopWidth),r=(parseInt(this.options.maxHeight)+2*n+2*i).toString()+"px";t.style.height=r},se.prototype.createSideBySide=function(){var e=this.codemirror,t=e.getWrapperElement(),n=t.nextSibling;if(!n||!n.classList.contains("editor-preview-side")){if((n=document.createElement("div")).className="editor-preview-side",this.options.previewClass)if(Array.isArray(this.options.previewClass))for(var i=0;i and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";function e(t){ +return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ +const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) +})),t}class t{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope +;class r{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ +if(e.startsWith("language:"))return e.replace("language:","language-") +;if(e.includes(".")){const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const o=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class a{constructor(){ +this.rootNode=o(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=o({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} +addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ +this.closeNode()}__addSublanguage(e,t){const n=e.root +;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ +return new r(this,this.options).value()}finalize(){ +return this.closeAllNodes(),!0}}function l(e){ +return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} +function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} +function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} +function p(e){return RegExp(e.toString()+"|").exec("").length-1} +const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} +s+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], +"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} +const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",y="\\b\\d+(\\.\\d+)?",_="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",w="\\b(0b[01]+)",O={ +begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, +contains:[]},n);s.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const r=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return s.contains.push({begin:h(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s +},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({ +__proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ +scope:"number",begin:w,relevance:0},BINARY_NUMBER_RE:w,COMMENT:N, +C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", +begin:_,relevance:0},C_NUMBER_RE:_,END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, +MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, +NUMBER_MODE:{scope:"number",begin:y,relevance:0},NUMBER_RE:y, +PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, +end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function L(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function P(e,t){ +void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},H=["of","and","for","in","not","or","if","then","parent","list","value"] +;function C(e,t,n="keyword"){const i=Object.create(null) +;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,C(e[n],t,n))})),i;function s(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,$(n[0],n[1])]}))}}function $(e,t){ +return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const U={},z=e=>{ +console.error(e)},W=(e,...t)=>{console.log("WARN: "+e,...t)},X=(e,t)=>{ +U[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),U[`${e}/${t}`]=!0) +},G=Error();function K(e,t,{key:n}){let i=0;const s=e[n],r={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=s[e],r[e+i]=!0,i+=p(t[e-1]) +;e[n]=o,e[n]._emit=r,e[n]._multi=!0}function F(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw z("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +G +;if("object"!=typeof e.beginScope||null===e.beginScope)throw z("beginScope must be object"), +G;K(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw z("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +G +;if("object"!=typeof e.endScope||null===e.endScope)throw z("endScope must be object"), +G;K(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function Z(e){ +function t(t,n){ +return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=i(e.classNameAliases||{}),function n(r,o){const a=r +;if(r.isCompiled)return a +;[I,B,F,D].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), +r.__beforeBegin=null,[T,L,P].forEach((e=>e(r,o))),r.isCompiled=!0;let c=null +;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), +c=r.keywords.$pattern, +delete r.keywords.$pattern),c=c||/\w+/,r.keywords&&(r.keywords=C(r.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(a.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), +r.end&&(a.endRe=t(a.end)), +a.terminatorEnd=l(a.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), +r.illegal&&(a.illegalRe=t(r.illegal)), +r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:V(e)?i(e,{ +starts:e.starts?i(e.starts):null +}):Object.isFrozen(e)?i(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) +})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new s +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function V(e){ +return!!e&&(e.endsWithParent||V(e.starts))}class q extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const J=n,Y=i,Q=Symbol("nomatch"),ee=n=>{ +const i=Object.create(null),s=Object.create(null),r=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let p={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function b(e){ +return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,s=t.language):(X("10.7.0","highlight(lang, code, ...args) has been deprecated."), +X("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,i=t),void 0===n&&(n=!0);const r={code:i,language:s};N("before:highlight",r) +;const o=r.result?r.result:E(r.language,r.code,n) +;return o.code=r.code,N("after:highlight",o),o}function E(e,n,s,r){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" +;for(;t;){n+=R.substring(e,t.index) +;const s=w.case_insensitive?t[0].toLowerCase():t[0],r=(i=s,N.keywords[i]);if(r){ +const[e,i]=r +;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{ +const n=w.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i +;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ +if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(R) +;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top +}else e=x(R,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language) +})():l(),R=""}function u(e,t){ +""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 +;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} +const i=w.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} +function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(w.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(u(R,w.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ +value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) +;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ +return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ +const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return Q;const r=N +;N.endScope&&N.endScope._wrap?(g(), +u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), +d(N.endScope,e)):r.skip?R+=t:(r.returnEnd||r.excludeEnd||(R+=t), +g(),r.excludeEnd&&(R=t));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent +}while(N!==s.parent);return s.starts&&h(s.starts,e),r.returnEnd?0:t.length} +let y={};function _(i,r){const a=r&&r[0];if(R+=i,null==a)return g(),0 +;if("begin"===y.type&&"end"===r.type&&y.index===r.index&&""===a){ +if(R+=n.slice(r.index,r.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=y.rule,t}return 1} +if(y=r,"begin"===r.type)return(e=>{ +const n=e[0],i=e.rule,s=new t(i),r=[i.__beforeBegin,i["on:begin"]] +;for(const t of r)if(t&&(t(e,s),s.isMatchIgnored))return b(n) +;return i.skip?R+=n:(i.excludeBegin&&(R+=n), +g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(r) +;if("illegal"===r.type&&!s){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===r.type){const e=m(r);if(e!==Q)return e} +if("illegal"===r.type&&""===a)return R+="\n",1 +;if(I>1e5&&I>3*r.index)throw Error("potential infinite loop, way more iterations than matches") +;return R+=a,a.length}const w=O(e) +;if(!w)throw z(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const v=Z(w);let k="",N=r||v;const S={},M=new p.__emitter(p);(()=>{const e=[] +;for(let t=N;t!==w;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{ +if(w.__emitTokens)w.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ +I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A +;const e=N.matcher.exec(n);if(!e)break;const t=_(n.substring(A,e.index),e) +;A=e.index+t}_(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e, +value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:J(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A, +context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(o)return{ +language:e,value:J(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} +;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ +const t={value:J(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} +;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1))) +;s.unshift(n);const r=s.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=r,c=o +;return c.secondBest=a,c}function y(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(W(a.replace("{}",n[1])), +W("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(N("before:highlightElement",{el:e,language:n +}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) +;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),p.throwUnescapedHTML))throw new q("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,r=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=r.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,r.language),e.result={language:r.language,re:r.relevance, +relevance:r.relevance},r.secondBest&&(e.secondBest={ +language:r.secondBest.language,relevance:r.secondBest.relevance +}),N("after:highlightElement",{el:e,result:r,text:i})}let _=!1;function w(){ +if("loading"===document.readyState)return _||window.addEventListener("DOMContentLoaded",(()=>{ +w()}),!1),void(_=!0);document.querySelectorAll(p.cssSelector).forEach(y)} +function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} +function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +s[e.toLowerCase()]=t}))}function k(e){const t=O(e) +;return t&&!t.disableAutodetect}function N(e,t){const n=e;r.forEach((e=>{ +e[n]&&e[n](t)}))}Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:w, +highlightElement:y, +highlightBlock:e=>(X("10.7.0","highlightBlock will be removed entirely in v12.0"), +X("10.7.0","Please use highlightElement now."),y(e)),configure:e=>{p=Y(p,e)}, +initHighlighting:()=>{ +w(),X("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +w(),X("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ +if(z("Language definition for '{}' could not be registered.".replace("{}",e)), +!o)throw t;z(t),s=l} +s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, +autoDetection:k,inherit:Y,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),r.push(e)}, +removePlugin:e=>{const t=r.indexOf(e);-1!==t&&r.splice(t,1)}}),n.debugMode=()=>{ +o=!1},n.safeMode=()=>{o=!0},n.versionString="11.11.1",n.regex={concat:h, +lookahead:g,either:f,optional:d,anyNumberOfTimes:u} +;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n +},te=ee({});return te.newInstance=()=>ee({}),te}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `bash` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{const s=e.regex,t={},n={begin:/\$\{/, +end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{ +className:"variable",variants:[{ +begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE] +},i=e.inherit(e.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),c={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},o={className:"string",begin:/"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,t,a]};a.contains.push(o);const r={begin:/\$?\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t] +},l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),m={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/, +keyword:["if","then","else","elif","fi","time","for","while","until","in","do","done","case","esac","coproc","function","select"], +literal:["true","false"], +built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","sudo","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"] +},contains:[l,e.SHEBANG(),m,r,i,c,{match:/(\/[a-z._-]+)+/},o,{match:/\\"/},{ +className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}})() +;hljs.registerLanguage("bash",e)})();/*! `css` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],i=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),t=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),r=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-align","box-decoration-break","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group","box-orient","box-pack","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","contain-intrinsic-block-size","contain-intrinsic-height","contain-intrinsic-inline-size","contain-intrinsic-size","contain-intrinsic-width","container","container-name","container-type","content","content-visibility","counter-increment","counter-reset","counter-set","cue","cue-after","cue-before","cursor","cx","cy","direction","display","dominant-baseline","empty-cells","enable-background","field-sizing","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flood-color","flood-opacity","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-palette","font-size","font-size-adjust","font-smooth","font-smoothing","font-stretch","font-style","font-synthesis","font-synthesis-position","font-synthesis-small-caps","font-synthesis-style","font-synthesis-weight","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-emoji","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","forced-color-adjust","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphenate-character","hyphenate-limit-chars","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","initial-letter","initial-letter-align","inline-size","inset","inset-area","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","kerning","left","letter-spacing","lighting-color","line-break","line-height","line-height-step","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","margin-trim","marker","marker-end","marker-mid","marker-start","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","masonry-auto-flow","math-depth","math-shift","math-style","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-anchor","overflow-block","overflow-clip-margin","overflow-inline","overflow-wrap","overflow-x","overflow-y","overlay","overscroll-behavior","overscroll-behavior-block","overscroll-behavior-inline","overscroll-behavior-x","overscroll-behavior-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","paint-order","pause","pause-after","pause-before","perspective","perspective-origin","place-content","place-items","place-self","pointer-events","position","position-anchor","position-visibility","print-color-adjust","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","ruby-align","ruby-position","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scroll-timeline","scroll-timeline-axis","scroll-timeline-name","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","speak","speak-as","src","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","tab-size","table-layout","text-align","text-align-all","text-align-last","text-anchor","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-size-adjust","text-transform","text-underline-offset","text-underline-position","text-wrap","text-wrap-mode","text-wrap-style","timeline-scope","top","touch-action","transform","transform-box","transform-origin","transform-style","transition","transition-behavior","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-modify","user-select","vector-effect","vertical-align","view-timeline","view-timeline-axis","view-timeline-inset","view-timeline-name","view-transition-name","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","white-space-collapse","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index","zoom"].sort().reverse() +;return n=>{const a=n.regex,l=(e=>({IMPORTANT:{scope:"meta",begin:"!important"}, +BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number", +begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{ +className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{ +scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/} +}))(n),s=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", +case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, +classNameAliases:{keyframePosition:"selector-tag"},contains:[l.BLOCK_COMMENT,{ +begin:/-(webkit|moz|ms|o)-(?=[a-z])/},l.CSS_NUMBER_MODE,{ +className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{ +className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 +},l.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ +begin:":("+t.join("|")+")"},{begin:":(:)?("+o.join("|")+")"}]},l.CSS_VARIABLE,{ +className:"attribute",begin:"\\b("+r.join("|")+")\\b"},{begin:/:/,end:/[;}{]/, +contains:[l.BLOCK_COMMENT,l.HEXCOLOR,l.IMPORTANT,l.CSS_NUMBER_MODE,...s,{ +begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" +},contains:[...s,{className:"string",begin:/[^)]/,endsWithParent:!0, +excludeEnd:!0}]},l.FUNCTION_DISPATCH]},{begin:a.lookahead(/@/),end:"[{;]", +relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/ +},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{ +$pattern:/[a-z-]+/,keyword:"and or not only",attribute:i.join(" ")},contains:[{ +begin:/[a-z-]+(?=:)/,className:"attribute"},...s,l.CSS_NUMBER_MODE]}]},{ +className:"selector-tag",begin:"\\b("+e.join("|")+")\\b"}]}}})() +;hljs.registerLanguage("css",e)})();/*! `diff` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=e.regex;return{name:"Diff", +aliases:["patch"],contains:[{className:"meta",relevance:10, +match:a.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/) +},{className:"comment",variants:[{ +begin:a.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/), +end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{ +className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, +end:/$/}]}}})();hljs.registerLanguage("diff",e)})();/*! `graphql` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=e.regex;return{name:"GraphQL", +aliases:["gql"],case_insensitive:!0,disableAutodetect:!1,keywords:{ +keyword:["query","mutation","subscription","type","input","schema","directive","interface","union","scalar","fragment","enum","on"], +literal:["true","false","null"]}, +contains:[e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{ +scope:"punctuation",match:/[.]{3}/,relevance:0},{scope:"punctuation", +begin:/[\!\(\)\:\=\[\]\{\|\}]{1}/,relevance:0},{scope:"variable",begin:/\$/, +end:/\W/,excludeEnd:!0,relevance:0},{scope:"meta",match:/@\w+/,excludeEnd:!0},{ +scope:"symbol",begin:a.concat(/[_A-Za-z][_0-9A-Za-z]*/,a.lookahead(/\s*:/)), +relevance:0}],illegal:[/[;<']/,/BEGIN/]}}})();hljs.registerLanguage("graphql",e) +})();/*! `javascript` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends","using"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s) +;return o=>{const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="e+"\\s*\\(")), +l.concat("(?!",T.join("|"),")")),d,l.lookahead(/\s*\(/)), +className:"title.function",relevance:0};var T;const C={ +begin:l.concat(/\./,l.lookahead(l.concat(d,/(?![0-9A-Za-z$_(])/))),end:d, +excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={ +match:[/get|set/,/\s+/,d,/(?=\()/],className:{1:"keyword",3:"title.function"}, +contains:[{begin:/\(\)/},R] +},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={ +match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} +;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,h,_,N,f,p,{match:/\$\d+/},A,k,{ +scope:"attr",match:d+l.lookahead(":"),relevance:0},$,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[p,o.REGEXP_MODE,{ +className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0 +},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin, +"on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{ +begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},I,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d, +className:"title.function"})]},{match:/\.\.\./,relevance:0},C,{match:"\\$"+d, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[R]},x,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},O,M,{match:/\$[(.]/}]}}})() +;hljs.registerLanguage("javascript",e)})();/*! `json` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],s={ +scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",aliases:["jsonc"], +keywords:{literal:a},contains:[{className:"attr", +begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/, +className:"punctuation",relevance:0 +},e.QUOTE_STRING_MODE,s,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE], +illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();/*! `markdown` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{const n={begin:/<\/?[A-Za-z_]/, +end:">",subLanguage:"xml",relevance:0},a={variants:[{begin:/\[.+?\]\[.*?\]/, +relevance:0},{ +begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{ +begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/ +},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},i={className:"strong",contains:[], +variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}] +},s={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{ +begin:/_(?![_\s])/,end:/_/,relevance:0}]},c=e.inherit(i,{contains:[] +}),t=e.inherit(s,{contains:[]});i.contains.push(t),s.contains.push(c) +;let g=[n,a];return[i,s,c,t].forEach((e=>{e.contains=e.contains.concat(g) +})),g=g.concat(i,s),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:g},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:g}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:g, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]},{scope:"literal", +match:/&([a-zA-Z0-9]+|#[0-9]{1,7}|#[Xx][0-9a-fA-F]{1,6});/}]}}})() +;hljs.registerLanguage("markdown",e)})();/*! `plaintext` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var t=(()=>{"use strict";return t=>({name:"Plain text", +aliases:["text","txt"],disableAutodetect:!0})})() +;hljs.registerLanguage("plaintext",t)})();/*! `ruby` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n=e.regex,a="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s=n.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),i=n.concat(s,/(::\w+)*/),t={ +"variable.constant":["__FILE__","__LINE__","__ENCODING__"], +"variable.language":["self","super"], +keyword:["alias","and","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield","include","extend","prepend","public","private","protected","raise","throw"], +built_in:["proc","lambda","attr_accessor","attr_reader","attr_writer","define_method","private_constant","module_function"], +literal:["true","false","nil"]},c={className:"doctag",begin:"@[A-Za-z]+"},r={ +begin:"#<",end:">"},b=[e.COMMENT("#","$",{contains:[c] +}),e.COMMENT("^=begin","^=end",{contains:[c],relevance:10 +}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],l={className:"subst",begin:/#\{/, +end:/\}/,keywords:t},d={className:"string",contains:[e.BACKSLASH_ESCAPE,l], +variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{ +begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{ +begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//, +end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{ +begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{ +begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{ +begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{ +begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{ +begin:n.concat(/<<[-~]?'?/,n.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)), +contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, +contains:[e.BACKSLASH_ESCAPE,l]})]}]},o="[0-9](_?[0-9])*",g={className:"number", +relevance:0,variants:[{ +begin:`\\b([1-9](_?[0-9])*|0)(\\.(${o}))?([eE][+-]?(${o})|r)?i?\\b`},{ +begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" +},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ +begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ +begin:"\\b0(_?[0-7])+r?i?\\b"}]},_={variants:[{match:/\(\)/},{ +className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0, +keywords:t}]},u=[d,{variants:[{match:[/class\s+/,i,/\s+<\s+/,i]},{ +match:[/\b(class|module)\s+/,i]}],scope:{2:"title.class", +4:"title.class.inherited"},keywords:t},{match:[/(include|extend)\s+/,i],scope:{ +2:"title.class"},keywords:t},{relevance:0,match:[i,/\.new[. (]/],scope:{ +1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},{relevance:0,match:s,scope:"title.class"},{ +match:[/def/,/\s+/,a],scope:{1:"keyword",3:"title.function"},contains:[_]},{ +begin:e.IDENT_RE+"::"},{className:"symbol", +begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol", +begin:":(?!\\s)",contains:[d,{begin:a}],relevance:0},g,{className:"variable", +begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ +className:"params",begin:/\|(?!=)/,end:/\|/,excludeBegin:!0,excludeEnd:!0, +relevance:0,keywords:t},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*", +keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,l], +illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{ +begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[", +end:"\\][a-z]*"}]}].concat(r,b),relevance:0}].concat(r,b) +;l.contains=u,_.contains=u;const m=[{begin:/^\s*=>/,starts:{end:"$",contains:u} +},{className:"meta.prompt", +begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", +starts:{end:"$",keywords:t,contains:u}}];return b.unshift(r),{name:"Ruby", +aliases:["rb","gemspec","podspec","thor","irb"],keywords:t,illegal:/\/\*/, +contains:[e.SHEBANG({binary:"ruby"})].concat(m).concat(b).concat(u)}}})() +;hljs.registerLanguage("ruby",e)})();/*! `shell` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var s=(()=>{"use strict";return s=>({name:"Shell Session", +aliases:["console","shellsession"],contains:[{className:"meta.prompt", +begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/, +subLanguage:"bash"}}]})})();hljs.registerLanguage("shell",s)})();/*! `sql` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const r=e.regex,t=e.COMMENT("--","$"),a=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],n=a,s=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!a.includes(e))),i={ +match:r.concat(/\b/,r.either(...n),/\s*\(/),relevance:0,keywords:{built_in:n}} +;function o(e){ +return r.concat(/\b/,r.either(...e.map((e=>e.replace(/\s+/,"\\s+")))),/\b/)} +const c={scope:"keyword", +match:o(["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"]), +relevance:0};return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ +$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const a=t +;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:a(e)?e+"|0":e)) +})(s,{when:e=>e.length<3}),literal:["true","false","unknown"], +type:["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"], +built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] +},contains:[{scope:"type", +match:o(["double precision","large object","with timezone","without timezone"]) +},c,i,{scope:"variable",match:/@[a-z0-9][a-z0-9_]*/},{scope:"string",variants:[{ +begin:/'/,end:/'/,contains:[{match:/''/}]}]},{begin:/"/,end:/"/,contains:[{ +match:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{scope:"operator", +match:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})() +;hljs.registerLanguage("sql",e)})();/*! `typescript` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends","using"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],c=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],r=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(c,t,s) +;function o(o){const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="e+"\\s*\\(")), +l.concat("(?!",C.join("|"),")")),d,l.lookahead(/\s*\(/)), +className:"title.function",relevance:0};var C;const T={ +begin:l.concat(/\./,l.lookahead(l.concat(d,/(?![0-9A-Za-z$_(])/))),end:d, +excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={ +match:[/get|set/,/\s+/,d,/(?=\()/],className:{1:"keyword",3:"title.function"}, +contains:[{begin:/\(\)/},R] +},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={ +match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} +;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:w,CLASS_REFERENCE:x},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,p,N,f,_,h,{match:/\$\d+/},A,x,{ +scope:"attr",match:d+l.lookahead(":"),relevance:0},$,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{ +className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0 +},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin, +"on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{ +begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},O,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d, +className:"title.function"})]},{match:/\.\.\./,relevance:0},T,{match:"\\$"+d, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[R]},I,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},k,M,{match:/\$[(.]/}]}}return t=>{ +const s=t.regex,c=o(t),l=e,d=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],b={ +begin:[/namespace/,/\s+/,t.IDENT_RE],beginScope:{1:"keyword",3:"title.class"} +},g={beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:{ +keyword:"interface extends",built_in:d},contains:[c.exports.CLASS_REFERENCE] +},u={$pattern:e, +keyword:n.concat(["type","interface","public","private","protected","implements","declare","abstract","readonly","enum","override","satisfies"]), +literal:a,built_in:i.concat(d),"variable.language":r},m={className:"meta", +begin:"@"+l},E=(e,n,a)=>{const t=e.contains.findIndex((e=>e.label===n)) +;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,a)} +;Object.assign(c.keywords,u),c.exports.PARAMS_CONTAINS.push(m) +;const A=c.contains.find((e=>"attr"===e.scope)),y=Object.assign({},A,{ +match:s.concat(l,s.lookahead(/\s*\?:/))}) +;return c.exports.PARAMS_CONTAINS.push([c.exports.CLASS_REFERENCE,A,y]), +c.contains=c.contains.concat([m,b,g,y]), +E(c,"shebang",t.SHEBANG()),E(c,"use_strict",{className:"meta",relevance:10, +begin:/^\s*['"]use strict['"]/ +}),c.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(c,{ +name:"TypeScript",aliases:["ts","tsx","mts","cts"]}),c}})() +;hljs.registerLanguage("typescript",e)})();/*! `xml` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},i=e.inherit(t,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),r={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin://,relevance:10,contains:[t,l,c,i,{begin:/\[/,end:/\]/,contains:[{ +className:"meta",begin://,contains:[t,i,l,c]}]}] +},e.COMMENT(//,{relevance:10}),{begin://, +relevance:10},s,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/, +relevance:10,contains:[l]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[r],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[r],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a.concat(//,/>/,/\s/)))), +end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:r}]},{ +className:"tag",begin:a.concat(/<\//,a.lookahead(a.concat(n,/>/))),contains:[{ +className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}} +})();hljs.registerLanguage("xml",e)})();/*! `yaml` grammar compiled for Highlight.js 11.11.1 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ +className:"string",relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}], +contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{ +begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{variants:[{ +begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{ +begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,keywords:n, +relevance:0},t={begin:/\{/,end:/\}/,contains:[l],illegal:"\\n",relevance:0},c={ +begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},r=[{ +className:"attr",variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{ +begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{ +begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},{className:"meta", +begin:"^---\\s*$",relevance:10},{className:"string", +begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ +begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, +relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", +begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a +},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", +begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", +relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ +className:"number", +begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" +},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,c,{ +className:"string",relevance:0,begin:/'/,end:/'/,contains:[{match:/''/, +scope:"char.escape",relevance:0}]},s],g=[...r] +;return g.pop(),g.push(i),l.contains=g,{name:"YAML",case_insensitive:!0, +aliases:["yml"],contains:r}}})();hljs.registerLanguage("yaml",e)})(); + +/*! `liquid` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e=["as","assign","break","capture","case","color","comment","continue","cycle","decrement","echo","else","elsif","endcapture","endcase","endcomment","endfor","endform","endif","endjavascript","endraw","endschema","endsection","endstylesheet","endtablerow","endunless","font","for","for-render","form","if","ifchanged","include","increment","javascript","layout","liquid","paginate","raw","react","render","schema","section","sections","style","style-tag","stylesheet","tablerow","unless","when","with"],t=["additional_checkout_buttons","address","all_country_option_tags","all_products","app","app_settings","article","articles","block","block_order","blocks","blog","blogs","canonical_url","cart","checkout","collection","collections","color_scheme","comment","content_for_additional_checkout_buttons","content_for_header","content_for_index","content_for_layout","country_option_tags","currency","current_page","current_tags","customer","customer_address","discount_allocation","discount_application","external_video","font","forloop","form","fulfillment","gift_card","global_block","handle","i","image","images","index","item","letters","line_item","link","linklist","linklists","location","localization","media","metafield","model","model_source","numbers","order","page","page_description","page_image","page_title","pages","paginate","part","policy","powered_by_link","predictive_search","predictive_search_autocomplete","product","product_option","product_variant","products","recommendations","request","routes","script","scripts","search","section","section_blocks","selling_plan","selling_plan_allocation","selling_plan_group","settings","shipping_method","shipping_rates","shop","shop_locale","store_availability","tablerow","tax_line","template","theme","transaction","unit_price_measurement","value","variant","video","video_source"],a=["abs","append","at_least","at_most","capitalize","ceil","color_brightness","color_darken","color_desaturate","color_extract","color_lighten","color_modify","color_saturate","color_to_rgb","compact","concat","date","default","divided_by","downcase","escape","escape_once","first","floor","font_face","font_modify","highlight","highlight_active","join","last","lstrip","map","minus","modulo","newline_to_br","payment_type_img_url","plus","prepend","remove","remove_first","replace","replace_first","reverse","round","rstrip","size","slice","sort","sort_natural","split","strip","strip_html","strip_newlines","time_tag","times","truncate","truncatewords","uniq","upcase","url_decode","url_encode","where"],s=["==","=","\\:","\\.","\\|","!=","<>",">","<",">=","<=","contains","and","or","\\[","\\]"] +;return o=>({name:"Liquid",aliases:["shopify"],case_insensitive:!0, +contains:[o.COMMENT("{%-?\\s*comment\\s*-?%}","{%-?\\s*endcomment\\s*-?%}"),o.COMMENT("{%-?\\s*raw\\s*-?%}","{%-?\\s*endraw\\s*-?%}"),{ +className:"template-tag",begin:"{%-?\\s*",end:"\\s*-?%}",keywords:e.join(" "), +contains:[{className:"comment",begin:"#.*?(?=%})",relevance:10},{ +beginKeywords:e.join(" "),relevance:10},o.QUOTE_STRING_MODE,o.C_NUMBER_MODE,{ +className:"literal",begin:"\\b(true|false|nil)\\b"},{className:"operator", +begin:"("+s.join("|")+")"},{className:"built_in",begin:"\\b("+t.join("|")+")\\b" +},{className:"function", +begin:"\\|\\s*("+a.join("|")+")\\b(?:\\s*:[^:\\s,|}]+(?:\\s*:[^:\\s,|}]+)*)?", +keywords:a.join(" ")}]},{className:"template-variable",begin:"{{-?\\s*", +end:"\\s*-?}}",contains:[o.QUOTE_STRING_MODE,o.C_NUMBER_MODE,{ +className:"literal",begin:"\\b(true|false|nil)\\b"},{className:"operator", +begin:"("+s.join("|")+")"},{className:"built_in",begin:"\\b("+t.join("|")+")\\b" +},{className:"function", +begin:"\\|\\s*("+a.join("|")+")\\b(?:\\s*:[^:\\s,|}]+(?:\\s*:[^:\\s,|}]+)*)?", +keywords:a.join(" ")}]},{className:"property", +begin:"\\b[a-zA-Z0-9_]+\\.([a-zA-Z0-9_]+)\\b"}]})})() +;hljs.registerLanguage("liquid",e)})(); \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-proseMirror.js b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-proseMirror.js new file mode 100644 index 00000000..9c413393 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-proseMirror.js @@ -0,0 +1,31 @@ +// import { EditorState } from 'prosemirror-state'; +// import { EditorView } from 'prosemirror-view'; +// import { Schema, DOMParser } from 'prosemirror-model'; +// import { exampleSetup } from 'prosemirror-example-setup'; +// import { schema, defaultMarkdownParser, defaultMarkdownSerializer } from 'prosemirror-markdown'; +// import { addMentionNodes, addTagNodes, getMentionsPlugin } from 'prosemirror-mentions' +// import { getSingletonHighlighter } from 'shiki'; +// import { createHighlightPlugin } from 'prosemirror-highlight' +// import { createParser } from 'prosemirror-highlight/shiki' + +// import 'prosemirror-view/style/prosemirror.css' +// import 'prosemirror-menu/style/menu.css' +// import 'prosemirror-example-setup/style/style.css' + + +// // const proseMirrorSchema = new Schema({ +// // nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'), +// // marks: schema.spec.marks +// // }); + + +// const highlighter = await getSingletonHighlighter({ +// themes: ['github-light'], +// langs: ['javascript', 'typescript', 'python'], +// }); + +// const parser = createParser(highlighter); + +// const shikiPlugin = createHighlightPlugin({ parser }); + +// export { EditorView, EditorState, DOMParser, schema, exampleSetup, addMentionNodes, addTagNodes, getMentionsPlugin, defaultMarkdownParser, defaultMarkdownSerializer, shikiPlugin } diff --git a/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-uppy.js b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-uppy.js new file mode 100644 index 00000000..5b75b41b --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/assets/js/dependency-uppy.js @@ -0,0 +1,26 @@ +function e(e,t){return Object.hasOwn(e,t)}const{AbortController:t}=globalThis,{AbortSignal:i}=globalThis,s=(t="Aborted",i)=>{const s=new DOMException(t,"AbortError");return null!=i&&e(i,"cause")&&Object.defineProperty(s,"cause",{__proto__:null,configurable:!0,writable:!0,value:i.cause}),s};const n=/^data:([^/]+\/[^,;]+(?:[^,]*?))(;base64)?,([\s\S]*)$/;function r(e,t,i){const s=n.exec(e),r=t.mimeType??s?.[1]??"plain/text";let a;if(null!=s?.[2]){const e=atob(decodeURIComponent(s[3])),t=new Uint8Array(e.length);for(let i=0;i(t+=`-${function(e){return e.charCodeAt(0).toString(32)}(e)}`,"/"))+t}function g(e,t){if(function(e){return!(!e.isRemote||!e.remote)&&new Set(["box","dropbox","drive","facebook","unsplash"]).has(e.remote.provider)}(e))return e.id;const i=m(e);return function(e,t){let i=t||"uppy";return"string"==typeof e.name&&(i+=`-${f(e.name.toLowerCase())}`),void 0!==e.type&&(i+=`-${e.type}`),e.meta&&"string"==typeof e.meta.relativePath&&(i+=`-${f(e.meta.relativePath.toLowerCase())}`),void 0!==e.data?.size&&(i+=`-${e.data.size}`),void 0!==e.data.lastModified&&(i+=`-${e.data.lastModified}`),i}({...e,type:i},t)}function y(e,t){return!0===e?Object.keys(t):Array.isArray(e)?e:[]}var v=Array.from;function b(e,t,i,{onSuccess:s}){e.readEntries(n=>{const r=[...t,...n];n.length?queueMicrotask(()=>{b(e,r,i,{onSuccess:s})}):s(r)},e=>{i(e),s(t)})}function w(e,t){return null==e?e:{kind:e.isFile?"file":e.isDirectory?"directory":void 0,name:e.name,getFile:()=>new Promise((t,i)=>e.file(t,i)),async*values(){const i=e.createReader(),s=await new Promise(e=>{b(i,[],t,{onSuccess:i=>e(i.map(e=>w(e,t)))})});yield*s},isSameEntry:void 0}}async function*_(e,t,i=void 0){const s=()=>`${t}/${e.name}`;if("file"===e.kind){const n=await e.getFile();null!=n?(n.relativePath=t?s():null,yield n):null!=i&&(yield i)}else if("directory"===e.kind)for await(const i of e.values())yield*_(i,t?s():e.name);else null!=i&&(yield i)}async function S(e,t){const i=t?.logDropError??Function.prototype;try{const t=[];for await(const s of async function*(e,t){const i=await Promise.all(Array.from(e.items,async e=>{let i;return i??=w("function"==typeof e.getAsEntry?e.getAsEntry():e.webkitGetAsEntry(),t),{fileSystemHandle:i,lastResortFile:e.getAsFile()}}));for(const{lastResortFile:e,fileSystemHandle:s}of i)if(null!=s)try{yield*_(s,"",e)}catch(i){null!=e?yield e:t(i)}else null!=e&&(yield e)}(e,i))t.push(s);return t}catch{return function(e){const t=v(e.files);return Promise.resolve(t)}(e)}}const C={__proto__:null,"audio/mp3":"mp3","audio/mp4":"mp4","audio/ogg":"ogg","audio/webm":"webm","image/gif":"gif","image/heic":"heic","image/heif":"heif","image/jpeg":"jpg","image/webp":"webp","image/png":"png","image/svg+xml":"svg","video/mp4":"mp4","video/ogg":"ogv","video/quicktime":"mov","video/webm":"webm","video/x-matroska":"mkv","video/x-msvideo":"avi"};function F(e){return[e]=e.split(";",1),C[e]||null}function k(e){return e<10?`0${e}`:e.toString()}function P(){const e=new Date;return`${k(e.getHours())}:${k(e.getMinutes())}:${k(e.getSeconds())}`}function T(){if("undefined"==typeof window)return!1;const e=document.body;return null!=e&&null!=window&&("draggable"in e&&"ondragstart"in e&&"ondrop"in e&&("FormData"in window&&"FileReader"in window))}function x(e){return e.startsWith("blob:")}function E(e){return!!e&&/^[^/]+\/(jpe?g|gif|png|svg|svg\+xml|bmp|webp|avif)$/.test(e)}function M(e){const t=(i=e,{hours:Math.floor(i/3600)%24,minutes:Math.floor(i/60)%60,seconds:Math.floor(i%60)});var i;return`${0===t.hours?"":`${t.hours}h`}${0===t.minutes?"":`${0===t.hours?t.minutes:` ${t.minutes.toString(10).padStart(2,"0")}`}m`}${0!==t.hours?"":`${0===t.minutes?t.seconds:` ${t.seconds.toString(10).padStart(2,"0")}`}s`}`}function U(e){if(null!=e){const t=()=>this.abort(e.reason);e.addEventListener("abort",t,{once:!0});const i=()=>{e.removeEventListener("abort",t)};this.then?.(i,i)}return this}class A{#e=0;#t=[];#i=!1;#s;#n=1;#r;#a;limit;constructor(e){this.limit="number"!=typeof e||0===e?1/0:e}#o(e){this.#e+=1;let t,i=!1;try{t=e()}catch(e){throw this.#e-=1,e}return{abort:e=>{i||(i=!0,this.#e-=1,t?.(e),this.#l())},done:()=>{i||(i=!0,this.#e-=1,this.#l())}}}#l(){queueMicrotask(()=>this.#h())}#h(){if(this.#i||this.#e>=this.limit)return;if(0===this.#t.length)return;const e=this.#t.shift();if(null==e)throw new Error("Invariant violation: next is null");const t=this.#o(e.fn);e.abort=t.abort,e.done=t.done}#d(e,t){const i={fn:e,priority:t?.priority||0,abort:()=>{this.#p(i)},done:()=>{throw new Error("Cannot mark a queued request as done: this indicates a bug")}},s=this.#t.findIndex(e=>i.priority>e.priority);return-1===s?this.#t.push(i):this.#t.splice(s,0,i),i}#p(e){const t=this.#t.indexOf(e);-1!==t&&this.#t.splice(t,1)}run(e,t){return!this.#i&&this.#e{const s=this.run(()=>(e(...i),queueMicrotask(()=>s.done()),()=>{}),t);return{abortOn:U,abort(){s.abort()}}}}wrapPromiseFunction(e,t){return(...i)=>{let s;const n=new Promise((n,r)=>{s=this.run(()=>{let t,a;try{a=Promise.resolve(e(...i))}catch(e){a=Promise.reject(e)}return a.then(e=>{t?r(t):(s.done(),n(e))},e=>{t?r(t):(s.done(),r(e))}),e=>{t=function(e){return new Error("Cancelled",{cause:e})}(e)}},t)});return n.abort=e=>{s.abort(e)},n.abortOn=U,n}}resume(){this.#i=!1,clearTimeout(this.#s);for(let e=0;ethis.resume();pause(e=null){this.#i=!0,clearTimeout(this.#s),null!=e&&(this.#s=setTimeout(this.#u,e))}rateLimit(e){clearTimeout(this.#a),this.pause(e),this.limit>1&&Number.isFinite(this.limit)&&(this.#r=this.limit-1,this.limit=this.#n,this.#a=setTimeout(this.#c,e))}#c=()=>{if(this.#i)this.#a=setTimeout(this.#c,0);else{this.#n=this.limit,this.limit=Math.ceil((this.#r+this.#n)/2);for(let e=this.#n;e<=this.limit;e++)this.#l();this.#r-this.#n>3?this.#a=setTimeout(this.#c,2e3):this.#n=Math.floor(this.#n/2)}};get isPaused(){return this.#i}}Symbol("__queue");function D(e,t,i){const s=[];return e.forEach(e=>"string"!=typeof e?s.push(e):t[Symbol.split](e).forEach((e,t,n)=>{""!==e&&s.push(e),t{throw new Error(`missing string: ${e}`)};class N{locale;constructor(e,{onMissingKey:t=O}={}){this.locale={strings:{},pluralize:e=>1===e?0:1},Array.isArray(e)?e.forEach(this.#m,this):this.#m(e),this.#f=t}#f;#m(e){if(!e?.strings)return;const t=this.locale;Object.assign(this.locale,{strings:{...t.strings,...e.strings},pluralize:e.pluralize||t.pluralize})}translate(e,t){return this.translateArray(e,t).join("")}translateArray(e,t){let i=this.locale.strings[e];null==i&&(this.#f(e),i=e);if("object"==typeof i){if(t&&void 0!==t.smart_count){return R(i[this.locale.pluralize(t.smart_count)],t)}throw new Error("Attempted to use a string with plural forms, but no value was given for %{smart_count}")}if("string"!=typeof i)throw new Error("string was not a string");return R(i,t)}}const I="...";function B(e,t){if(0===t)return"";if(e.length<=t)return e;if(t<=4)return`${e.slice(0,t-1)}…`;const i=t-3,s=Math.ceil(i/2),n=Math.floor(i/2);return e.slice(0,s)+I+e.slice(-n)}class L extends Error{name="UserFacingApiError"}var z,H,q,$,j,W,V,X,G,Y,K,Q={},Z=[],J=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,ee=Array.isArray;function te(e,t){for(var i in t)e[i]=t[i];return e}function ie(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function se(e,t,i){var s,n,r,a={};for(r in t)"key"==r?s=t[r]:"ref"==r?n=t[r]:a[r]=t[r];if(arguments.length>2&&(a.children=arguments.length>3?z.call(arguments,2):i),"function"==typeof e&&null!=e.defaultProps)for(r in e.defaultProps)void 0===a[r]&&(a[r]=e.defaultProps[r]);return ne(e,a,s,n,null)}function ne(e,t,i,s,n){var r={type:e,props:t,key:i,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==n?++q:n,__i:-1,__u:0};return null==n&&null!=H.vnode&&H.vnode(r),r}function re(e){return e.children}function ae(e,t){this.props=e,this.context=t}function oe(e,t){if(null==t)return e.__?oe(e.__,e.__i+1):null;for(var i;to&&$.sort(V),e=$.shift(),o=$.length,e.__d&&(i=void 0,s=void 0,n=(s=(t=e).__v).__e,r=[],a=[],t.__P&&((i=te({},s)).__v=s.__v+1,H.vnode&&H.vnode(i),ve(t.__P,i,s,t.__n,t.__P.namespaceURI,32&s.__u?[n]:null,r,null==n?oe(s):n,!!(32&s.__u),a),i.__v=s.__v,i.__.__k[i.__i]=i,we(r,i,a),s.__e=s.__=null,i.__e!=n&&le(i)));de.__r=0}function pe(e,t,i,s,n,r,a,o,l,h,d){var p,u,c,m,f,g,y,v=s&&s.__k||Z,b=t.length;for(l=function(e,t,i,s,n){var r,a,o,l,h,d=i.length,p=d,u=0;for(e.__k=new Array(n),r=0;r0?a=e.__k[r]=ne(a.type,a.props,a.key,a.ref?a.ref:null,a.__v):e.__k[r]=a,l=r+u,a.__=e,a.__b=e.__b+1,-1!=(h=a.__i=me(a,i,l,p))&&(p--,(o=i[h])&&(o.__u|=2)),null==o||null==o.__v?(-1==h&&(n>d?u--:nl?u--:u++,a.__u|=4))):e.__k[r]=null;if(p)for(r=0;r(d?1:0))for(n=i-1,r=i+1;n>=0||r=0?n--:r++])&&!(2&h.__u)&&o==h.key&&l==h.type)return a;return-1}function fe(e,t,i){"-"==t[0]?e.setProperty(t,null==i?"":i):e[t]=null==i?"":"number"!=typeof i||J.test(t)?i:i+"px"}function ge(e,t,i,s,n){var r,a;e:if("style"==t)if("string"==typeof i)e.style.cssText=i;else{if("string"==typeof s&&(e.style.cssText=s=""),s)for(t in s)i&&t in i||fe(e.style,t,"");if(i)for(t in i)s&&i[t]==s[t]||fe(e.style,t,i[t])}else if("o"==t[0]&&"n"==t[1])r=t!=(t=t.replace(X,"$1")),a=t.toLowerCase(),t=a in e||"onFocusOut"==t||"onFocusIn"==t?a.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+r]=i,i?s?i.u=s.u:(i.u=G,e.addEventListener(t,r?K:Y,r)):e.removeEventListener(t,r?K:Y,r);else{if("http://www.w3.org/2000/svg"==n)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!=t&&"height"!=t&&"href"!=t&&"list"!=t&&"form"!=t&&"tabIndex"!=t&&"download"!=t&&"rowSpan"!=t&&"colSpan"!=t&&"role"!=t&&"popover"!=t&&t in e)try{e[t]=null==i?"":i;break e}catch(e){}"function"==typeof i||(null==i||!1===i&&"-"!=t[4]?e.removeAttribute(t):e.setAttribute(t,"popover"==t&&1==i?"":i))}}function ye(e){return function(t){if(this.l){var i=this.l[t.type+e];if(null==t.t)t.t=G++;else if(t.t0?e:ee(e)?e.map(_e):te({},e)}function Se(e,t,i){try{if("function"==typeof e){var s="function"==typeof e.__u;s&&e.__u(),s&&null==t||(e.__u=e(t))}else e.current=t}catch(e){H.__e(e,i)}}function Ce(e,t,i){var s,n;if(H.unmount&&H.unmount(e),(s=e.ref)&&(s.current&&s.current!=e.__e||Se(s,null,t)),null!=(s=e.__c)){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(e){H.__e(e,t)}s.base=s.__P=null}if(s=e.__k)for(n=0;n2&&(o.children=arguments.length>3?z.call(arguments,2):i),ne(e.type,o,s||e.key,n||e.ref,null)}z=Z.slice,H={__e:function(e,t,i,s){for(var n,r,a;t=t.__;)if((n=t.__c)&&!n.__)try{if((r=n.constructor)&&null!=r.getDerivedStateFromError&&(n.setState(r.getDerivedStateFromError(e)),a=n.__d),null!=n.componentDidCatch&&(n.componentDidCatch(e,s||{}),a=n.__d),a)return n.__E=n}catch(t){e=t}throw e}},q=0,ae.prototype.setState=function(e,t){var i;i=null!=this.__s&&this.__s!=this.state?this.__s:this.__s=te({},this.state),"function"==typeof e&&(e=e(te({},i),this.props)),e&&te(i,e),null!=e&&this.__v&&(t&&this._sb.push(t),he(this))},ae.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),he(this))},ae.prototype.render=re,$=[],W="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,V=function(e,t){return e.__v.__b-t.__v.__b},de.__r=0,X=/(PointerCapture)$|Capture$/i,G=0,Y=ye(!1),K=ye(!0);var Te=0;Array.isArray;function xe(e,t,i,s,n,r){t||(t={});var a,o,l=t;if("ref"in l)for(o in l={},t)"ref"==o?a=t[o]:l[o]=t[o];var h={type:e,props:l,key:i,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Te,__i:-1,__u:0,__source:n,__self:r};if("function"==typeof e&&(a=e.defaultProps))for(o in a)void 0===l[o]&&(l[o]=a[o]);return H.vnode&&H.vnode(h),h}var Ee,Me,Ue,Ae,De=0,Re=[],Oe=H,Ne=Oe.__b,Ie=Oe.__r,Be=Oe.diffed,Le=Oe.__c,ze=Oe.unmount,He=Oe.__;function qe(e,t){Oe.__h&&Oe.__h(Me,e,De||t),De=0;var i=Me.__H||(Me.__H={__:[],__h:[]});return e>=i.__.length&&i.__.push({}),i.__[e]}function $e(e){return De=1,function(e,t,i){var s=qe(Ee++,2);if(s.t=e,!s.__c&&(s.__=[i?i(t):et(void 0,t),function(e){var t=s.__N?s.__N[0]:s.__[0],i=s.t(t,e);t!==i&&(s.__N=[i,s.__[1]],s.__c.setState({}))}],s.__c=Me,!Me.__f)){var n=function(e,t,i){if(!s.__c.__H)return!0;var n=s.__c.__H.__.filter(function(e){return!!e.__c});if(n.every(function(e){return!e.__N}))return!r||r.call(this,e,t,i);var a=s.__c.props!==e;return n.forEach(function(e){if(e.__N){var t=e.__[0];e.__=e.__N,e.__N=void 0,t!==e.__[0]&&(a=!0)}}),r&&r.call(this,e,t,i)||a};Me.__f=!0;var r=Me.shouldComponentUpdate,a=Me.componentWillUpdate;Me.componentWillUpdate=function(e,t,i){if(this.__e){var s=r;r=void 0,n(e,t,i),r=s}a&&a.call(this,e,t,i)},Me.shouldComponentUpdate=n}return s.__N||s.__}(et,e)}function je(e,t){var i=qe(Ee++,3);!Oe.__s&&Je(i.__H,t)&&(i.__=e,i.u=t,Me.__H.__h.push(i))}function We(e){return De=5,Ve(function(){return{current:e}},[])}function Ve(e,t){var i=qe(Ee++,7);return Je(i.__H,t)&&(i.__=e(),i.__H=t,i.__h=e),i.__}function Xe(e,t){return De=8,Ve(function(){return e},t)}function Ge(){for(var e;e=Re.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(Qe),e.__H.__h.forEach(Ze),e.__H.__h=[]}catch(t){e.__H.__h=[],Oe.__e(t,e.__v)}}Oe.__b=function(e){Me=null,Ne&&Ne(e)},Oe.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),He&&He(e,t)},Oe.__r=function(e){Ie&&Ie(e),Ee=0;var t=(Me=e.__c).__H;t&&(Ue===Me?(t.__h=[],Me.__h=[],t.__.forEach(function(e){e.__N&&(e.__=e.__N),e.u=e.__N=void 0})):(t.__h.forEach(Qe),t.__h.forEach(Ze),t.__h=[],Ee=0)),Ue=Me},Oe.diffed=function(e){Be&&Be(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(1!==Re.push(t)&&Ae===Oe.requestAnimationFrame||((Ae=Oe.requestAnimationFrame)||Ke)(Ge)),t.__H.__.forEach(function(e){e.u&&(e.__H=e.u),e.u=void 0})),Ue=Me=null},Oe.__c=function(e,t){t.some(function(e){try{e.__h.forEach(Qe),e.__h=e.__h.filter(function(e){return!e.__||Ze(e)})}catch(i){t.some(function(e){e.__h&&(e.__h=[])}),t=[],Oe.__e(i,e.__v)}}),Le&&Le(e,t)},Oe.unmount=function(e){ze&&ze(e);var t,i=e.__c;i&&i.__H&&(i.__H.__.forEach(function(e){try{Qe(e)}catch(e){t=e}}),i.__H=void 0,t&&Oe.__e(t,i.__v))};var Ye="function"==typeof requestAnimationFrame;function Ke(e){var t,i=function(){clearTimeout(s),Ye&&cancelAnimationFrame(t),setTimeout(e)},s=setTimeout(i,35);Ye&&(t=requestAnimationFrame(i))}function Qe(e){var t=Me,i=e.__c;"function"==typeof i&&(e.__c=void 0,i()),Me=t}function Ze(e){var t=Me;e.__c=e.__(),Me=t}function Je(e,t){return!e||e.length!==t.length||t.some(function(t,i){return t!==e[i]})}function et(e,t){return"function"==typeof t?t(e):t}const tt={position:"relative",width:"100%",minHeight:"100%"},it={position:"absolute",top:0,left:0,width:"100%",overflow:"visible"};function st({data:e,rowHeight:t,renderRow:i,overscanCount:s=10,padding:n=4,...r}){const a=We(null),[o,l]=$e(0),[h,d]=$e(0);je(()=>{function e(){null!=a.current&&h!==a.current.offsetHeight&&d(a.current.offsetHeight)}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}},[h]);const p=Xe(()=>{a.current&&l(a.current.scrollTop)},[]);let u=Math.floor(o/t),c=Math.floor(h/t);s&&(u=Math.max(0,u-u%s),c+=s);const m=u+c+n,f=e.slice(u,m),g={...tt,height:e.length*t},y={...it,top:u*t};return xe("div",{onScroll:p,ref:a,...r,children:xe("div",{role:"presentation",style:g,children:xe("div",{role:"presentation",style:y,children:f.map(i)})})})}class nt{uppy;opts;id;defaultLocale;i18n;i18nArray;type;VERSION;constructor(e,t){this.uppy=e,this.opts=t??{}}getPluginState(){const{plugins:e}=this.uppy.getState();return e?.[this.id]||{}}setPluginState(e){const{plugins:t}=this.uppy.getState();this.uppy.setState({plugins:{...t,[this.id]:{...t[this.id],...e}}})}setOptions(e){this.opts={...this.opts,...e},this.setPluginState(void 0),this.i18nInit()}i18nInit(){const e=new N([this.defaultLocale,this.uppy.locale,this.opts.locale]);this.i18n=e.translate.bind(e),this.i18nArray=e.translateArray.bind(e),this.setPluginState(void 0)}addTarget(e){throw new Error("Extend the addTarget method to add your plugin to another plugin's target")}install(){}uninstall(){}update(e){}afterUpdate(){}}class rt{#g;#y=[];constructor(e){this.#g=e}on(e,t){return this.#y.push([e,t]),this.#g.on(e,t)}remove(){for(const[e,t]of this.#y.splice(0))this.#g.off(e,t)}onFilePause(e,t){this.on("upload-pause",(i,s)=>{e===i?.id&&t(s)})}onFileRemove(e,t){this.on("file-removed",i=>{e===i.id&&t(i.id)})}onPause(e,t){this.on("upload-pause",(i,s)=>{e===i?.id&&t(s)})}onRetry(e,t){this.on("upload-retry",i=>{e===i?.id&&t()})}onRetryAll(e,t){this.on("retry-all",()=>{this.#g.getFile(e)&&t()})}onPauseAll(e,t){this.on("pause-all",()=>{this.#g.getFile(e)&&t()})}onCancelAll(e,t){this.on("cancel-all",(...i)=>{this.#g.getFile(e)&&t(...i)})}onResumeAll(e,t){this.on("resume-all",()=>{this.#g.getFile(e)&&t()})}}const at={debug:()=>{},warn:()=>{},error:(...e)=>console.error(`[Uppy] [${P()}]`,...e)},ot={debug:(...e)=>console.debug(`[Uppy] [${P()}]`,...e),warn:(...e)=>console.warn(`[Uppy] [${P()}]`,...e),error:(...e)=>console.error(`[Uppy] [${P()}]`,...e)};var lt,ht,dt="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function pt(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ut,ct,mt,ft,gt=pt(ht?lt:(ht=1,lt=function(e){if("number"!=typeof e||Number.isNaN(e))throw new TypeError("Expected a number, got "+typeof e);const t=e<0;let i=Math.abs(e);if(t&&(i=-i),0===i)return"0 B";const s=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],n=Math.min(Math.floor(Math.log(i)/Math.log(1024)),s.length-1),r=Number(i/1024**n),a=s[n];return`${r>=10||r%1==0?Math.round(r):r.toFixed(1)} ${a}`}));function yt(){if(ct)return ut;function e(e,t){this.text=e=e||"",this.hasWild=~e.indexOf("*"),this.separator=t,this.parts=e.split(t)}return ct=1,e.prototype.match=function(e){var t,i,s=!0,n=this.parts,r=n.length;if("string"==typeof e||e instanceof String)if(this.hasWild||this.text==e){for(i=(e||"").split(this.separator),t=0;s&&t=2}return s?n(s.split(";")[0]):n}}(),bt=pt(vt);const wt={maxFileSize:null,minFileSize:null,maxTotalFileSize:null,maxNumberOfFiles:null,minNumberOfFiles:null,allowedFileTypes:null,requiredMetaFields:[]};class _t extends Error{isUserFacing;file;constructor(e,t){super(e),this.isUserFacing=t?.isUserFacing??!0,t?.file&&(this.file=t.file)}isRestriction=!0}class St{getI18n;getOpts;constructor(e,t){this.getI18n=t,this.getOpts=()=>{const t=e();if(null!=t.restrictions?.allowedFileTypes&&!Array.isArray(t.restrictions.allowedFileTypes))throw new TypeError("`restrictions.allowedFileTypes` must be an array");return t}}validateAggregateRestrictions(e,t){const{maxTotalFileSize:i,maxNumberOfFiles:s}=this.getOpts().restrictions;if(s){const i=e.filter(e=>!e.isGhost);if(i.length+t.length>s)throw new _t(`${this.getI18n()("youCanOnlyUploadX",{smart_count:s})}`)}if(i){const s=[...e,...t].reduce((e,t)=>e+(t.size??0),0);if(s>i)throw new _t(this.getI18n()("aggregateExceedsSize",{sizeAllowed:gt(i),size:gt(s)}))}}validateSingleFile(e){const{maxFileSize:t,minFileSize:i,allowedFileTypes:s}=this.getOpts().restrictions;if(s){const t=s.some(t=>t.includes("/")?!!e.type&&bt(e.type.replace(/;.*?$/,""),t):!("."!==t[0]||!e.extension)&&e.extension.toLowerCase()===t.slice(1).toLowerCase());if(!t){const t=s.join(", ");throw new _t(this.getI18n()("youCanOnlyUploadFileTypes",{types:t}),{file:e})}}if(t&&null!=e.size&&e.size>t)throw new _t(this.getI18n()("exceedsSize",{size:gt(t),file:e.name??this.getI18n()("unnamed")}),{file:e});if(i&&null!=e.size&&e.size{this.validateSingleFile(e)}),this.validateAggregateRestrictions(e,t)}validateMinNumberOfFiles(e){const{minNumberOfFiles:t}=this.getOpts().restrictions;if(t&&Object.keys(e).length{e instanceof i&&(t=e)})}return t}mount(e,t){const i=t.id,s=function(e,t=document){return"string"==typeof e?t.querySelector(e):d(e)?e:null}(e);if(s){this.isTargetDOMEl=!0;const t=document.createElement("div");return t.classList.add("uppy-Root"),this.#v=function(e){let t,i=null;return(...s)=>(t=s,i||(i=Promise.resolve().then(()=>(i=null,e(...t)))),i)}(e=>{this.uppy.getPlugin(this.id)&&(ke(this.render(e,t),t),this.afterUpdate())}),this.uppy.log(`Installing ${i} to a DOM element '${e}'`),this.opts.replaceTargetContent&&(s.innerHTML=""),ke(this.render(this.uppy.getState(),t),t),this.el=t,s.appendChild(t),t.dir=this.opts.direction||function(e){for(;e&&!e.dir;)e=e.parentNode;return e?.dir}(t)||"ltr",this.onMount(),this.el}const n=this.getTargetPlugin(e);if(n)return this.uppy.log(`Installing ${i} to ${n.id}`),this.parent=n,this.el=n.addTarget(t),this.onMount(),this.el;this.uppy.log(`Not installing ${i}`);let r=`Invalid target option given to ${i}.`;throw r+="function"==typeof e?" The given target is not a Plugin class. Please check that you're not specifying a React Component instead of a plugin. If you are using @uppy/* packages directly, make sure you have only 1 version of @uppy/core installed: run `npm ls @uppy/core` on the command line and verify that all the versions match and are deduped correctly.":"If you meant to target an HTML element, please make sure that the element exists. Check that the + + + + + + + {{ content_for_layout }} + + {% liquid + render 'modules/common-styling/toasts' + %} + + + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/pages/style-guide.liquid b/pos-module-user-invites/modules/common-styling/public/views/pages/style-guide.liquid new file mode 100644 index 00000000..037635d8 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/pages/style-guide.liquid @@ -0,0 +1,57 @@ +--- +layout: 'modules/common-styling/style-guide' +--- + +
    + + +
    + {% liquid + render 'modules/common-styling/style-guide/initialization' + render 'modules/common-styling/style-guide/colors' + render 'modules/common-styling/style-guide/gradients' + render 'modules/common-styling/style-guide/icons' + render 'modules/common-styling/style-guide/spacings' + render 'modules/common-styling/style-guide/fonts' + render 'modules/common-styling/style-guide/headings' + render 'modules/common-styling/style-guide/text-styles' + render 'modules/common-styling/style-guide/links' + render 'modules/common-styling/style-guide/buttons' + render 'modules/common-styling/style-guide/forms' + render 'modules/common-styling/style-guide/boxes' + render 'modules/common-styling/style-guide/tables' + render 'modules/common-styling/style-guide/toasts' + render 'modules/common-styling/style-guide/tags' + render 'modules/common-styling/style-guide/navigation' + render 'modules/common-styling/style-guide/upload' + %} +
    +
    + + diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/content/alert.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/content/alert.liquid new file mode 100644 index 00000000..6e8422e9 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/content/alert.liquid @@ -0,0 +1,37 @@ +{% doc %} + @param {string} type - one of success, error, warning, info + @param {string} content - alert content +{% enddoc %} +{% comment %} + + alert box + + type - (string) one of 'success', 'error', 'warning', 'info' (default: 'info') + content - (string) card description + +{% endcomment %} + + +{% liquid + + assign type = type | default: 'info' + +%} + + +
    + {% case type %} + {% when 'info' %} + {% render 'modules/common-styling/icon', icon: 'info', class: null %} + {% when 'warning' %} + {% render 'modules/common-styling/icon', icon: 'warning', class: null %} + {% when 'error' %} + {% render 'modules/common-styling/icon', icon: 'delete', class: null %} + {% when 'success' %} + {% render 'modules/common-styling/icon', icon: 'checkBadge', class: null %} + {% endcase %} + + + {{ content | html_safe }} + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/content/card.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/content/card.liquid new file mode 100644 index 00000000..23c32222 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/content/card.liquid @@ -0,0 +1,55 @@ +{% doc %} + @param {string} url - where the card should link to + @param {string} image - image object with versions or URL string + @param {string} title - card title + @param {string} content - card description + @param {string} footer - secondary related content + @param {boolean} highlighted - whether to distinguish the card +{% enddoc %} +{% comment %} + + content card with an image, title and a description + + url - (string) where the card should link to + image - (object or URL) platformOS generated object with image versions or just an URL to specific image + title - (string) card title that will be linked + content - (string) card description + footer - (string) secondary related content + + highlighted - (bool) should the card be distinguished among other cards + +{% endcomment %} + + + + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/content/dialog.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/content/dialog.liquid new file mode 100644 index 00000000..1ef69849 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/content/dialog.liquid @@ -0,0 +1,29 @@ +{% doc %} + @param {string} title - dialog title + @param {string} content - html content for the dialog + @param {string} id - unique ID for the dialog +{% enddoc %} +{% comment %} + + modal dialog that is hidden by default and can be shown with a button + + id - (string) unique ID for the dialog + title - (string) dialog title + content - (string) html content for the dialog + +{% endcomment %} + + + + +
    + {% if title %} +

    {{ title }}

    + {% endif %} + +
    + {% print content %} +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_input_handler.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_input_handler.liquid new file mode 100644 index 00000000..ee0986ba --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_input_handler.liquid @@ -0,0 +1,7 @@ +{% doc %} + @param {string} name - form input name used for error element ID + @param {object} errors - list of validation errors +{% enddoc %} +{% if errors %} + aria-invalid="true" aria-describedby="pos-form-{{ name }}-error" +{% endif %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_list.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_list.liquid new file mode 100644 index 00000000..d1989557 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/error_list.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {object} errors - list of validation errors to display + @param {string} name - form input name used for error element ID +{% enddoc %} +{% if errors %} +
      + {% for error in errors %} +
    • {{ error }}
    • + {% endfor %} +
    +{% endif %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/hcaptcha.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/hcaptcha.liquid new file mode 100644 index 00000000..da174f86 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/hcaptcha.liquid @@ -0,0 +1,13 @@ +{% if context.constants.VERIFY_HCAPTCHA == "true" %} +
    + +
    + + {% #render 'theme/simple/field_error', errors: object.errors.hcaptcha %} +
    + {% elsif context.environment == 'staging' %} + + + + {% endif %} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/markdown.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/markdown.liquid new file mode 100644 index 00000000..087ee18f --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/markdown.liquid @@ -0,0 +1,52 @@ +{% doc %} + @param {string} id - unique id for the module + @param {string} value - pre-filled content for the textarea + @param {number} minlength - minimum number of characters allowed + @param {number} maxlength - maximum number of characters allowed + @param {string} name - name for the textarea + @param {object} presigned_upload - presigned upload data for file uploads +{% enddoc %} +{% comment %} + + Rich text editor + + Arguments: + - id (string) unique id for the module + - name (string, required) name for the + + +
      +
    • {{ 'modules/common-styling/form.minimum_length_validation' | t: count: minlength }}
    • +
    • {{ 'modules/common-styling/form.maximum_length_validation' | t: count: maxlength }}
    • +
    + + + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/multiselect.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/multiselect.liquid new file mode 100644 index 00000000..0193905f --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/multiselect.liquid @@ -0,0 +1,109 @@ +{% doc %} + @param {string} id - unique ID of the input + @param {object} list - array of objects with value and label properties + @param {object} selected - array of selected values + @param {string} view - display view mode + @param {string} placeholder - translation key for placeholder + @param {string} placeholder_filter - translation key for filter placeholder + @param {string} placeholder_empty - translation key for empty filter results + @param {boolean} combine_selected - combine selected items into single element + @param {boolean} showFilter - show filter text input + @param {string} name - name for the multiselect checkboxes + @param {string} form - form element the multiselect belongs to + @param {boolean} required - whether at least one option is required + @param {boolean} multiline - extend list vertically for overflow +{% enddoc %} +{% comment %} + Multiselect input component + + Arguments: + - id (string) unique ID of the input + + - list (array, required) an array of objects with items to show, must include 'value' and 'label' + [ { value: 'item1value', label: 'Item 1 label' }, { value: 'item2value', label: 'Item 2 label' } ] + - selected (array) array with selected values (the same as in the 'list') + [ 'item2value' ] + + - form (string) the
    element that the multiselect corresponds to + - name (string) the name="" property for the multiselect checkboxes (no need for adding [] at the end) + - required (bool, false) at least one option is required + + - combine_selected (bool, false) if you want to combine selected items into a single element ('2 selected' instead of displaying names) + - multiline (bool, false) if you want the list to extend vertically if there are more items than fit the single line + - showFilter (bool, false) allow to filter the list of options with a text input + + - placeholder (string, default) translation key for the main select input placeholder + - placeholder_filter (string, default) translation key for the filter input placeholder + - placeholder_empty (string, default) translation key shown when the filter brings no results +{% endcomment %} + + + +{% unless list %} + +{% endunless %} + + + +{% liquid + assign list = list | default: '[]' + + if selected[0] + assign selected = selected | default: '[]' + endif + + assign view = view | default: 'list' + + assign placeholder = placeholder | default: 'modules/common-styling/form.select' + assign placeholder_filter = placeholder_filter | default: 'modules/common-styling/form.type_to_filter' + assign placeholder_empty = placeholder_empty | default: 'modules/common-styling/form.no_filter_results' +%} + +
    + + + +
    + {% if showFilter %} + + {% endif %} +
      + {% for item in list %} +
    • + +
    • + {% endfor %} +
    + {% if showFilter %} + {{ placeholder_empty | t }} + {% endif %} +
    + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/password.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/password.liquid new file mode 100644 index 00000000..055a3d0a --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/password.liquid @@ -0,0 +1,58 @@ +{% doc %} + @param {string} name - form input name + @param {string} id - input id + @param {string} value - value in the input + @param {boolean} meter - whether to show password strength meter + @param {string} class - class list added to the input container +{% enddoc %} +{% comment %} + + password input with an optional strength meter + + arguments: + name - form input name (string) + id - input id (string) + value - value in the input (string) + class - class list added to the input container (string) + meter - if you want the password weakness to be shown (bool) + +{% endcomment %} + + + +
    + +
    + {% comment %} input {% endcomment %} + + + {% comment %} show/hide password toggle {% endcomment %} + +
    + + {% comment %} strength meter {% endcomment %} + {% if meter %} +
    + +
    + +
    + {{ 'modules/common-styling/password.weak' | t }} + {{ 'modules/common-styling/password.medium' | t }} + {{ 'modules/common-styling/password.strong' | t }} +
    + {% endif %} + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/forms/upload.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/upload.liquid new file mode 100644 index 00000000..e3e0d0cd --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/forms/upload.liquid @@ -0,0 +1,69 @@ +{% doc %} + @param {boolean} image_editor_enabled - whether to enable image editor + @param {string} allowed_file_types - allowed file types + @param {number} max_number_of_files - maximum number of files to upload + @param {string} aspect_ratio - aspect ratio for image editor cropping + @param {string} name - name for the input with uploaded file URLs + @param {object} files - previously uploaded files to display + @param {string} id - unique id for the upload module + @param {object} presigned_upload - presigned upload data +{% enddoc %} +{% comment %} + + File uploading + + Arguments: + - id (string) unique id for the upload module + - name (string, required) name for the with the URLs of uploaded images + - presigned_upload (object, required) presigned upload data (upload url and payload) returned from a `property_upload_presigned_url` query + - files (array of objects) files that were uploaded before for this upload module and you want them to be shown as already uploaded, should be a result of querying property_upload + + - image_editor_enabled (boolean) whether to enable image editor for uploaded images + - allowed_file_types (array of strings) allowed file types, e.g. ['image/*', '.jpg', '.jpeg', '.png', '.gif'] + - aspect_ratio (float) aspect ratio for the image editor cropping tool, e.g. 1 for square, 1.78 for widescreen + +{% endcomment %} + + +{% liquid + + assign image_editor_enabled = image_editor_enabled | default: false + assign allowed_file_types = allowed_file_types | default: null + assign max_number_of_files = max_number_of_files | default: null + assign aspect_ratio = aspect_ratio | default: null + +%} + + +
    + +
    + + + + + + {% for file in files %} + {% if file.file.url %} + + {% endif %} + {% endfor %} + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/icon.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/icon.liquid new file mode 100644 index 00000000..b5b70862 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/icon.liquid @@ -0,0 +1,163 @@ +{% doc %} + @param {string} icon - name of the icon to render + @param {string} class - CSS class to apply to the icon +{% enddoc %} +{% comment %} + + List of icons in SVG format + + Params: + - icon name (string) + - class (string, optional) + +{% endcomment %} + + +{% liquid + assign class = class | default: '' +%} + +{% capture attrs %} + viewBox="0 0 24 24" + fill="none" + class="pos-icon {{ class }}" + focusable="false" + role="img" + xmlns="http://www.w3.org/2000/svg" +{% endcapture %} + + +{% case icon %} + + {% when 'plus', 'all' %} + + + {% when 'x', 'all' %} + + + {% when 'dashUp', 'all' %} + + + {% when 'dashDown', 'all' %} + + + {% when 'dashRight', 'all' %} + + + {% when 'dashLeft', 'all' %} + + + {% when 'pencil', 'all' %} + + + {% when 'check', 'all' %} + + + {% when 'dots', 'all' %} + + + {% when 'menu', 'all' %} + + + {% when 'expand', 'all' %} + + + {% when 'eye', 'all' %} + + + {% when 'eyeStriked', 'all' %} + + + {% when 'search' or 'all' %} + + + {% when 'bell', 'all' %} + + + {% when 'mail', 'all' %} + + + {% when 'messagesTyping', 'all' %} + + + {% when 'messageBubblesDouble', 'all' %} + + + {% when 'dashboard', 'all' %} + + + {% when 'groups', 'all' %} + + + {% when 'binocular', 'all' %} + + + {% when 'calendar', 'all' %} + + + {% when 'user', 'all' %} + + + {% when 'users', 'all' %} + + + {% when 'userAdd', 'all' %} + + + {% when 'userRemove', 'all' %} + + + {% when 'cog', 'all' %} + + + {% when 'bookmarksDocument', 'all' %} + + + {% when 'info', 'all' %} + + + {% when 'warning', 'all' %} + + + {% when 'delete', 'all' %} + + + {% when 'checkBadge', 'all' %} + + + {% when 'leave', 'all' %} + + + {% when 'location', 'all' %} + + + {% when 'globe', 'all' %} + + + {% when 'clock', 'all' %} + + + {% when 'crown', 'all' %} + + + {% when 'crownRotated', 'all' %} + + + {% when 'linkedin', 'all' %} + + + {% when 'heart', 'all' %} + + + {% when 'heartFull', 'all' %} + + + + + + {% else %} + + +{% endcase %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/init.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/init.liquid new file mode 100644 index 00000000..5d2b0003 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/init.liquid @@ -0,0 +1,182 @@ +{% doc %} + @param {boolean} reset - whether to include the CSS reset stylesheet +{% enddoc %} +{% if reset %} + +{% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/navigation/collapsible.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/navigation/collapsible.liquid new file mode 100644 index 00000000..f3c48f7a --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/navigation/collapsible.liquid @@ -0,0 +1,61 @@ +{% doc %} + @param {boolean} inert - whether to render without collapsible class + @param {boolean} active - active URL to highlight + @param {object} items - array of navigation items with url, label, children +{% enddoc %} +{% liquid + assign inert = inert | default: false + assign active = active | default: false +%} + + +{% capture output %} + + + + {% for item in items %} + + + {% if item.url %}{% endif %} + {{ item.label }} + {% if item.url %}{% endif %} + + {% if item.children.size > 0 %} + + {% endif %} + + {% if item.children.size > 0 %} + {% liquid + assign active_child = item.children | array_detect: url: active + + unless active_child + for child in item.children + assign active_child = child.children | array_detect: url: active + if active_child + break + endif + endfor + endunless + %} + +
    + {% liquid + function render_submenu = 'modules/common-styling/navigation/collapsible', items: item.children, inert: true, active: active + print render_submenu + %} +
    + {% endif %} + + + {% endfor %} + + + +{% endcapture %} + + +{{ output | html_safe }} +{% return output %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/pagination.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/pagination.liquid new file mode 100644 index 00000000..1b97492f --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/pagination.liquid @@ -0,0 +1,64 @@ +{% doc %} + @param {number} total_pages - how many total pages available +{% enddoc %} +{% comment %} + + numbered pagination with arrows if the number of pages is large + + total pages - (int) how many total pages available + +{% endcomment %} + + +{% liquid + assign current = context.location.search.page | to_positive_integer: 1 + + assign url = '?' + if context.location.search + assign query_string = context.location.search + assign _ = query_string | hash_delete_key: 'page' + + if query_string.size > 0 + assign query_string = query_string | querify + assign url = url | append: query_string | append: '&page=' + else + assign url = url | append: 'page=' + endif + endif +%} + +{% if total_pages > 1 %} + + + +{% endif %} diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/boxes.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/boxes.liquid new file mode 100644 index 00000000..c520830a --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/boxes.liquid @@ -0,0 +1,58 @@ +
    +

    Boxes

    + +
    +
    +
    +
    The quick brown fox jumps over the lazy dog
    +
    +{% capture code %}{% raw %} +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    class
    pos-card
    +
    props
    --pos-padding-card, --pos-radius-card, --pos-color-content-background
    +
    +
    +
    +
    +
    The quick brown fox jumps over the lazy dog
    +
    +{% capture code %}{% raw %} +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    class
    pos-card pos-card-highlighted
    +
    props
    --pos-padding-card, --pos-radius-card, --pos-color-highlight-background
    +
    +
    +
    + +

    Content card

    +
    +
    + {% render 'modules/common-styling/content/card', url: '/', image: 'https://picsum.photos/1000/400', title: 'Lorem ipsum dolor sit amet', content: 'Quisque vel velit mi. Proin malesuada iaculis viverra. Vestibulum tristique sollicitudin rhoncus. Vivamus sollicitudin nisi in lorem gravida aliquam.', footer: '
    • Item
    • Item
    Aside item', highlighted: null %} +{% capture code %}{% raw %} +{% render 'modules/common-styling/content/card', url: '/', image: 'https://picsum.photos/1000/400', title: 'Title', content: 'Content', footer: '
    • Item
    • Item
    Aside item' %} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + {% render 'modules/common-styling/content/card', url: '/', image: 'https://picsum.photos/1000/400?random=2', title: 'Lorem ipsum dolor sit amet', content: 'Quisque vel velit mi. Proin malesuada iaculis viverra. Vestibulum tristique sollicitudin rhoncus. Vivamus sollicitudin nisi in lorem gravida aliquam.', footer: 'Cras lacinia lorem', highlighted: true %} +{% capture code %}{% raw %} +{% render 'modules/common-styling/content/card', url: '/', image: 'https://picsum.photos/1000/400', title: 'Title', content: 'Content', footer: 'Footer', highlighted: true %} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/buttons.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/buttons.liquid new file mode 100644 index 00000000..1addac46 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/buttons.liquid @@ -0,0 +1,158 @@ +
    + +

    Buttons

    + +
    +
    +
    +

    Default

    + + + +
    +
    Class
    pos-button
    +
    +
    +{% capture code %}{% raw %} + +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +

    Primary

    + + + +
    +
    Class
    pos-button pos-button-primary
    +
    +
    +{% capture code %}{% raw %} + +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    + +
    +
    +

    Default small

    + + + +
    +
    Class
    pos-button pos-button-small
    +
    +
    +{% capture code %}{% raw %} + +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +

    Primary small

    + + + +
    +
    Class
    pos-button pos-button-small pos-button-small
    +
    +
    +{% capture code %}{% raw %} + +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + + {% render 'modules/common-styling/tip', content: 'When overwriting the <button> classes, please remember to also overwrite the debug classes used in the style guide: pos-debug-button-hover, pos-debug-button-active, pos-debug-button-focus-visible.' %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    DefaultPrimaryDefault smallPrimary small
    Enabled
    Hover
    Active
    Focused
    Disabled
    Icon + + + + + + + +
    LinkLinkLinkLinkLink
    + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/colors.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/colors.liquid new file mode 100644 index 00000000..f2ab08f3 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/colors.liquid @@ -0,0 +1,382 @@ +
    +

    Colors

    + +

    General content

    +
      +
    • +

      Page background

      +
      +
      +
      + --pos-color-page-background +
      + # +
      +
      +
    • +
    • +

      Content background

      +
      +
      +
      + --pos-color-content-background +
      + # +
      +
      +
    • +
    • +

      Content text & icons

      +
      +
      +
      --pos-color-content-text
      + # +
      +
      +
      --pos-color-content-icon
      + # +
      +
      +
      --pos-color-content-text-supplementary
      + # +
      +
      +
      --pos-color-content-text-prominent
      + # +
      +
      +
    • +
    • +

      Borders & separators

      +
      +
      +
      --pos-color-frame
      + # +
      +
      +
    • +
    • +

      Highlighted elements

      +
      +
      +
      --pos-color-highlight-background
      + # +
      +
      +
      --pos-color-highlight-text
      + # +
      +
      +
    • +
    • +

      Standout sections, call to actions

      +
      +
      +
      --pos-color-standout-background
      + # +
      +
      +
      --pos-color-standout-background-hover
      + # +
      +
      +
      --pos-color-standout-text
      + # +
      +
      +
    • +
    + +

    Interactive elements

    +
      +
    • +

      Links

      +
      +
      +
      --pos-color-interactive
      + # +
      +
      +
      --pos-color-interactive-hover
      + # +
      +
      +
      --pos-color-interactive-active
      + # +
      +
      +
      --pos-color-interactive-disabled
      + # +
      +
      +
    • + +
    • +

      Primary buttons

      +
      +
      +
      --pos-color-button-primary-background
      + # +
      +
      +
      --pos-color-button-primary-frame
      + # +
      +
      +
      --pos-color-button-primary-text
      + # +
      +
      +
      +
      +
      --pos-color-button-primary-hover-background
      + # +
      +
      +
      --pos-color-button-primary-hover-frame
      + # +
      +
      +
      --pos-color-button-primary-hover-text
      + # +
      +
      +
      +
      +
      --pos-color-button-primary-active-background
      + # +
      +
      +
      --pos-color-button-primary-active-frame
      + # +
      +
      +
      --pos-color-button-primary-active-text
      + # +
      +
      +
      +
      +
      --pos-color-button-primary-disabled-background
      + # +
      +
      +
      --pos-color-button-primary-disabled-frame
      + # +
      +
      +
      --pos-color-button-primary-disabled-text
      + # +
      +
      +
    • + +
    • +

      Secondary buttons

      +
      +
      +
      --pos-color-button-secondary-background
      + # +
      +
      +
      --pos-color-button-secondary-frame
      + # +
      +
      +
      --pos-color-button-secondary-text
      + # +
      +
      +
      +
      +
      --pos-color-button-secondary-hover-background
      + # +
      +
      +
      --pos-color-button-secondary-hover-frame
      + # +
      +
      +
      --pos-color-button-secondary-hover-text
      + # +
      +
      +
      +
      +
      --pos-color-button-secondary-active-background
      + # +
      +
      +
      --pos-color-button-secondary-active-frame
      + # +
      +
      +
      --pos-color-button-secondary-active-text
      + # +
      +
      +
      +
      +
      --pos-color-button-secondary-disabled-background
      + # +
      +
      +
      --pos-color-button-secondary-disabled-frame
      + # +
      +
      +
      --pos-color-button-secondary-disabled-text
      + # +
      +
      +
    • +
    + +

    Browser UI

    +
      +
    • +

      Focused elements highlight

      +
      +
      +
      --pos-color-focused
      + # +
      +
      +
    • +
    • +

      Text selection highlight

      +
      +
      +
      --pos-color-selection-background
      + # +
      +
      +
      --pos-color-selection-text
      + # +
      +
      +
    • +
    + +

    Forms

    +
      +
    • +

      Placeholder text

      +
      +
      +
      --pos-color-input-placeholder
      + # +
      +
      +
    • +
    • +

      Input field

      +
      +
      +
      --pos-color-input-background
      + # +
      +
      +
      --pos-color-input-frame
      + # +
      +
      +
      --pos-color-input-text
      + # +
      +
      +
      +
      +
      --pos-color-input-hover-background
      + # +
      +
      +
      --pos-color-input-hover-frame
      + # +
      +
      +
      --pos-color-input-hover-text
      + # +
      +
      +
      +
      +
      --pos-color-input-active-background
      + # +
      +
      +
      --pos-color-input-active-frame
      + # +
      +
      +
      --pos-color-input-active-text
      + # +
      +
      +
      +
      +
      --pos-color-input-disabled-background
      + # +
      +
      +
      --pos-color-input-disabled-frame
      + # +
      +
      +
      --pos-color-input-disabled-text
      + # +
      +
      +
    • +
    + +

    Utility

    +
      +
    • +

      Statuses

      +
      +
      +
      --pos-color-important
      + # +
      +
      +
      --pos-color-important-hover
      + # +
      +
      +
      --pos-color-important-disabled
      + # +
      +
      +
      +
      +
      --pos-color-warning
      + # +
      +
      +
      --pos-color-warning-hover
      + # +
      +
      +
      --pos-color-warning-disabled
      + # +
      +
      +
      +
      +
      --pos-color-confirmation
      + # +
      +
      +
      --pos-color-confirmation-hover
      + # +
      +
      +
      --pos-color-confirmation-disabled
      + # +
      +
      +
    • +
    + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/fonts.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/fonts.liquid new file mode 100644 index 00000000..a6d299af --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/fonts.liquid @@ -0,0 +1,68 @@ +
    +

    Fonts

    + +
    +
    +
    +

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. In euismod aliquet nisi euismod eleifend. Phasellus justo tellus, aliquet ac aliquam ut, dictum eu augue.

    +

    Nullam vitae ex sed ligula convallis suscipit. Maecenas et neque facilisis.

    +
    + + + Aa +
      +
    • Light
    • +
    • Regular
    • +
    • Medium
    • +
    • Semi Bold
    • +
    • Bold
    • +
    + +
    +
    +
    Property
    --pos-font-default
    +
    Font family
    +
    Default font size
    +
    +
    + +
    +
    +

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. In euismod aliquet nisi euismod eleifend. Phasellus justo tellus, aliquet ac aliquam ut, dictum eu augue.

    +

    Nullam vitae ex sed ligula convallis suscipit. Maecenas et neque facilisis.

    +
    + + + Aa +
      +
    • Light
    • +
    • Regular
    • +
    • Medium
    • +
    • Semi Bold
    • +
    • Bold
    • +
    + +
    +
    +
    Property
    --pos-font-heading
    +
    Font family
    +
    Default font size
    +
    +
    +
    + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/forms.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/forms.liquid new file mode 100644 index 00000000..a4bd6920 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/forms.liquid @@ -0,0 +1,483 @@ +
    +

    Forms

    +

    There are two ways for styling form controlls. You can add a pos-form class to a container and make all the child inputs styled automatically or you can add one of the following classes to any single input to style it separately.

    + +

    Basic example

    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +{% capture code %}{% raw %} +
    +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'styleguide-example-error', errors: errors['styleguide-form-example-a'] %} +
    +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'styleguide-example-error', errors: errors['styleguide-form-example-b'] %} +
    +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'styleguide-example-error', errors: errors['styleguide-form-example-c'] %} +
    +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + + +

    Containers

    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    Class
    pos-form
    +
    +

    Used for complex forms that needs more manual customized styling. No automatic labels styling, no automatic spacing between elements.

    +
    + +
    +
    +
    +
    +
    +
    +
    +
    Class
    pos-form pos-form-simple
    +
    +

    Used for simple forms that can be styled automatically. Styles the labels and spacing between items as well. You can just throw this class onto the container and forget about styling each separate control.

    +
    + +
    + +

    Rows

    + +
    +
    +
    +
    Class
    pos-form-fieldset
    +
    Properties
    --pos-gap-text-text
    +
    +{% capture code %}{% raw %} +
    + +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Class
    pos-form-fieldset-combined
    +
    +{% capture code %}{% raw %} +
    + +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    Form actions

    +
    +
    +
    +
    +
    +
    +{% capture code %}{% raw %} +
    + +
    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + + +

    Labels

    + +
    + {% render 'modules/common-styling/tip', content: 'Labels that are placed in a fieldset that has a reqired input will automatically be marked with an asterisk.' %} +
    +
    +
    +
    + + +
    +
    +
    + {% capture code %}{% raw %} + + {% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +
    + +
    +

    Radio

    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    +

    Checkbox

    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    + + +

    Text inputs

    + +
    + +
    +
    + +
    +
    Class
    pos-form-input
    +
    +
    +{% capture code %}{% raw %} + +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + + {% render 'modules/common-styling/tip', content: 'When overwriting the <input> classes, please remember to also overwrite the debug classes used in the style guide: pos-debug-form-input-hover, pos-debug-form-input-focus-visible.' %} +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PlaceholderFilled
    Default
    Hover
    Focused
    Disabled
    Error
    +
    + +
    + +
    + +
    +
    + +
    +
    Class
    pos-form-input
    +
    +
    + {% capture code %}{% raw %} + + {% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + + {% render 'modules/common-styling/tip', content: 'When overwriting the <input> classes, please remember to also overwrite the debug classes used in the style guide: pos-debug-form-input-hover, pos-debug-form-input-focus-visible.' %} +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PlaceholderFilled
    Default
    Hover
    Focused
    Disabled
    Error
    +
    +
    + + +

    Markdown editor

    + {% render 'modules/common-styling/forms/markdown', id: 'styleguide-markdown-editor', name: 'styleguide-markdown-editor', value: null, minlength: null, maxlength: null, presigned_upload: null %} + +{% capture code %}{% raw %} +{% render 'modules/common-styling/forms/markdown', + id: 'styleguide-markdown-editor', + name: 'styleguide-markdown-editor', + presigned_upload: presigned_upload +%} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + + +

    Password input

    + +
    +
    +
    +
    name
    Input name attribute string
    +
    id
    Input id attribute string
    +
    value
    Current input value string
    +
    class
    Class list added to input container string
    +
    meter
    If you want to show the password strength meter bool
    +
    + {% render 'modules/common-styling/tip', content: 'Strong passwords consists of small and capitalized letters, numbers, special signs and are at least 6 characters long. Remember to provide clear instructios for your users.' %} +
    +
    +
    + {% render 'modules/common-styling/forms/password', name: 'styleguide-form-password-test', id: 'styleguide-form-password-test', value: '123456', meter: true, class: null %} +
    +{% capture code %}{% raw %} +{% render 'modules/common-styling/forms/password', + name: 'styleguide-form-password-test', + value: '123', + id: 'styleguide-form-password-test', + meter: true +%} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + + +

    Select

    + +
    +
    +
    +
    class
    pos-form-select
    +
    +
    +
    + + + +
    +
    + + +

    Multiselect

    + +
    +
    +
    +
    id
    Unique ID for the input string
    +
    list
    +
    + an array of objects with items to show, must include 'value' and 'label' array
    + [ { value: 'item1value', label: 'Item 1 label' }, { value: 'item2value', label: 'Item 2 label' } ] +
    +
    selected
    +
    + array with selected values (the same as in the 'list') array
    + [ 'item2value' ] +
    +
    form
    the <form> element that the multiselect corresponds to string
    +
    name
    the name="" property for the multiselect checkboxes string
    +
    required
    at least one option is required bool
    +
    combine_selected
    if you want to combine selected items into a single element ('2 selected' instead of displaying names) bool
    +
    multiline
    if you want the list to extend vertically if there are more items than fit the single line bool
    +
    showFilter
    allow to filter the list of options with a text input bool
    +
    placeholder
    translation key for the main select input placeholder string
    +
    placeholder_filter
    translation key for the filter input placeholder string
    +
    placeholder_empty
    translation key shown when the filter brings no results string
    +
    +
    +
    +
    + {% liquid + assign example_list = '' | split: '' + + for i in (0..10) + assign value = 'value' | append: i + assign label = 'Label for value ' | append: i + assign example_item = {"value": value, "label": label} + assign example_list << example_item + assign selected = ["value0", "value5", "value6"] + endfor + %} + {% render 'modules/common-styling/forms/multiselect', name: 'styleguide-form-multiselect-test-1', id: 'styleguide-form-multiselect-test-1', list: example_list, showFilter: true, combine_selected: true, selected: selected, required: null, multiline: null, form: null, view: null, placeholder: null, placeholder_filter: null, placeholder_empty: null %} + {% render 'modules/common-styling/forms/multiselect', name: 'styleguide-form-multiselect-test-2', id: 'styleguide-form-multiselect-test-2', list: example_list, showFilter: true, selected: selected, required: null, multiline: null, combine_selected: null, form: null, view: null, placeholder: null, placeholder_filter: null, placeholder_empty: null %} + {% render 'modules/common-styling/forms/multiselect', name: 'styleguide-form-multiselect-test-3', id: 'styleguide-form-multiselect-test-3', list: example_list, showFilter: false, multiline: true, selected: selected, required: null, combine_selected: null, form: null, view: null, placeholder: null, placeholder_filter: null, placeholder_empty: null %} + {% render 'modules/common-styling/forms/multiselect', name: 'styleguide-form-multiselect-test-4', id: 'styleguide-form-multiselect-test-4', list: example_list, selected: selected, showFilter: true, combine_selected: true, required: null, multiline: null, form: null, view: null, placeholder: null, placeholder_filter: null, placeholder_empty: null %} +
    +{% capture code %}{% raw %} +{% render 'modules/common-styling/forms/multiselect', + name: 'styleguide-form-multiselect-test', + id: 'styleguide-form-multiselect-test' +%} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + + +

    Error handling

    + +

    There are two partials that can be helpful when dealing with forms validation. One can be added to the input itself to handle usability code and the other can output the error message.

    + + {% liquid + assign errors = { "styleguide-example-error": ["This is a field with two errors", "This is the second error"] } + %} +
    + + {% render 'modules/common-styling/forms/error_list', name: 'styleguide-example-error', errors: errors['styleguide-example-error'] %} +{% capture code %}{% raw %} + + +{% render 'modules/common-styling/forms/error_list', name: 'styleguide-example-error', errors: errors['styleguide-example-error'] %} +{% endraw %}{% endcapture %} +
    +
    +
    {{ code | lstrip | rstrip }}
    +
    + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/gradients.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/gradients.liquid new file mode 100644 index 00000000..828be522 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/gradients.liquid @@ -0,0 +1,14 @@ +
    +

    Gradients and shadows

    + +

    Increasing text legibility over images

    +

    When placing text on top of an image, you may need to improve legibility and ensure the contrast stays high. You can achieve this with the eased gradient available through the CSS custom property --pos-gradient-legibility or by using the pre-defined class pos-increaseLegibility. Use the class with caution, as it relies on relative positioning and may affect your layout in some cases.

    +
    +
    Class
    pos-increaseLegibility
    +
    Properties
    --pos-gradient-legibility
    +
    + + +

    The quick brown fox

    +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/headings.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/headings.liquid new file mode 100644 index 00000000..44c6ff84 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/headings.liquid @@ -0,0 +1,96 @@ +
    +

    Headings

    + +

    Heading 1

    +
    +
    +
    Class
    pos-heading-1
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + The quick brown fox jumps over the lazy dog + +{% capture code %}{% raw %} +

    The quick brown fox jumps over the lazy dog

    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +

    Heading 2

    +
    +
    +
    Class
    pos-heading-2
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + The quick brown fox jumps over the lazy dog + +{% capture code %}{% raw %} +

    The quick brown fox jumps over the lazy dog

    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +

    Heading 3

    +
    +
    +
    Class
    pos-heading-3
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + The quick brown fox jumps over the lazy dog + +{% capture code %}{% raw %} +

    The quick brown fox jumps over the lazy dog

    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +

    Heading 4

    +
    +
    +
    Class
    pos-heading-4
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + The quick brown fox jumps over the lazy dog + +{% capture code %}{% raw %} +

    The quick brown fox jumps over the lazy dog

    +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/icons.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/icons.liquid new file mode 100644 index 00000000..5f1ae919 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/icons.liquid @@ -0,0 +1,12 @@ +
    +

    Icons

    +{% capture code %}{% raw %} +{% render 'modules/common-styling/icon', icon: 'dashDown', class: null %} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
      + {% render 'modules/common-styling/icon', icon: 'all', class: null %} +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/initialization.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/initialization.liquid new file mode 100644 index 00000000..d89341b9 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/initialization.liquid @@ -0,0 +1,32 @@ +
    +

    Initialization

    +
    +
    +

    All of the following CSS (except CSS custom properties) are scoped to container that uses pos-app class. You can apply this class to the root html tag to style your entire app, or add it to a specific container to limit the scope.

    +{% capture code %}{% raw %} + +… +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + +

    Dark mode

    +

    To enable dark mode, add the pos-theme-darkEnabled class to the same container. This will switch the theme automatically based on the user’s system settings. If you want to force dark mode manually, use the pos-theme-dark class instead.

    +{% capture code %}{% raw %} + +… +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    +
    Initialize common styling class
    pos-app
    +
    Enable automatic dark mode class
    pos-theme-darkEnabled
    +
    Manually turn on dark theme class
    pos-theme-dark
    +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/links.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/links.liquid new file mode 100644 index 00000000..1bc7a0e1 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/links.liquid @@ -0,0 +1,48 @@ + diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/navigation.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/navigation.liquid new file mode 100644 index 00000000..56c8959f --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/navigation.liquid @@ -0,0 +1,219 @@ + diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/spacings.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/spacings.liquid new file mode 100644 index 00000000..013aee30 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/spacings.liquid @@ -0,0 +1,31 @@ +
    + +

    Spacings

    + +
    + +
    +
    +
    +
    +
    +
    +
    Class
    pos-gap-section-section, pos-mt-section-section
    +
    Properties
    --pos-gap-section-section
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    Class
    pos-gap-text-text, pos-mt-text-text
    +
    Properties
    --pos-gap-text-text
    +
    +
    + +
    + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tables.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tables.liquid new file mode 100644 index 00000000..960f8ca1 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tables.liquid @@ -0,0 +1,159 @@ +
    +

    Tables

    + +
    + {% capture code %}{% raw %} +
    +
    +
    Column 1
    +
    Column 2
    +
    Column 3
    +
    +
    +
      +
    • + Column 1 + Content 1 +
    • +
    • + Column 1 + Content 2 +
    • +
    • + Column 3 + 321 +
    • +
    +
    +
    + {% endraw %}{% endcapture %} +
    +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    +
    +
    +
    Column 1
    +
    Column 2
    +
    Column 3
    +
    +
    +
      +
    • + Column 1 + Content 1 +
    • +
    • + Column 1 + Content 2 +
    • +
    • + Column 3 + 321 +
    • +
    +
      +
    • + Column 1 + Content 2 +
    • +
    • + Column 2 + Content 2 +
    • +
    • + Column 3 + 123 +
    • +
    +
    +
    +
    +
    +
    class
    pos-table
    +
    props
    --pos-padding-cell
    +
    +
    +
    + +
    + {% capture code %}{% raw %} +
    +
    +
    Column 1
    +
    Column 2
    +
    Column 3
    +
    +
    +
      +
    • + Column 1 + Content 1 +
    • +
    • + Column 1 + Content 2 +
    • +
    • + Column 3 + 321 +
    • +
    +
    +
    + {% endraw %}{% endcapture %} +
    +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    +
    +
    +
    Column 1
    +
    Column 2
    +
    Column 3
    +
    +
    +
      +
    • + Column 1 + Content 1 +
    • +
    • + Column 1 + Content 2 +
    • +
    • + Column 3 + 321 +
    • +
    +
      +
    • + Column 1 + Content 2 +
    • +
    • + Column 2 + Content 2 +
    • +
    • + Column 3 + 123 +
    • +
    +
    +
    +
    +
    +
    class
    pos-table
    +
    props
    --pos-padding-cell
    +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tags.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tags.liquid new file mode 100644 index 00000000..c6e977f5 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/tags.liquid @@ -0,0 +1,58 @@ +
    + +

    Tags and badges

    + +
    + +
    +
    Class
    pos-tag
    +
    Modifiers
    pos-tag-confirmation, pos-tag-warning, pos-tag-important, pos-tag-interactive
    +
    Properties
    --pos-radius-tag
    +
    + +
    +
    +
      +
    • Default
    • +
    • Confirmation
    • +
    • Warning
    • +
    • Important
    • +
    • Interactive
    • +
    +
    + {% capture code %}{% raw %} + Confirmation + {% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    + +
    + +

    Tags list

    + +
    + +
    +
    Class
    pos-tags-list
    +
    Properties
    --pos-gap-tag-tag
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/text-styles.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/text-styles.liquid new file mode 100644 index 00000000..fa125cac --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/text-styles.liquid @@ -0,0 +1,78 @@ +
    +

    Text styles

    +

    Sidenote

    +
    +
    +
    Class
    pos-supplementary
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + The quick brown fox jumps over the lazy dog + +{% capture code %}{% raw %} +The quick brown fox jumps over the lazy dog +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +

    Tip

    +
    +
    +
    Class
    pos-tip
    +
    Font family
    +
    Color
    +
    Size
    +
    Weight
    +
    Line height
    +
    +
    + + {% render 'modules/common-styling/tip', content: 'The quick brown fox jumps over the lazy dog' %} + + {% capture code %}{% raw %} + {% render 'modules/common-styling/tip', content: 'The quick brown fox jumps over the lazy dog' %} + {% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    +
    + + +
    + +

    Long text

    + +
    +
    Class
    +
    pos-prose
    +
    + +
    +

    Lorem ipsum dolor

    +

    Phasellus ultricies porta dui ac dapibus. Donec ipsum mi, interdum id turpis vel, aliquam ullamcorper orci.

    +

    Donec accumsan dignissim ligula, vitae imperdiet velit varius a. Phasellus quis elementum nibh. Suspendisse suscipit nisl sit amet quam tincidunt, in fermentum est mattis. Vivamus volutpat sagittis mattis. Praesent eu dapibus enim, in dignissim eros.

    + +
    Donec laoreet vitae
    +

    Cras consequat, ipsum id consectetur elementum, nisl nulla blandit neque, ut commodo neque nisl non sapien. Integer rhoncus nisl semper nulla iaculis fringilla. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

    +

    Morbi venenatis condimentum dolor, sit amet consequat est blandit eu. Nam dapibus mollis cursus.

    +
      +
    1. Maecenas elementum nisi dolor, id viverra orci pretium placerat. Duis a elit quis purus pharetra vehicula. Vestibulum eu venenatis nisi.
    2. +
    3. Ut ante ex, ultrices non commodo ut, dictum at nibh.
    4. +
    +
      +
    • Fusce non est in mi dignissim dictum sit amet a urna.
    • +
    • Nunc in turpis sit amet purus hendrerit tincidunt nec eu quam.
    • +
    +
    + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/toasts.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/toasts.liquid new file mode 100644 index 00000000..09dc782f --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/toasts.liquid @@ -0,0 +1,66 @@ +
    +

    Toasts

    + +
    +
    +

    A standard platformOS way of showing toast notifications would be to store and get the messages in the session.

    +

    Adding the following code to your application `layout` file will initialize the module:

    + + {% capture code %}{% raw %} +{% liquid + function flash = 'modules/core/commands/session/get', key: 'sflash' + if context.location.pathname != flash.from or flash.force_clear + function _ = 'modules/core/commands/session/clear', key: 'sflash' + endif + render 'modules/common-styling/toasts', message: flash.message, severity: flash.severity, autohide: flash.autohide, delay: flash.delay +%} + {% endraw %}{% endcapture %} + +
    +
    {{ code | lstrip | rstrip }}
    +
    + +

    Then, you can use the following JavaScript to show a message on page:

    + {% capture code %}{% raw %} + new pos.modules.toast('[severity]', '[message]'); + {% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    + +
    +
    severity
    how important the message is - error, success, info string
    +
    message
    user-readable message for the toast notification string
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/upload.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/upload.liquid new file mode 100644 index 00000000..eb924834 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/style-guide/upload.liquid @@ -0,0 +1,99 @@ +
    +

    File upload

    + +
    +
    +
    + {% render 'modules/common-styling/forms/upload', + id: 'styleguide-upload-1', + presigned_upload: context.presigned_upload, + name: 'styleguide-upload-1', + image_editor_enabled: null, + allowed_file_types: null, + max_number_of_files: null, + aspect_ratio: null, + files: null + %} +
    +{% capture code %}{% raw %} +{% render 'modules/common-styling/forms/upload', + id: 'styleguide-upload-1', + presigned_upload: presigned_upload, + name: 'styleguide-upload-1' +%} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    + +
    +
    + {% parse_json files %} + [ + { + "id": "1", + "file": { + "url": "https://cdn.staging.oregon.platform-os.com/instances/12434/property_uploads/uploads/upload/ba62e7f2-1217-4d5c-b599-531632062cd7/nowy.png" + } + }, + { + "id": "2", + "file": { + "url": "https://cdn.staging.oregon.platform-os.com/instances/12434/property_uploads/uploads/upload/1dcf38fb-ae99-48a7-a587-5487e9494b41/test.txt" + } + } + ] + {% endparse_json %} + {% render 'modules/common-styling/forms/upload', + id: 'styleguide-upload-2', + presigned_upload: context.presigned_upload, + name: 'styleguide-upload-2', + files: files, + image_editor_enabled: null, + allowed_file_types: null, + max_number_of_files: null, + aspect_ratio: null + %} +
    +{% capture code %}{% raw %} +{% parse_json files %} + [ + { + "id": "1", + "file": { + "url": "https://cdn.staging.oregon.platform-os.com/instances/12434/property_uploads/uploads/upload/ba62e7f2-1217-4d5c-b599-531632062cd7/nowy.png" + } + }, + { + "id": "2", + "file": { + "url": "https://cdn.staging.oregon.platform-os.com/instances/12434/property_uploads/uploads/upload/1dcf38fb-ae99-48a7-a587-5487e9494b41/test.txt" + } + } + ] +{% endparse_json %} + +{% render 'modules/common-styling/forms/upload', + id: 'styleguide-upload-2', + presigned_upload: presigned_upload, + name: 'styleguide-upload-2', + files: files +%} +{% endraw %}{% endcapture %} +
    +
    {{ code | lstrip | rstrip }}
    +
    +
    +
    + +
    +
    name
    string, required name for the <input> with the URLs of uploaded images
    +
    presigned_upload
    object, required presigned upload data (upload url and payload) returned from a property_upload_presigned_url query
    +
    files
    array of objects files that were uploaded before and you want them to be shown as already uploaded, should be a result of querying property_upload
    +
    image_editor_enabled
    bool if you want to allow editing of images inside the upload dashboard
    +
    allowed_file_types
    array of strings allowed file types, e.g. ['image/*', '.jpg', '.jpeg', '.png', '.gif']
    +
    max_number_of_files
    int total number of files that can be selected
    +
    aspect_ratio
    float aspect ratio for the image editor cropping tool, e.g. 1 for square, 1.78 for widescreen
    +
    +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/tip.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/tip.liquid new file mode 100644 index 00000000..810d8795 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/tip.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {string} content - content to display in the tip +{% enddoc %} +
    + +
    + {% liquid + print content + %} +
    +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/toasts.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/toasts.liquid new file mode 100644 index 00000000..765fa2a3 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/toasts.liquid @@ -0,0 +1,38 @@ +{% doc %} + @param {boolean} [autohide] - whether the toast auto-hides + @param {number} [delay] - delay in milliseconds before auto-hide + @param {string} [message] - toast message content + @param {string} [severity] - toast severity level +{% enddoc %} +{% liquid + assign delay = delay | default: 1000 +%} + + + + \ No newline at end of file diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/user/avatar.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/user/avatar.liquid new file mode 100644 index 00000000..715591b6 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/user/avatar.liquid @@ -0,0 +1,42 @@ +{% doc %} + @param {string} size - avatar size (xs, sm, md, lg, xl, 2xl, 3xl) + @param {string} [class] - additional CSS classes + @param {string} name - user display name + @param {string} image_src - URL of the avatar image +{% enddoc %} +{% liquid + assign size = size | default: 'md' + + assign names = name | split: " " + + case size + when 'xs' + assign dimensions = 20 + when 'sm' + assign dimensions = 24 + when 'md' + assign dimensions = 32 + when 'lg' + assign dimensions = 48 + when 'xl' + assign dimensions = 94 + when '2xl' + assign dimensions = 160 + when '3xl' + assign dimensions = 192 + endcase +%} + +{% if image_src == blank %} + +
    + {{ names[0] | slice: 0 }}{{ names[1] | slice: 0 }} +
    + +{% else %} + +
    + +
    + +{% endif %} diff --git a/pos-module-user-invites/modules/common-styling/public/views/partials/user/card.liquid b/pos-module-user-invites/modules/common-styling/public/views/partials/user/card.liquid new file mode 100644 index 00000000..f7b39e46 --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/public/views/partials/user/card.liquid @@ -0,0 +1,56 @@ +{% doc %} + @param {string} last_name - user last name + @param {string} first_name - user first name + @param {string} image_src - URL of the user avatar image + @param {string} url - link to user profile + @param {string} job_title - user job title + @param {string} employer - user employer name + @param {string} location - user location + @param {object} my_profile - current user profile object + @param {string} profile_id - profile ID for follow button + @param {boolean} allow_to_follow - whether to show follow button +{% enddoc %} +{% liquid + assign name = first_name | append: ' ' | append: last_name +%} + + +
    + + + {% render 'modules/common-styling/user/avatar', size: 'xxl', name: name, image_src: image_src %} + {{ name }} + + +
    + {% if job_title != blank %} + {{ job_title }} + {% endif %} + {% if employer != blank %} + {% comment %}platformos-check-disable TranslationKeyExists{% endcomment %} + {{ 'modules/community/app.at' | t: default: 'at' }} {{ employer }}{% if location != blank %}, {{ location }} {% endif %} + {% comment %}platformos-check-enable TranslationKeyExists{% endcomment %} + {% endif %} +
    + + + +
    diff --git a/pos-module-user-invites/modules/common-styling/template-values.json b/pos-module-user-invites/modules/common-styling/template-values.json new file mode 100644 index 00000000..68786eda --- /dev/null +++ b/pos-module-user-invites/modules/common-styling/template-values.json @@ -0,0 +1,7 @@ +{ + "name": "platformOS common styling", + "machine_name": "common-styling", + "type": "module", + "version": "1.37.26", + "dependencies": {} +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/core/generators/command/index.js b/pos-module-user-invites/modules/core/generators/command/index.js new file mode 100644 index 00000000..29fb67e8 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/command/index.js @@ -0,0 +1,46 @@ +import Generator from 'yeoman-generator'; +import path from 'path'; +import pluralize from 'pluralize'; +import fs from 'fs'; + +export default class extends Generator { + constructor(args, opts) { + super(args, opts); + + this.description = 'Generate basic command files with build and check phase'; + this.argument('commandName', { type: String, required: true, description: 'name of the command' }); + this.props = { + commandName: this.options.commandName, + actionName: this.options.commandName.split('/').pop(), + modelName: this.options.commandName.split('/')[0] + }; + } + + writing() { + try{ + this.fs.copyTpl( + this.templatePath('./lib/commands/create.liquid'), + this.destinationPath(`app/lib/commands/${this.props.commandName}.liquid`), + this.props + ) + + this.fs.copyTpl( + this.templatePath('./lib/commands/create/'), + this.destinationPath(`app/lib/commands/${this.props.commandName}/`), + this.props + ) + + this.fs.copyTpl( + this.templatePath('./graphql/create.graphql'), + this.destinationPath(`app/graphql/${this.props.commandName}.graphql`), + this.props + ) + } catch (e) { + console.error(e); + } + } + + end() { + console.log('Command generated'); + } +}; diff --git a/pos-module-user-invites/modules/core/generators/command/templates/graphql/create.graphql b/pos-module-user-invites/modules/core/generators/command/templates/graphql/create.graphql new file mode 100644 index 00000000..0ffb1e58 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/command/templates/graphql/create.graphql @@ -0,0 +1,20 @@ +mutation <%= actionName %>( + # some arguments + # $foo: String! +) { + record: record_create( + record: { + table: "<%= modelName %>" + properties: [ + # { name: "foo" property: $foo } + ] + } + ){ + id + created_at + deleted_at + type: table + + # foo: (name: "foo") + } +} diff --git a/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create.liquid b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create.liquid new file mode 100644 index 00000000..6d7102e8 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create.liquid @@ -0,0 +1,10 @@ +{% liquid + function object = 'commands/<%= commandName %>/build', object: object + function object = 'commands/<%= commandName %>/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: '<%= commandName %>' object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/build.liquid b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/build.liquid new file mode 100644 index 00000000..1fc25913 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/build.liquid @@ -0,0 +1,4 @@ +{% liquid + assign data = {"id": object.id, "name": object.name} + return data +%} diff --git a/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/check.liquid b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/check.liquid new file mode 100644 index 00000000..2c53a6c0 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/command/templates/lib/commands/create/check.liquid @@ -0,0 +1,12 @@ +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'name' + + assign object.valid = c.valid + + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/index.js b/pos-module-user-invites/modules/core/generators/crud/index.js new file mode 100644 index 00000000..dd839bcb --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/index.js @@ -0,0 +1,116 @@ +import Generator from 'yeoman-generator'; +import pluralize from 'pluralize'; +import startCase from 'lodash.startcase'; + +export default class extends Generator { + constructor(args, opts) { + super(args, opts); + + this.description = 'Generate table definition and commands for CRUD with graphql files'; + this.argument('modelName', { type: String, required: true, description: 'name of the table' }); + this.argument('attributes', { type: Array, required: false, description: 'table column names with types', default: "[]" }); + this.option('include-views', { type: Boolean, default: false, description: 'generate pages and partials', hide: 'no' }); + + const attributes = this.options.attributes.map((attr) => { + const values = attr.split(':'); + return { + name: values[0], + nameHuman: startCase(values[0]), + type: values[1] + }; + }); + this.props = { + modelName: this.options.modelName, + modelNamePlural: pluralize(this.options.modelName), + attributes: attributes, + graphqlArgumentMap: { + string: "String", + text: "String", + integer: "Int", + boolean: "Boolean", + float: "Float", + date: "String", + datetime: "String", + array: "[String]" + }, + graphqlArgumentValueMap: { + string: "value", + text: "value", + integer: "value_int", + boolean: "value_boolean", + float: "value_float", + date: "value", + datetime: "value", + array: "value_array" + }, + graphqlPropertyMap: { + string: "property", + text: "property", + integer: "property_int", + boolean: "property_boolean", + float: "property_float", + date: "property", + datetime: "property", + array: "property_array" + } + }; + } + + writing() { + try{ + this.fs.copyTpl( + this.templatePath('./translations/model.yml'), + this.destinationPath(`app/translations/en/${this.props.modelNamePlural}.yml`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./schema/model.yml'), + this.destinationPath(`app/schema/${this.props.modelName}.yml`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./graphql/*.graphql'), + this.destinationPath(`app/graphql/${this.props.modelNamePlural}/`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./lib/queries/model'), + this.destinationPath(`app/lib/queries/${this.props.modelNamePlural}`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./lib/commands/model'), + this.destinationPath(`app/lib/commands/${this.props.modelNamePlural}`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./config.yml'), + this.destinationPath(`app/config.yml`), + this.props + ) + if(this.options['include-views']){ + this.fs.copyTpl( + this.templatePath('./views/pages/model'), + this.destinationPath(`app/views/pages/${this.props.modelNamePlural}`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./views/partials/theme/simple/model'), + this.destinationPath(`app/views/partials/theme/simple/${this.props.modelNamePlural}`), + this.props + ) + this.fs.copyTpl( + this.templatePath('./views/partials/theme/simple/field_error.liquid'), + this.destinationPath(`app/views/partials/theme/simple/field_error.liquid`), + this.props + ) + } + } catch (e) { + console.error(e); + } + } + + end() { + console.log('CRUD generated'); + } +}; diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/config.yml b/pos-module-user-invites/modules/core/generators/crud/templates/config.yml new file mode 100644 index 00000000..45cd4ce1 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/config.yml @@ -0,0 +1,16 @@ +--- +escape_output_instead_of_sanitize: true +graphql_argument_type_mismatch_mode: 'error' +liquid_add_old_variables: false +liquid_check_mode: 'error' +liquid_raise_mode: true +require_table_for_record_delete_mutation: true +safe_translate: true +skip_elasticsearch: false +slug_exact_match: true +websockets_require_csrf_token: true +maintenance: + enabled: false + password_constant: 'MAINTENANCE_PASSWORD' + partial: 'maintenance' +--- diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/graphql/create.graphql b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/create.graphql new file mode 100644 index 00000000..67905af1 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/create.graphql @@ -0,0 +1,25 @@ +mutation create_<%= modelName %>( +<% attributes.forEach((attr) => { -%> + $<%= attr.name %>: <%= graphqlArgumentMap[attr.type] %>! +<% }); -%> +) { + record: record_create( + record: { + table: "<%= modelName %>" + properties: [ + <% attributes.forEach((attr) => { -%> + { name: "<%= attr.name %>" <%= graphqlArgumentValueMap[attr.type] %>: $<%= attr.name %> } + <% }); -%> + ] + } + ){ + id + created_at + deleted_at + type: table + + <% attributes.forEach((attr) => { -%> + <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>") + <% }); -%> + } +} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/graphql/delete.graphql b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/delete.graphql new file mode 100644 index 00000000..c77948f4 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/delete.graphql @@ -0,0 +1,6 @@ +mutation delete($id: ID!) { + record: record_delete( + table: "<%= modelName %>" + id: $id + ){ id } +} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/graphql/search.graphql b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/search.graphql new file mode 100644 index 00000000..a22b2fd7 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/search.graphql @@ -0,0 +1,39 @@ +query search( + $id: ID + $limit: Int = 20 + $page: Int = 1 +<% attributes.forEach((attr) => { -%> + $<%= attr.name %>: String +<% }); -%> +) { + <%= modelNamePlural %>: records( + per_page: $limit + page: $page + filter: { + id: { value: $id } + table: { value: "<%= modelName %>" } + properties: [ + <% attributes.forEach((attr) => { -%> + { name: "<%= attr.name %>" value: $<%= attr.name %> } + <% }); -%> + ] + } + sort: [ + { created_at: { order: DESC }} + ] + ){ + total_entries + total_pages + has_previous_page + has_next_page + results { + id + created_at + type: table + + <% attributes.forEach((attr) => { -%> + <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>") + <% }); -%> + } + } +} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/graphql/update.graphql b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/update.graphql new file mode 100644 index 00000000..73e45562 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/graphql/update.graphql @@ -0,0 +1,27 @@ +mutation update_<%= modelName %>( + $id: ID! +<% attributes.forEach((attr) => { -%> + $<%= attr.name %>: <%= graphqlArgumentMap[attr.type] %> +<% }); -%> +) { + record: record_update( + id: $id + record: { + table: "<%= modelName %>" + properties: [ + <% attributes.forEach((attr) => { -%> + { name: "<%= attr.name %>" <%= graphqlArgumentValueMap[attr.type] %>: $<%= attr.name %> } + <% }); -%> + ] + } + ){ + id + created_at + updated_at + type: table + + <% attributes.forEach((attr) => { -%> + <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>") + <% }); -%> + } +} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create.liquid new file mode 100644 index 00000000..26b0a030 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create.liquid @@ -0,0 +1,10 @@ +{% liquid + function object = 'commands/<%= modelNamePlural %>/create/build', object: object + function object = 'commands/<%= modelNamePlural %>/create/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/create' object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid new file mode 100644 index 00000000..94a17bf9 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid @@ -0,0 +1,16 @@ +{% parse_json object %} + { + "id": {{ object.id | json }}, +<% attributes.forEach((attr, i) => { -%> + <% if (attr.type == 'integer' || attr.type == 'float') { %> + "<%= attr.name %>": {{ object.<%= attr.name %> | plus: 0 | json }}<% if (i+1 < attributes.length){ %>,<% } %> + <%} else { %> + "<%= attr.name %>": {{ object.<%= attr.name %> | json }}<% if (i+1 < attributes.length){ %>,<% } %> + <% } %> +<% }); -%> + } +{% endparse_json %} + +{% liquid + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid new file mode 100644 index 00000000..caf4d8da --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid @@ -0,0 +1,12 @@ +{% liquid + assign c = { "errors": {}, "valid": true } + +<% attributes.forEach((attr, i) => { -%> + function c = 'modules/core/validations/presence', c: c, object: object, field_name: '<%= attr.name %>' +<% }); -%> + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete.liquid new file mode 100644 index 00000000..1ce0a603 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete.liquid @@ -0,0 +1,9 @@ +{% liquid + function object = 'commands/<%= modelNamePlural %>/delete/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/delete', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid new file mode 100644 index 00000000..4fada405 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid @@ -0,0 +1,10 @@ +{% liquid + assign c = { "valid": true, "errors": {} } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update.liquid new file mode 100644 index 00000000..29a229c0 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update.liquid @@ -0,0 +1,10 @@ +{% liquid + function object = 'commands/<%= modelNamePlural %>/update/build', object: object + function object = 'commands/<%= modelNamePlural %>/update/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/update' object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid new file mode 100644 index 00000000..94a17bf9 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid @@ -0,0 +1,16 @@ +{% parse_json object %} + { + "id": {{ object.id | json }}, +<% attributes.forEach((attr, i) => { -%> + <% if (attr.type == 'integer' || attr.type == 'float') { %> + "<%= attr.name %>": {{ object.<%= attr.name %> | plus: 0 | json }}<% if (i+1 < attributes.length){ %>,<% } %> + <%} else { %> + "<%= attr.name %>": {{ object.<%= attr.name %> | json }}<% if (i+1 < attributes.length){ %>,<% } %> + <% } %> +<% }); -%> + } +{% endparse_json %} + +{% liquid + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid new file mode 100644 index 00000000..cffe5645 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid @@ -0,0 +1,13 @@ +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' +<% attributes.forEach((attr, i) => { -%> + function c = 'modules/core/validations/presence', c: c, object: object, field_name: '<%= attr.name %>' +<% }); -%> + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/find.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/find.liquid new file mode 100644 index 00000000..7f84e124 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/find.liquid @@ -0,0 +1,9 @@ +{% liquid + if id == blank + return null + endif + + graphql r = '<%= modelNamePlural %>/search', id: id, limit: 1 + + return r.<%= modelNamePlural %>.results.first +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/search.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/search.liquid new file mode 100644 index 00000000..369ec372 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/lib/queries/model/search.liquid @@ -0,0 +1,4 @@ +{% liquid + graphql r = '<%= modelNamePlural %>/search', limit: limit, page: 1 + return r.<%= modelNamePlural %> +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/schema/model.yml b/pos-module-user-invites/modules/core/generators/crud/templates/schema/model.yml new file mode 100644 index 00000000..380c67bd --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/schema/model.yml @@ -0,0 +1,6 @@ +name: <%= modelName %> +properties: +<% attributes.forEach((attr) => { -%> + - name: <%= attr.name %> + type: <%= attr.type %> +<% }); -%> diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/translations/model.yml b/pos-module-user-invites/modules/core/generators/crud/templates/translations/model.yml new file mode 100644 index 00000000..879b076f --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/translations/model.yml @@ -0,0 +1,15 @@ +en: + app: + <%= modelNamePlural %>: + new: + new: New <%= modelName %> + edit: + edit: Edit <%= modelName %> + list: + add: Add <%= modelName %> + empty_state: You haven't added any <%= modelNamePlural %> yet.
    Create your first one now! + edit: Edit + attr: + <% attributes.forEach((attr) => { -%> + <%= attr.name %>: <%= attr.nameHuman %> + <% }); -%> diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/create.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/create.liquid new file mode 100644 index 00000000..cf27c95f --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/create.liquid @@ -0,0 +1,14 @@ +--- +slug: <%= modelNamePlural %> +method: post +--- +{% liquid + function object = 'commands/<%= modelNamePlural %>/create', object: context.params.<%= modelName %> + if object.valid + # platformos-check-disable ConvertIncludeToRender + include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>' + # platformos-check-enable ConvertIncludeToRender + else + render 'theme/simple/<%= modelNamePlural %>/new', object: object + endif +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/delete.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/delete.liquid new file mode 100644 index 00000000..bb26a02e --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/delete.liquid @@ -0,0 +1,16 @@ +--- +slug: <%= modelNamePlural %> +method: delete +--- +{% liquid + function object = 'queries/<%= modelNamePlural %>/find', id: context.params.id + function object = 'commands/<%= modelNamePlural %>/delete', object: object + + # platformos-check-disable ConvertIncludeToRender + if object.valid + include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>', notice: 'modules/core/common.deleted' + else + include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>', error: 'modules/core/common.delete_failed' + endif + # platformos-check-enable ConvertIncludeToRender +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/edit.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/edit.liquid new file mode 100644 index 00000000..b098d38c --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/edit.liquid @@ -0,0 +1,5 @@ +{% liquid + function object = 'queries/<%= modelNamePlural %>/find', id: context.params.id + + render 'theme/simple/<%= modelNamePlural %>/edit', object: object +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/index.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/index.liquid new file mode 100644 index 00000000..75290a71 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/index.liquid @@ -0,0 +1,5 @@ +{% liquid + function <%= modelNamePlural %> = 'queries/<%= modelNamePlural %>/search', limit: 100 + + render 'theme/simple/<%= modelNamePlural %>/index', <%= modelNamePlural %>: <%= modelNamePlural %> +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/new.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/new.liquid new file mode 100644 index 00000000..43c1b24e --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/new.liquid @@ -0,0 +1,4 @@ +{% liquid + assign object = {} + render 'theme/simple/<%= modelNamePlural %>/new', object: object + %} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/show.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/show.liquid new file mode 100644 index 00000000..c9672cc7 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/show.liquid @@ -0,0 +1,13 @@ +--- +slug: <%= modelNamePlural %>/:id +--- +{% liquid + + assign <%= modelName %>_id = context.params.id | split: '-' | last + function <%= modelName %> = 'queries/<%= modelNamePlural %>/find', id: <%= modelName %>_id + if <%= modelName %>.id + render 'theme/simple/<%= modelNamePlural %>/show', <%= modelName %>: <%= modelName %> + else + response_status 404 + endif +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/update.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/update.liquid new file mode 100644 index 00000000..06644bd7 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/pages/model/update.liquid @@ -0,0 +1,14 @@ +--- +slug: <%= modelNamePlural %> +method: put +--- +{% liquid + function object = 'commands/<%= modelNamePlural %>/update', object: context.params.<%= modelName %> + if object.valid + # platformos-check-disable ConvertIncludeToRender + include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>' + # platformos-check-enable ConvertIncludeToRender + else + render 'theme/simple/<%= modelNamePlural %>/edit', object: object + endif +%} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid new file mode 100644 index 00000000..16d306b9 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid @@ -0,0 +1,5 @@ +{% if errors %} + + {{ errors | join: ', ' }} + +{% endif %} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid new file mode 100644 index 00000000..6bd91f21 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid @@ -0,0 +1,5 @@ +
    +

    {{ 'app.<%= modelNamePlural %>.edit.edit' | t }} {{ object.name }}

    +
    + +{% render 'theme/simple/<%= modelNamePlural %>/form', object: object %} diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid new file mode 100644 index 00000000..5abe3175 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid @@ -0,0 +1,9 @@ +
    +

    + {{ 'app.<%= modelNamePlural %>.list.empty_state' | t }} +

    + + + {{ 'app.<%= modelNamePlural %>.list.add' | t }} + +
    diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid new file mode 100644 index 00000000..e12d1eef --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid @@ -0,0 +1,27 @@ +{% liquid + if object.id + assign method = 'put' + else + assign method = 'post' + endif +%} +
    +
    + + + + {% if object.id %} + + {% endif %} + +<% attributes.forEach((attr) => { -%> +
    + + + {% render 'theme/simple/field_error', errors: object.errors.<%= attr.name %> %} +
    +<% }); -%> + + +
    +
    diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid new file mode 100644 index 00000000..352f7a05 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid @@ -0,0 +1,49 @@ +
    + +
    + {% if <%= modelNamePlural %>.results.size > 0 %} + + + +<% attributes.forEach((attr) => { -%> + +<% }); -%> + + + + {% for <%= modelName %> in <%= modelNamePlural %>.results %} + +<% attributes.forEach((attr) => { -%> + +<% }); -%> + + + {% endfor %} + +
    + {{ "app.<%= modelNamePlural %>.attr.<%= attr.name %>" | t }} +
    + + {{ <%= modelName %>.<%= attr.name %> }} + + + + {{ 'app.<%= modelNamePlural %>.list.edit' | t }} + +
    + + + + + +
    +
    + {% else %} + {% render 'theme/simple/<%= modelNamePlural %>/empty_state' %} + {% endif %} +
    +
    diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid new file mode 100644 index 00000000..e15a8d4f --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid @@ -0,0 +1,4 @@ +
    +

    {{ 'app.<%= modelNamePlural %>.new.new' | t }}

    + {% render 'theme/simple/<%= modelNamePlural %>/form', object: object %} +
    diff --git a/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid new file mode 100644 index 00000000..483dd892 --- /dev/null +++ b/pos-module-user-invites/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid @@ -0,0 +1,15 @@ +
    +

    + <%= modelName %> - {{ <%= modelName %>.id }} +

    + + <% attributes.forEach((attr) => { -%> + + {{ 'app.<%= modelNamePlural %>.attr.<%= attr.name %>' | t }} + +

    + {{ <%= modelName %>.<%= attr.name %> }} +

    + + <% }); -%> +
    diff --git a/pos-module-user-invites/modules/core/package-lock.json b/pos-module-user-invites/modules/core/package-lock.json new file mode 100644 index 00000000..655962cc --- /dev/null +++ b/pos-module-user-invites/modules/core/package-lock.json @@ -0,0 +1,3225 @@ +{ + "name": "pos-module-core", + "version": "1.2.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "pos-module-core", + "version": "1.2.1", + "license": "MIT", + "devDependencies": { + "auto-changelog": "^2.4.0", + "lodash.startcase": "^4.4.0", + "pluralize": "^8.0.0" + }, + "peerDependencies": { + "yeoman-generator": "^7.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", + "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", + "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/npm-conf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.2.tgz", + "integrity": "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "license": "MIT" + }, + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "25.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz", + "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "license": "MIT" + }, + "node_modules/@types/vinyl": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", + "license": "MIT", + "dependencies": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "node_modules/@yeoman/namespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@yeoman/namespace/-/namespace-1.0.1.tgz", + "integrity": "sha512-XGdYL0HCoPvrzW7T8bxD6RbCY/B8uvR2jpOzJc/yEwTueKHwoVhjSLjVXkokQAO0LNl8nQFLVZ1aKfr2eFWZeA==", + "license": "MIT", + "engines": { + "node": "^16.13.0 || >=18.12.0" + } + }, + "node_modules/@yeoman/types": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@yeoman/types/-/types-1.9.1.tgz", + "integrity": "sha512-5BMdA/zMzLv/ahnL1ktaV46nSXorb4sU4kQPQKDhIcK8ERbx9TAbGAE+XAlCXKioNIiOrihYj6gW1d/GEfU9Zw==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^16.13.0 || >=18.12.0" + }, + "peerDependencies": { + "@types/node": ">=16.18.26", + "@yeoman/adapter": "^1.6.0 || ^2.0.0-beta.0 || ^3.0.0 || ^4.0.0", + "mem-fs": "^3.0.0 || ^4.0.0-beta.1", + "mem-fs-editor": "^10.0.2 || >=10.0.2" + }, + "peerDependenciesMeta": { + "@yeoman/adapter": { + "optional": true + }, + "mem-fs": { + "optional": true + }, + "mem-fs-editor": { + "optional": true + } + } + }, + "node_modules/array-differ": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", + "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/auto-changelog": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz", + "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==", + "dev": true, + "dependencies": { + "commander": "^7.2.0", + "handlebars": "^4.7.7", + "node-fetch": "^2.6.1", + "parse-github-url": "^1.0.2", + "semver": "^7.3.5" + }, + "bin": { + "auto-changelog": "src/index.js" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "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.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/first-chunk-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-5.0.0.tgz", + "integrity": "sha512-WdHo4ejd2cG2Dl+sLkW79SctU7mUQDfr4s1i26ffOZRs5mgv+BRttIM9gwcq0rDbemo0KlpVPaa3LBVLqPXzcQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-username": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-9.0.0.tgz", + "integrity": "sha512-lY7+mymwQUEhRwWTLxieKkxcZkVNnUh8iAGnl30DMB1ZtYODHkMAckZk8Jx5dLQs1YKPYM2ibnzQu02aCLFcYQ==", + "license": "MIT", + "dependencies": { + "@octokit/rest": "^21.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.3.tgz", + "integrity": "sha512-VR4gNjFaDP8csJQvzInG20JvBj8MaHYLxNOMXysxRbGM7tcsHZwCjhch3FubFtZBkuDbN55i4dUukGeIrzF+6g==", + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/ky": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, + "node_modules/latest-version": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", + "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", + "license": "MIT", + "dependencies": { + "package-json": "^10.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/mem-fs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-4.1.3.tgz", + "integrity": "sha512-+2zSUVKcDWgcF90mPPwyH4J814uRI1PJcVt2RZ4/E8VggPEiIEL7ikMTlPR91P2ZySkyPgD0YGrccwo55SZvnw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": ">=18", + "@types/vinyl": "^2.0.12", + "vinyl": "^3.0.0", + "vinyl-file": "^5.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/mem-fs-editor": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-11.1.4.tgz", + "integrity": "sha512-Z4QX14Ev6eOVTuVSayS5rdiOua6C3gHcFw+n9Qc7WiaVTbC+H8b99c32MYGmbQN9UFHJeI/p3lf3LAxiIzwEmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/ejs": "^3.1.4", + "@types/node": ">=18", + "binaryextensions": "^6.11.0", + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^3.1.10", + "globby": "^14.0.2", + "isbinaryfile": "5.0.3", + "minimatch": "^9.0.3", + "multimatch": "^7.0.0", + "normalize-path": "^3.0.0", + "textextensions": "^6.11.0", + "vinyl": "^3.0.0" + }, + "acceptDependencies": { + "isbinaryfile": "^5.0.3" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "mem-fs": "^4.0.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multimatch": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-7.0.0.tgz", + "integrity": "sha512-SYU3HBAdF4psHEL/+jXDKHO95/m5P2RvboHT2Y0WtTttvJLP4H/2WS9WlQPFvF6C8d6SpLw8vjCnQOnVIVOSJQ==", + "license": "MIT", + "dependencies": { + "array-differ": "^4.0.0", + "array-union": "^3.0.1", + "minimatch": "^9.0.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", + "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", + "license": "MIT", + "dependencies": { + "ky": "^1.2.0", + "registry-auth-token": "^5.0.2", + "registry-url": "^6.0.1", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true, + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^3.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "license": "ISC" + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-git": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-keys": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", + "integrity": "sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "license": "CC0-1.0" + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/strip-bom-buf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-3.0.1.tgz", + "integrity": "sha512-iJaWw2WroigLHzQysdc5WWeUc99p7ea7AEgB6JkY8CMyiO1yTVAA1gIlJJgORElUIR+lcZJkNl1OGChMhvc2Cw==", + "license": "MIT", + "dependencies": { + "is-utf8": "^0.2.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-bom-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-5.0.0.tgz", + "integrity": "sha512-Yo472mU+3smhzqeKlIxClre4s4pwtYZEvDNQvY/sJpnChdaxmKuwU28UVx/v1ORKNMxkmj1GBuvxJQyBk6wYMQ==", + "license": "MIT", + "dependencies": { + "first-chunk-stream": "^5.0.0", + "strip-bom-buf": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-file": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-5.0.0.tgz", + "integrity": "sha512-MvkPF/yA1EX7c6p+juVIvp9+Lxp70YUfNKzEWeHMKpUNVSnTZh2coaOqLxI0pmOe2V9nB+OkgFaMDkodaJUyGw==", + "license": "MIT", + "dependencies": { + "@types/vinyl": "^2.0.7", + "strip-bom-buf": "^3.0.1", + "strip-bom-stream": "^5.0.0", + "vinyl": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/yeoman-generator": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-7.5.1.tgz", + "integrity": "sha512-MYncRvzSTd71BMwiUMAVhfX00sDD8DZDrmPzRxQkWuWQ0V1Qt4Rd0gS/Nee2QDTWvRjvCa+KBfiAVrtOySq+JA==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@types/lodash-es": "^4.17.9", + "@yeoman/namespace": "^1.0.0", + "chalk": "^5.3.0", + "debug": "^4.1.1", + "execa": "^8.0.1", + "github-username": "^9.0.0", + "json-schema": "^0.4.0", + "latest-version": "^9.0.0", + "lodash-es": "^4.17.21", + "mem-fs-editor": "^11.0.1", + "minimist": "^1.2.8", + "read-package-up": "^11.0.0", + "semver": "^7.5.4", + "simple-git": "^3.20.0", + "sort-keys": "^5.0.0", + "text-table": "^0.2.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "peerDependencies": { + "@types/node": ">=18.18.5", + "@yeoman/types": "^1.1.1", + "mem-fs": "^4.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "requires": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" + }, + "@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "requires": { + "debug": "^4.1.1" + } + }, + "@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==" + }, + "@octokit/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", + "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "peer": true, + "requires": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + } + }, + "@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "requires": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "requires": { + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + } + }, + "@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==" + }, + "@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "requires": { + "@octokit/types": "^13.10.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "requires": { + "@octokit/openapi-types": "^24.2.0" + } + } + } + }, + "@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", + "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "requires": { + "@octokit/types": "^13.10.0" + }, + "dependencies": { + "@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==" + }, + "@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "requires": { + "@octokit/openapi-types": "^24.2.0" + } + } + } + }, + "@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "requires": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + } + }, + "@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "requires": { + "@octokit/types": "^14.0.0" + } + }, + "@octokit/rest": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "requires": { + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" + } + }, + "@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "requires": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==" + }, + "@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "requires": { + "graceful-fs": "4.2.10" + } + }, + "@pnpm/npm-conf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.2.tgz", + "integrity": "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==", + "requires": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + } + }, + "@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==" + }, + "@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==" + }, + "@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==" + }, + "@types/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==" + }, + "@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "25.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz", + "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", + "peer": true, + "requires": { + "undici-types": "~7.16.0" + } + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + }, + "@types/vinyl": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", + "requires": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "@yeoman/namespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@yeoman/namespace/-/namespace-1.0.1.tgz", + "integrity": "sha512-XGdYL0HCoPvrzW7T8bxD6RbCY/B8uvR2jpOzJc/yEwTueKHwoVhjSLjVXkokQAO0LNl8nQFLVZ1aKfr2eFWZeA==" + }, + "@yeoman/types": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@yeoman/types/-/types-1.9.1.tgz", + "integrity": "sha512-5BMdA/zMzLv/ahnL1ktaV46nSXorb4sU4kQPQKDhIcK8ERbx9TAbGAE+XAlCXKioNIiOrihYj6gW1d/GEfU9Zw==", + "peer": true, + "requires": {} + }, + "array-differ": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", + "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==" + }, + "array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==" + }, + "async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "auto-changelog": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz", + "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==", + "dev": true, + "requires": { + "commander": "^7.2.0", + "handlebars": "^4.7.7", + "node-fetch": "^2.6.1", + "parse-github-url": "^1.0.2", + "semver": "^7.3.5" + } + }, + "b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "requires": {} + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "requires": {} + }, + "before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" + }, + "binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "requires": { + "editions": "^6.21.0" + } + }, + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "requires": { + "fill-range": "^7.1.1" + } + }, + "chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==" + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "requires": { + "version-range": "^4.15.0" + } + }, + "ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "requires": { + "jake": "^10.8.5" + } + }, + "events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "requires": { + "bare-events": "^2.7.0" + } + }, + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==" + }, + "fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, + "fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + } + }, + "fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==" + }, + "first-chunk-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-5.0.0.tgz", + "integrity": "sha512-WdHo4ejd2cG2Dl+sLkW79SctU7mUQDfr4s1i26ffOZRs5mgv+BRttIM9gwcq0rDbemo0KlpVPaa3LBVLqPXzcQ==" + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==" + }, + "github-username": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-9.0.0.tgz", + "integrity": "sha512-lY7+mymwQUEhRwWTLxieKkxcZkVNnUh8iAGnl30DMB1ZtYODHkMAckZk8Jx5dLQs1YKPYM2ibnzQu02aCLFcYQ==", + "requires": { + "@octokit/rest": "^21.1.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "requires": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "requires": { + "lru-cache": "^10.0.1" + } + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==" + }, + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==" + }, + "index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==" + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "isbinaryfile": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.3.tgz", + "integrity": "sha512-VR4gNjFaDP8csJQvzInG20JvBj8MaHYLxNOMXysxRbGM7tcsHZwCjhch3FubFtZBkuDbN55i4dUukGeIrzF+6g==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "requires": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "ky": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==" + }, + "latest-version": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", + "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", + "requires": { + "package-json": "^10.0.0" + } + }, + "lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==" + }, + "lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "mem-fs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-4.1.3.tgz", + "integrity": "sha512-+2zSUVKcDWgcF90mPPwyH4J814uRI1PJcVt2RZ4/E8VggPEiIEL7ikMTlPR91P2ZySkyPgD0YGrccwo55SZvnw==", + "peer": true, + "requires": { + "@types/node": ">=18", + "@types/vinyl": "^2.0.12", + "vinyl": "^3.0.0", + "vinyl-file": "^5.0.0" + } + }, + "mem-fs-editor": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-11.1.4.tgz", + "integrity": "sha512-Z4QX14Ev6eOVTuVSayS5rdiOua6C3gHcFw+n9Qc7WiaVTbC+H8b99c32MYGmbQN9UFHJeI/p3lf3LAxiIzwEmA==", + "peer": true, + "requires": { + "@types/ejs": "^3.1.4", + "@types/node": ">=18", + "binaryextensions": "^6.11.0", + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^3.1.10", + "globby": "^14.0.2", + "isbinaryfile": "5.0.3", + "minimatch": "^9.0.3", + "multimatch": "^7.0.0", + "normalize-path": "^3.0.0", + "textextensions": "^6.11.0", + "vinyl": "^3.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==" + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "multimatch": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-7.0.0.tgz", + "integrity": "sha512-SYU3HBAdF4psHEL/+jXDKHO95/m5P2RvboHT2Y0WtTttvJLP4H/2WS9WlQPFvF6C8d6SpLw8vjCnQOnVIVOSJQ==", + "requires": { + "array-differ": "^4.0.0", + "array-union": "^3.0.1", + "minimatch": "^9.0.3" + } + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "requires": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "requires": { + "path-key": "^4.0.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==" + } + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "package-json": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", + "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", + "requires": { + "ky": "^1.2.0", + "registry-auth-token": "^5.0.2", + "registry-url": "^6.0.1", + "semver": "^7.6.0" + } + }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true + }, + "parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "requires": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==" + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "requires": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + } + }, + "read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "requires": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "dependencies": { + "unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==" + } + } + }, + "registry-auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "requires": { + "@pnpm/npm-conf": "^3.0.2" + } + }, + "registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "requires": { + "rc": "1.2.8" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" + }, + "replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==" + }, + "reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==" + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + }, + "simple-git": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz", + "integrity": "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==", + "requires": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + } + }, + "slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==" + }, + "sort-keys": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", + "integrity": "sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==", + "requires": { + "is-plain-obj": "^4.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==" + }, + "streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "requires": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "strip-bom-buf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-3.0.1.tgz", + "integrity": "sha512-iJaWw2WroigLHzQysdc5WWeUc99p7ea7AEgB6JkY8CMyiO1yTVAA1gIlJJgORElUIR+lcZJkNl1OGChMhvc2Cw==", + "requires": { + "is-utf8": "^0.2.1" + } + }, + "strip-bom-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-5.0.0.tgz", + "integrity": "sha512-Yo472mU+3smhzqeKlIxClre4s4pwtYZEvDNQvY/sJpnChdaxmKuwU28UVx/v1ORKNMxkmj1GBuvxJQyBk6wYMQ==", + "requires": { + "first-chunk-stream": "^5.0.0", + "strip-bom-buf": "^3.0.0" + } + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" + }, + "teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "requires": { + "streamx": "^2.12.5" + } + }, + "text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "requires": { + "b4a": "^1.6.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "requires": { + "editions": "^6.21.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==" + }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true + }, + "undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + }, + "unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==" + }, + "universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==" + }, + "vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "requires": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + } + }, + "vinyl-file": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-5.0.0.tgz", + "integrity": "sha512-MvkPF/yA1EX7c6p+juVIvp9+Lxp70YUfNKzEWeHMKpUNVSnTZh2coaOqLxI0pmOe2V9nB+OkgFaMDkodaJUyGw==", + "requires": { + "@types/vinyl": "^2.0.7", + "strip-bom-buf": "^3.0.1", + "strip-bom-stream": "^5.0.0", + "vinyl": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "yeoman-generator": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-7.5.1.tgz", + "integrity": "sha512-MYncRvzSTd71BMwiUMAVhfX00sDD8DZDrmPzRxQkWuWQ0V1Qt4Rd0gS/Nee2QDTWvRjvCa+KBfiAVrtOySq+JA==", + "peer": true, + "requires": { + "@types/lodash-es": "^4.17.9", + "@yeoman/namespace": "^1.0.0", + "chalk": "^5.3.0", + "debug": "^4.1.1", + "execa": "^8.0.1", + "github-username": "^9.0.0", + "json-schema": "^0.4.0", + "latest-version": "^9.0.0", + "lodash-es": "^4.17.21", + "mem-fs-editor": "^11.0.1", + "minimist": "^1.2.8", + "read-package-up": "^11.0.0", + "semver": "^7.5.4", + "simple-git": "^3.20.0", + "sort-keys": "^5.0.0", + "text-table": "^0.2.0" + } + } + } +} diff --git a/pos-module-user-invites/modules/core/package.json b/pos-module-user-invites/modules/core/package.json new file mode 100644 index 00000000..49515a04 --- /dev/null +++ b/pos-module-user-invites/modules/core/package.json @@ -0,0 +1,32 @@ +{ + "name": "pos-module-core", + "version": "1.2.1", + "description": "Module description", + "type": "module", + "scripts": { + "version": "(cd ../../ && pos-cli modules version core -p) && git add template-values.json && auto-changelog -p && git add CHANGELOG.md" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Platform-OS/pos-module-core.git" + }, + "author": "", + "license": "MIT", + "bugs": { + "url": "https://github.com/Platform-OS/pos-module-core/issues" + }, + "homepage": "https://github.com/Platform-OS/pos-module-core#readme", + "peerDependencies": { + "yeoman-generator": "^7.0.0" + }, + "devDependencies": { + "auto-changelog": "^2.4.0", + "lodash.startcase": "^4.4.0", + "pluralize": "^8.0.0" + }, + "auto-changelog": { + "template": "changelog-template.hbs", + "unreleased": true, + "commitLimit": false + } +} diff --git a/pos-module-user-invites/modules/core/pos-module.json b/pos-module-user-invites/modules/core/pos-module.json new file mode 100644 index 00000000..da094b18 --- /dev/null +++ b/pos-module-user-invites/modules/core/pos-module.json @@ -0,0 +1,5 @@ +{ + "machine_name": "core", + "version": "2.1.8", + "name": "Pos Module Core" +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/core/public/api_calls/generic.liquid b/pos-module-user-invites/modules/core/public/api_calls/generic.liquid new file mode 100644 index 00000000..0a3289b6 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/api_calls/generic.liquid @@ -0,0 +1,6 @@ +--- +request_type: "{{ data.request_type }}" +request_headers: '{{ data.headers | json }}' +to: "{{ data.to }}" +--- +{{ data.payload }} diff --git a/pos-module-user-invites/modules/core/public/api_calls/generic_x_form_encoded.liquid b/pos-module-user-invites/modules/core/public/api_calls/generic_x_form_encoded.liquid new file mode 100644 index 00000000..40852222 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/api_calls/generic_x_form_encoded.liquid @@ -0,0 +1,10 @@ +--- +request_type: "{{ data.request_type }}" +request_headers: '{{ data.headers | json }}' +to: "{{ data.to }}" +--- +{% liquid + function url = 'modules/core/helpers/hash_to_x_form_encoded', payload: data.payload + print url +%} + diff --git a/pos-module-user-invites/modules/core/public/emails/generic.liquid b/pos-module-user-invites/modules/core/public/emails/generic.liquid new file mode 100644 index 00000000..240ce94e --- /dev/null +++ b/pos-module-user-invites/modules/core/public/emails/generic.liquid @@ -0,0 +1,13 @@ +--- +from: "{{ data.from }}" +layout: "{{ data.layout }}" +to: "{{ data.to }}" +cc: "{{ data.cc }}" +bcc: "{{ data.bcc }}" +subject: "{{ data.subject }}" +--- +{% liquid + # platformos-check-disable + include data.partial, data: data.data + # platformos-check-enable +%} diff --git a/pos-module-user-invites/modules/core/public/graphql/api_calls/send.graphql b/pos-module-user-invites/modules/core/public/graphql/api_calls/send.graphql new file mode 100644 index 00000000..b26d03ff --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/api_calls/send.graphql @@ -0,0 +1,12 @@ +mutation ($template: String!, $data: HashObject!, $options: ApiCallSendOptions) { + api_call: api_call_send( + data: $data + template: { name: $template } + options: $options + ) { + response{ status body } + errors { + message + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/email/send.graphql b/pos-module-user-invites/modules/core/public/graphql/email/send.graphql new file mode 100644 index 00000000..2f9fc396 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/email/send.graphql @@ -0,0 +1,9 @@ +mutation ($data: HashObject!, $template: String!){ + email_send( + template: { name: $template } + data: $data + ){ + is_scheduled_to_send + errors { message } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/events/consumers.graphql b/pos-module-user-invites/modules/core/public/graphql/events/consumers.graphql new file mode 100644 index 00000000..b13d23bf --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/events/consumers.graphql @@ -0,0 +1,15 @@ +query consumers($name: String) { + admin_liquid_partials( + filter: { + path: { contains: $name } + } + sort: { + path: { order: ASC } + } + ) { + results { + path + metadata + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/events/create.graphql b/pos-module-user-invites/modules/core/public/graphql/events/create.graphql new file mode 100644 index 00000000..77bc1d91 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/events/create.graphql @@ -0,0 +1,7 @@ +mutation create_event($payload: ActivityStreamsPayload!) { + activity_create( + payload: $payload + ) { + payload + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/events/events_checks.graphql b/pos-module-user-invites/modules/core/public/graphql/events/events_checks.graphql new file mode 100644 index 00000000..c326d870 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/events/events_checks.graphql @@ -0,0 +1,11 @@ +query events_checks($name: String) { + admin_liquid_partials( + filter: { + path: { ends_with: $name } + } + ) { + results { + path + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/events/search.graphql b/pos-module-user-invites/modules/core/public/graphql/events/search.graphql new file mode 100644 index 00000000..4e78dd25 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/events/search.graphql @@ -0,0 +1,14 @@ +query ac($limit: Int = 100 $page: Int = 1 $uuids: [String!]) { + activities: activities( + per_page: $limit, + page: $page + uuids: $uuids + sort: { created_at: { order: DESC } } + ){ + total_entries + total_pages + results { + payload + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/hook/search.graphql b/pos-module-user-invites/modules/core/public/graphql/hook/search.graphql new file mode 100644 index 00000000..37e31e2e --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/hook/search.graphql @@ -0,0 +1,7 @@ +query ($hook: String) { + admin_liquid_partials(filter: { path: { ends_with: $hook } }) { + results { + path + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/records/count.graphql b/pos-module-user-invites/modules/core/public/graphql/records/count.graphql new file mode 100644 index 00000000..9a21894c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/records/count.graphql @@ -0,0 +1,26 @@ +query records_count( + $property_name: String! + $property_value: String! + $scope_name: String! + $scope_value: String + $table: String! + $not_ids: [ID!] + $ids: [ID!] + $exclude_name: String! + $exclude_value: String +) { + records( + per_page: 1 + filter: { + id: { not_value_in: $not_ids, value_in: $ids } + table: { value: $table } + properties: [ + { name: $property_name, value: $property_value } + { name: $scope_name, value: $scope_value } + { name: $exclude_name, not_value: $exclude_value } + ] + } + ) { + total_entries + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/session/delete.graphql b/pos-module-user-invites/modules/core/public/graphql/session/delete.graphql new file mode 100644 index 00000000..c83de59f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/session/delete.graphql @@ -0,0 +1,5 @@ +mutation ($name: String!){ + session_delete_field( + name: $name + ) +} diff --git a/pos-module-user-invites/modules/core/public/graphql/session/set.graphql b/pos-module-user-invites/modules/core/public/graphql/session/set.graphql new file mode 100644 index 00000000..9069f25a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/session/set.graphql @@ -0,0 +1,6 @@ +mutation ($name: String!, $value: Any!){ + session_create_field( + name: $name + value: $value + ) +} diff --git a/pos-module-user-invites/modules/core/public/graphql/statuses/create.graphql b/pos-module-user-invites/modules/core/public/graphql/statuses/create.graphql new file mode 100644 index 00000000..7274afc1 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/statuses/create.graphql @@ -0,0 +1,34 @@ +mutation create_status( + $name: String! + $timestamp: String! + $reference_id: String! + $reference_schema: String + $payload: String + $requester_id: String! +) { + record: record_create( + record: { + table: "modules/core/status" + properties: [ + { name: "name", value: $name } + { name: "timestamp", value: $timestamp } + { name: "reference_id", value: $reference_id } + { name: "reference_schema", value: $reference_schema } + { name: "payload", value: $payload } + { name: "requester_id", value: $requester_id } + ] + } + ) { + id + created_at + deleted_at + type: table + + name: property(name: "name") + timestamp: property(name: "timestamp") + reference_id: property(name: "reference_id") + reference_schema: property(name: "reference_schema") + payload: property(name: "payload") + requester_id: property(name: "requester_id") + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/statuses/delete.graphql b/pos-module-user-invites/modules/core/public/graphql/statuses/delete.graphql new file mode 100644 index 00000000..fb333ab9 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/statuses/delete.graphql @@ -0,0 +1,5 @@ +mutation delete_status($id: ID!) { + record_delete(table: "modules/core/status", id: $id) { + id + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/statuses/search.graphql b/pos-module-user-invites/modules/core/public/graphql/statuses/search.graphql new file mode 100644 index 00000000..8beffdcd --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/statuses/search.graphql @@ -0,0 +1,45 @@ +query search( + $id: ID + $limit: Int! + $page: Int! + $name: String + $timestamp: String + $reference_id: String + $reference_schema: String + $requester_id: String +) { + statuses: records( + per_page: $limit + page: $page + filter: { + id: { value: $id } + table: { value: "modules/core/status" } + properties: [ + { name: "name", value: $name } + { name: "timestamp", value: $timestamp } + { name: "reference_id", value: $reference_id } + { name: "reference_schema", value: $reference_schema } + { name: "requester_id", value: $requester_id } + ] + } + sort: [{ created_at: { order: DESC } }] + ) { + total_entries + has_next_page + has_previous_page + current_page + + results { + id + created_at + type: table + + name: property(name: "name") + timestamp: property(name: "timestamp") + reference_id: property(name: "reference_id") + reference_schema: property(name: "reference_schema") + payload: property(name: "payload") + requester_id: property(name: "requester_id") + } + } +} diff --git a/pos-module-user-invites/modules/core/public/graphql/variable/set.graphql b/pos-module-user-invites/modules/core/public/graphql/variable/set.graphql new file mode 100644 index 00000000..3c7b0d97 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/graphql/variable/set.graphql @@ -0,0 +1,6 @@ +mutation ($name: String!, $value: String!) { + variable: constant_set(name: $name, value: $value) { + name + value + } +} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/email/send.liquid b/pos-module-user-invites/modules/core/public/lib/commands/email/send.liquid new file mode 100644 index 00000000..1fc5273a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/email/send.liquid @@ -0,0 +1,21 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/core/commands/email/send/build', object: object + function object = 'modules/core/commands/email/send/check', object: object + + if object.valid + graphql r = 'modules/core/email/send', template: 'modules/core/generic', data: object + if r.errors + log r.errors, type: 'errors.graphql.invalid' + + assign object.valid = false + assign object.errors = r.errors + endif + else + log object.errors, type: 'payload validation error in core: commands/email' + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/email/send/build.liquid b/pos-module-user-invites/modules/core/public/lib/commands/email/send/build.liquid new file mode 100644 index 00000000..5e57d280 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/email/send/build.liquid @@ -0,0 +1,13 @@ +{% parse_json object %} + { + "layout": {{ object.layout | default: 'modules/core/mailer' | json }}, + "from": {{ object.from | json }}, + "to": {{ object.to | json }}, + "subject": {{ object.subject | json }}, + "cc": {{ object.cc | json }}, + "bcc": {{ object.bcc | json }}, + "partial": {{ object.partial | json }}, + "data": {{ object.data | json }} + } +{% endparse_json %} +{% return object %} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/email/send/check.liquid b/pos-module-user-invites/modules/core/public/lib/commands/email/send/check.liquid new file mode 100644 index 00000000..50c8aec5 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/email/send/check.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'from', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'to', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'layout', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'partial', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/broadcast.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/broadcast.liquid new file mode 100644 index 00000000..ec2b6bd0 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/broadcast.liquid @@ -0,0 +1,29 @@ +{% doc %} + @param {object} object - The object to process + @param {number} deprecated_delay - Deprecated: use metadata.delay in consumer file instead + @param {number} deprecated_max_attempts - Deprecated: use metadata.max_attempts in consumer file instead +{% enddoc %} +{% liquid + if object.type == blank + log 'ERROR: events broadcast type blank' + return null + endif + assign priorities = 'low,default,high' | split: ',' + + assign name = 'consumers/' | append: object.type | append: '/' + graphql consumers = 'modules/core/events/consumers', name: name | dig: "admin_liquid_partials", "results" + + assign object.consumers = consumers + for consumer in consumers + assign priority = 'default' + if priorities contains consumer.metadata.priority + assign priority = consumer.metadata.priority + endif + assign max_attempts = consumer.metadata.max_attempts | default: deprecated_max_attempts | default: 9 + assign delay = consumer.metadata.delay | default: deprecated_delay | default: 0 + + background _id = consumer.path, event: object, priority: priority, delay: delay, max_attempts: max_attempts + endfor + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/create.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/create.liquid new file mode 100644 index 00000000..c32c9702 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/create.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param {object} object - The object to process + @param {string} type - The type identifier + @param {number} deprecated_delay - Deprecated: use metadata.delay in consumer file instead + @param {number} deprecated_max_attempts - Deprecated: use metadata.max_attempts in consumer file instead +{% enddoc %} +{% liquid + function event = 'modules/core/commands/events/create/build', type: type, object: object + function event = 'modules/core/commands/events/create/check', object: event, type: type + if event.valid + function event = 'modules/core/commands/events/create/execute', object: event + if event.valid + assign source_name = 'modules/core/commands/events/create:' | append: type + background _job_id = 'modules/core/commands/events/broadcast', object: event, deprecated_max_attempts: deprecated_max_attempts, deprecated_delay: deprecated_delay, source_name: source_name, priority: 'high' + else + log event, type: 'ERROR: modules/core/commands/events invalid' + endif + else + log event, type: 'ERROR: modules/core/commands/events invalid' + endif + + return event +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/create/build.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/create/build.liquid new file mode 100644 index 00000000..0f692d19 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/create/build.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {object} object - The object to process + @param {string} type - The type identifier +{% enddoc %} +{% liquid + assign now = 'now' | to_time + assign data = object + assign data.type = type + assign data.date = data.date | default: now + + return data +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/create/check.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/create/check.liquid new file mode 100644 index 00000000..a11a644d --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/create/check.liquid @@ -0,0 +1,36 @@ +{% doc %} + @param {object} object - The object to process + @param {string} type - The type identifier +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'type', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'date', key: null + + assign name = 'events/' | append: object.type + graphql event_check_partials = 'modules/core/events/events_checks', name: name | dig: "admin_liquid_partials", "results" + for partial in event_check_partials + assign is_event_definition = partial.path | matches: '^(modules/[^/]+/events/[^/]++|events/[^/]+)$' + if is_event_definition + assign event_check_partial = partial + break + endif + endfor + + if event_check_partial + function event_result = event_check_partial.path, event: object + if event_result.valid != true + assign c.errors.object = event_result.errors + assign c.valid = false + endif + else + assign message = 'There is no such event: ' | append: object.type | append: '. Please add event check in events/' | append: object.type + function c = 'modules/core/helpers/register_error', contract: c, field_name: type, message: message, key: null + endif + + assign object.valid = c.valid + + assign object.errors = c.errors + return object + %} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/create/execute.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/create/execute.liquid new file mode 100644 index 00000000..d94fff4c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/create/execute.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + graphql r = 'modules/core/events/create', payload: object + + assign object = r.activity_create.payload + assign object.valid = true + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/events/publish.liquid b/pos-module-user-invites/modules/core/public/lib/commands/events/publish.liquid new file mode 100644 index 00000000..586ad27a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/events/publish.liquid @@ -0,0 +1,27 @@ +{% doc %} + @param {object} object - The object to process + @param {string} type - The type identifier + @param {number} delay - Delay in minutes before processing + @param {number} max_attempts - Maximum number of retry attempts +{% enddoc %} +{% liquid + if delay > 0 + log 'use metadata.delay in the consumer file instead of passing it to modules/core/commands/events/publish', type: 'DEPRECATION' + endif + if max_attempts + log 'use metadata.max_attempts in the consumer file instead of passing it to modules/core/commands/events/publish', type: 'DEPRECATION' + endif + + unless type + log 'type is required', type: 'ERROR: modules/core/commands/events publish' + return null + endunless + unless object + log 'object is required', type: 'ERROR: modules/core/commands/events publish' + return null + endunless + + function event = "modules/core/commands/events/create", type: type, object: object, deprecated_max_attempts: max_attempts, deprecated_delay: delay + + return event +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/execute.liquid b/pos-module-user-invites/modules/core/public/lib/commands/execute.liquid new file mode 100644 index 00000000..e0510a4d --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/execute.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {string} mutation_name - The GraphQL mutation name + @param {object} object - The object to process + @param {string} selection - The GraphQL result selection key +{% enddoc %} +{% liquid + assign selection = selection | default: 'record' + + graphql r = mutation_name, args: object + if r.errors + log r, type: "ERROR: modules/core/commands/execute" + endif + + assign object = r[selection] + assign object.valid = true + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/hook/alter.liquid b/pos-module-user-invites/modules/core/public/lib/commands/hook/alter.liquid new file mode 100644 index 00000000..19f42fb6 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/hook/alter.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix + @param {object} params - Parameters to pass to the hook + @param {object} params_to_modify - The object to be modified by the alter hook +{% enddoc %} +{% liquid + assign original_params = params_to_modify | deep_clone + + assign hook = '/hook_' | append: hook | append: '_alter' + function implementations = 'modules/core/queries/hook/search', hook: hook + + for implementation in implementations + function _ = implementation.path, params_to_modify: params_to_modify, params: params + endfor + + assign result = { "original_params": original_params } + return result +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/hook/fire.liquid b/pos-module-user-invites/modules/core/public/lib/commands/hook/fire.liquid new file mode 100644 index 00000000..0b35c386 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/hook/fire.liquid @@ -0,0 +1,38 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix + @param {object} params - Parameters to pass to the hook + @param {boolean} merge_to_object - If true, merge results into one object instead of collecting in an array +{% enddoc %} +{% liquid + if merge_to_object + assign results = {} + else + assign results = [] + endif + + assign hook = '/hook_' | append: hook + function implementations = 'modules/core/queries/hook/search', hook: hook + + for implementation in implementations + function hook_result = implementation.path, params: params + if hook_result != nil + comment + Check if the result is an array and merge the values one by one. + endcomment + if hook_result[0] + for h_result in hook_result + assign results << h_result + endfor + comment + Check if the result is an object. + endcomment + elsif hook_result.first and merge_to_object + assign results = results | hash_merge: hook_result + else + assign results << hook_result + endif + endif + endfor + + return results +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/session/clear.liquid b/pos-module-user-invites/modules/core/public/lib/commands/session/clear.liquid new file mode 100644 index 00000000..b823fa54 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/session/clear.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + if context.session[key] != blank + graphql _ = 'modules/core/session/delete', name: key + return true + endif + return false +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/session/get.liquid b/pos-module-user-invites/modules/core/public/lib/commands/session/get.liquid new file mode 100644 index 00000000..02b82408 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/session/get.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {boolean} clear - If true, clear the session value after reading + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + if context.session[key] != blank + assign value = context.session[key] | parse_json + if clear + graphql _ = 'modules/core/session/delete', name: key + endif + + return value + endif + return null +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/session/set.liquid b/pos-module-user-invites/modules/core/public/lib/commands/session/set.liquid new file mode 100644 index 00000000..3441120f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/session/set.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {string} key - The translation key for the error message + @param {string} value - The value +{% enddoc %} +{% liquid + assign value = value | json + graphql _ = 'modules/core/session/set', name: key, value: value + return true +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/create.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create.liquid new file mode 100644 index 00000000..dc5f46df --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create.liquid @@ -0,0 +1,25 @@ +{% doc %} + @param {string} name - The name identifier + @param {object} payload - The payload data + @param {string} reference_id - The reference record ID + @param {string} requester_id - The ID of the requester + @param {number} delay - Delay in minutes before processing + @param {number} max_attempts - Maximum number of retry attempts + @param {string} reference_schema - The reference schema name + @param {string} timestamp - The timestamp +{% enddoc %} +{% liquid + function object = 'modules/core/commands/statuses/create/build', name: name, timestamp: timestamp, reference_id: reference_id, reference_schema: reference_schema, payload: payload, requester_id: requester_id + function object = 'modules/core/commands/statuses/create/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/core/statuses/create' object: object, selection: null + if object.valid + function _ = 'modules/core/commands/events/publish', type: 'status_created', object: object, delay: delay, max_attempts: max_attempts + endif + else + log object, 'showme STATUS-INVALID' + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/build.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/build.liquid new file mode 100644 index 00000000..b46956ab --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/build.liquid @@ -0,0 +1,22 @@ +{% doc %} + @param {string} name - The name identifier + @param {object} payload - The payload data + @param {string} reference_id - The reference record ID + @param {string} requester_id - The ID of the requester + @param {string} reference_schema - The reference schema name + @param {string} timestamp - The timestamp +{% enddoc %} +{% parse_json object %} + { + "name": {{ name | json }}, + "timestamp": {{ timestamp | default: 'now' | to_time | json }}, + "reference_id": {{ reference_id | json }}, + "reference_schema": {{ reference_schema | json }}, + "payload": {{ payload | json }}, + "requester_id": {{ requester_id | json }} + } +{% endparse_json %} + +{% liquid + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/check.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/check.liquid new file mode 100644 index 00000000..61a2d21e --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/create/check.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'name', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'timestamp', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'reference_id', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'requester_id', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete.liquid new file mode 100644 index 00000000..5c79d786 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% liquid + function object = 'modules/core/commands/statuses/delete/build', id: id + function object = 'modules/core/commands/statuses/delete/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/core/statuses/delete', selection: 'record_delete', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/build.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/build.liquid new file mode 100644 index 00000000..29c1322b --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/build.liquid @@ -0,0 +1,7 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% liquid + assign object = {"id": id} + return object +%} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/check.liquid b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/check.liquid new file mode 100644 index 00000000..737a3fd6 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/statuses/delete/check.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "valid": true, "errors": {} } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/core/public/lib/commands/variable/set.liquid b/pos-module-user-invites/modules/core/public/lib/commands/variable/set.liquid new file mode 100644 index 00000000..cdbc3b85 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/commands/variable/set.liquid @@ -0,0 +1,8 @@ +{% doc %} + @param {string} name - The name identifier + @param {string} value - The value +{% enddoc %} +{% liquid + graphql result = 'modules/core/variable/set', name: name, value: value + return result.variable +%} diff --git a/pos-module-user-invites/modules/core/public/lib/events/status_created.liquid b/pos-module-user-invites/modules/core/public/lib/events/status_created.liquid new file mode 100644 index 00000000..02541f7c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/events/status_created.liquid @@ -0,0 +1,21 @@ +--- +metadata: + event: + name + reference_id + reference_schema + requester_id + payload +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'name', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'reference_id', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'requester_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/authenticity_token.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/authenticity_token.liquid new file mode 100644 index 00000000..6262ed4a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/authenticity_token.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {string} authenticity_token - The authenticity token from the form + @param {string} token - The authenticity token value +{% enddoc %} +{% assign token = token | default: authenticity_token | default: context.authenticity_token %} +{% unless token %} + Liquid Error AuthenticityTokenNotFound +{% endunless %} + diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/flash/publish.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/flash/publish.liquid new file mode 100644 index 00000000..cd5847d9 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/flash/publish.liquid @@ -0,0 +1,35 @@ +{% doc %} + @param {string} error - The error flash message + @param {string} info - The info flash message + @param {string} notice - The notice flash message + @param {boolean} force_clear - If true, clear flash messages immediately +{% enddoc %} +{% liquid + if error and error contains 'app.' + assign error = error | t + endif + + if notice and notice contains 'app.' + assign notice = notice | t + endif + + if info and info contains 'app.' + assign info = info | t + endif +%} + +{% parse_json flash %} + { + "error": {{ error | json }}, + "notice": {{ notice | json }}, + "info": {{ info | json }}, + "from": {{ context.location.pathname | json }}, + "now": {{ force_clear | default: false }} + } +{% endparse_json %} + +{% liquid + assign sflash = flash | json + session sflash = sflash +%} + diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid new file mode 100644 index 00000000..05d1820b --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {object} payload - The payload data +{% enddoc %} +{% liquid + assign parameters = '' | split: ',' + for pair in payload + assign component = pair[0] | append: '={' | append: pair[0] | append: '}' + assign parameters << component + endfor + if parameters.size > 0 + assign x_form_encoded = parameters | join: '&' | expand_url_template: payload + else + assign x_form_encoded = '' + endif + + return x_form_encoded +%} + diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/log_time.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/log_time.liquid new file mode 100644 index 00000000..447397af --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/log_time.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {string} _start - The start time for measuring elapsed time + @param {string} type - The type identifier + @param {string} env - The environment name for logging +{% enddoc %} +{% liquid + assign _stop = 'now' | to_time + assign _diff = _start | time_diff: _stop + if env + log _diff, type: type, env: env + else + log _diff, type: type + endif + + return true +%} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/redirect_to.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/redirect_to.liquid new file mode 100644 index 00000000..d9517afb --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/redirect_to.liquid @@ -0,0 +1,50 @@ +{% doc %} + @param {string} error - The error flash message + @param {string} info - The info flash message + @param {string} notice - The notice flash message + @param {object} object - The object to process + @param {string} default - The default value + @param {string} format - The response format + @param {string} url - The URL to redirect to +{% enddoc %} +{% liquid + if url == blank and context.session.return_to != blank + assign url = context.session.return_to + session return_to = null + endif + + if context.params.return_to != blank or context.params.redirect_to != blank and url == blank + assign url = context.params.return_to | default: context.params.redirect_to | url_decode + assign not_start_with_slash = url | matches: '^(?!\/)(.+)' + + # for security reasons, we do not allow redirecting to external URLs based on unsafe user input + assign wrong_url = url | matches: '^\/\/' + if not_start_with_slash or wrong_url + assign url = '/' + endif + else + assign default = default | default: '/' + assign url = url | default: default + endif + + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/flash/publish', notice: notice, error: error, info: info, force_clear: null + # platformos-check-enable DeprecatedTag + + if format == 'json' + assign response_json = {"type": "redirect", "url": url} + if object.valid + echo response_json + else + response_status 422 + assign res = { "errors": object.errors } + + echo res + endif + + else + redirect_to url + endif + + break +%} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/register_error.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/register_error.liquid new file mode 100644 index 00000000..f016b3e7 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/register_error.liquid @@ -0,0 +1,26 @@ +{% doc %} + @param {object} contract - The contract object for collecting errors + @param {string} field_name - The name of the field to validate + @param {string} key - The translation key for the error message + @param {string} message - Custom error message override +{% enddoc %} +{% liquid + assign key = key | default: null + assign message = message | default: null + if key + assign msg = key | t + else + assign msg = message + endif + + assign errors = contract.errors + + assign default = [] + assign field_errors = errors[field_name] | default: default + assign field_errors << msg + + assign errors[field_name] = field_errors + assign contract.valid = false + + return contract +%} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_all.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_all.liquid new file mode 100644 index 00000000..7ed01d5c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_all.liquid @@ -0,0 +1,18 @@ +{% comment %} + we need the to_json | parse_json hack because time_zones.all is an array of TimeZoneDrop (not an object) + this prevents us from using array filters or pass the timezone as reference (return it from a function, etc) + should be fixed on the platform level +{% endcomment %} +{% comment %} +Returns an array of timezone objects in the following format: +{ + "formatted_name":"(GMT-12:00) International Date Line West", + "formatted_offset":"-12:00", + "name":"International Date Line West", + "utc_offset":-43200, + "abbreviation":"-12", + "friendly_name_with_region":"Etc - GMT+12", + "friendly_name_without_region":"GMT+12" +} +{% endcomment %} +{% return context.globals.time_zones.all | parse_json %} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_name.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_name.liquid new file mode 100644 index 00000000..20f429d3 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_name.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {string} name - The name identifier +{% enddoc %} +{% liquid + function timezones = 'modules/core/helpers/timezone/get_all' + assign timezone = timezones | array_detect: name: name + + return timezone +%} diff --git a/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_offset.liquid b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_offset.liquid new file mode 100644 index 00000000..478d3ae2 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/helpers/timezone/get_by_offset.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {number} offset +{% enddoc %} +{% liquid + function timezones = 'modules/core/helpers/timezone/get_all' + assign timezone = timezones | array_detect: formatted_offset: offset + + return timezone +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/constants/find.liquid b/pos-module-user-invites/modules/core/public/lib/queries/constants/find.liquid new file mode 100644 index 00000000..84fe8d82 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/constants/find.liquid @@ -0,0 +1,38 @@ +{% doc %} + @param {string} name - The name identifier + @param {string} type - The type identifier +{% enddoc %} +{% if context.constants %} + {% assign value = context.constants[name] %} +{% else %} + {% graphql r, name: name %} + query get_constant($name: String!) { + constant(filter: { name: $name }) { + name + value + } + } + {% endgraphql %} + {% assign value = r.constant.value %} +{% endif %} + +{% liquid + case type + when "boolean" + if value == "true" + return true + else + return false + endif + when "integer" + assign value = value | plus: 0 + return value + when "array" + assign value = value | split: ',' + return value + when "time" + return value | to_time + else + return value + endcase +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/events/find.liquid b/pos-module-user-invites/modules/core/public/lib/queries/events/find.liquid new file mode 100644 index 00000000..c3d264ae --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/events/find.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {string} uuid - The UUID identifier +{% enddoc %} +{% liquid + if uuid == blank + return null + endif + + function events = 'modules/core/queries/events/search', limit: 1, uuids: uuid, page: null + + return events.results.first.payload +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/events/search.liquid b/pos-module-user-invites/modules/core/public/lib/queries/events/search.liquid new file mode 100644 index 00000000..25695985 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/events/search.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {number} limit - Maximum number of results + @param {number} page - Page number for pagination + @param {string} uuids - List of UUID identifiers +{% enddoc %} +{% liquid + assign page = page | to_positive_integer: 1 + assign uuids = uuids | default: null + + graphql r = 'modules/core/events/search', limit: limit, page: page, uuids: uuids + + assign events = r.activities + + return events +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/headscripts/get.liquid b/pos-module-user-invites/modules/core/public/lib/queries/headscripts/get.liquid new file mode 100644 index 00000000..e2453efb --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/headscripts/get.liquid @@ -0,0 +1,5 @@ +{% liquid + # TODO: remove after rewriting dependent modules + function res = 'modules/core/queries/headscripts/search', merge_to_object: null + return res +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/headscripts/search.liquid b/pos-module-user-invites/modules/core/public/lib/queries/headscripts/search.liquid new file mode 100644 index 00000000..989f536a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/headscripts/search.liquid @@ -0,0 +1,5 @@ +{% liquid + function headscript_implementations = 'modules/core/commands/hook/fire', hook: 'headscripts', merge_to_object: false, params: null + assign results = headscript_implementations | join: '' + return results | html_safe +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/hook/search.liquid b/pos-module-user-invites/modules/core/public/lib/queries/hook/search.liquid new file mode 100644 index 00000000..5b49f62f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/hook/search.liquid @@ -0,0 +1,7 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix +{% enddoc %} +{% liquid + graphql implementations = 'modules/core/hook/search', hook: hook + return implementations.admin_liquid_partials.results +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/module/exists.liquid b/pos-module-user-invites/modules/core/public/lib/queries/module/exists.liquid new file mode 100644 index 00000000..474665d7 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/module/exists.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} name - The name identifier + @param {string} type - The type identifier +{% enddoc %} +{% liquid + function modules = 'modules/core/queries/registry/search', type: type + assign module = modules | array_detect: machine_name: name + + if module + return true + endif + + return false +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/registry/get.liquid b/pos-module-user-invites/modules/core/public/lib/queries/registry/get.liquid new file mode 100644 index 00000000..aa3524ab --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/registry/get.liquid @@ -0,0 +1,8 @@ +{% doc %} + @param {string} type - The type identifier +{% enddoc %} +{% liquid + # TODO: remove after rewriting dependent modules + function registry = 'modules/core/queries/registry/search', type: type + return registry +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/registry/search.liquid b/pos-module-user-invites/modules/core/public/lib/queries/registry/search.liquid new file mode 100644 index 00000000..96116a45 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/registry/search.liquid @@ -0,0 +1,26 @@ +{% doc %} + @param {string} type - The type identifier +{% enddoc %} +{% liquid + function registry = 'modules/core/commands/hook/fire', hook: 'module_info', merge_to_object: false, params: null + + case type + when 'module' + assign modules = [] + for module in registry + if module.type == 'module' + assign modules << module + endif + endfor + return modules + when 'theme' + assign themes = [] + for module in registry + if module.type == 'theme' + assign themes << module + endif + endfor + return themes + endcase + return registry +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/statuses/find.liquid b/pos-module-user-invites/modules/core/public/lib/queries/statuses/find.liquid new file mode 100644 index 00000000..b7cf0787 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/statuses/find.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% liquid + if id == blank + return null + endif + + graphql r = 'modules/core/statuses/search', id: id, limit: 1, page: 1 + + return r.statuses.results.first +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/statuses/search.liquid b/pos-module-user-invites/modules/core/public/lib/queries/statuses/search.liquid new file mode 100644 index 00000000..f4f79d81 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/statuses/search.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} id - The record ID + @param {string} name - The name identifier + @param {string} reference_id - The reference record ID + @param {string} requester_id - The ID of the requester + @param {number} limit - Maximum number of results + @param {number} page - Page number for pagination + @param {string} reference_schema - The reference schema name + @param {string} timestamp - The timestamp +{% enddoc %} +{% liquid + assign page = page | to_positive_integer: 1 + assign limit = limit | default: 20 + + graphql r = 'modules/core/statuses/search', limit: limit, page: page, id: id, name: name, reference_id: reference_id, requester_id: requester_id, reference_schema: reference_schema, timestamp: timestamp + + return r.statuses +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/variable/find.liquid b/pos-module-user-invites/modules/core/public/lib/queries/variable/find.liquid new file mode 100644 index 00000000..c2ec54ce --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/variable/find.liquid @@ -0,0 +1,28 @@ +{% doc %} + @param {string} default - The default value + @param {string} type - The type identifier + @param {string} name - The name identifier +{% enddoc %} +{% liquid + assign value = context.constants[name] | default: default, allow_false: true + + case type + when 'boolean' + if value == 'true' or value == true + return true + else + return false + endif + when 'integer' + assign value = value | plus: 0 + return value + when 'float' + assign value = value | plus: 0 + return value + when 'array' + assign value = value | split: ',' + return value + else + return value + endcase +%} diff --git a/pos-module-user-invites/modules/core/public/lib/queries/variable/get.liquid b/pos-module-user-invites/modules/core/public/lib/queries/variable/get.liquid new file mode 100644 index 00000000..e51e5de0 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/queries/variable/get.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} default - The default value + @param {string} name - The name identifier + @param {string} type - The type identifier +{% enddoc %} +{% liquid + # TODO: remove after rewriting dependent modules + function res = 'modules/core/queries/variable/find', name: name, default: default, type: type + return res +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/date.liquid b/pos-module-user-invites/modules/core/public/lib/validations/date.liquid new file mode 100644 index 00000000..7125e988 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/date.liquid @@ -0,0 +1,78 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {boolean} can_be_future - Whether the date can be in the future + @param {boolean} can_be_past - Whether the date can be in the past + @param {string} date - The date to validate + @param {number} gt - Must be greater than this value + @param {number} gte - Must be greater than or equal to this value + @param {number} lt - Must be less than this value + @param {number} lte - Must be less than or equal to this value + @param {string} message_can_be_future - Custom error message for can_be_future validation + @param {string} message_can_be_past - Custom error message for can_be_past validation + @param {string} message_gt - Custom error message for gt validation + @param {string} message_gte - Custom error message for gte validation + @param {string} message_lt - Custom error message for lt validation + @param {string} message_lte - Custom error message for lte validation +{% enddoc %} +{% liquid + assign date = date | default: object[field_name] | to_date + + assign is_past = date | is_date_in_past + assign now = 'now' | to_date + + if date > now + assign is_future = true + else + assign is_future = false + endif + + if can_be_past == false and is_past + assign message = message_can_be_past | default: 'modules/core/validation.date.can_be_past' | t: count: can_be_past, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if can_be_future == false and is_future + assign message = message_can_be_future | default: 'modules/core/validation.date.can_be_future' | t: count: can_be_future, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if lt != null + assign lt = lt | to_date + if date >= lt + assign localized_date = lt | l + assign message = message_lt | default: 'modules/core/validation.date.lt' | t: date: localized_date, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if lte != null + assign lte = lte | to_date + if date > lte + assign localized_date = lte | l + assign message = message_lte | default: 'modules/core/validation.date.lte' | t: date: localized_date, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if gt != null + assign gt = gt | to_date + if date <= gt + assign localized_date = gt | l + assign message = message_gt | default: 'modules/core/validation.date.gt' | t: date: localized_date, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if gte != null + assign gte = gte | to_date + if date < gte + assign localized_date = gte | l + assign message = message_gte | default: 'modules/core/validation.date.gte' | t: date: localized_date, value: date + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/each_element_length.liquid b/pos-module-user-invites/modules/core/public/lib/validations/each_element_length.liquid new file mode 100644 index 00000000..85f5315c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/each_element_length.liquid @@ -0,0 +1,35 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {number} is - Exact value to match + @param {number} maximum - Maximum allowed value + @param {number} minimum - Minimum allowed value +{% enddoc %} +{% liquid + + for el in object[field_name] + + assign size = el.size + + if minimum != null and size < minimum + assign message = 'modules/core/validation.length.minimum' | t: count: minimum, value: size + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if maximum != null and size > maximum + assign message = 'modules/core/validation.length.maximum' | t: count: maximum, value: size + assign message = el | append: ' ' | append: message + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if is != null and size != is + assign message = 'modules/core/validation.length.is' | t: count: is, value: size + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + endfor + + return c + +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/elements_included.liquid b/pos-module-user-invites/modules/core/public/lib/validations/elements_included.liquid new file mode 100644 index 00000000..6b58bde8 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/elements_included.liquid @@ -0,0 +1,19 @@ +{% doc %} + @param {string} array - The array of allowed values + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + for val in object[field_name] + unless array contains val + assign key = key | default: "modules/core/validation.array.not_included" + assign message = key | t: value: val + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endunless + endfor + + return c +%} + diff --git a/pos-module-user-invites/modules/core/public/lib/validations/email.liquid b/pos-module-user-invites/modules/core/public/lib/validations/email.liquid new file mode 100644 index 00000000..39c80296 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/email.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + assign valid_email = object[field_name] | is_email_valid + unless valid_email + assign key = key | default: "modules/core/validation.email" + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/equal.liquid b/pos-module-user-invites/modules/core/public/lib/validations/equal.liquid new file mode 100644 index 00000000..6b367e45 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/equal.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} expected - The expected value to compare against + @param {string} field_name - The name of the field to validate + @param {string} given - The given value to compare + @param {string} key - The translation key for the error message + @param {string} message - Custom error message override + @param {boolean} not_verbose - If true, suppress detailed error output +{% enddoc %} +{% liquid + if given != expected + + if message == blank and key == blank + if not_verbose + assign message = 'modules/core/validation.equal_not_verbose' | t + else + assign message = 'modules/core/validation.equal' | t: given: given, expected: expected + endif + endif + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: key + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/exist_in_db.liquid b/pos-module-user-invites/modules/core/public/lib/validations/exist_in_db.liquid new file mode 100644 index 00000000..abc8a510 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/exist_in_db.liquid @@ -0,0 +1,31 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {string} table - The database table name + @param {string} exclude_name - The property name to exclude + @param {string} exclude_value - The property value to exclude + @param {string} ids - List of record IDs to include + @param {string} key - The translation key for the error message + @param {string} not_ids - List of record IDs to exclude + @param {string} property_name - The property name to check + @param {string} property_value - The property value to check + @param {string} scope_name - The scope property name for filtering + @param {string} scope_value - The scope property value for filtering +{% enddoc %} +{% liquid + assign property_name = property_name | default: '' + assign property_value = property_value | default: '' + assign scope_name = scope_name | default: '' + assign scope_value = scope_value | default: '' + assign exclude_name = exclude_name | default: '' + assign exclude_value = exclude_value | default: '' + assign key = key | default: 'modules/core/validation.not_exist' + + graphql r = 'modules/core/records/count', ids: ids, not_ids: not_ids, property_name: property_name, property_value: property_value, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value + + assign count = r.records.total_entries + if count == 0 + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/hcaptcha.liquid b/pos-module-user-invites/modules/core/public/lib/validations/hcaptcha.liquid new file mode 100644 index 00000000..21289c97 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/hcaptcha.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {object} hcaptcha_params - The hCaptcha verification parameters + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + assign hcaptcha_solved = hcaptcha_params | hcaptcha + unless hcaptcha_solved + assign key = key | default: "modules/core/validation.hcaptcha" + function c = 'modules/core/helpers/register_error', contract: c, field_name: 'hcaptcha', key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/included.liquid b/pos-module-user-invites/modules/core/public/lib/validations/included.liquid new file mode 100644 index 00000000..a432b8c0 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/included.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {string} array - The array of allowed values + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message + @param {string} value - The value +{% enddoc %} +{% liquid + assign value = value | default: object[field_name] + unless array contains value + assign key = key | default: "modules/core/validation.not_included" + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} + diff --git a/pos-module-user-invites/modules/core/public/lib/validations/is_url.liquid b/pos-module-user-invites/modules/core/public/lib/validations/is_url.liquid new file mode 100644 index 00000000..8ffaa466 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/is_url.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {string} url - The URL to redirect to + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + assign key = key | default: 'modules/core/validation.not_url' + assign is_url = url | matches: '^https?:\/\/[\S]+' + + if is_url != true + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + + return c +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/core/public/lib/validations/length.liquid b/pos-module-user-invites/modules/core/public/lib/validations/length.liquid new file mode 100644 index 00000000..fba5e45f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/length.liquid @@ -0,0 +1,44 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {boolean} allow_blank - Whether blank values are allowed + @param {number} is - Exact value to match + @param {number} maximum - Maximum allowed value + @param {string} message_is - Custom error message for is validation + @param {string} message_maximum - Custom error message for maximum validation + @param {string} message_minimum - Custom error message for minimum validation + @param {number} minimum - Minimum allowed value + @param {string} value - The value +{% enddoc %} +{% liquid + assign value = value | default: object[field_name] + assign size = value.size + assign is = is | default: null + assign minimum = minimum | default: null + assign maximum = maximum | default: null + + if allow_blank == null + assign allow_blank = true + endif + if allow_blank != true + function c = 'modules/core/validations/presence', c: c, object: object, field_name: field_name, key: null + endif + + if minimum != null and size < minimum + assign message = message_minimum | default: 'modules/core/validation.length.minimum' | t: count: minimum, value: size + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if maximum != null and size > maximum + assign message = message_maximum | default: 'modules/core/validation.length.maximum' | t: count: maximum, value: size + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if is != null and size != is + assign message = message_is | default: 'modules/core/validation.length.is' | t: count: is, value: size + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/matches.liquid b/pos-module-user-invites/modules/core/public/lib/validations/matches.liquid new file mode 100644 index 00000000..19a1c8ae --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/matches.liquid @@ -0,0 +1,20 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} regexp - The regular expression pattern to match against + @param {boolean} allow_blank - Whether blank values are allowed + @param {string} message - Custom error message override +{% enddoc %} +{% liquid + if allow_blank and object[field_name] == blank + return c + endif + + assign matches = object[field_name] | matches: regexp + if matches != true + assign message = message | default: 'modules/core/validation.matches' | t + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/not_null.liquid b/pos-module-user-invites/modules/core/public/lib/validations/not_null.liquid new file mode 100644 index 00000000..810b5f87 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/not_null.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + if object[field_name] == null + assign key = key | default: "modules/core/validation.null" + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/number.liquid b/pos-module-user-invites/modules/core/public/lib/validations/number.liquid new file mode 100644 index 00000000..d39591f7 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/number.liquid @@ -0,0 +1,69 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {number} eq - Must be equal to this value + @param {number} gt - Must be greater than this value + @param {number} gte - Must be greater than or equal to this value + @param {number} lt - Must be less than this value + @param {number} lte - Must be less than or equal to this value + @param {string} message - Custom error message override + @param {string} message_eq - Custom error message for eq validation + @param {string} message_gt - Custom error message for gt validation + @param {string} message_gte - Custom error message for gte validation + @param {string} message_lt - Custom error message for lt validation + @param {string} message_lte - Custom error message for lte validation + @param {string} message_ne - Custom error message for ne validation + @param {number} ne - Must not be equal to this value + @param {number} number - The number to validate +{% enddoc %} +{% liquid + assign number = number | default: object[field_name] +%} +{% capture test1 %}{{ number }}{% endcapture %} +{% capture test2 %}{{ test1 | plus: 0 }}{% endcapture %} +{% liquid + if test1 != test2 + assign message = message | default: 'modules/core/validation.number.invalid' | t: value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + + return c + endif + + assign number = number | plus: 0 + + if lt != null and number >= lt + assign message = message_lt | default: 'modules/core/validation.number.lt' | t: count: lt, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if lte == blank + assign lte = 2147483647 + endif + if number > lte + assign message = message_lte | default: 'modules/core/validation.number.lte' | t: count: lte, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if gt != null and number <= gt + assign message = message_gt | default: 'modules/core/validation.number.gt' | t: count: gt, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if gte != null and number < gte + assign message = message_gte | default: 'modules/core/validation.number.gte' | t: count: gte, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if eq != null and number != eq + assign message = message_eq | default: 'modules/core/validation.number.eq' | t: count: eq, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if ne != null and number == ne + assign message = message_ne | default: 'modules/core/validation.number.ne' | t: count: ne, value: number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/password_complexity.liquid b/pos-module-user-invites/modules/core/public/lib/validations/password_complexity.liquid new file mode 100644 index 00000000..634daa60 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/password_complexity.liquid @@ -0,0 +1,36 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {object} object - The object to process + @param {string} field_name - The name of the field to validate + @param {number} maximum - Maximum allowed value + @param {number} minimum - Minimum allowed value +{% enddoc %} +{% liquid + assign decoded_pw = object.password + assign minimum = minimum | default: 6 + assign maximum = maximum | default: 256 + assign field_name = field_name | default: 'password' + + function complex_password = 'modules/core/queries/variable/find', name: "MODULES/CORE/USE_COMPLEX_PASSWORD", type: "boolean", default: null + if complex_password + assign has_lowercase = decoded_pw | matches: '[a-z]' + unless has_lowercase + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.lowercase', message: null + endunless + + assign has_uppercase = decoded_pw | matches: '[A-Z]' + unless has_uppercase + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.uppercase', message: null + endunless + + assign has_number = decoded_pw | matches: '\d' + unless has_number + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.number', message: null + endunless + endif + + assign message_minimum = 'modules/core/validation.too_short' + function c = 'modules/core/validations/length', c: c, object: object, value: decoded_pw, field_name: field_name, maximum: maximum, minimum: minimum, message_minimum: message_minimum, allow_blank: null, is: null, message_is: null, message_maximum: null + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/presence.liquid b/pos-module-user-invites/modules/core/public/lib/validations/presence.liquid new file mode 100644 index 00000000..6526d2b3 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/presence.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + if object[field_name] == blank + assign key = key | default: "modules/core/validation.blank" + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/truthy.liquid b/pos-module-user-invites/modules/core/public/lib/validations/truthy.liquid new file mode 100644 index 00000000..86b428ee --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/truthy.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + unless object[field_name] + assign key = key | default: "modules/core/validation.not_truthy" + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/unique_elements.liquid b/pos-module-user-invites/modules/core/public/lib/validations/unique_elements.liquid new file mode 100644 index 00000000..4bca1e83 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/unique_elements.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + + assign unique_count = object[field_name] | uniq | size + + if unique_count != object[field_name].size + assign key = key | default: 'modules/core/validation.array.not_unique' + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/uniqueness.liquid b/pos-module-user-invites/modules/core/public/lib/validations/uniqueness.liquid new file mode 100644 index 00000000..76a99488 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/uniqueness.liquid @@ -0,0 +1,37 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} table - The database table name + @param {string} exclude_name - The property name to exclude + @param {string} key - The translation key for the error message + @param {string} scope_name - The scope property name for filtering +{% enddoc %} +{% liquid + assign key = key | default: 'modules/core/validation.taken' + assign value = object[field_name] + if value != blank + if object.id != blank + assign not_ids = object.id | split: ',' + endif + if scope_name + assign scope_value = object[scope_name] + else + assign scope_name = '' + endif + + if exclude_name + assign exclude_value = object[exclude_name] + else + assign exclude_name = '' + endif + + graphql r = 'modules/core/records/count', property_name: field_name, property_value: value, not_ids: not_ids, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value + + assign count = r.records.total_entries + if count > 0 + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/lib/validations/valid_object.liquid b/pos-module-user-invites/modules/core/public/lib/validations/valid_object.liquid new file mode 100644 index 00000000..6693ec3b --- /dev/null +++ b/pos-module-user-invites/modules/core/public/lib/validations/valid_object.liquid @@ -0,0 +1,20 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} check_function - The validation function to call + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} value - The value +{% enddoc %} +{% liquid + assign value = value | default: object[field_name] + if value + function check_object = check_function, object: value + if check_object.valid != true + function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.invalid', message: null + assign errors_key = field_name | append: '_errors' + assign c.errors[errors_key] = check_object.errors + endif + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/schema/status.yml b/pos-module-user-invites/modules/core/public/schema/status.yml new file mode 100644 index 00000000..5a8a0de2 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/schema/status.yml @@ -0,0 +1,14 @@ +name: status +properties: + - name: name + type: string + - name: timestamp + type: datetime + - name: reference_id + type: string + - name: reference_schema + type: string + - name: payload + type: string + - name: requester_id + type: string diff --git a/pos-module-user-invites/modules/core/public/translations/en/common.yml b/pos-module-user-invites/modules/core/public/translations/en/common.yml new file mode 100644 index 00000000..19ed613c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/translations/en/common.yml @@ -0,0 +1,4 @@ +en: + common: + deleted: 'Deleted' + deleted_failed: 'Deleted failed' diff --git a/pos-module-user-invites/modules/core/public/translations/en/validation.yml b/pos-module-user-invites/modules/core/public/translations/en/validation.yml new file mode 100644 index 00000000..06a1a480 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/translations/en/validation.yml @@ -0,0 +1,50 @@ +--- +en: + validation: + disallowed: is not valid + not_url: is not valid url + blank: cannot be blank + email: must be a valid email + equal: expected %{given} to equal %{expected} + equal_not_verbose: does not match + array: + not_included: '`%{value}` is not a valid value' + not_unique: elements must be unique + hcaptcha: Captcha has not been solved properly, please try again + length: + minimum: is too short (minimum is %{count} characters) + maximum: is too long (maximum is %{count} characters) + is: is the wrong length (should be %{count} characters) + blank: is blank + number: + invalid: '`%{value}` is not a number' + greater_than: must be greater than %{count} + greater_than_or_equal: must be greater than or equal to %{count} + less_than: must be less than %{count} + less_than_or_equal: must be less than or equal to %{count} + equal_to: must be equal to %{count} + gt: must be greater than %{count} + gte: must be greater than or equal to %{count} + lt: must be less than %{count} + lte: must be less than or equal to %{count} + eq: must be equal to %{count} + ne: must be not equal to %{count} + date: + can_be_past: The date cannot be in the past + can_be_future: The date cannot be in the future + lt: must be before %{date} + lte: must be before %{date} + gt: must be after %{date} + gte: must be after or equal to %{date} + too_short: has to be longer than %{value} characters + taken: already taken + not_uniq: not unique + matches: not valid format + not_truthy: not true + not_null: not null + password: + lowercase: must include at least one lower case + uppercase: must include at least one upper case + number: must include at least one number + invalid: invalid + not_exist: not exist diff --git a/pos-module-user-invites/modules/core/public/views/layouts/basic.liquid b/pos-module-user-invites/modules/core/public/views/layouts/basic.liquid new file mode 100644 index 00000000..6b57c725 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/layouts/basic.liquid @@ -0,0 +1,154 @@ + + + + + + + +
    +
    + {{ content_for_layout }} +
    +
    + + diff --git a/pos-module-user-invites/modules/core/public/views/layouts/mailer.html.liquid b/pos-module-user-invites/modules/core/public/views/layouts/mailer.html.liquid new file mode 100644 index 00000000..510f6a1a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/layouts/mailer.html.liquid @@ -0,0 +1,46 @@ +{% liquid + assign rtl_languages = 'ar,arc,dv,fa,ha,he,khw,ks,ku,ps,ur,yi' | split: ',' + if rtl_languages contains context.language + assign direction = 'rtl' + else + assign direction = 'ltr' + endif + assign url = 'https://' | append: context.location.host +%} + + + + + + + + +
    + {{ content_for_layout }} + + +
    + + + diff --git a/pos-module-user-invites/modules/core/public/views/pages/_events/index.liquid b/pos-module-user-invites/modules/core/public/views/pages/_events/index.liquid new file mode 100644 index 00000000..e5c90c86 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/pages/_events/index.liquid @@ -0,0 +1,11 @@ +--- +layout: modules/core/basic +slug: _events +--- +{% liquid + if context.environment == 'staging' or context.environment == 'development' + function events = 'modules/core/queries/events/search', limit: 50, page: null, uuids: null + + render 'modules/core/events/list', events: events + endif +%} diff --git a/pos-module-user-invites/modules/core/public/views/pages/_events/trigger.liquid b/pos-module-user-invites/modules/core/public/views/pages/_events/trigger.liquid new file mode 100644 index 00000000..85099b80 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/pages/_events/trigger.liquid @@ -0,0 +1,20 @@ +--- +layout: modules/core/basic +slug: _events/:uuid/trigger +--- +{% liquid + if context.environment == 'staging' or context.environment == 'development' + function event = 'modules/core/queries/events/find', uuid: context.params.uuid + + if context.params.trigger + function event = 'modules/core/commands/events/broadcast', object: event, deprecated_delay: null, deprecated_max_attempts: null + echo 'BROADCASTED' + else + assign name = 'consumers/' | append: event.type | append: '/' + graphql consumers = 'modules/core/events/consumers', name: name | dig: "admin_liquid_partials", "results" + assign event.consumers = consumers + endif + + render 'modules/core/events/show', event: event + endif +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/events/event_card.liquid b/pos-module-user-invites/modules/core/public/views/partials/events/event_card.liquid new file mode 100644 index 00000000..fcee8e27 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/events/event_card.liquid @@ -0,0 +1,56 @@ +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign event_slim = event | deep_clone + assign _ = event_slim | hash_delete_key: 'object' + assign _ = event_slim | hash_delete_key: 'actor' + assign _ = event_slim | hash_delete_key: 'target' + assign _ = event_slim | hash_delete_key: 'id' + assign _ = event_slim | hash_delete_key: 'uuid' + assign _ = event_slim | hash_delete_key: 'date' + assign _ = event_slim | hash_delete_key: 'valid' + assign _ = event_slim | hash_delete_key: 'errors' + assign _ = event_slim | hash_delete_key: 'attributed_to' + assign _ = event_slim | hash_delete_key: 'type' + assign consumers = event_slim | hash_delete_key: 'consumers' +%} +
    +
    + Event: {{ event.type }} {{ event.object.name | replace: "app.statuses.", "" }} +
    +
    + Date: {{ event.date | l }} +
    +
    + Attributes:
    + + + +
    
    +    
    + + +
    +
    UUID: {{ event.uuid }}
    + {% if consumers %} +
    + Consumers: +
      + {% for consumer in consumers %} +
    • {{ consumer.path }}
    • + {% endfor %} +
    +
    + {% endif %} + + show | + broadcast | + + +
    diff --git a/pos-module-user-invites/modules/core/public/views/partials/events/list.liquid b/pos-module-user-invites/modules/core/public/views/partials/events/list.liquid new file mode 100644 index 00000000..d6c0c4a0 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/events/list.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} events - The events collection +{% enddoc %} +
    +

    Events

    + {{ events.results.size }} / {{ events.total_entries }} + {% for event in events.results %} + {% render 'modules/core/events/event_card', event: event.payload %} +
    + {% else %} +

    no events found

    + {% endfor %} +
    diff --git a/pos-module-user-invites/modules/core/public/views/partials/events/show.liquid b/pos-module-user-invites/modules/core/public/views/partials/events/show.liquid new file mode 100644 index 00000000..665a5055 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/events/show.liquid @@ -0,0 +1,6 @@ +{% doc %} + @param {object} event - The event object +{% enddoc %} +

    Event

    +<< List +{% render 'modules/core/events/event_card', event: event %} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send.liquid new file mode 100644 index 00000000..f03248b2 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send.liquid @@ -0,0 +1,22 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + log 'Use modules/core/commands/email/send instead of modules/core/lib/commands/email/send', type: 'DEPRECATION' + function object = 'modules/core/commands/email/send/build', object: object + function object = 'modules/core/commands/email/send/check', object: object + + if object.valid + graphql r = 'modules/core/email/send', template: 'modules/core/generic', data: object + if r.errors + log r.errors, type: 'errors.graphql.invalid' + + assign object.valid = false + assign object.errors = r.errors + endif + else + log object.errors, type: 'payload validation error in core: lib/commands/email' + endif + + return object +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/build.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/build.liquid new file mode 100644 index 00000000..5e57d280 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/build.liquid @@ -0,0 +1,13 @@ +{% parse_json object %} + { + "layout": {{ object.layout | default: 'modules/core/mailer' | json }}, + "from": {{ object.from | json }}, + "to": {{ object.to | json }}, + "subject": {{ object.subject | json }}, + "cc": {{ object.cc | json }}, + "bcc": {{ object.bcc | json }}, + "partial": {{ object.partial | json }}, + "data": {{ object.data | json }} + } +{% endparse_json %} +{% return object %} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/check.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/check.liquid new file mode 100644 index 00000000..50c8aec5 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/email/send/check.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'from', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'to', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'layout', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'partial', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/alter.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/alter.liquid new file mode 100644 index 00000000..43fbfa5a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/alter.liquid @@ -0,0 +1,19 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix + @param {object} params - Parameters to pass to the hook + @param {object} params_to_modify - The object to be modified by the alter hook +{% enddoc %} +{% liquid + log 'Use modules/core/commands/hook/alter instead of modules/core/lib/commands/hook/alter', type: 'DEPRECATION' + assign original_params = params_to_modify | deep_clone + + assign hook = '/hook_' | append: hook | append: '_alter' + function implementations = 'modules/core/lib/queries/hook/search', hook: hook + + for implementation in implementations + function _ = implementation.path, params_to_modify: params_to_modify, params: params + endfor + + assign result = { "original_params": original_params } + return result +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/fire.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/fire.liquid new file mode 100644 index 00000000..48cd149d --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/hook/fire.liquid @@ -0,0 +1,38 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix + @param {object} params - Parameters to pass to the hook + @param {boolean} merge_to_object - If true, merge results into one object instead of collecting in an array +{% enddoc %} +{% liquid + if merge_to_object + assign results = {} + else + assign results = [] + endif + + assign hook = '/hook_' | append: hook + function implementations = 'modules/core/lib/queries/hook/search', hook: hook + + for implementation in implementations + function hook_result = implementation.path, params: params + if hook_result != nil + comment + Check if the result is an array and merge the values one by one. + endcomment + if hook_result[0] + for h_result in hook_result + assign results << h_result + endfor + comment + Check if the result is an object. + endcomment + elsif hook_result.first and merge_to_object + assign results = results | hash_merge: hook_result + else + assign results << hook_result + endif + endif + endfor + + return results +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/commands/variable/set.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/variable/set.liquid new file mode 100644 index 00000000..dc2577bd --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/commands/variable/set.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {string} name - The name identifier + @param {string} value - The value +{% enddoc %} +{% liquid + log 'Use modules/core/commands/variable/set instead of modules/core/lib/commands/variable/set', type: 'DEPRECATION' + graphql result = 'modules/core/variable/set', name: name, value: value + return result.variable +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/helpers/register_error.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/helpers/register_error.liquid new file mode 100644 index 00000000..f016b3e7 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/helpers/register_error.liquid @@ -0,0 +1,26 @@ +{% doc %} + @param {object} contract - The contract object for collecting errors + @param {string} field_name - The name of the field to validate + @param {string} key - The translation key for the error message + @param {string} message - Custom error message override +{% enddoc %} +{% liquid + assign key = key | default: null + assign message = message | default: null + if key + assign msg = key | t + else + assign msg = message + endif + + assign errors = contract.errors + + assign default = [] + assign field_errors = errors[field_name] | default: default + assign field_errors << msg + + assign errors[field_name] = field_errors + assign contract.valid = false + + return contract +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/get.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/get.liquid new file mode 100644 index 00000000..37efd30c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/get.liquid @@ -0,0 +1,6 @@ +{% liquid + # TODO: remove after rewriting dependent modules + log 'Use queries/headscripts/get instead of lib/queries/headscripts/get', type: 'DEPRECATION' + function res = 'modules/core/lib/queries/headscripts/search', merge_to_object: false + return res +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/search.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/search.liquid new file mode 100644 index 00000000..72607a41 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/headscripts/search.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {boolean} merge_to_object - If true, merge results into one object instead of collecting in an array +{% enddoc %} +{% liquid + log 'Use queries/headscripts/search instead of lib/queries/headscripts/search', type: 'DEPRECATION' + function headscript_implementations = 'modules/core/lib/commands/hook/fire', hook: 'headscripts', merge_to_object: merge_to_object, params: null + assign results = headscript_implementations | join: '' + return results | html_safe +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/hook/search.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/hook/search.liquid new file mode 100644 index 00000000..f97ad065 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/hook/search.liquid @@ -0,0 +1,8 @@ +{% doc %} + @param {string} hook - The hook name without hook_ prefix +{% enddoc %} +{% liquid + log 'Use modules/core/queries/hook/search instead of modules/core/lib/queries/hook/search', type: 'DEPRECATION' + graphql implementations = 'modules/core/hook/search', hook: hook + return implementations.admin_liquid_partials.results +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/module/exists.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/module/exists.liquid new file mode 100644 index 00000000..9801f78e --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/module/exists.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} name - The name identifier + @param {string} type - The type identifier +{% enddoc %} +{% liquid + function modules = 'modules/core/lib/queries/registry/search', type: type + assign module = modules | array_detect: machine_name: name + + if module + return true + endif + + return false +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/get.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/get.liquid new file mode 100644 index 00000000..adbdeda3 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/get.liquid @@ -0,0 +1,8 @@ +{% doc %} + @param {string} type - The type identifier +{% enddoc %} +{% liquid + # TODO: remove after rewriting dependent modules + function registry = 'modules/core/lib/queries/registry/search', type: type + return registry +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/search.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/search.liquid new file mode 100644 index 00000000..ae8f96c1 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/registry/search.liquid @@ -0,0 +1,26 @@ +{% doc %} + @param {string} type - The type identifier +{% enddoc %} +{% liquid + function registry = 'modules/core/lib/commands/hook/fire', hook: 'module_info', merge_to_object: false, params: null + + case type + when 'module' + assign modules = [] + for module in registry + if module.type == 'module' + assign modules << module + endif + endfor + return modules + when 'theme' + assign themes = [] + for module in registry + if module.type == 'theme' + assign themes << module + endif + endfor + return themes + endcase + return registry +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/find.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/find.liquid new file mode 100644 index 00000000..c2ec54ce --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/find.liquid @@ -0,0 +1,28 @@ +{% doc %} + @param {string} default - The default value + @param {string} type - The type identifier + @param {string} name - The name identifier +{% enddoc %} +{% liquid + assign value = context.constants[name] | default: default, allow_false: true + + case type + when 'boolean' + if value == 'true' or value == true + return true + else + return false + endif + when 'integer' + assign value = value | plus: 0 + return value + when 'float' + assign value = value | plus: 0 + return value + when 'array' + assign value = value | split: ',' + return value + else + return value + endcase +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/get.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/get.liquid new file mode 100644 index 00000000..f6ba4828 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/queries/variable/get.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} default - The default value + @param {string} name - The name identifier + @param {string} type - The type identifier +{% enddoc %} +{% liquid + # TODO: remove after rewriting dependent modules + function res = 'modules/core/lib/queries/variable/find', name: name, default: default, type: type + return res +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/date.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/date.liquid new file mode 100644 index 00000000..e4d6a7b9 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/date.liquid @@ -0,0 +1,79 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {boolean} can_be_future - Whether the date can be in the future + @param {boolean} can_be_past - Whether the date can be in the past + @param {string} date - The date to validate + @param {number} gt - Must be greater than this value + @param {number} gte - Must be greater than or equal to this value + @param {number} lt - Must be less than this value + @param {number} lte - Must be less than or equal to this value + @param {string} message_can_be_future - Custom error message for can_be_future validation + @param {string} message_can_be_past - Custom error message for can_be_past validation + @param {string} message_gt - Custom error message for gt validation + @param {string} message_gte - Custom error message for gte validation + @param {string} message_lt - Custom error message for lt validation + @param {string} message_lte - Custom error message for lte validation +{% enddoc %} +{% liquid + log 'Use modules/core/validations/date instead of modules/core/lib/validations/date ', type: 'DEPRECATION' + assign date = date | default: object[field_name] | to_date + + assign is_past = date | is_date_in_past + assign now = 'now' | to_date + + if date > now + assign is_future = true + else + assign is_future = false + endif + + if can_be_past == false and is_past + assign message = message_can_be_past | default: 'modules/core/validation.date.can_be_past' | t: count: can_be_past, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if can_be_future == false and is_future + assign message = message_can_be_future | default: 'modules/core/validation.date.can_be_future' | t: count: can_be_future, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if lt != null + assign lt = lt | to_date + if date >= lt + assign localized_date = lt | l + assign message = message_lt | default: 'modules/core/validation.date.lt' | t: date: localized_date, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if lte != null + assign lte = lte | to_date + if date > lte + assign localized_date = lte | l + assign message = message_lte | default: 'modules/core/validation.date.lte' | t: date: localized_date, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if gt != null + assign gt = gt | to_date + if date <= gt + assign localized_date = gt | l + assign message = message_gt | default: 'modules/core/validation.date.gt' | t: date: localized_date, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if gte != null + assign gte = gte | to_date + if date < gte + assign localized_date = gte | l + assign message = message_gte | default: 'modules/core/validation.date.gte' | t: date: localized_date, value: date + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/each_element_length.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/each_element_length.liquid new file mode 100644 index 00000000..2c7f1071 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/each_element_length.liquid @@ -0,0 +1,35 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {number} is - Exact value to match + @param {number} maximum - Maximum allowed value + @param {number} minimum - Minimum allowed value +{% enddoc %} +{% liquid + log 'Use modules/core/validations/each_element_length instead of modules/core/lib/validations/each_element_length ', type: 'DEPRECATION' + for el in object[field_name] + + assign size = el.size + + if minimum != null and size < minimum + assign message = 'modules/core/validation.length.minimum' | t: count: minimum, value: size + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if maximum != null and size > maximum + assign message = 'modules/core/validation.length.maximum' | t: count: maximum, value: size + assign message = el | append: ' ' | append: message + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if is != null and size != is + assign message = 'modules/core/validation.length.is' | t: count: is, value: size + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + endfor + + return c + +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/elements_included.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/elements_included.liquid new file mode 100644 index 00000000..bd8035b5 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/elements_included.liquid @@ -0,0 +1,20 @@ +{% doc %} + @param {string} array - The array of allowed values + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/elements_included instead of modules/core/lib/validations/elements_included ', type: 'DEPRECATION' + for val in object[field_name] + unless array contains val + assign key = key | default: "modules/core/validation.array.not_included" + assign message = key | t: value: val + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endunless + endfor + + return c +%} + diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/email.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/email.liquid new file mode 100644 index 00000000..6699b19a --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/email.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/email instead of modules/core/lib/validations/email ', type: 'DEPRECATION' + assign valid_email = object[field_name] | is_email_valid + unless valid_email + assign key = key | default: "modules/core/validation.email" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/equal.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/equal.liquid new file mode 100644 index 00000000..97284b8f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/equal.liquid @@ -0,0 +1,24 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} expected - The expected value to compare against + @param {string} field_name - The name of the field to validate + @param {string} given - The given value to compare + @param {string} key - The translation key for the error message + @param {string} message - Custom error message override + @param {boolean} not_verbose - If true, suppress detailed error output +{% enddoc %} +{% liquid + log 'Use modules/core/validations/equal instead of modules/core/lib/validations/equal ', type: 'DEPRECATION' + if given != expected + + if message == blank and key == blank + if not_verbose + assign message = 'modules/core/validation.equal_not_verbose' | t + else + assign message = 'modules/core/validation.equal' | t: given: given, expected: expected + endif + endif + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: key + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/exist_in_db.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/exist_in_db.liquid new file mode 100644 index 00000000..c86b2fce --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/exist_in_db.liquid @@ -0,0 +1,32 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {string} table - The database table name + @param {string} exclude_name - The property name to exclude + @param {string} exclude_value - The property value to exclude + @param {string} ids - List of record IDs to include + @param {string} key - The translation key for the error message + @param {string} not_ids - List of record IDs to exclude + @param {string} property_name - The property name to check + @param {string} property_value - The property value to check + @param {string} scope_name - The scope property name for filtering + @param {string} scope_value - The scope property value for filtering +{% enddoc %} +{% liquid + log 'Use modules/core/validations/exist_in_db instead of modules/core/lib/validations/exist_in_db ', type: 'DEPRECATION' + assign property_name = property_name | default: '' + assign property_value = property_value | default: '' + assign scope_name = scope_name | default: '' + assign scope_value = scope_value | default: '' + assign exclude_name = exclude_name | default: '' + assign exclude_value = exclude_value | default: '' + assign key = key | default: 'modules/core/validation.not_exist' + + graphql r = 'modules/core/records/count', ids: ids, not_ids: not_ids, property_name: property_name, property_value: property_value, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value + + assign count = r.records.total_entries + if count == 0 + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/hcaptcha.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/hcaptcha.liquid new file mode 100644 index 00000000..7693b5aa --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/hcaptcha.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {object} hcaptcha_params - The hCaptcha verification parameters + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/hcaptcha instead of modules/core/lib/validations/hcaptcha ', type: 'DEPRECATION' + assign hcaptcha_solved = hcaptcha_params | hcaptcha + unless hcaptcha_solved + assign key = key | default: "modules/core/validation.hcaptcha" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'hcaptcha', key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/included.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/included.liquid new file mode 100644 index 00000000..85b4d169 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/included.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} array - The array of allowed values + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message + @param {string} value - The value +{% enddoc %} +{% liquid + log 'Use modules/core/validations/included instead of modules/core/lib/validations/included ', type: 'DEPRECATION' + assign value = value | default: object[field_name] + unless array contains value + assign key = key | default: "modules/core/validation.not_included" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} + diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/length.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/length.liquid new file mode 100644 index 00000000..403a064f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/length.liquid @@ -0,0 +1,49 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {boolean} allow_blank - Whether blank values are allowed + @param {number} is - Exact value to match + @param {number} maximum - Maximum allowed value + @param {string} message_blank - Custom error message for blank validation + @param {string} message_is - Custom error message for is validation + @param {string} message_maximum - Custom error message for maximum validation + @param {string} message_minimum - Custom error message for minimum validation + @param {number} minimum - Minimum allowed value + @param {string} value - The value +{% enddoc %} +{% liquid + log 'Use modules/core/validations/length instead of modules/core/lib/validations/length ', type: 'DEPRECATION' + assign value = value | default: object[field_name] + assign size = value.size + assign is = is | default: null + assign minimum = minimum | default: null + assign maximum = maximum | default: null + + if allow_blank == null + assign allow_blank = true + endif + if allow_blank != true + if size == blank + assign message = message_blank | default: 'modules/core/validation.length.blank' | t + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + endif + + if minimum != null and size < minimum + assign message = message_minimum | default: 'modules/core/validation.length.minimum' | t: count: minimum, value: size + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if maximum != null and size > maximum + assign message = message_maximum | default: 'modules/core/validation.length.maximum' | t: count: maximum, value: size + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if is != null and size != is + assign message = message_is | default: 'modules/core/validation.length.is' | t: count: is, value: size + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/matches.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/matches.liquid new file mode 100644 index 00000000..fb47b05c --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/matches.liquid @@ -0,0 +1,21 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} regexp - The regular expression pattern to match against + @param {boolean} allow_blank - Whether blank values are allowed + @param {string} message - Custom error message override +{% enddoc %} +{% liquid + log 'Use modules/core/validations/matches instead of modules/core/lib/validations/matches ', type: 'DEPRECATION' + if allow_blank and object[field_name] == blank + return c + endif + + assign matches = object[field_name] | matches: regexp + if matches != true + assign message = message | default: 'modules/core/validation.matches' | t + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/not_null.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/not_null.liquid new file mode 100644 index 00000000..23d6bd0f --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/not_null.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/not_null instead of modules/core/lib/validations/not_null ', type: 'DEPRECATION' + if object[field_name] == null + assign key = key | default: "modules/core/validation.null" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/number.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/number.liquid new file mode 100644 index 00000000..6a11fe0b --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/number.liquid @@ -0,0 +1,70 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {number} eq - Must be equal to this value + @param {number} gt - Must be greater than this value + @param {number} gte - Must be greater than or equal to this value + @param {number} lt - Must be less than this value + @param {number} lte - Must be less than or equal to this value + @param {string} message - Custom error message override + @param {string} message_eq - Custom error message for eq validation + @param {string} message_gt - Custom error message for gt validation + @param {string} message_gte - Custom error message for gte validation + @param {string} message_lt - Custom error message for lt validation + @param {string} message_lte - Custom error message for lte validation + @param {string} message_ne - Custom error message for ne validation + @param {number} ne - Must not be equal to this value + @param {number} number - The number to validate +{% enddoc %} +{% liquid + assign number = number | default: object[field_name] + log 'Use modules/core/validations/number instead of modules/core/lib/validations/number ', type: 'DEPRECATION' +%} +{% capture test1 %}{{ number }}{% endcapture %} +{% capture test2 %}{{ test1 | plus: 0 }}{% endcapture %} +{% liquid + if test1 != test2 + assign message = message | default: 'modules/core/validation.number.invalid' | t: value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + + return c + endif + + assign number = number | plus: 0 + + if lt != null and number >= lt + assign message = message_lt | default: 'modules/core/validation.number.lt' | t: count: lt, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if lte == blank + assign lte = 2147483647 + endif + if number > lte + assign message = message_lte | default: 'modules/core/validation.number.lte' | t: count: lte, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if gt != null and number <= gt + assign message = message_gt | default: 'modules/core/validation.number.gt' | t: count: gt, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if gte != null and number < gte + assign message = message_gte | default: 'modules/core/validation.number.gte' | t: count: gte, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if eq != null and number != eq + assign message = message_eq | default: 'modules/core/validation.number.eq' | t: count: eq, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + if ne != null and number == ne + assign message = message_ne | default: 'modules/core/validation.number.ne' | t: count: ne, value: number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/password_complexity.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/password_complexity.liquid new file mode 100644 index 00000000..04bb51ca --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/password_complexity.liquid @@ -0,0 +1,31 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {object} object - The object to process +{% enddoc %} +{% liquid + log 'Use modules/core/validations/password_complexity instead of modules/core/lib/validations/password_complexity ', type: 'DEPRECATION' + assign decoded_pw = object.password + + function complex_password = 'modules/core/lib/queries/variable/find' name: "MODULES/CORE/USE_COMPLEX_PASSWORD", type: "boolean", default: null + if complex_password + assign has_lowercase = decoded_pw | matches: '[a-z]' + unless has_lowercase + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.lowercase', message: null + endunless + + assign has_uppercase = decoded_pw | matches: '[A-Z]' + unless has_uppercase + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.uppercase', message: null + endunless + + assign has_number = decoded_pw | matches: '\d' + unless has_number + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.number', message: null + endunless + endif + + assign message_minimum = 'modules/core/validation.too_short' + function c = 'modules/core/lib/validations/length', c: c, object: object, value: decoded_pw, field_name: 'password', maximum: 256, minimum: 6, message_minimum: message_minimum, allow_blank: null, is: null, message_blank: null, message_is: null, message_maximum: null + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/presence.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/presence.liquid new file mode 100644 index 00000000..06862bdf --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/presence.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/presence instead of modules/core/lib/validations/presence ', type: 'DEPRECATION' + if object[field_name] == blank + assign key = key | default: "modules/core/validation.blank" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/truthy.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/truthy.liquid new file mode 100644 index 00000000..9b2a93e2 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/truthy.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/truthy instead of modules/core/lib/validations/truthy ', type: 'DEPRECATION' + unless object[field_name] + assign key = key | default: "modules/core/validation.not_truthy" + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endunless + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/unique_elements.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/unique_elements.liquid new file mode 100644 index 00000000..f0524837 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/unique_elements.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} key - The translation key for the error message +{% enddoc %} +{% liquid + log 'Use modules/core/validations/unique_elements instead of modules/core/lib/validations/unique_elements ', type: 'DEPRECATION' + assign unique_count = object[field_name] | uniq | size + + if unique_count != object[field_name].size + assign key = key | default: 'modules/core/validation.array.not_unique' + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/uniqueness.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/uniqueness.liquid new file mode 100644 index 00000000..66d62c72 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/uniqueness.liquid @@ -0,0 +1,38 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} table - The database table name + @param {string} exclude_name - The property name to exclude + @param {string} key - The translation key for the error message + @param {string} scope_name - The scope property name for filtering +{% enddoc %} +{% liquid + log 'Use modules/core/validations/uniqueness instead of modules/core/lib/validations/uniqueness ', type: 'DEPRECATION' + assign key = key | default: 'modules/core/validation.taken' + assign value = object[field_name] + if value != blank + if object.id != blank + assign not_ids = object.id | split: ',' + endif + if scope_name + assign scope_value = object[scope_name] + else + assign scope_name = '' + endif + + if exclude_name + assign exclude_value = object[exclude_name] + else + assign exclude_name = '' + endif + + graphql r = 'modules/core/records/count', property_name: field_name, property_value: value, not_ids: not_ids, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value + + assign count = r.records.total_entries + if count > 0 + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key, message: null + endif + endif + return c +%} diff --git a/pos-module-user-invites/modules/core/public/views/partials/lib/validations/valid_object.liquid b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/valid_object.liquid new file mode 100644 index 00000000..690addf9 --- /dev/null +++ b/pos-module-user-invites/modules/core/public/views/partials/lib/validations/valid_object.liquid @@ -0,0 +1,21 @@ +{% doc %} + @param {object} c - The contract object for collecting validation errors + @param {string} check_function - The validation function to call + @param {string} field_name - The name of the field to validate + @param {object} object - The object to process + @param {string} value - The value +{% enddoc %} +{% liquid + log 'Use modules/core/validations/valid_object instead of modules/core/lib/validations/valid_object ', type: 'DEPRECATION' + assign value = value | default: object[field_name] + if value + function check_object = check_function, object: value + if check_object.valid != true + function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.invalid', message: null + assign errors_key = field_name | append: '_errors' + assign c.errors[errors_key] = check_object.errors + endif + endif + + return c +%} diff --git a/pos-module-user-invites/modules/core/template-values.json b/pos-module-user-invites/modules/core/template-values.json new file mode 100644 index 00000000..dfe07931 --- /dev/null +++ b/pos-module-user-invites/modules/core/template-values.json @@ -0,0 +1,7 @@ +{ + "name": "Pos Module Core", + "machine_name": "core", + "type": "module", + "version": "2.1.8", + "dependencies": {} +} diff --git a/pos-module-user-invites/modules/oauth_github/pos-module.json b/pos-module-user-invites/modules/oauth_github/pos-module.json new file mode 100644 index 00000000..0cc31a3f --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/pos-module.json @@ -0,0 +1,8 @@ +{ + "machine_name": "oauth_github", + "version": "0.0.12", + "name": "pos-module-oauth-github", + "dependencies": { + "core": "^2.1.8" + } +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/assets/img/icon.svg b/pos-module-user-invites/modules/oauth_github/public/assets/img/icon.svg new file mode 100644 index 00000000..d5e64918 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/assets/img/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/graphql/get_token.graphql b/pos-module-user-invites/modules/oauth_github/public/graphql/get_token.graphql new file mode 100644 index 00000000..c9895c16 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/graphql/get_token.graphql @@ -0,0 +1,13 @@ +mutation ($headers: HashObject, $body: String){ + api_call_send( + api_call: { + url: "https://github.com/login/oauth/access_token" + method: "POST" + body: $body + headers: $headers + }) { + response { + body + } + } +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_email.graphql b/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_email.graphql new file mode 100644 index 00000000..42bcd365 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_email.graphql @@ -0,0 +1,11 @@ +mutation ($headers: HashObject) { + api_call_send(api_call: { + url: "https://api.github.com/user/emails" + method: "GET" + headers: $headers + }) { + response { + body + } + } +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_info.graphql b/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_info.graphql new file mode 100644 index 00000000..2bdee53c --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/graphql/get_user_info.graphql @@ -0,0 +1,11 @@ +mutation ($headers: HashObject) { + api_call_send(api_call: { + url: "https://api.github.com/user" + method: "GET" + headers: $headers + }) { + response { + body + } + } +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token.liquid new file mode 100644 index 00000000..b26bf538 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token.liquid @@ -0,0 +1,18 @@ +{% liquid + function object = 'modules/oauth_github/commands/get_token/build', object: data + function object = 'modules/oauth_github/commands/get_token/check', object: object + assign query = object | querify + + if object.valid + assign headers = { "Accept": "application/json" } + + graphql r = "modules/oauth_github/get_token", body: query, headers: headers + assign result = r.api_call_send.response.body | parse_json + return result + else + log object.errors, type: "ERROR" + endif + + return null +%} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/build.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/build.liquid new file mode 100644 index 00000000..745634a4 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/build.liquid @@ -0,0 +1,10 @@ +{% parse_json object %} + { + "grant_type": "authorization_code", + "code": {{ object.code | json }}, + "client_id": {{ object.client_id | json }}, + "client_secret": {{ object.client_secret | json }} + } + {% endparse_json %} + {% return object %} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/check.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/check.liquid new file mode 100644 index 00000000..f8ecdc8a --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_token/check.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {object} object - The object to validate +{% enddoc %} +{% liquid +assign c = { "errors": {}, "valid": true } + +function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'grant_type', key: null +function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'code', key: null +function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'client_id', key: null +function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'client_secret', key: null + +assign object.valid = c.valid +assign object.errors = c.errors + +return object +%} diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email.liquid new file mode 100644 index 00000000..53c773b0 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email.liquid @@ -0,0 +1,15 @@ +{% liquid + assign bearer = "Bearer " | append: data.access_token + function object = 'modules/oauth_github/commands/get_user_email/build', object: bearer + function object = 'modules/oauth_github/commands/get_user_email/check', object: object + + if object.valid + graphql r = 'modules/oauth_github/get_user_email', headers: object + assign result = r.api_call_send.response.body | parse_json + return result + else + log object.errors, type: "ERROR" + endif + + return null +%} diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/build.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/build.liquid new file mode 100644 index 00000000..0932a0d3 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/build.liquid @@ -0,0 +1,8 @@ +{% parse_json object %} + { + "Accept": "application/json", + "Authorization": {{ object | json }} + } +{% endparse_json %} +{% return object %} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/check.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/check.liquid new file mode 100644 index 00000000..dfda33e6 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_email/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to validate +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'Accept', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'Authorization', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info.liquid new file mode 100644 index 00000000..9ba2af23 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info.liquid @@ -0,0 +1,16 @@ +{% liquid + assign bearer = "Bearer " | append: data.access_token + function object = 'modules/oauth_github/commands/get_user_info/build', object: bearer + function object = 'modules/oauth_github/commands/get_user_info/check', object: object + + if object.valid + graphql r = 'modules/oauth_github/get_user_info', headers: object + assign result = r.api_call_send.response.body | parse_json + return result + else + log object.errors, type: "ERROR" + endif + + return null +%} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/build.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/build.liquid new file mode 100644 index 00000000..0932a0d3 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/build.liquid @@ -0,0 +1,8 @@ +{% parse_json object %} + { + "Accept": "application/json", + "Authorization": {{ object | json }} + } +{% endparse_json %} +{% return object %} + \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/check.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/check.liquid new file mode 100644 index 00000000..dfda33e6 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/commands/get_user_info/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to validate +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'Accept', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'Authorization', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_redirect_url.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_redirect_url.liquid new file mode 100644 index 00000000..32cfeb23 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_redirect_url.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {object} provider - The OAuth provider configuration + @param {string} state - The OAuth state parameter +{% enddoc %} +{% liquid +assign data = { "scope": "user:email", "client_id": provider.client_id, "state": state } + +assign querified_data = data | querify +assign url = "https://github.com/login/oauth/authorize?" | append: querified_data + +return url +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_user_info.liquid b/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_user_info.liquid new file mode 100644 index 00000000..47222e1d --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/lib/helpers/get_user_info.liquid @@ -0,0 +1,42 @@ +{% doc %} + @param {object} provider - The OAuth provider configuration +{% enddoc %} +{% liquid +# fetch token and get user data +assign get_token_request = { "client_id": provider.client_id, "client_secret": provider.secret_value, "code": context.params.code } + +# get access token +function access_token = "modules/oauth_github/commands/get_token", data: get_token_request +assign access_token = access_token.access_token + +assign result = { "valid": false } + +if access_token == null + return result +endif + +# get user info +assign request_data = { "access_token": access_token } + +function user_info = "modules/oauth_github/commands/get_user_info", data: request_data +if user_info.email == null + function user_emails = "modules/oauth_github/commands/get_user_email", data: request_data + for email in user_emails + if email.primary == true + assign user_info.email = email.email + endif + endfor +endif + +assign name = user_info.name | split: ' ' +assign result.first_name = name[0] | default: user_info.login +assign result.last_name = name[1] | default: '' +assign result.sub = user_info.id +assign result.email = user_info.email + +if result.sub != null and result["email"] != null + assign result.valid = true +endif + +return result +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/public/translations/en/provider.yml b/pos-module-user-invites/modules/oauth_github/public/translations/en/provider.yml new file mode 100644 index 00000000..0536efa8 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/public/translations/en/provider.yml @@ -0,0 +1,5 @@ +en: + provider: + button: + continue: Continue with GitHub + disconnect: Disconnect from GitHub \ No newline at end of file diff --git a/pos-module-user-invites/modules/oauth_github/template-values.json b/pos-module-user-invites/modules/oauth_github/template-values.json new file mode 100644 index 00000000..489a0738 --- /dev/null +++ b/pos-module-user-invites/modules/oauth_github/template-values.json @@ -0,0 +1,9 @@ +{ + "name": "pos-module-oauth-github", + "machine_name": "oauth_github", + "type": "module", + "version": "0.0.12", + "dependencies": { + "core": "^2.1.8" + } +} diff --git a/pos-module-user-invites/modules/user/package-lock.json b/pos-module-user-invites/modules/user/package-lock.json new file mode 100644 index 00000000..378a87da --- /dev/null +++ b/pos-module-user-invites/modules/user/package-lock.json @@ -0,0 +1,318 @@ +{ + "name": "user", + "version": "1.0.2", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "user", + "version": "1.0.2", + "license": "MIT", + "devDependencies": { + "auto-changelog": "^2.4.0" + } + }, + "node_modules/auto-changelog": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz", + "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==", + "dev": true, + "dependencies": { + "commander": "^7.2.0", + "handlebars": "^4.7.7", + "node-fetch": "^2.6.1", + "parse-github-url": "^1.0.2", + "semver": "^7.3.5" + }, + "bin": { + "auto-changelog": "src/index.js" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true, + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz", + "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + }, + "dependencies": { + "auto-changelog": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz", + "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==", + "dev": true, + "requires": { + "commander": "^7.2.0", + "handlebars": "^4.7.7", + "node-fetch": "^2.6.1", + "parse-github-url": "^1.0.2", + "semver": "^7.3.5" + } + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "uglify-js": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz", + "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==", + "dev": true, + "optional": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/pos-module-user-invites/modules/user/package.json b/pos-module-user-invites/modules/user/package.json new file mode 100644 index 00000000..720b25a6 --- /dev/null +++ b/pos-module-user-invites/modules/user/package.json @@ -0,0 +1,26 @@ +{ + "name": "user", + "version": "1.0.4", + "description": "This module handles the user operations, assign users to roles and add permissions to roles.", + "scripts": { + "version": "(cd ../../ && pos-cli modules version user -p) && git add template-values.json && auto-changelog -p && git add CHANGELOG.md" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Platform-OS/pos-module-user.git" + }, + "author": "", + "license": "MIT", + "bugs": { + "url": "https://github.com/Platform-OS/pos-module-user/issues" + }, + "homepage": "https://github.com/Platform-OS/pos-module-user#readme", + "devDependencies": { + "auto-changelog": "^2.4.0" + }, + "auto-changelog": { + "template": "changelog-template.hbs", + "unreleased": true, + "commitLimit": false + } +} diff --git a/pos-module-user-invites/modules/user/pos-module.json b/pos-module-user-invites/modules/user/pos-module.json new file mode 100644 index 00000000..eeb5cf4e --- /dev/null +++ b/pos-module-user-invites/modules/user/pos-module.json @@ -0,0 +1,13 @@ +{ + "machine_name": "user", + "version": "5.2.8", + "name": "User", + "dependencies": { + "core": "^2.1.8", + "common-styling": "^1.11.0", + "oauth_github": "^0.0.12" + }, + "devDependencies": { + "tests": "1.3.3" + } +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/assets/style/pos-user-form.css b/pos-module-user-invites/modules/user/public/assets/style/pos-user-form.css new file mode 100644 index 00000000..a7be35be --- /dev/null +++ b/pos-module-user-invites/modules/user/public/assets/style/pos-user-form.css @@ -0,0 +1,122 @@ +/* + styling for the user forms + + layout + texts + form +*/ + + + +/* layout +============================================================================ */ +.pos-user-content { + width: 100%; + max-width: 350px; +} + + + +/* texts +============================================================================ */ +.pos-user-content .pos-heading-2 { + margin-block-end: calc(var(--pos-gap-text-text) / 3); +} + + + +/* form +============================================================================ */ +.pos-user-content .pos-form { + margin-block-start: var(--pos-gap-title-content); + margin-block-end: var(--pos-gap-content-footer); +} + +.pos-user-content fieldset { + display: flex; + flex-direction: column; + gap: .2em; +} + +.pos-user-label-password { + display: flex; + justify-content: space-between; +} + +.pos-user-label-password a:not(:hover):not(:active) { + color: var(--pos-color-content-foreground-supplementary); +} + +.pos-form-simple fieldset:has(.pos-user-label-password) { + display: flex; + flex-direction: column; + gap: .2em; +} + +.pos-user-social-login-separator { + margin: 20px 0px; + text-align: center; + display: flex; + flex-wrap: nowrap; + align-items: center; + gap: 8px; + text-transform: uppercase; +} + +.pos-user-social-login-separator::before, +.pos-user-social-login-separator::after { + content: ""; + display: inline-block; + border-top: 1px solid var(--pos-color-content-foreground-supplementary); + flex-grow: 1; +} + +.pos-user-content .pos-user-social-login-providers form { + margin-top: 0; + margin-bottom: 10px; +} + +.pos-user-content .pos-user-social-login-providers .pos-button { + width: 100%; +} + +.pos-button-social { + display: flex; + place-items: center; +} + +.pos-button-social { + width: 100%; + box-sizing: border-box; +} + +.pos-button-social-icon { + width: 30%; + display: flex; + place-content: center; + place-items: center; +} + +.pos-button-social-text { + width: 70%; +} + +.pos-social-listing { + margin: 10px 0; + display: flex; + flex-direction: column; + max-width: 350px; + gap: 10px; +} + +.pos-2fa-input { + width: 50px; +} + +.pos-2fa-spacing { + padding-top: var(--pos-gap-title-content); +} + +.pos-user-2fa .submit-2fa { + margin-top: 5px; +} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/graphql/api_call.graphql b/pos-module-user-invites/modules/user/public/graphql/api_call.graphql new file mode 100644 index 00000000..2aab5d79 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/api_call.graphql @@ -0,0 +1,19 @@ +mutation api_call( + $api_template: String! + $data: HashObject! + $timeout: Int = 60 +) { + api_call_send( + data: $data + template: { name: $api_template } + options: { timeout: $timeout } + ) { + response { + status + body + } + errors { + message + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/oauth/create.graphql b/pos-module-user-invites/modules/user/public/graphql/oauth/create.graphql new file mode 100644 index 00000000..26fc4240 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/oauth/create.graphql @@ -0,0 +1,21 @@ +mutation ($user_id: String!, $provider: String!, $sub: String!) { + record: record_create( + record: { + table: "modules/user/oauth" + properties: [ + { name: "user_id", value: $user_id } + { name: "provider", value: $provider } + { name: "sub", value: $sub } + ] + } + ) { + id + create_at: created_at + updated_at: updated_at + table + + user_id: property(name: "user_id") + provider: property(name: "provider") + sub: property(name: "sub") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/oauth/delete.graphql b/pos-module-user-invites/modules/user/public/graphql/oauth/delete.graphql new file mode 100644 index 00000000..8fea3d66 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/oauth/delete.graphql @@ -0,0 +1,6 @@ +mutation delete($id: ID!) { + record: record_delete( + table: "modules/user/oauth" + id: $id + ){ id } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_sub.graphql b/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_sub.graphql new file mode 100644 index 00000000..86c78ca3 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_sub.graphql @@ -0,0 +1,30 @@ +query find_by_sub( + $sub: String! + $provider: String! +) { + records( + per_page: 1 + filter: { + table: { value: "modules/user/oauth" } + properties: [ + { name: "sub", value: $sub } + { name: "provider", value: $provider } + ] + } + ) { + total_entries + total_pages + has_previous_page + has_next_page + results { + id + created_at: created_at + updated_at: updated_at + table + + user_id: property(name: "user_id") + sub: property(name: "sub") + provider: property(name: "provider") + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_user_id.graphql b/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_user_id.graphql new file mode 100644 index 00000000..9ffa0d21 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/oauth/find_by_user_id.graphql @@ -0,0 +1,29 @@ +query find_by_user_id( + $user_id: String! + $provider: String = null +) { + records( + per_page: 1 + filter: { + table: { value: "modules/user/oauth" } + properties: [ + { name: "user_id", value: $user_id } + { name: "provider", value: $provider } + ] + } + ) { + total_entries + total_pages + has_previous_page + has_next_page + results { + id + created_at: created_at + updated_at: updated_at + table + + user_id: property(name: "user_id") + provider: property(name: "provider") + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/create.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/create.graphql new file mode 100644 index 00000000..a3e1d5f0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/create.graphql @@ -0,0 +1,39 @@ +mutation ( + $uuid: String! + $user_id: String! + $first_name: String + $last_name: String + $name: String + $email: String + $roles: [String] + $c__names: String +) { + record: record_create( + record: { + table: "modules/user/profile" + properties: [ + { name: "user_id", value: $user_id } + { name: "first_name", value: $first_name } + { name: "last_name", value: $last_name } + { name: "uuid", value: $uuid } + { name: "name", value: $name } + { name: "email", value: $email } + { name: "roles", value_array: $roles } + { name: "c__names", value: $c__names } + ] + } + ) { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + otp_configured: property_boolean(name: "otp_configured") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/delete.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/delete.graphql new file mode 100644 index 00000000..8ceda25b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/delete.graphql @@ -0,0 +1,6 @@ +mutation delete_profile($id: ID!) { + record: record_delete( + table: "modules/user/profile" + id: $id + ){ id } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/mark_otp.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/mark_otp.graphql new file mode 100644 index 00000000..5d023c13 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/mark_otp.graphql @@ -0,0 +1,17 @@ +mutation mark_otp( + $id: ID! + $otp_configured: Boolean! +) { + record: record_update( + id: $id + record: { + table: "modules/user/profile" + properties: [ + { name: "otp_configured", value_boolean: $otp_configured } + ] + } + ) { + id + otp_configured: property_boolean(name: "otp_configured") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/roles/append.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/append.graphql new file mode 100644 index 00000000..27d801f0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/append.graphql @@ -0,0 +1,26 @@ +mutation ( + $id: ID! + $role: String! +) { + record: record_update( + id: $id + record: { + table: "modules/user/profile" + properties: [ + { name: "roles", array_append: $role } + ] + } + ) { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/roles/remove.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/remove.graphql new file mode 100644 index 00000000..37bda282 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/remove.graphql @@ -0,0 +1,26 @@ +mutation ( + $id: ID! + $role: String! +) { + record: record_update( + id: $id + record: { + table: "modules/user/profile" + properties: [ + { name: "roles", array_remove: $role } + ] + } + ) { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/roles/set.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/set.graphql new file mode 100644 index 00000000..0f341ee9 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/roles/set.graphql @@ -0,0 +1,26 @@ +mutation ( + $id: ID! + $roles: [String!] +) { + record: record_update( + id: $id + record: { + table: "modules/user/profile" + properties: [ + { name: "roles", value_array: $roles } + ] + } + ) { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/search.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/search.graphql new file mode 100644 index 00000000..6dccfc8e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/search.graphql @@ -0,0 +1,52 @@ +query ( + $page: Int = 1 + $limit: Int = 20 + $first_name: String + $last_name: String + $email: String + $emails: [String!] + $id: ID + $ids: [ID!] + $not_ids: [ID!] + $uuid: String + $user_id: String + $sort: RecordsSortInput = { created_at: { order: DESC } } + $query: String +) { + records( + page: $page + per_page: $limit + filter: { + id: { value: $id, value_in: $ids, not_value_in: $not_ids } + table: { value: "modules/user/profile" } + properties: [ + { name: "uuid", value: $uuid } + { name: "first_name", value: $first_name } + { name: "last_name", value: $last_name } + { name: "user_id", value: $user_id } + { name: "email", value: $email, value_in: $emails } + { name: "c__names", contains: $query } + ] + } + sort: [$sort] + ) { + total_entries + total_pages + has_previous_page + has_next_page + results { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + otp_configured: property_boolean(name: "otp_configured") + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/profiles/update.graphql b/pos-module-user-invites/modules/user/public/graphql/profiles/update.graphql new file mode 100644 index 00000000..b47b7906 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/profiles/update.graphql @@ -0,0 +1,37 @@ +mutation profiles_update( + $id: ID! + $name: String + $first_name: String + $last_name: String + $email: String + $roles: [String] + $c__names: String +) { + record: record_update( + id: $id + record: { + table: "modules/user/profile" + properties: [ + { name: "name", value: $name } + { name: "first_name", value: $first_name } + { name: "last_name", value: $last_name } + { name: "email", value: $email } + { name: "roles", value_array: $roles } + { name: "c__names", value: $c__names } + ] + } + ) { + id + created_at + type: table + + email: property(name: "email") + first_name: property(name: "first_name") + last_name: property(name: "last_name") + name: property(name: "name") + user_id: property(name: "user_id") + uuid: property(name: "uuid") + roles: property_array(name: "roles") + otp_configured: property_boolean(name: "otp_configured") + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/session/destroy.graphql b/pos-module-user-invites/modules/user/public/graphql/session/destroy.graphql new file mode 100644 index 00000000..a268679e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/session/destroy.graphql @@ -0,0 +1,3 @@ +mutation { + user_session_destroy +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/count.graphql b/pos-module-user-invites/modules/user/public/graphql/user/count.graphql new file mode 100644 index 00000000..aa197dd2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/count.graphql @@ -0,0 +1,5 @@ +query { + users(per_page: 1) { + total_entries + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/create.graphql b/pos-module-user-invites/modules/user/public/graphql/user/create.graphql new file mode 100644 index 00000000..8acc3ee6 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/create.graphql @@ -0,0 +1,6 @@ +mutation ($email: String!, $password: String!) { + user: user_create(user: { email: $email, password: $password, properties: []}) { + id + email + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/delete.graphql b/pos-module-user-invites/modules/user/public/graphql/user/delete.graphql new file mode 100644 index 00000000..639c7723 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/delete.graphql @@ -0,0 +1,8 @@ +mutation ($id: ID!) { + user: user_delete(id: $id) { + created_at + deleted_at + id + email + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/email_update.graphql b/pos-module-user-invites/modules/user/public/graphql/user/email_update.graphql new file mode 100644 index 00000000..600a5683 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/email_update.graphql @@ -0,0 +1,10 @@ +mutation update_email($id: ID!, $email: String!) { + user: user_update( + id: $id + user: { + email: $email + } + ){ + id + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/emails_count.graphql b/pos-module-user-invites/modules/user/public/graphql/user/emails_count.graphql new file mode 100644 index 00000000..e1659a12 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/emails_count.graphql @@ -0,0 +1,5 @@ +query emails_count($email: String!){ + users(filter: { email: { value: $email} }, per_page:1){ + total_entries + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/find.graphql b/pos-module-user-invites/modules/user/public/graphql/user/find.graphql new file mode 100644 index 00000000..9887224e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/find.graphql @@ -0,0 +1,23 @@ +query ( + $id: ID + $email: String + $with_token: Boolean = false + $valid_for: Int = 1 + $expires_in: Float = 48 + $limit: Int = 1 +) { + users( + per_page: $limit, + filter: { + id: { value: $id } + email: { value: $email } + } + ) { + results { + created_at + email + id + token: temporary_token(valid_for: $valid_for, expires_in: $expires_in) @include(if: $with_token) + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/list.graphql b/pos-module-user-invites/modules/user/public/graphql/user/list.graphql new file mode 100644 index 00000000..79c111ee --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/list.graphql @@ -0,0 +1,10 @@ +query users_list($email:String) { + users(per_page: 1000, filter: { email: { exact: $email } }) { + total_entries + results { + created_at + email + id + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/load.graphql b/pos-module-user-invites/modules/user/public/graphql/user/load.graphql new file mode 100644 index 00000000..8cd98eff --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/load.graphql @@ -0,0 +1,10 @@ +query ($id: ID!) { + users(per_page: 1, filter: { id: { value: $id } }) { + results { + created_at + email + id, + roles: property_array(name: "roles") + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/otp.graphql b/pos-module-user-invites/modules/user/public/graphql/user/otp.graphql new file mode 100644 index 00000000..d598ca79 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/otp.graphql @@ -0,0 +1,15 @@ +query otp($email: String!, $issuer: String!){ + users( + filter: { email: { value: $email} }, per_page:1 + ){ + results{ + id + email + otp { + current_code + secret_as_svg_qr_code(label: $email, issuer: $issuer) + secret + } + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/search.graphql b/pos-module-user-invites/modules/user/public/graphql/user/search.graphql new file mode 100644 index 00000000..55bc396c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/search.graphql @@ -0,0 +1,35 @@ +query ( + $id: ID + $not_ids: [ID!] + $email: String + $limit: Int = 20 + $page: Int = 1 + $sort: UsersSortInput = { id: { order: DESC } } + $include_profiles: Boolean = false +) { + users( + per_page: $limit + page: $page + filter: { + id: { value: $id, not_value_in: $not_ids } + email: { value: $email } + } + sort: [$sort] + ) { + results { + id + email + created_at + roles: property_array(name: "roles") + profiles: related_records( + table: "modules/user/profile" + join_on_property: "id" + foreign_property: "user_id" + limit: 1 + ) @include(if: $include_profiles) { + id + properties + } + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/update.graphql b/pos-module-user-invites/modules/user/public/graphql/user/update.graphql new file mode 100644 index 00000000..00ea4151 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/update.graphql @@ -0,0 +1,6 @@ +mutation ($id: ID!, $email: String, $password: String) { + user: user_update(id: $id, user: { email: $email, password: $password, properties: [] }) { + id + email + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/update_password.graphql b/pos-module-user-invites/modules/user/public/graphql/user/update_password.graphql new file mode 100644 index 00000000..5951eab7 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/update_password.graphql @@ -0,0 +1,10 @@ +mutation update_password($id: ID!, $password: String) { + user: user_update( + id: $id + user: { + password: $password + } + ){ + id + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/verify_otp.graphql b/pos-module-user-invites/modules/user/public/graphql/user/verify_otp.graphql new file mode 100644 index 00000000..556d415e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/verify_otp.graphql @@ -0,0 +1,14 @@ +query verify($email: String!, $otp_code: String!, $password: String!){ + users( + filter: { email: { value: $email} }, per_page:1 + ){ + results{ + id + email + authenticate{ + otp_code(code: $otp_code, drift: 30) + password(password: $password) + } + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/verify_password.graphql b/pos-module-user-invites/modules/user/public/graphql/user/verify_password.graphql new file mode 100644 index 00000000..37a543a5 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/verify_password.graphql @@ -0,0 +1,11 @@ +query ($email: String!, $password: String!) { + users(filter: { email: { value: $email } }, per_page: 1) { + results { + id + email + authenticate { + password(password: $password) + } + } + } +} diff --git a/pos-module-user-invites/modules/user/public/graphql/user/verify_password_for_user_id.graphql b/pos-module-user-invites/modules/user/public/graphql/user/verify_password_for_user_id.graphql new file mode 100644 index 00000000..98b78f0b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/graphql/user/verify_password_for_user_id.graphql @@ -0,0 +1,16 @@ +query verify($id: ID!, $password: String!){ + users( + filter: { + id: { value: $id } + } + per_page: 1 + ){ + results{ + id + email + authenticate{ + password(password: $password) + } + } + } +} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create.liquid new file mode 100644 index 00000000..da08617c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} email - The email address + @param {object} hcaptcha_params - The hCaptcha verification parameters + @param {string} host - The host URL + @param {number} valid_for - Token validity duration in minutes +{% enddoc %} +{% liquid + function object = 'modules/user/commands/authentication_links/create/build', email: email, host: host, valid_for: valid_for + function object = 'modules/user/commands/authentication_links/create/check', object: object, hcaptcha_params: hcaptcha_params + + if object.valid + function object = 'modules/user/commands/authentication_links/create/execute', object: object + assign event_payload = {"email": email} + function _ = 'modules/core/commands/events/publish', type: 'authentication_link_created', object: event_payload, delay: null, max_attempts: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/build.liquid new file mode 100644 index 00000000..eb4ad014 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/build.liquid @@ -0,0 +1,22 @@ +{% doc %} + @param {string} email - The email address + @param {string} host - The host URL + @param {number} valid_for - Token validity duration in minutes +{% enddoc %} +{% liquid + assign valid_for = valid_for | default: 5 + function user = 'modules/user/queries/user/find', email: email, with_token: true, id: null +%} + +{% parse_json object %} +{ + "email": "{{ email }}", + "id": "{{ user.id }}", + "token": "{{ user.token }}", + "host": "{{ host }}" +} +{% endparse_json %} + +{% liquid + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/check.liquid new file mode 100644 index 00000000..7d49cd57 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/check.liquid @@ -0,0 +1,20 @@ +{% doc %} + @param {object} hcaptcha_params - The hCaptcha verification parameters + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'host', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'token', key: null + + if context.constants.VERIFY_HCAPTCHA == "true" + function c = 'modules/core/validations/hcaptcha', c: c, hcaptcha_params: hcaptcha_params, key: null + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/execute.liquid b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/execute.liquid new file mode 100644 index 00000000..e22ed51e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/authentication_links/create/execute.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + if object.valid + assign object.url = 'https://{host}/passwords/new?token={token}&email={email}' | expand_url_template: object + endif + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/emails/auth-link.liquid b/pos-module-user-invites/modules/user/public/lib/commands/emails/auth-link.liquid new file mode 100644 index 00000000..5ce5df4f --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/emails/auth-link.liquid @@ -0,0 +1,28 @@ +--- +metadata: + parameters: + object: + - url + - email + - id +--- +{% parse_json object %} + { + "to": {{ object.email | json }}, + "from": {% print 'modules/user/emails.from_email' | t: default: 'noreply@platformos.com' | json %}, + "subject": {% print 'modules/user/emails.passwords.reset.subject' | t | json %}, + "partial": "modules/user/emails/passwords/reset", + "layout": null, + "data": { + "url": {% print object.url | json %}, + "user": { + "id": {% print object.id | json %} + } + } + } +{% endparse_json %} + +{% liquid + function object = 'modules/core/commands/email/send', object: object + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/oauth/create_user.liquid b/pos-module-user-invites/modules/user/public/lib/commands/oauth/create_user.liquid new file mode 100644 index 00000000..463fad16 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/oauth/create_user.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {string} user_email - The user email address + @param {string} user_first_name - The user first name + @param {string} user_last_name - The user last name +{% enddoc %} +{% liquid + assign password = 30 | random_string + assign full_name = user_first_name | append: " " | append: user_last_name + assign object = {"email": user_email, "firstName": user_first_name, "lastName": user_last_name, "fullName": full_name} + + function new_user = "modules/user/commands/user/create", first_name: user_first_name, last_name: user_last_name, email: user_email, password: password, hook_params: object, roles: null + return new_user +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/lib/commands/passwords/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create.liquid new file mode 100644 index 00000000..8d9eec1f --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/passwords/create/build', object: object + function object = 'modules/user/commands/passwords/create/check', object: object + + if object.valid + function object = 'modules/user/commands/passwords/create/execute', object: object + assign event_payload = {"user_id": object.user_id} + function _ = 'modules/core/commands/events/publish', type: 'password_created', object: event_payload, delay: null, max_attempts: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/build.liquid new file mode 100644 index 00000000..3fb14d0d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/build.liquid @@ -0,0 +1,16 @@ +--- +metadata: + parameters: + - name: password + - name: password_confirmation + - name: user_id +--- +{% parse_json object %} +{ + "id": {{ object.user_id | json }}, + "password": {{ object.password | json }}, + "password_confirmation": {{ object.password_confirmation | json }} +} +{% endparse_json %} + +{% return object %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/check.liquid new file mode 100644 index 00000000..48e8611f --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/check.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password_confirmation', key: null + function c = 'modules/core/validations/equal', c: c, given: object.password, expected: object.password_confirmation, field_name: 'password_confirmation', key: 'modules/user/validation.password.do_not_match', not_verbose: true, message: null + function c = 'modules/core/validations/password_complexity', c: c, object: object, field_name: 'password', maximum: null, minimum: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/execute.liquid b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/execute.liquid new file mode 100644 index 00000000..48eda9ff --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/passwords/create/execute.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + graphql r = 'modules/user/user/update_password', args: object + + if r.errors + log r.errors, type: 'errors.graphql.invalid' + + assign object.valid = false + assign object.errors = r.errors + endif + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create.liquid new file mode 100644 index 00000000..74fdd55e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/profiles/create/build', object: object + function object = 'modules/user/commands/profiles/create/check', object: object + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/user/profiles/create', object: object, selection: null + assign object = object | hash_merge: object.properties + endif + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/build.liquid new file mode 100644 index 00000000..be89d739 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/build.liquid @@ -0,0 +1,34 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function tokenized_names = 'modules/user/commands/profiles/tokenize_names', object: object + assign uuid_new = '' | uuid + assign uuid = object.uuid | default: uuid_new + assign name = object.first_name | append: ' ' | append: object.last_name + + assign data = {"first_name": object.first_name, "last_name": object.last_name, "user_id": object.user_id, "email": object.email, "uuid": uuid, "name": name, "c__names": tokenized_names} + if object.roles == null + assign roles = [] + if context.constants.USER_DEFAULT_ROLE != blank + assign roles << context.constants.USER_DEFAULT_ROLE + endif + else + assign roles_type = object.roles | type_of + if roles_type == 'String' + assign roles = object.roles | split: ',' + elsif roles_type == 'Array' + assign roles = object.roles + else + log object.roles, type: 'ERROR: roles must be an array or a coma separated string' + assign roles = [] + + if context.constants.USER_DEFAULT_ROLE != blank + assign roles << context.constants.USER_DEFAULT_ROLE + endif + endif + endif + + assign data.roles = roles + return data +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/check.liquid new file mode 100644 index 00000000..70894035 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create/check.liquid @@ -0,0 +1,19 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'user_id', key: null + function c = 'modules/core/validations/uniqueness', c: c, object: object, field_name: 'user_id', table: 'modules/user/profile', scope_name: null, exclude_name: null, key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'uuid', key: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'name', maximum: 80, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'first_name', maximum: 40, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'last_name', maximum: 40, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + + assign object.valid = c.valid + + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_proxy.liquid new file mode 100644 index 00000000..be2d4f21 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_proxy.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/commands/profiles/create' + function profile = function_name, object: object + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate.liquid new file mode 100644 index 00000000..58622330 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/profiles/create/build', object: object + function object = 'modules/user/commands/profiles/create/check', object: object + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate_proxy.liquid new file mode 100644 index 00000000..c2a60cdb --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/create_validate_proxy.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/commands/profiles/create_validate' + function profile = function_name, object: object + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete.liquid new file mode 100644 index 00000000..9a1554f4 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/profiles/delete/build', object: object + function object = 'modules/user/commands/profiles/delete/check', object: object + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/user/profiles/delete', object: object, selection: null + endif + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/build.liquid new file mode 100644 index 00000000..dbbbe712 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/build.liquid @@ -0,0 +1,8 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign data = {"id": object.id} + + return data +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/check.liquid new file mode 100644 index 00000000..ba60f2a0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/delete/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + + assign object.valid = c.valid + + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp.liquid new file mode 100644 index 00000000..c6831196 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/profiles/mark_otp/build', object: object + function object = 'modules/user/commands/profiles/mark_otp/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/user/profiles/mark_otp' object: object, selection: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/build.liquid new file mode 100644 index 00000000..e5f9753c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/build.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign data = { "id": object.id } + if object.otp_configured == null + assign data.otp_configured = true + else + assign data.otp_configured = object.otp_configured + endif + + return data + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/check.liquid new file mode 100644 index 00000000..d01c0f8c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/mark_otp/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + function c = 'modules/core/validations/not_null', c: c, object: object, field_name: 'otp_configured', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/append.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/append.liquid new file mode 100644 index 00000000..e8c2a83e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/append.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {string} id - The record ID + @param {string} role - The role name +{% enddoc %} +{% liquid + assign object = { "valid": true, "id": id, "role": role } + function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/profiles/roles/append', selection: null + + if object.errors == blank + assign event_payload = {"profile_id": id, "role": role} + function _ = 'modules/core/commands/events/publish', type: 'user_role_appended', object: event_payload, delay: null, max_attempts: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/remove.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/remove.liquid new file mode 100644 index 00000000..47c93220 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/remove.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} id - The record ID + @param {string} role - The role name +{% enddoc %} +{% liquid + assign object = { "valid": true, "id": id, "role": role } + function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/profiles/roles/remove', selection: null + + if object.errors == blank + assign event_payload = {"profile_id": id, "role": role} + function _ = 'modules/core/commands/events/publish', type: 'user_role_removed', object: event_payload, delay: null, max_attempts: null + endif + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/set.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/set.liquid new file mode 100644 index 00000000..d9e35e50 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/roles/set.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} id - The record ID + @param {string} roles - The roles to assign +{% enddoc %} +{% liquid + assign object = { "valid": true, "id": id, "roles": roles } + function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/profiles/roles/set', selection: null + + if object.errors == blank + assign event_payload = {"profile_id": id, "roles": roles} + function _ = 'modules/core/commands/events/publish', type: 'user_roles_set', object: event_payload, delay: null, max_attempts: null + endif + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/tokenize_names.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/tokenize_names.liquid new file mode 100644 index 00000000..0998c4a3 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/tokenize_names.liquid @@ -0,0 +1,7 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign tokenized_names = [] | push: object.email | push: object.first_name | push: object.last_name | compact | uniq | join: ' ' | downcase + return tokenized_names + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/update.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update.liquid new file mode 100644 index 00000000..e09eaae2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to process + @param {object} profile - The profile object +{% enddoc %} +{% liquid + function object = 'modules/user/commands/profiles/update/build', object: object, profile: profile + function object = 'modules/user/commands/profiles/update/check', object: object + + if object.valid + function object = 'modules/core/commands/execute', mutation_name: 'modules/user/profiles/update', object: object, selection: null + assign object = object | hash_merge: object.properties + endif + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/build.liquid new file mode 100644 index 00000000..12a7102f --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/build.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {object} object - The object to process + @param {object} profile - The profile object +{% enddoc %} +{% liquid + function tokenized_names = 'modules/user/commands/profiles/tokenize_names', object: object + assign name = object.first_name | append: ' ' | append: object.last_name + assign data = {"id": profile.id, "first_name": object.first_name, "last_name": object.last_name, "name": name, "c__names": tokenized_names, "email": profile.email} + + return data +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/check.liquid new file mode 100644 index 00000000..c846f1e2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update/check.liquid @@ -0,0 +1,20 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + function c = 'modules/core/validations/uniqueness', c: c, object: object, field_name: 'email', table: 'modules/user/profile', scope_name: null, exclude_name: null, key: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'name', maximum: 80, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'first_name', maximum: 40, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'last_name', maximum: 40, allow_blank: null, is: null, message_is: null, message_maximum: null, message_minimum: null, minimum: null, value: null + + + assign object.valid = c.valid + + + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/profiles/update_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update_proxy.liquid new file mode 100644 index 00000000..173e584b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/profiles/update_proxy.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {object} object - The object to process + @param {object} profile - The profile object +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/commands/profiles/update' + function profile = function_name, object: object, profile: profile + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/create.liquid new file mode 100644 index 00000000..1d9feed3 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/create.liquid @@ -0,0 +1,48 @@ +{% doc %} + @param {string} email - The email address + @param {object} hook_params - Additional parameters to pass to hooks + @param {string} password - The password + @param {boolean} skip_otp - Whether to skip OTP verification + @param {string} user_id - The user ID (used when validate_password is false) + @param {boolean} validate_password - Whether to validate the password +{% enddoc %} +{% liquid + if validate_password == nil + assign validate_password = true + endif + + if skip_otp == nil + assign skip_otp = false + endif + + if validate_password + function user = 'modules/user/commands/user/verify_password', email: email, password: password + unless user.valid + return user + endunless + assign user_id = user.id + endif + + function object = 'modules/user/commands/session/create/build', id: user_id + function object = 'modules/user/commands/session/create/check', object: object + if object.valid + function user = 'modules/user/queries/user/load', id: object.id + function profile = 'modules/user/queries/profiles/find', user_id: user.id, id: null, uuid: null, first_name: null, last_name: null + if profile.otp_configured and skip_otp == false + assign object.otp_required = true + else + if user.id + sign_in user_id: user.id + assign params = { "user": user, "hook_params": hook_params } + function results = 'modules/core/commands/hook/fire', hook: 'user_login', params: params, merge_to_object: true + assign user.hook_results = results + endif + assign object.user = user + + assign event_payload = {"user_id": object.id} + function _ = 'modules/core/commands/events/publish', type: 'user_signed_in', object: event_payload, delay: null, max_attempts: null + endif + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/create/build.liquid new file mode 100644 index 00000000..2666900c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/create/build.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% parse_json object %} + { + "id": {{ id | json }} + } +{% endparse_json %} + +{% return object %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/create/check.liquid new file mode 100644 index 00000000..bcda570b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/create/check.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/destroy.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/destroy.liquid new file mode 100644 index 00000000..55fdfbda --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/destroy.liquid @@ -0,0 +1,20 @@ +{% comment %} + Destroys the current user's session. +{% endcomment %} +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + graphql destroy = 'modules/user/session/destroy' + assign destroy.user = current_profile.user + + unless destroy.errors + assign params = { "destroy": destroy } + function results = 'modules/core/commands/hook/fire', hook: 'user_logout', params: params, merge_to_object: null + assign destroy.hook_results = results + assign event_payload = {"user_id": current_profile.user.id} + function _ = 'modules/core/commands/events/publish', type: 'user_logout', object: event_payload, delay: null, max_attempts: null + session original_user_id = null + session return_to = null + endunless + return destroy +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create.liquid new file mode 100644 index 00000000..ccd43c84 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create.liquid @@ -0,0 +1,19 @@ +{% doc %} + @param {string} current_user_id - The current user ID + @param {object} user - The user object +{% enddoc %} +{% liquid + function object = 'modules/user/commands/session/impersonation/create/build', user: user, current_user_id: current_user_id + function object = 'modules/user/commands/session/impersonation/create/check', object: object + if object.valid + sign_in user_id: object.id + session original_user_id = object.current_user_id + + assign event_object = {"actor_id": object.current_user_id, "target_id": object.user_id} + function _ = 'modules/core/commands/events/publish', type: 'impersonation_started', object: event_object, delay: null, max_attempts: null + endif + + return object +%} + + diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/build.liquid new file mode 100644 index 00000000..fb8ecafc --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/build.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {string} current_user_id - The current user ID + @param {object} user - The user object +{% enddoc %} +{% parse_json object %} + { + "id": {{ user.id | json }}, + "current_user_id": {{ current_user_id | json }} + } +{% endparse_json %} + +{% return object %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/check.liquid new file mode 100644 index 00000000..527fb456 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/create/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'current_user_id', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy.liquid new file mode 100644 index 00000000..5f68cd05 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} current_user_id - The current user ID + @param {object} user - The user object +{% enddoc %} +{% liquid + function object = 'modules/user/commands/session/impersonation/create/build', user: user, current_user_id: current_user_id + function object = 'modules/user/commands/session/impersonation/destroy/check', object: object + + if object.valid + sign_in user_id: object.id + session original_user_id = null + + assign event_object = {"actor_id": object.id, "impersonated_user_id": object.current_user_id} + function _ = 'modules/core/commands/events/publish', type: 'impersonation_ended', object: event_object, delay: null, max_attempts: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy/check.liquid new file mode 100644 index 00000000..527fb456 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/session/impersonation/destroy/check.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'current_user_id', key: null + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/create.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/create.liquid new file mode 100644 index 00000000..cfa93cca --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/create.liquid @@ -0,0 +1,28 @@ +{% doc %} + @param {string} email - The email address + @param {string} first_name - The first name + @param {object} hook_params - Additional parameters to pass to hooks + @param {string} last_name - The last name + @param {string} password - The password + @param {string} roles - The roles to assign +{% enddoc %} +{% liquid + function object = 'modules/user/commands/user/create/build', first_name: first_name, last_name: last_name, email: email, password: password, hook_params: hook_params, roles: roles + function object = 'modules/user/commands/user/create/check', object: object + if object.valid + function user = 'modules/core/commands/execute', mutation_name: 'modules/user/user/create', object: object, selection: 'user' + assign object.user_id = user.id + + function profile = 'modules/user/commands/profiles/create', object: object + if profile.valid != true + return profile + endif + + assign event_payload = {"user_id": user.id} + function _ = 'modules/core/commands/events/publish', type: 'user_created', object: event_payload, delay: null, max_attempts: null + + return user + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/create/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/create/build.liquid new file mode 100644 index 00000000..73386d49 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/create/build.liquid @@ -0,0 +1,21 @@ +{% doc %} + @param {string} email - The email address + @param {string} first_name - The first name + @param {object} hook_params - Additional parameters to pass to hooks + @param {string} last_name - The last name + @param {string} password - The password + @param {string} roles - The roles to assign +{% enddoc %} +{% parse_json object %} + { + "first_name": {{ first_name | json }}, + "last_name": {{ last_name | json }}, + "email": {{ email | json }}, + "password": {{ password | json }}, + "hook_params": {{ hook_params | json }} + } +{% endparse_json %} + +{% assign object.roles = roles %} + +{% return object %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/create/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/create/check.liquid new file mode 100644 index 00000000..61ab6b54 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/create/check.liquid @@ -0,0 +1,26 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'first_name', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'last_name', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password', key: null + function c = 'modules/core/validations/password_complexity', c: c, object: object, field_name: 'password', maximum: null, minimum: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: 'modules/user/validation.email.required' + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'roles', minimum: 0, allow_blank: true, is: null, maximum: null, message_is: null, message_maximum: null, message_minimum: null, value: null + function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email', key: 'modules/user/validation.email.format' + + if object.email != blank + graphql user_exists = 'modules/user/user/list', email: object.email + if user_exists.users.total_entries > 0 + assign message = 'modules/user/validation.user_exists' | t + function c = 'modules/core/helpers/register_error', contract: c, field_name: 'email', message: message, key: null + endif + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/delete.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/delete.liquid new file mode 100644 index 00000000..d2253c5b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/delete.liquid @@ -0,0 +1,17 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% liquid + graphql user = 'modules/user/user/delete', id: id + + unless user.errors + assign params = { "user": user.user } + function results = 'modules/core/commands/hook/fire', hook: 'user_delete', params: params, merge_to_object: null + assign user.hook_results = results + + assign event_payload = {"user_id": id} + function _ = 'modules/core/commands/events/publish', type: 'user_deleted', object: event_payload, delay: null, max_attempts: null + endunless + + return user +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/email_update.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update.liquid new file mode 100644 index 00000000..e5abab04 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} current_user - The current user object + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/user/email_update/build', object: object, current_user: current_user + function object = 'modules/user/commands/user/email_update/check', object: object, current_user: current_user + + if object.valid + function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/user/email_update', selection: 'user' + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/build.liquid new file mode 100644 index 00000000..e2a8c186 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/build.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {object} current_user - The current user object + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign object = {"id": current_user.id, "email": object.email, "password": object.password} + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/check.liquid new file mode 100644 index 00000000..02c2ef47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/email_update/check.liquid @@ -0,0 +1,28 @@ +{% doc %} + @param {object} current_user - The current user object + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: null + function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email', key: null + if object.email != blank and object.email != current_user.email + graphql emails_count = 'modules/user/user/emails_count', email: object.email | dig: 'users', 'total_entries' + if emails_count > 0 + render 'modules/core/helpers/register_error', contract: c, field_name: 'email', key: 'app.errors.taken', message: null + endif + endif + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password', key: null + if object.password + function r = 'modules/core/commands/execute', mutation_name: 'modules/user/user/verify_password_for_user_id' object: object, selection: 'users' + assign user = r.results.first + + function c = 'modules/core/validations/truthy', c: c, field_name: 'password', object: user.authenticate, key: 'app.errors.invalid_password' + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/update.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/update.liquid new file mode 100644 index 00000000..547bf488 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/update.liquid @@ -0,0 +1,32 @@ +{% doc %} + @param {string} email - The email address + @param {object} hook_params - Additional parameters to pass to hooks + @param {string} id - The record ID + @param {string} password - The password +{% enddoc %} +{% liquid + function object = 'modules/user/commands/user/update/build', id: id, email: email, password: password + function object = 'modules/user/commands/user/update/check', object: object + + if object.valid + graphql user = 'modules/user/user/update', args: object + assign object.update_result = user + unless user.errors + assign params = { "updated_user": user.user, "hook_params": hook_params } + function results = 'modules/core/commands/hook/fire', hook: 'user_update', params: params, merge_to_object: true + for result in results + if result[1].valid == false or result[1].errors != blank + assign object.valid = false + assign object.errors = result[1].errors + break + endif + endfor + assign object.hook_results = results + endunless + + assign event_payload = {"user_id": object.id} + function _ = 'modules/core/commands/events/publish', type: 'user_updated', object: event_payload, delay: null, max_attempts: null + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/update/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/update/build.liquid new file mode 100644 index 00000000..9f262882 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/update/build.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} email - The email address + @param {string} id - The record ID + @param {string} password - The password +{% enddoc %} +{% parse_json object %} + { + "id": {{ id | json }}, + "email": {{ email | json }}, + "password": {{ password | json }} + } +{% endparse_json %} + +{% return object %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/update/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/update/check.liquid new file mode 100644 index 00000000..733c74c4 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/update/check.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + if object['email'] + function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email', key: null + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp.liquid new file mode 100644 index 00000000..efed4cd1 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} email - The email address + @param {object} object - The object to process +{% enddoc %} +{% liquid + function object = 'modules/user/commands/user/verify_otp/build', email: email, object: object + function object = 'modules/user/commands/user/verify_otp/check', object: object + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/build.liquid new file mode 100644 index 00000000..c56ceb93 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/build.liquid @@ -0,0 +1,9 @@ +{% doc %} + @param {string} email - The email address + @param {object} object - The object containing password and otp_code +{% enddoc %} +{% liquid + assign email = email | default: object.email + assign object = { "email": email, "password": object.password, "otp_code": object.otp_code } + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/check.liquid new file mode 100644 index 00000000..a6b4d754 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_otp/check.liquid @@ -0,0 +1,24 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'otp_code', key: null + + if c.valid + function r = 'modules/core/commands/execute', mutation_name: 'modules/user/user/verify_otp' object: object, selection: 'users' + assign user = r.results.first + + function c = 'modules/core/validations/truthy', c: c, field_name: 'otp_code', object: user.authenticate, key: 'modules/user/2fa.errors.otp_code' + function c = 'modules/core/validations/truthy', c: c, field_name: 'password', object: user.authenticate, key: 'modules/user/2fa.errors.password' + assign object.id = user.id + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password.liquid new file mode 100644 index 00000000..baa0326d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} email - The email address + @param {string} password - The password +{% enddoc %} +{% liquid + function object = 'modules/user/commands/user/verify_password/build', email: email, password: password + function object = 'modules/user/commands/user/verify_password/check', object: object + + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/build.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/build.liquid new file mode 100644 index 00000000..47b72f7c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/build.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {string} email - The email address + @param {string} password - The password +{% enddoc %} +{% parse_json object %} + { + "email": {{ email | json }}, + "password": {{ password | json }} + } +{% endparse_json %} + +{% liquid + return object +%} diff --git a/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/check.liquid b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/check.liquid new file mode 100644 index 00000000..3b76b903 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/commands/user/verify_password/check.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: null + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password', key: null + + if c.valid + graphql user = 'modules/user/user/verify_password', args: object + assign user = user.users.results.first + + function c = 'modules/core/validations/truthy', c: c, field_name: 'password', object: user.authenticate, key: 'modules/user/validation.invalid_email_or_password' + assign object.id = user.id + endif + + assign object.valid = c.valid + assign object.errors = c.errors + + return object + %} diff --git a/pos-module-user-invites/modules/user/public/lib/events/authentication_link_created.liquid b/pos-module-user-invites/modules/user/public/lib/events/authentication_link_created.liquid new file mode 100644 index 00000000..41be3c93 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/authentication_link_created.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + email +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'email', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/impersonation_ended.liquid b/pos-module-user-invites/modules/user/public/lib/events/impersonation_ended.liquid new file mode 100644 index 00000000..4b78d11d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/impersonation_ended.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + actor_id + impersonation_ended +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'actor_id', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'impersonation_ended', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/impersonation_started.liquid b/pos-module-user-invites/modules/user/public/lib/events/impersonation_started.liquid new file mode 100644 index 00000000..70121d1d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/impersonation_started.liquid @@ -0,0 +1,19 @@ +--- +metadata: + event: + actor_id + target_id + +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'actor_id', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'target_id', key: null + + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/password_created.liquid b/pos-module-user-invites/modules/user/public/lib/events/password_created.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/password_created.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_created.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_created.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_created.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_deleted.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_deleted.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_deleted.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_logout.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_logout.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_logout.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_role_appended.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_role_appended.liquid new file mode 100644 index 00000000..6a7476c7 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_role_appended.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + profile_id + role +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'profile_id', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'role', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_role_removed.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_role_removed.liquid new file mode 100644 index 00000000..6a7476c7 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_role_removed.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + profile_id + role +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'profile_id', key: null + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'role', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_roles_set.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_roles_set.liquid new file mode 100644 index 00000000..d04e39cc --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_roles_set.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + profile_id + roles +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'profile_id', key: null + function c = 'modules/core/validations/length', c: c, object: event, field_name: 'roles', minimum: 0, allow_blank: false, is: null, maximum: null, message_is: null, message_maximum: null, message_minimum: null, value: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_signed_in.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_signed_in.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_signed_in.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/events/user_updated.liquid b/pos-module-user-invites/modules/user/public/lib/events/user_updated.liquid new file mode 100644 index 00000000..56dc2e47 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/events/user_updated.liquid @@ -0,0 +1,15 @@ +--- +metadata: + event: + user_id +--- +{% doc %} + @param {object} event - The event object +{% enddoc %} +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id', key: null + + return c +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/can_do.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/can_do.liquid new file mode 100644 index 00000000..626789c1 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/can_do.liquid @@ -0,0 +1,36 @@ +{% doc %} + @param {string} access_callback - Custom authorization callback path + @param {string} do - The permission to check + @param {object} entity - The entity to check access against + @param {object} requester - The user profile requesting access +{% enddoc %} +{% liquid + assign roles_type = requester.roles | type_of + unless roles_type == 'Array' + log requester, type: 'ERROR the requester does not have "roles" array in modules/user/helpers/can_do' + return false + endunless + + if access_callback + function can = access_callback, requester: requester, entity: entity, do: do + return can + endif + + function permissions = 'modules/user/queries/role_permissions/permissions' + assign found_permission = false + for role in requester.roles + if permissions[role] == null + assign msg = 'WARNING: the following role is not defined in modules/user/queries/role_permissions/permissions: ' | append: role + log requester, type: msg + endif + if role == 'superadmin' + assign found_permission = true + break + elsif permissions[role] contains do + assign found_permission = true + break + endif + endfor + + return found_permission + %} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_redirect.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_redirect.liquid new file mode 100644 index 00000000..af52c14a --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_redirect.liquid @@ -0,0 +1,16 @@ +{% doc %} + @param {string} access_callback - Custom authorization callback path + @param {string} do - The permission to check + @param {object} entity - The entity to check access against + @param {object} requester - The user profile requesting access + @param {string} return_url - URL to redirect to +{% enddoc %} +{% liquid + function can = 'modules/user/helpers/can_do', requester: requester, entity: entity, do: do, access_callback: access_callback + unless can + assign return_url = return_url | default: '/' + + redirect_to return_url + break + endunless +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid new file mode 100644 index 00000000..d20dcf95 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid @@ -0,0 +1,29 @@ +{% doc %} + @param {string} access_callback - Custom authorization callback path + @param {string} anonymous_return_to - URL to redirect anonymous users to + @param {string} do - The permission to check + @param {object} entity - The entity to check access against + @param {string} forbidden_partial - Custom partial to render for forbidden access + @param {boolean} redirect_anonymous_to_login - Whether to redirect anonymous users to login + @param {object} requester - The user profile requesting access +{% enddoc %} +{% liquid + function can = 'modules/user/helpers/can_do', requester: requester, entity: entity, do: do, access_callback: access_callback + unless can + if requester.roles contains 'anonymous' and redirect_anonymous_to_login + session return_to = anonymous_return_to | default: context.location.href + assign info = 'modules/user/authorization.redirect_anonymous_info' | t + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', url: '/sessions/new', info: info, default: null, error: null, format: null, notice: null, object: null + # platformos-check-enable DeprecatedTag + else + response_status 403 + if forbidden_partial + # platformos-check-disable DeprecatedTag + include forbidden_partial + # platformos-check-enable DeprecatedTag + endif + break + endif + endunless +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/current_profile.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/current_profile.liquid new file mode 100644 index 00000000..3dc7e458 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/current_profile.liquid @@ -0,0 +1,17 @@ +{% liquid + function user = 'modules/user/queries/user/current' + if user.id == null + assign current_profile = { "user": null, "roles": ["anonymous"] } + else + function current_profile = 'modules/user/queries/profiles/find', user_id: user.id, id: null, uuid: null, first_name: null, last_name: null + assign current_profile.user = user + if current_profile.roles != null + assign current_profile.roles << 'authenticated' + else + assign current_profile.roles = ["authenticated"] + endif + endif + + export current_profile + return current_profile + %} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/flash.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/flash.liquid new file mode 100644 index 00000000..ced93543 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/flash.liquid @@ -0,0 +1,28 @@ +{% doc %} + @param {string} error - The error flash message + @param {boolean} force_clear - If true, clear flash messages immediately + @param {string} info - The info flash message + @param {string} notice - The notice flash message +{% enddoc %} +{% liquid + assign error = error + assign notice = notice + assign info = info + assign force_clear = force_clear | default: false + + if error + assign message = error | t + assign severity = 'error' + elsif notice + assign message = notice | t + assign severity = 'success' + elsif info + assign message = info | t + assign severity = 'info' + endif + assign flash = {"message": message, "severity": severity, "from": context.location.pathname, "force_clear": force_clear} + + function _ = 'modules/core/commands/session/set', key: 'sflash', value: flash + + return null +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/get_assigned_oauth_providers.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/get_assigned_oauth_providers.liquid new file mode 100644 index 00000000..225b0590 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/get_assigned_oauth_providers.liquid @@ -0,0 +1,7 @@ +{% liquid + function current_user = 'modules/user/queries/user/current' + graphql g = 'modules/user/oauth/find_by_user_id', user_id: current_user.id + + assign providers = g.records.results | map: 'provider' + return providers +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/get_available_oauth_providers.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/get_available_oauth_providers.liquid new file mode 100644 index 00000000..7153b6ca --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/get_available_oauth_providers.liquid @@ -0,0 +1,22 @@ +{% liquid + assign available_providers = {} + assign keys = context.constants | hash_keys + for item in keys + assign starts_with = item | start_with: "OAUTH2_" + assign ends_with = item | end_with: "_PROVIDER" + if starts_with and ends_with and context.constants[item] != null + assign provider_id = item | replace: "OAUTH2_", "" | replace: "_PROVIDER", "" | upcase + + assign provider_key = "OAUTH2_" | append: provider_id | append: "_PROVIDER" + assign name_key = "OAUTH2_" | append: provider_id | append: "_NAME" + assign client_id_key = "OAUTH2_" | append: provider_id | append: "_CLIENT_ID" + assign secret_value_key = "OAUTH2_" | append: provider_id | append: "_SECRET_VALUE" + + assign provider_data = { "key": context.constants[provider_key], "name": context.constants[name_key], "client_id": context.constants[client_id_key], "secret_value": context.constants[secret_value_key] } + + assign available_providers[provider_id] = provider_data + endif + endfor + + return available_providers + %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/profiles/slugs/build.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/profiles/slugs/build.liquid new file mode 100644 index 00000000..56f02cb0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/profiles/slugs/build.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {object} current_profile - The current user profile + @param {object} profile - The profile object +{% enddoc %} +{% liquid + assign profile = profile | default: current_profile + assign first_name = profile.first_name + assign last_name = profile.last_name + assign slug = first_name | append: '-' | append: last_name | append: '-' | append: profile.id | slugify + + return slug +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/table_name.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/table_name.liquid new file mode 100644 index 00000000..2988af37 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/table_name.liquid @@ -0,0 +1,5 @@ +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + + return profile_module | append: '/profile' +%} diff --git a/pos-module-user-invites/modules/user/public/lib/helpers/user_from_temporary_token.liquid b/pos-module-user-invites/modules/user/public/lib/helpers/user_from_temporary_token.liquid new file mode 100644 index 00000000..a9320f5f --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/helpers/user_from_temporary_token.liquid @@ -0,0 +1,21 @@ +{% doc %} + @param {string} email - The email address + @param {string} token - The authentication token +{% enddoc %} +{% liquid + if token == blank or email == blank + return null + endif + + function user = 'modules/user/queries/user/find', email: email, id: null, with_token: null + + if user + assign authenticated = token | is_token_valid: user.id + endif + + if user and authenticated + return user + else + return null + endif +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/api_call.liquid b/pos-module-user-invites/modules/user/public/lib/queries/api_call.liquid new file mode 100644 index 00000000..b6389e2a --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/api_call.liquid @@ -0,0 +1,11 @@ +{% doc %} + @param {string} api_template - The API call template path + @param {number} timeout - Request timeout in seconds +{% enddoc %} +{%- liquid + graphql g = 'modules/user/api_call', api_template: api_template, data: data, timeout: timeout + if g.api_call_send == blank + log g, type: "QUERY ERROR" + endif + return g.api_call_send +-%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters.liquid new file mode 100644 index 00000000..43704217 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters.liquid @@ -0,0 +1,13 @@ +{% doc %} + @param {object} params - The request parameters +{% enddoc %} +{% liquid + assign sort_options = {"first_name_desc": {"properties": {"name": "first_name", "order": "DESC"}}, "first_name_asc": {"properties": {"name": "first_name", "order": "ASC"}}} + assign filters = {} + assign filters.page = params.page | to_positive_integer: 1 + assign filters.keyword = params.keyword | default: '' + assign filters.sort_by = params.sort_by | default: 'first_name_desc' + assign filters.sort = sort_options[filters.sort_by] + + return filters + %} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters_proxy.liquid new file mode 100644 index 00000000..99f3cdd9 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/filters_proxy.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {object} params - The request parameters +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/queries/profiles/filters' + function filters = function_name, params: params + + return filters +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/find.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/find.liquid new file mode 100644 index 00000000..a997b5c0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/find.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param {string} first_name - The first name + @param {string} id - The record ID + @param {string} last_name - The last name + @param {string} user_id - The user ID + @param {string} uuid - The UUID identifier +{% enddoc %} +{% liquid + if user_id == blank and id == blank and uuid == blank + log 'ERROR: missing ID argument in modules/user/queries/profile/find' + return nil + endif + + graphql result = 'modules/user/profiles/search', user_id: user_id, id: id, first_name: first_name, last_name: last_name, uuid: uuid, limit: 1, page: 1 + assign profile = result.records.results.first + + if profile + function slug = 'modules/user/helpers/profiles/slugs/build', current_profile: profile, profile: null + assign profile.slug = slug + endif + + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/find_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/find_proxy.liquid new file mode 100644 index 00000000..044bc927 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/find_proxy.liquid @@ -0,0 +1,12 @@ +{% doc %} + @param {object} filters - The filter parameters + @param {string} id - The record ID + @param {string} user_id - The user ID + @param {string} uuid - The UUID identifier +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/queries/profiles/find' + function profile = function_name, user_id: user_id, id: id, uuid: uuid, filters: filters + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/search.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/search.liquid new file mode 100644 index 00000000..8ffac736 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/search.liquid @@ -0,0 +1,36 @@ +{% doc %} + @param {string} emails - List of email addresses + @param {string} first_name - The first name + @param {string} id - The record ID + @param {string} ids - List of record IDs to include + @param {string} last_name - The last name + @param {number} limit - Maximum number of results + @param {string} not_ids - List of record IDs to exclude + @param {number} page - Page number for pagination + @param {string} query - Search query string + @param {string} sort - Sort order + @param {string} user_id - The user ID + @param {string} uuid - The UUID identifier +{% enddoc %} +{% liquid + assign page = page | to_positive_integer: 1 + if not_ids == blank + assign not_ids = null + endif + + graphql r = 'modules/user/profiles/search', limit: limit, uuid: uuid, id: id, ids: ids, first_name: first_name , last_name: last_name , user_id: user_id, not_ids: not_ids, query: query, emails: emails, sort: sort, page: page + + assign records = r.records + assign profiles = [] + for profile in records.results + function slug = 'modules/user/helpers/profiles/slugs/build' , current_profile: profile, profile: null + assign profile.slug = slug + assign p = profile + + assign profiles << p + endfor + assign records.results = profiles + + return records +%} + diff --git a/pos-module-user-invites/modules/user/public/lib/queries/profiles/search_proxy.liquid b/pos-module-user-invites/modules/user/public/lib/queries/profiles/search_proxy.liquid new file mode 100644 index 00000000..586fb1e1 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/profiles/search_proxy.liquid @@ -0,0 +1,22 @@ +{% doc %} + @param {string} emails - List of email addresses + @param {object} filters - The filter parameters + @param {string} first_name - The first name + @param {string} id - The record ID + @param {string} ids - List of record IDs to include + @param {string} last_name - The last name + @param {number} limit - Maximum number of results + @param {string} not_ids - List of record IDs to exclude + @param {number} page - Page number for pagination + @param {string} query - Search query string + @param {string} sort - Sort order + @param {string} user_id - The user ID + @param {string} uuid - The UUID identifier +{% enddoc %} +{% liquid + function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/user', type: null + assign function_name = profile_module | append: '/queries/profiles/search' + function profile = function_name, limit: limit, uuid: uuid, id: id, ids: ids, first_name: first_name, last_name: last_name, user_id: user_id, not_ids: not_ids, query: query, emails: emails, sort: sort, page: page, filters: filters + + return profile +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/registration_fields/load.liquid b/pos-module-user-invites/modules/user/public/lib/queries/registration_fields/load.liquid new file mode 100644 index 00000000..7c8c4a18 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/registration_fields/load.liquid @@ -0,0 +1,19 @@ +{% comment %} + Loads the registration fields. +{% endcomment %} + +{% parse_json fields %} +[ + {% comment %} + Example value: + { + "name": "email", + "type": "email", + "label": "Email" + } + {% endcomment %} +] +{% endparse_json %} +{% liquid + return fields +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/role_permissions/permissions.liquid b/pos-module-user-invites/modules/user/public/lib/queries/role_permissions/permissions.liquid new file mode 100644 index 00000000..5557577c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/role_permissions/permissions.liquid @@ -0,0 +1,14 @@ +{% parse_json data %} +{ + {% if context.constants.USER_DEFAULT_ROLE != blank %} + "{{ context.constants.USER_DEFAULT_ROLE }}": [], + {% endif %} + "anonymous": ["sessions.create", "users.register"], + "authenticated": ["sessions.destroy","oauth.manage"], + "admin": ["admin_pages.view", "admin.users.manage", "users.impersonate"], + "member": ["profile.manage"], + "superadmin": ["users.impersonate_superadmin"] +} +{% endparse_json %} + +{% return data %} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/roles/all.liquid b/pos-module-user-invites/modules/user/public/lib/queries/roles/all.liquid new file mode 100644 index 00000000..0d481bb9 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/roles/all.liquid @@ -0,0 +1,3 @@ +{% function permissions = 'modules/user/queries/role_permissions/permissions' %} + +{% return permissions | hash_keys | sort %} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/roles/custom.liquid b/pos-module-user-invites/modules/user/public/lib/queries/roles/custom.liquid new file mode 100644 index 00000000..bebd8aa4 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/roles/custom.liquid @@ -0,0 +1,6 @@ +{% liquid + function roles = 'modules/user/queries/roles/all' + assign built_in_roles = 'anonymous,authenticated' | split: ',' + + return roles | array_subtract: built_in_roles +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/count.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/count.liquid new file mode 100644 index 00000000..3c8098a4 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/count.liquid @@ -0,0 +1,7 @@ +{% comment %} + Counts the created users +{% endcomment %} +{% liquid + graphql count = 'modules/user/user/count' + return count.users.total_entries +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/current.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/current.liquid new file mode 100644 index 00000000..80c343a8 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/current.liquid @@ -0,0 +1,11 @@ +{% comment %} + Loads the current user. +{% endcomment %} +{% liquid + if context.current_user + function user = 'modules/user/queries/user/load', id: context.current_user.id + else + assign user = null + endif + return user +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/find.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/find.liquid new file mode 100644 index 00000000..665863ed --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/find.liquid @@ -0,0 +1,18 @@ +{% doc %} + @param {string} email - The email address + @param {string} id - The record ID + @param {string} with_token - Include temporary token in results +{% enddoc %} +{% liquid + assign id = id + assign email = email + assign with_token = with_token | default: false + + if id == blank and email == blank + return null + endif + + graphql r = 'modules/user/user/find', id: id, email: email, limit: 1, with_token: with_token + + return r.users.results.first +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/get_all.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/get_all.liquid new file mode 100644 index 00000000..a7003888 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/get_all.liquid @@ -0,0 +1,6 @@ +{% liquid + # log 1, type: 'user/list' + graphql g = 'modules/user/user/list' + + return g.users.results +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/load.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/load.liquid new file mode 100644 index 00000000..8f6e0d0a --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/load.liquid @@ -0,0 +1,10 @@ +{% doc %} + @param {string} id - The record ID +{% enddoc %} +{% liquid + + graphql g = 'modules/user/user/load', id: id + assign user = g.users.results.first + + return user +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/otp.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/otp.liquid new file mode 100644 index 00000000..0553906c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/otp.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param {string} email - The email address + @param {string} name +{% enddoc %} +{% liquid + if email == blank + log 'Something went wrong. Email cannot be blank.', type: 'ERROR' + return null + endif + + # platformos-check-disable TranslationKeyExists + assign issuer = 'app.title' | t: default: 'App' + # platformos-check-enable TranslationKeyExists + graphql r = 'modules/user/user/otp', email: email, issuer: issuer + + if r.errors + assign type = 'ERROR' | append: name + log r, type: type + break + endif + + return r.users.results.first +%} diff --git a/pos-module-user-invites/modules/user/public/lib/queries/user/search.liquid b/pos-module-user-invites/modules/user/public/lib/queries/user/search.liquid new file mode 100644 index 00000000..7d0e61f7 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/lib/queries/user/search.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {string} email - The email address + @param {string} id - The record ID + @param {number} limit - Maximum number of results + @param {string} not_ids - List of record IDs to exclude + @param {number} page - Page number for pagination + @param {string} sort - Sort order +{% enddoc %} +{% liquid + assign limit = limit | default: 20 + assign page = page | to_positive_integer: 1 + + graphql r = 'modules/user/user/search', id: id, not_ids: not_ids, email: email, page: page, limit: limit, sort: sort + return r.users +%} diff --git a/pos-module-user-invites/modules/user/public/schema/oauth.yml b/pos-module-user-invites/modules/user/public/schema/oauth.yml new file mode 100644 index 00000000..2e88f77d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/schema/oauth.yml @@ -0,0 +1,8 @@ +name: oauth +properties: + - name: user_id + type: string + - name: provider + type: string + - name: sub + type: string \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/schema/profile.yml b/pos-module-user-invites/modules/user/public/schema/profile.yml new file mode 100644 index 00000000..1cdf1f81 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/schema/profile.yml @@ -0,0 +1,17 @@ +name: profile +properties: + - name: uuid + - name: user_id + - name: name + - name: first_name + - name: last_name + - name: email # duplication from user + - name: roles + type: array + + # tokenized downcased names for searching + - name: c__names + + # 2fa + - name: otp_configured + type: boolean diff --git a/pos-module-user-invites/modules/user/public/translations/en/2fa.yml b/pos-module-user-invites/modules/user/public/translations/en/2fa.yml new file mode 100644 index 00000000..813ae048 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/2fa.yml @@ -0,0 +1,25 @@ +en: + 2fa: + errors: + otp_code: Invalid OTP code provided. + password: Invalid password provided. + new: + enter_password: Enter password + your_password: Please enter your password. + submit: Submit + confirm_and_enable: Confirm and Enable Two Factor + two_factor_authentication: Two-factor authentication + scan_qr_code: Scan QR Code + 2fa_info: |- + To be able to log in you need to scan this QR Code with your authentication app. + + You can use [Authy](https://authy.com) or [any other authentication tool](https://www.lastpass.com/two-factor-authentication). + if_you_cannot_scan: 'Or enter the following code manually in the app:' + confirm_otp_code: Confirm code + please_confirm: Enter 6-digit code from your two-factor authenticator app + disable: + two_factor_authentication: Disable two factor authentication + create: + success: Successfully enabled two factor authentication. + delete: + success: Successfully disabled two factor authentication. diff --git a/pos-module-user-invites/modules/user/public/translations/en/authentication_links.yml b/pos-module-user-invites/modules/user/public/translations/en/authentication_links.yml new file mode 100644 index 00000000..3f0000eb --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/authentication_links.yml @@ -0,0 +1,6 @@ +en: + authentication_links: + created: + Please check your inbox. If the provided email was correct, you'll + receive some instructions on how to reset your password. + something_went_wrong: Something went wrong diff --git a/pos-module-user-invites/modules/user/public/translations/en/authorization.yml b/pos-module-user-invites/modules/user/public/translations/en/authorization.yml new file mode 100644 index 00000000..b291143c --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/authorization.yml @@ -0,0 +1,3 @@ +en: + authorization: + redirect_anonymous_info: 'Please log in to access this page.' diff --git a/pos-module-user-invites/modules/user/public/translations/en/emails.yml b/pos-module-user-invites/modules/user/public/translations/en/emails.yml new file mode 100644 index 00000000..3a312a8e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/emails.yml @@ -0,0 +1,14 @@ +en: + emails: + from_email: noreply@platformos.com + passwords: + reset: + subject: Reset password + title: Password reset request + cta: Reset password + cta_button: Go to reset password form + content: It seems that you requested a password reset. To proceed use the + following button. + ignore: If it wasn’t you who requested this just ignore this message. + + diff --git a/pos-module-user-invites/modules/user/public/translations/en/oauth.yml b/pos-module-user-invites/modules/user/public/translations/en/oauth.yml new file mode 100644 index 00000000..c57af4d2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/oauth.yml @@ -0,0 +1,13 @@ +en: + oauth: + app: + no_providers_available: 'There are no providers available' + provider_already_assigned: 'Selected provider is already in use.' + sub_already_assigned: 'External account is already connected to a different user.' + signed_in: 'Successfully signed in using OAuth 2.' + assigned_provider: 'Successfully assigned OAuth 2 provider.' + unassigned_provider: 'Successfully unassigned OAuth 2 provider.' + failed_to_create_account: 'Could not create a new account. Please try again later.' + invalid_request: 'Invalid request.' + unassign_provider: 'Unassign' + user_info_error: 'Could not fetch user info from OAuth 2 provider. Please try again later.' \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/translations/en/passwords.yml b/pos-module-user-invites/modules/user/public/translations/en/passwords.yml new file mode 100644 index 00000000..0ffe4f42 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/passwords.yml @@ -0,0 +1,17 @@ +en: + passwords: + password: Password + password_confirmation: Confirm password + password_update: Update password + new_password: New password + confirm_new_password: Confirm new password + login: Login + register: Register + reset_password: Email an authentication link + edit: Reset Password + email: Email + email_desc: Enter your registered email and we will send you a link to reset your password + reset_password_title: Reset password + expired_link: The reset password link you’ve entered is invalid or has expired. + remembered_password: You've remembered the password? + forgot: Forgot password? \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/translations/en/sessions.yml b/pos-module-user-invites/modules/user/public/translations/en/sessions.yml new file mode 100644 index 00000000..d3c68fc8 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/sessions.yml @@ -0,0 +1,8 @@ +en: + sessions: + new: + log_in: Log In + dont_have_account: Don't have an account? + request_to_join: Request to join + social_login_separator: or + back_to_login: Return to login page diff --git a/pos-module-user-invites/modules/user/public/translations/en/users.yml b/pos-module-user-invites/modules/user/public/translations/en/users.yml new file mode 100644 index 00000000..8163d8e3 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/users.yml @@ -0,0 +1,12 @@ +en: + users: + new: + create_account: Create an Account + already_have_account: Already have an account? Log in + logout: Log out + email: + new_email: 'New email' + current_password: 'Current password' + change_email: 'Change email' + email_update: 'Update' + change_success: 'Email updated' \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/translations/en/validation.yml b/pos-module-user-invites/modules/user/public/translations/en/validation.yml new file mode 100644 index 00000000..07d8b3d5 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/translations/en/validation.yml @@ -0,0 +1,18 @@ +en: + validation: + email: + required: Please provide your email address + format: The email doesn't look right, please check again + user_exists: It seems you already have a registered account. Please check the email field again or log in with your credentials. + taken: already taken + not_uniq: not unique + invalid_email_or_password: Invalid email or password + invalid_password: Invalid password. + matches: not valid format + not_truthy: not true + password: + lowercase: must include at least one lower case + uppercase: must include at least one upper case + number: must include at least one number + do_not_match: passwords do not match + invalid: invalid diff --git a/pos-module-user-invites/modules/user/public/views/pages/authentication_links/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/authentication_links/create.liquid new file mode 100644 index 00000000..e3cbde9e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/authentication_links/create.liquid @@ -0,0 +1,33 @@ +--- +method: post +slug: authentication_links +--- +{% liquid + function object = 'modules/user/commands/authentication_links/create', email: context.params.authentication_link.email, host: context.location.host, hcaptcha_params: context.params, valid_for: null + if object.valid + function email = 'modules/user/commands/emails/auth-link', object: object + if email.valid + if object.email == 'change-password@example.com' and context.environment == 'staging' + echo object.url + break + endif + + function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.created', error: null, force_clear: null, info: null + redirect_to '/' + else + log email.errors, type: 'ERROR: authentication_links/create email' + + function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.something_went_wrong', error: null, force_clear: null, info: null + redirect_to '/' + endif + elsif object.token == blank + if context.environment == 'staging' + log object, type: 'DEBUG: reset-password-user-not-found' + endif + + function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.created', error: null, force_clear: null, info: null + redirect_to '/' + else + render 'modules/user/passwords/reset', context: context, errors: object.errors, values: null + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/oauth/callback.liquid b/pos-module-user-invites/modules/user/public/views/pages/oauth/callback.liquid new file mode 100644 index 00000000..f7d1ac23 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/oauth/callback.liquid @@ -0,0 +1,104 @@ +--- +method: get +slug: oauth/:provider/callback +--- +{% liquid + # platformos-check-disable ConvertIncludeToRender + + function current_user = "modules/user/queries/user/current" + assign state = context.session.state + if context.params.code == blank or context.params.provider == blank or context.params.state != state + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', error: "modules/user/oauth.app.invalid_request", default: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + endif + + function available_providers = "modules/user/helpers/get_available_oauth_providers" + assign provider = context.params.provider | upcase + assign selected_provider = available_providers[provider] + + if selected_provider == blank + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + endif + + # check if user already has a given provider + if current_user.id != blank + graphql g = "modules/user/oauth/find_by_user_id", provider: provider, user_id: current_user.id + if g.records.total_entries > 0 + log "Provider already assigned", type: "ERROR" + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.provider_already_assigned", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + endif + endif + + # fetch user info using the appropriate module + assign command_path = "modules/oauth_" | append: selected_provider.key | append: "/helpers/get_user_info" + function user_info = command_path, provider: selected_provider, code: context.params.code + + if user_info.valid == false + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.user_info_error", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + endif + + assign user_sub = user_info.sub | json + assign user_email = user_info.email + assign user_first_name = user_info.first_name + assign user_last_name = user_info.last_name + + # check if sub is already registered to an existing user + graphql g = "modules/user/oauth/find_by_sub", provider: provider, sub: user_sub + assign found_user_id = current_user.id + assign create_provider_assignment = true + if g.records.total_entries > 0 + if current_user.id != null + log "Sub already assigned", type: "ERROR" + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.sub_already_assigned", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + else + assign found_user_id = g.records.results[0].user_id + assign create_provider_assignment = false + endif + endif + + # check if user account should be created + if current_user.id == null and found_user_id == null + function new_user = "modules/user/commands/oauth/create_user", user_first_name: user_first_name, user_last_name: user_last_name, user_email: user_email + if new_user == null or new_user.valid == false + log new_user.errors, type: "ERROR" + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.failed_to_create_account", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + return + endif + assign found_user_id = new_user.id + endif + + # create a connection between user and provider + if create_provider_assignment + graphql g = "modules/user/oauth/create", sub: user_sub, provider: provider, user_id: found_user_id + endif + + # sign in as user + if current_user.id == blank + function _ = "modules/user/commands/session/create", validate_password: false, skip_otp: true, email: null, password: null, hook_params: null, user_id: null + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.signed_in", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', notice: "modules/user/oauth.app.assigned_provider", default: null, error: null, format: null, info: null, object: null, url: null + # platformos-check-enable DeprecatedTag + endif + # platformos-check-enable ConvertIncludeToRender +%} + diff --git a/pos-module-user-invites/modules/user/public/views/pages/oauth/start.liquid b/pos-module-user-invites/modules/user/public/views/pages/oauth/start.liquid new file mode 100644 index 00000000..9356a656 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/oauth/start.liquid @@ -0,0 +1,27 @@ +--- +method: post +slug: oauth/:provider/start +--- + +{% liquid + if context.params.provider == blank + log "Provider not provided", type: "ERROR" + redirect_to '/' + endif + + function available_providers = 'modules/user/helpers/get_available_oauth_providers' + assign provider = context.params.provider | upcase + assign selected_provider = available_providers[provider] + + if selected_provider == blank + assign error = "Provider does not exist: " | append: provider + log error, type: "ERROR" + redirect_to '/' + endif + + session state = '' | uuid + + assign command_path = "modules/oauth_" | append: selected_provider.key | append: "/helpers/get_redirect_url" + function url = command_path, provider: selected_provider, state: context.session.state + redirect_to url +%} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/pages/oauth/unassign.liquid b/pos-module-user-invites/modules/user/public/views/pages/oauth/unassign.liquid new file mode 100644 index 00000000..de609148 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/oauth/unassign.liquid @@ -0,0 +1,21 @@ +--- +slug: oauth/:provider/unassign +method: delete +--- +{% liquid + function current_user = 'modules/user/queries/user/current' + + if context.params.provider == blank or current_user.id == blank + redirect_to '/' + endif + + assign provider = context.params.provider | upcase + + graphql g = 'modules/user/oauth/find_by_user_id', provider: provider, user_id: current_user.id + if g.records.total_entries > 0 + graphql g = 'modules/user/oauth/delete', id: g.records.results[0].id + endif + + function _ = 'modules/user/helpers/flash', notice: 'modules/user/oauth.app.unassigned_provider', error: null, force_clear: null, info: null + redirect_to '/' +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/passwords/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/passwords/create.liquid new file mode 100644 index 00000000..52531507 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/passwords/create.liquid @@ -0,0 +1,19 @@ +--- +slug: passwords +method: post +--- +{% liquid + assign input = context.params.password + assign redirect_url = context.params.redirect_to | default: '/' + assign input.user_id = context.session.reset_password_session_user_id + + function object = 'modules/user/commands/passwords/create', object: input + if object.valid + session reset_password_session_user_id = null + + function _ = 'modules/user/commands/session/create', validate_password: false, email: null, password: null, hook_params: null, skip_otp: null, user_id: context.session.reset_password_session_user_id + redirect_to redirect_url + else + render 'modules/user/passwords/new', context: context, errors: object.errors + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/passwords/new.liquid b/pos-module-user-invites/modules/user/public/views/pages/passwords/new.liquid new file mode 100644 index 00000000..66d8958d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/passwords/new.liquid @@ -0,0 +1,15 @@ +{% liquid + if context.session.reset_password_session_user_id == blank + function user = 'modules/user/helpers/user_from_temporary_token', token: context.params.token, email: context.params.email + + if user + session reset_password_session_user_id = user.id + else + function _ = 'modules/user/helpers/flash', error: 'modules/user/passwords.expired_link', force_clear: null, info: null, notice: null + redirect_to '/sessions/new' + break + endif + endif + + render 'modules/user/passwords/new', context: context, errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/passwords/reset.liquid b/pos-module-user-invites/modules/user/public/views/pages/passwords/reset.liquid new file mode 100644 index 00000000..ac953216 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/passwords/reset.liquid @@ -0,0 +1 @@ +{% render 'modules/user/passwords/reset', context: context, values: null, errors: null %} diff --git a/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/create.liquid new file mode 100644 index 00000000..3ec7f617 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/create.liquid @@ -0,0 +1,26 @@ +--- +slug: profiles/2fa +method: post +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.id == blank + redirect_to '/' + endif + + function object = 'modules/user/commands/user/verify_otp', object: context.params.2fa, email: current_profile.user.email + if object.valid + assign current_profile.otp_configured = true + function object = 'modules/user/commands/profiles/mark_otp', object: current_profile + if object.valid != true + log object, 'ERROR: modules/user/profiles/mark_otp' + endif + assign notice = 'modules/user/2fa.create.success' | t + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', url: '/', notice: notice, default: null, error: null, format: null, info: null, object: null + # platformos-check-enable DeprecatedTag + else + function user_otp = 'modules/user/queries/user/otp', email: current_profile.user.email, name: null + render 'modules/user/2fa/setup', otp: user_otp.otp, errors: object.errors, object: object + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/delete.liquid b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/delete.liquid new file mode 100644 index 00000000..7552075b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/delete.liquid @@ -0,0 +1,25 @@ +--- +slug: profiles/2fa/delete +method: post +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.id == blank + redirect_to '/' + endif + + function object = 'modules/user/commands/user/verify_otp', object: context.params.2fa, email: current_profile.user.email + if object.valid + assign current_profile.otp_configured = false + function object = 'modules/user/commands/profiles/mark_otp', object: current_profile + if object.valid != true + log object, 'ERROR: modules/user/profiles/mark_otp' + endif + assign notice = 'modules/user/2fa.delete.success' | t + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', url: '/', notice: notice, default: null, error: null, format: null, info: null, object: null + # platformos-check-enable DeprecatedTag + else + render 'modules/user/2fa/disable', errors: object.errors + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/disable.liquid b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/disable.liquid new file mode 100644 index 00000000..0ef75da2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/disable.liquid @@ -0,0 +1,8 @@ +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.user.id == null or current_profile.otp_configured != true + redirect_to '/' + endif + + render 'modules/user/2fa/disable', errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/new.liquid b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/new.liquid new file mode 100644 index 00000000..70c73db5 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/profiles/2fa/new.liquid @@ -0,0 +1,10 @@ +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.user.id == null + redirect_to '/' + endif + + function user_otp = 'modules/user/queries/user/otp', email: current_profile.user.email, name: null + + render 'modules/user/2fa/setup', otp: user_otp.otp, object: null, errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/2fa.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/2fa.liquid new file mode 100644 index 00000000..7e16d764 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/2fa.liquid @@ -0,0 +1,29 @@ +--- +method: post +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.user != null + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + endif + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'sessions.create', return_url: '/', access_callback: null, entity: null + # platformos-check-enable DeprecatedTag + + function object = 'modules/user/commands/user/verify_otp', object: context.params.2fa, email: null + if object.valid + function res = 'modules/user/commands/session/create', email: object.email, password: object.password, hook_params: context.params, skip_otp: true, validate_password: null, user_id: null + if res.valid + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + render 'modules/user/sessions/new', context: context, errors: res.errors, values: null + endif + else + render 'modules/user/2fa/verify', object: object + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/create.liquid new file mode 100644 index 00000000..24f37072 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/create.liquid @@ -0,0 +1,21 @@ +--- +method: post +slug: sessions +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'sessions.create', return_url: '/', access_callback: null, entity: null + # platformos-check-enable DeprecatedTag + function res = 'modules/user/commands/session/create', email: context.params.email, password: context.params.password, hook_params: context.params, validate_password: true, skip_otp: null, user_id: null + if res.valid and res.otp_required + render 'modules/user/2fa/verify', object: context.params + elsif res.valid + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + render 'modules/user/sessions/new', context: context, errors: res.errors, values: null + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/destroy.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/destroy.liquid new file mode 100644 index 00000000..563bb06e --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/destroy.liquid @@ -0,0 +1,16 @@ +--- +slug: sessions +method: delete +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'sessions.destroy', return_url: '/', access_callback: null, entity: null + # platformos-check-enable DeprecatedTag + + function res = 'modules/user/commands/session/destroy' + + assign redirect_path = res.hook_results.redirect_to | default: context.params.redirect_to | default: '/' + redirect_to redirect_path +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/create.liquid new file mode 100644 index 00000000..d50500af --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/create.liquid @@ -0,0 +1,34 @@ +--- +slug: sessions/impersonations +method: post +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + function user_to_impersonate = 'modules/user/queries/user/load', id: context.params.user_id + + if user_to_impersonate + if user_to_impersonate.roles contains 'superadmin' + assign permission = 'users.impersonate_superadmin' + else + assign permission = 'users.impersonate' + endif + + # platformos-check-disable UnreachableCode + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_unauthorized', do: permission, requester: current_profile, access_callback: null, anonymous_return_to: null, entity: null, forbidden_partial: null, redirect_anonymous_to_login: null + # platformos-check-enable DeprecatedTag + # platformos-check-enable UnreachableCode + + function impersonate_user = 'modules/user/commands/session/impersonation/create', current_user_id: context.current_user.id, user: user_to_impersonate + + if impersonate_user.valid + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + print "Something went wrong." + endif + else + print "Something went wrong." + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/destroy.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/destroy.liquid new file mode 100644 index 00000000..85bfbb61 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/impersonation/destroy.liquid @@ -0,0 +1,20 @@ +--- +slug: sessions/impersonations +method: delete +--- +{% liquid + if context.session.original_user_id == blank + redirect_to "/" + else + function admin_user = 'modules/user/queries/user/load', id: context.session.original_user_id + function object = 'modules/user/commands/session/impersonation/destroy', user: admin_user, current_user_id: context.current_user.id + + if object.valid + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + print "Something went wrong." + endif + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/sessions/new.liquid b/pos-module-user-invites/modules/user/public/views/pages/sessions/new.liquid new file mode 100644 index 00000000..9b470242 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/sessions/new.liquid @@ -0,0 +1,9 @@ +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'sessions.create', return_url: '/', access_callback: null, entity: null + # platformos-check-enable DeprecatedTag + + render 'modules/user/sessions/new', context: context, values: null, errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/users/create.liquid b/pos-module-user-invites/modules/user/public/views/pages/users/create.liquid new file mode 100644 index 00000000..9d00033b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/users/create.liquid @@ -0,0 +1,25 @@ +--- +method: post +slug: users +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'users.register', access_callback: null, entity: null, return_url: null + # platformos-check-enable DeprecatedTag + + function object = 'modules/user/commands/user/create', first_name: context.params.first_name, last_name: context.params.last_name, email: context.params.email, password: context.params.password, hook_params: context.params, roles: null + if object.valid + function _ = 'modules/user/commands/session/create', validate_password: false, user_id: object.id, email: null, password: null, hook_params: null, skip_otp: null + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + else + function registration_fields = 'modules/user/queries/registration_fields/load' + + assign values = context.params + assign values.password = '' + render 'modules/user/users/new', context: context, registration_fields: registration_fields, errors: object.errors, values: values + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/users/email/edit.liquid b/pos-module-user-invites/modules/user/public/views/pages/users/email/edit.liquid new file mode 100644 index 00000000..9705fbf5 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/users/email/edit.liquid @@ -0,0 +1,10 @@ +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.user == null + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + endif + + render 'modules/user/users/email/edit', context: context, otp_enabled: current_profile.otp_configured, errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/users/email/update.liquid b/pos-module-user-invites/modules/user/public/views/pages/users/email/update.liquid new file mode 100644 index 00000000..1b4b258d --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/users/email/update.liquid @@ -0,0 +1,35 @@ +--- +slug: users/email/edit +method: put +--- +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + if current_profile.user == null + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', default: null, error: null, format: null, info: null, notice: null, object: null, url: null + # platformos-check-enable DeprecatedTag + endif + + if current_profile.otp_configured + function object = 'modules/user/commands/user/verify_otp', object: context.params.user, email: current_profile.user.email + if object.valid == false + render 'modules/user/users/email/edit', context: null, otp_enabled: current_profile.otp_configured, errors: object.errors + break + endif + endif + + function object = 'modules/user/commands/user/email_update', object: context.params.user, current_user: current_profile.user + if object.valid + assign current_profile.email = context.params.user.email + function _ = 'modules/user/commands/profiles/update', object: current_profile, profile: current_profile + assign event_payload = {"actor_id": object.id, "object": object, "actor": object, "target": null, "object_id": null, "target_id": null} + function _event = 'modules/core/commands/events/publish', type: 'email_updated', object: event_payload, delay: null, max_attempts: null + + assign notice = 'modules/user/users.email.change_success' | t + # platformos-check-disable DeprecatedTag + include 'modules/core/helpers/redirect_to', url: '/', notice: notice, default: null, error: null, format: null, info: null, object: null + # platformos-check-enable DeprecatedTag + else + render 'modules/user/users/email/edit', context: context, otp_enabled: null, errors: null + endif +%} diff --git a/pos-module-user-invites/modules/user/public/views/pages/users/new.liquid b/pos-module-user-invites/modules/user/public/views/pages/users/new.liquid new file mode 100644 index 00000000..22d0a479 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/pages/users/new.liquid @@ -0,0 +1,12 @@ +{% liquid + function current_profile = 'modules/user/helpers/current_profile' + + # platformos-check-disable DeprecatedTag + include 'modules/user/helpers/can_do_or_redirect', requester: current_profile, do: 'users.register', access_callback: null, entity: null, return_url: null + # platformos-check-enable DeprecatedTag + + function registration_fields = 'modules/user/queries/registration_fields/load' + assign values = {"email": context.params.email} + + render 'modules/user/users/new', context: context, registration_fields: registration_fields, values: values, errors: null +%} diff --git a/pos-module-user-invites/modules/user/public/views/partials/2fa/disable.liquid b/pos-module-user-invites/modules/user/public/views/partials/2fa/disable.liquid new file mode 100644 index 00000000..839b71c1 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/2fa/disable.liquid @@ -0,0 +1,35 @@ +{% doc %} + @param {object} errors - The validation errors object +{% enddoc %} +
    +

    + {{ 'modules/user/2fa.disable.two_factor_authentication' | t }} +

    + +
    +
    + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'password', errors: errors.password %} +
    + +

    + {{ 'modules/user/2fa.new.confirm_otp_code' | t }} +

    +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'otp_code', errors: errors.otp_code %} +
    + +
    + +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/2fa/setup.liquid b/pos-module-user-invites/modules/user/public/views/partials/2fa/setup.liquid new file mode 100644 index 00000000..20974cc1 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/2fa/setup.liquid @@ -0,0 +1,54 @@ +{% doc %} + @param {object} errors - The validation errors object + @param {object} object - The object to process + @param {object} otp - The OTP configuration object +{% enddoc %} +
    +

    + {{ 'modules/user/2fa.new.two_factor_authentication' | t }} +

    + +
    + +
    +
    +
    + {{ 'modules/user/2fa.new.2fa_info' | t | markdown }} +
    + +

    + {{ 'modules/user/2fa.new.scan_qr_code' | t }} +

    + +
    + {{ otp.secret_as_svg_qr_code }} +
    + +
    + {{ 'modules/user/2fa.new.if_you_cannot_scan' | t }}
    + {{ otp.secret }} +
    + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'otp_code', errors: errors.otp_code %} +
    + +
    + + {{ 'modules/user/2fa.new.your_password' | t }} + + {% render 'modules/common-styling/forms/error_list', name: 'password', errors: errors.password %} +
    + +
    + +
    +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/2fa/verify.liquid b/pos-module-user-invites/modules/user/public/views/partials/2fa/verify.liquid new file mode 100644 index 00000000..0a03db8a --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/2fa/verify.liquid @@ -0,0 +1,33 @@ +{% doc %} + @param {object} object - The object to process +{% enddoc %} +
    +

    + {{ 'modules/user/2fa.new.two_factor_authentication' | t }} +

    + +
    + + + + +

    + {{ 'modules/user/2fa.new.confirm_otp_code' | t }} +

    +
    + {{ 'modules/user/2fa.new.please_confirm' | t }} +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'otp_code', errors: object.errors.otp_code %} + +
    + +
    + +
    +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/admin_pages/list.liquid b/pos-module-user-invites/modules/user/public/views/partials/admin_pages/list.liquid new file mode 100644 index 00000000..3fd9b147 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/admin_pages/list.liquid @@ -0,0 +1,52 @@ +{% function users = 'modules/user/queries/user/get_all' %} +
    + +

    Users

    > + + + + + {% for property in users.first %} + {% unless property[0] == 'id' or property[0] == 'hook_results' %} + + {% endunless %} + {% endfor %} + + + + + {% for user in users %} + {% liquid + assign id = user.id + assign hook_results = user.hook_results + assign user = user | hash_delete_key: 'id' + assign user = user | hash_delete_key: 'hook_results' + %} + + + {% for property in user %} + + {% endfor %} + + + {% endfor %} + +
    ID{{ property[0] }}Additional fields
    {{ id }} + {% assign type = property[1] | type_of %} + {% if type == 'Array' %} + {{ property[1] | join: ', ' }} + {% else %} + {{ property[1] }} + {% endif %} + + {% if hook_results %} + {% for hook_result in hook_results %} + {% if hook_result[1] %} + {{ hook_result[0] }}:
    + {{ hook_result[1] }} + {% endif %} + {% endfor %} + {% endif %} +
    + +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/components/pages/403.liquid b/pos-module-user-invites/modules/user/public/views/partials/components/pages/403.liquid new file mode 100644 index 00000000..5558d8cd --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/components/pages/403.liquid @@ -0,0 +1,4 @@ +
    +

    403 Forbidden

    +

    You don't have access to this page

    +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/emails/passwords/reset.liquid b/pos-module-user-invites/modules/user/public/views/partials/emails/passwords/reset.liquid new file mode 100644 index 00000000..6e16d0e2 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/emails/passwords/reset.liquid @@ -0,0 +1,18 @@ +

    {{ 'modules/user/emails.passwords.reset.title' | t }}

    + +

    {{ 'modules/user/emails.passwords.reset.content' | t }}

    +

    {{ 'modules/user/emails.passwords.reset.ignore' | t }}

    + + + + + +
    + +

    {{ 'modules/user/emails.passwords.reset.cta' | t }}

    + + + {{ 'modules/user/emails.passwords.reset.cta_button' | t }} + + +
    diff --git a/pos-module-user-invites/modules/user/public/views/partials/oauth/listing.liquid b/pos-module-user-invites/modules/user/public/views/partials/oauth/listing.liquid new file mode 100644 index 00000000..24e36355 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/oauth/listing.liquid @@ -0,0 +1,48 @@ +{% liquid + function available_providers = 'modules/user/helpers/get_available_oauth_providers' + function assigned_providers = 'modules/user/helpers/get_assigned_oauth_providers' + %} + +
    +

    OAuth 2

    +
    + + {% if available_providers.size == 0 %} + {{ 'modules/user/oauth.app.no_providers_available' | t }} + {% endif %} + +
    + {% for provider in available_providers %} + {% if assigned_providers contains provider[0] %} +
    + + + +
    + {% else %} +
    + + + +
    + {% endif %} + {% endfor %} +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/partials/oauth/providers.liquid b/pos-module-user-invites/modules/user/public/views/partials/oauth/providers.liquid new file mode 100644 index 00000000..cb17726b --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/oauth/providers.liquid @@ -0,0 +1,24 @@ +{% function available_providers = 'modules/user/helpers/get_available_oauth_providers' %} +{% if available_providers.size > 0 %} + + +{% endif %} \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/partials/passwords/new.liquid b/pos-module-user-invites/modules/user/public/views/partials/passwords/new.liquid new file mode 100644 index 00000000..25f03bc0 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/passwords/new.liquid @@ -0,0 +1,38 @@ +--- +metadata: + name: New password + params: + context: {} + errors: {} +--- +{% doc %} + @param {object} errors - The validation errors object + @param {object} context - The request context +{% enddoc %} +
    + +

    {{ 'modules/user/passwords.edit' | t }}

    + +
    + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'password', errors: errors['password'] %} +
    + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'password_confirmation', errors: errors['password_confirmation'] %} +
    + +
    + +
    + +
    + +
    + diff --git a/pos-module-user-invites/modules/user/public/views/partials/passwords/reset.liquid b/pos-module-user-invites/modules/user/public/views/partials/passwords/reset.liquid new file mode 100644 index 00000000..9a3b5a66 --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/passwords/reset.liquid @@ -0,0 +1,40 @@ +--- +metadata: + name: Reset password + params: + context: {} + errors: [] + values: {} +--- +{% doc %} + @param {object} errors - The validation errors object + @param {object} values - The form values object + @param {object} context - The request context +{% enddoc %} +
    + +

    {{ 'modules/user/passwords.reset_password_title' | t }}

    + +

    {{ 'modules/user/passwords.email_desc' | t }}

    + +
    + + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'email', errors: errors['email'] %} +
    + + {% render 'modules/common-styling/forms/hcaptcha' %} + +
    + +
    + +
    + + {{ 'modules/user/passwords.remembered_password' | t }} {{ 'modules/user/sessions.new.log_in' | t }} + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/partials/sessions/new.liquid b/pos-module-user-invites/modules/user/public/views/partials/sessions/new.liquid new file mode 100644 index 00000000..9e8a21eb --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/sessions/new.liquid @@ -0,0 +1,47 @@ +--- +metadata: + name: Login + params: + context: {} + errors: [] + values: {} +--- +{% doc %} + @param {object} errors - The validation errors object + @param {object} values - The form values object + @param {object} context - The request context +{% enddoc %} +
    + +

    {{ 'modules/user/sessions.new.log_in' | t }}

    + +
    + + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'email', errors: errors['email'] %} +
    + +
    +
    + + {{ 'modules/user/passwords.forgot' | t }} +
    + + {% render 'modules/common-styling/forms/error_list', name: 'password', errors: errors['password'] %} +
    + +
    + +
    + +
    + + {{ 'modules/user/sessions.new.dont_have_account' | t }} {{ 'modules/user/sessions.new.request_to_join' | t }} + + {% render 'modules/user/oauth/providers' %} + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/partials/users/email/edit.liquid b/pos-module-user-invites/modules/user/public/views/partials/users/email/edit.liquid new file mode 100644 index 00000000..333562fc --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/users/email/edit.liquid @@ -0,0 +1,51 @@ +--- +metadata: + name: New password + params: + context: {} + errors: {} + otp_enabled: null +--- +{% doc %} + @param {object} errors - The validation errors object + @param {boolean} otp_enabled - Whether OTP is enabled for the user + @param {object} context - The request context +{% enddoc %} +
    + +

    {{ 'modules/user/users.email.change_email' | t }}

    + +
    + + + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'email', errors: errors['email'] %} +
    + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'password', errors: errors['password'] %} +
    + + {% if otp_enabled %} +

    + {{ 'modules/user/2fa.new.confirm_otp_code' | t }} +

    +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'otp_code', errors: errors.otp_code %} +
    + {% endif %} + +
    + +
    + +
    + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/public/views/partials/users/new.liquid b/pos-module-user-invites/modules/user/public/views/partials/users/new.liquid new file mode 100644 index 00000000..c3319b8a --- /dev/null +++ b/pos-module-user-invites/modules/user/public/views/partials/users/new.liquid @@ -0,0 +1,75 @@ +--- +metadata: + name: Register + params: + context: {} + values: {} + errors: [] + registration_fields: [] +--- +{% doc %} + @param {object} errors - The validation errors object + @param {string} registration_fields - Additional registration form fields + @param {object} values - The form values object + @param {object} context - The request context +{% enddoc %} + +
    + +

    {{ 'modules/user/users.new.create_account' | t }}

    + +
    + + {% for field in registration_fields %} +
    + {% if field.label %} + + {% endif %} + + {% render 'modules/common-styling/forms/error_list', name: field.name, errors: errors[field.name] %} +
    + {% endfor %} + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'first_name', errors: errors['first_name'] %} +
    + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'last_name', errors: errors['last_name'] %} +
    + +
    + + + {% render 'modules/common-styling/forms/error_list', name: 'email', errors: errors['email'] %} +
    + +
    + + + {% if errors['password'] %} +
      + {% for error in errors['password'] %} +
    • {{ error }}
    • + {% endfor %} +
    + {% endif %} +
    + + {% render 'modules/common-styling/forms/hcaptcha' %} + +
    + +
    + +
    + + {{ 'modules/user/users.new.already_have_account' | t }} + + {% render 'modules/user/oauth/providers' %} + +
    \ No newline at end of file diff --git a/pos-module-user-invites/modules/user/template-values.json b/pos-module-user-invites/modules/user/template-values.json new file mode 100644 index 00000000..4b801ccb --- /dev/null +++ b/pos-module-user-invites/modules/user/template-values.json @@ -0,0 +1,10 @@ +{ + "name": "User", + "machine_name": "user", + "type": "module", + "version": "5.2.8", + "dependencies": { + "core": "^2.1.8", + "common-styling": "^1.11.0" + } +} diff --git a/pos-module-user-invites/modules/user_invites/pos-module.json b/pos-module-user-invites/modules/user_invites/pos-module.json new file mode 100644 index 00000000..cf03beb3 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/pos-module.json @@ -0,0 +1,10 @@ +{ + "machine_name": "user_invites", + "version": "1.0.0", + "name": "Pos Module User Invites", + "dependencies": { + "core": "^2.0.0", + "user": "5.2.8", + "common-styling": "1.37.26" + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/create.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/create.graphql new file mode 100644 index 00000000..77824478 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/create.graphql @@ -0,0 +1,22 @@ +mutation create( + $filename: String + $csv: String! + $status: String! + $created_by_id: String +) { + record_create( + record: { + table: "modules/user_invites/invite_csv" + properties: [ + { name: "filename" value: $filename } + { name: "csv" value: $csv } + { name: "status" value: $status } + { name: "created_by_id" value: $created_by_id } + ] + } + ) { + id + created_at + properties + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/find.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/find.graphql new file mode 100644 index 00000000..9c619b09 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/find.graphql @@ -0,0 +1,22 @@ +query find($id: ID!) { + records( + per_page: 1 + page: 1 + filter: { + id: { value: $id } + table: { value: "modules/user_invites/invite_csv" } + } + ) { + results { + id + created_at + updated_at + filename: property(name: "filename") + csv: property(name: "csv") + status: property(name: "status") + created_by_id: property(name: "created_by_id") + sent_at: property(name: "sent_at") + sent_count: property_int(name: "sent_count") + } + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/search.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/search.graphql new file mode 100644 index 00000000..0e9d5a68 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/search.graphql @@ -0,0 +1,31 @@ +query search( + $limit: Int = 20 + $page: Int = 1 + $status: String +) { + invite_csvs: records( + per_page: $limit + page: $page + filter: { + table: { value: "modules/user_invites/invite_csv" } + properties: [ + { name: "status", value: $status } + ] + } + sort: [{ created_at: { order: DESC } }] + ) { + total_entries + total_pages + has_next_page + current_page + results { + id + created_at + updated_at + filename: property(name: "filename") + status: property(name: "status") + created_by_id: property(name: "created_by_id") + sent_at: property(name: "sent_at") + } + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/update.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/update.graphql new file mode 100644 index 00000000..406b9692 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/invite_csvs/update.graphql @@ -0,0 +1,21 @@ +mutation update( + $id: ID! + $status: String + $sent_at: String + $sent_count: Int +) { + record_update( + id: $id + record: { + table: "modules/user_invites/invite_csv" + properties: [ + { name: "status" value: $status } + { name: "sent_at" value: $sent_at } + { name: "sent_count" value_int: $sent_count } + ] + } + ) { + id + properties + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/create.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/create.graphql new file mode 100644 index 00000000..473ba641 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/create.graphql @@ -0,0 +1,17 @@ +mutation create( + $user_id: String! +) { + record_create( + record: { + table: "modules/user_invites/user_invite" + properties: [ + { name: "user_id" value: $user_id } + ] + } + ) { + id + created_at + deleted_at + properties + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/find.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/find.graphql new file mode 100644 index 00000000..6184ad8a --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/find.graphql @@ -0,0 +1,17 @@ +query find($id: ID!) { + records( + per_page: 1 + page: 1 + filter: { + id: { value: $id } + table: { + value: "modules/user_invites/user_invite" + } + } + ) { + results { + id + properties + } + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/update.graphql b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/update.graphql new file mode 100644 index 00000000..656c5566 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/graphql/user_invites/update.graphql @@ -0,0 +1,23 @@ +mutation update( + $id: ID! + $expires_at: String + $sent_at: String + $accepted_at: String +) { + record_update( + id: $id + record: { + table: "modules/user_invites/user_invite" + properties: [ + { name: "expires_at" value: $expires_at } + { name: "sent_at" value: $sent_at } + { name: "accepted_at" value: $accepted_at } + ] + } + ) { + id + created_at + deleted_at + properties + } +} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/can/user_invites.liquid b/pos-module-user-invites/modules/user_invites/public/lib/can/user_invites.liquid new file mode 100644 index 00000000..7aa3ba35 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/can/user_invites.liquid @@ -0,0 +1,34 @@ +{% liquid + assign authenticated = entity.user_invite_token | is_token_valid: entity.user_id + + assign is_accepted = false + assign is_expired = false + + if entity.user_invite.properties.accepted_at + assign is_accepted = true + endif + + assign expires_at = entity.user_invite.properties.expires_at | to_time + assign now = 'now' | to_time + + if expires_at < now + assign is_expired = true + endif + + assign authenticated_success = false + if authenticated + unless is_accepted or is_expired + assign authenticated_success = true + endunless + endif + + case do + + when 'update' + return authenticated_success + when 'edit' + return authenticated_success + else + return false + endcase +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/emails/user_invite.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/emails/user_invite.liquid new file mode 100644 index 00000000..15ba85d1 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/emails/user_invite.liquid @@ -0,0 +1,23 @@ +{% doc %} + @param object {object} - email payload (email, sign_up_url) + @param site_name {string} - site name shown in subject line + @param from {string} - sender email address +{% enddoc %} +{% parse_json object %} + { + "to": {{ object.email | json }}, + "from": {{ from | json }}, + "subject": {% print 'modules/user_invites/emails.invitation_subject' | t: site_name: site_name | json %}, + "partial": "modules/user_invites/emails/user_invites/user_invite", + "layout": {{ context.constants.USER_INVITES_MAILER_LAYOUT | json }}, + "data": { + "sign_up_url": {% print object.sign_up_url | json %}, + "email": {{ object.email | json }} + } + } +{% endparse_json %} + +{% liquid + function object = 'modules/core/commands/email/send', object: object + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create.liquid new file mode 100644 index 00000000..342c7208 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create.liquid @@ -0,0 +1,18 @@ +{% doc %} + Persists an uploaded CSV as a new invite_csv record with status 'pending'. + @param csv {string} - raw CSV text + @param filename {string} - original filename + @param created_by_id {string} - user id of uploader +{% enddoc %} +{% liquid + assign object = '{}' | parse_json | hash_merge: csv: csv, filename: filename, created_by_id: created_by_id + + function object = 'modules/user_invites/commands/invite_csvs/create/build', object: object + function object = 'modules/user_invites/commands/invite_csvs/create/check', object: object + + if object.valid + function object = 'modules/user_invites/commands/invite_csvs/create/execute', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/build.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/build.liquid new file mode 100644 index 00000000..2349acd4 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/build.liquid @@ -0,0 +1,4 @@ +{% liquid + assign data = null | hash_merge: csv: object.csv, filename: object.filename, created_by_id: object.created_by_id, status: 'pending' + return data +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/check.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/check.liquid new file mode 100644 index 00000000..f11b8ee2 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/check.liquid @@ -0,0 +1,9 @@ +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'csv' + + assign object = object | hash_merge: c + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/execute.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/execute.liquid new file mode 100644 index 00000000..1f6c3f7f --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/create/execute.liquid @@ -0,0 +1,5 @@ +{% liquid + graphql created = 'modules/user_invites/invite_csvs/create', csv: object.csv, filename: object.filename, status: object.status, created_by_id: object.created_by_id + assign object = object | hash_merge: id: created.record_create.id + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send.liquid new file mode 100644 index 00000000..58b03610 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send.liquid @@ -0,0 +1,18 @@ +{% doc %} + Marks an invite_csv record as sent and dispatches per-row user_invite creation + in the background. + @param id {string} - invite_csv record id + @param csv {string} - invite_csv csv text +{% enddoc %} +{% liquid + assign object = '{}' | parse_json | hash_merge: id: id, csv: csv + + function object = 'modules/user_invites/commands/invite_csvs/send/build', object: object + function object = 'modules/user_invites/commands/invite_csvs/send/check', object: object + + if object.valid + function object = 'modules/user_invites/commands/invite_csvs/send/execute', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/build.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/build.liquid new file mode 100644 index 00000000..93965a65 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/build.liquid @@ -0,0 +1,4 @@ +{% liquid + assign data = null | hash_merge: id: object.id, csv: object.csv + return data +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/check.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/check.liquid new file mode 100644 index 00000000..f6e3c5bf --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/check.liquid @@ -0,0 +1,10 @@ +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'csv' + + assign object = object | hash_merge: c + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/execute.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/execute.liquid new file mode 100644 index 00000000..151cf0f1 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/invite_csvs/send/execute.liquid @@ -0,0 +1,24 @@ +{% liquid + function preview = 'modules/user_invites/queries/invite_csvs/preview', csv: object.csv + assign to_invite = preview.to_invite + + assign now_time = 'now' | to_time: 'UTC' + assign sent_at = now_time | strftime: '%Y-%m-%dT%H:%M:%S%Z' + graphql _ = 'modules/user_invites/invite_csvs/update', id: object.id, status: 'sent', sent_at: sent_at, sent_count: to_invite.size +%} + +{% background delay: 0.1, max_attempts: 0, to_invite: to_invite %} + {% liquid + for row in to_invite + function result = 'modules/user_invites/commands/user_invites/create', email: row.email, first_name: row.first_name, last_name: row.last_name + unless result.valid == false + log row.email, type: 'INFO: user_invite created' + endunless + endfor + %} +{% endbackground %} + +{% liquid + assign object = object | hash_merge: sent_count: to_invite.size + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept.liquid new file mode 100644 index 00000000..a02658e1 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept.liquid @@ -0,0 +1,10 @@ +{% liquid + function object = 'modules/user_invites/commands/user_invites/accept/build', object: object + function object = 'modules/user_invites/commands/user_invites/accept/check', object: object + + if object.valid + function object = 'modules/user_invites/commands/user_invites/accept/execute', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/build.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/build.liquid new file mode 100644 index 00000000..a946bb70 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/build.liquid @@ -0,0 +1,4 @@ +{% liquid + assign data = null | hash_merge: user_id: object.user_id, first_name: object.first_name, last_name: object.last_name, password: object.password, email: object.email, user_invite_id: object.user_invite_id, app_host: object.app_host + return data +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/check.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/check.liquid new file mode 100644 index 00000000..02c0cbd4 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/check.liquid @@ -0,0 +1,15 @@ +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'user_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'first_name' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'last_name' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password' + function c = 'modules/core/validations/password_complexity', c: c, object: object, field_name: 'password' + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'first_name', maximum: 40, allow_blank: null + function c = 'modules/core/validations/length', c: c, object: object, field_name: 'last_name', maximum: 40, allow_blank: null + + assign object = object | hash_merge: c + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/execute.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/execute.liquid new file mode 100644 index 00000000..1e363335 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/accept/execute.liquid @@ -0,0 +1,21 @@ +{% liquid + function profile = 'modules/user/queries/profiles/find', user_id: object.user_id, id: null, uuid: null, first_name: null, last_name: null + + graphql _ = 'modules/user/user/update', id: object.user_id, password: object.password + + assign full_name = object.first_name | append: ' ' | append: object.last_name + assign tokenize_object = null | hash_merge: email: object.email, first_name: object.first_name, last_name: object.last_name + function tokenized_names = 'modules/user/commands/profiles/tokenize_names', object: tokenize_object + graphql _ = 'modules/user/profiles/update', id: profile.id, first_name: object.first_name, last_name: object.last_name, name: full_name, email: object.email, roles: profile.roles, c__names: tokenized_names + + assign now_time = 'now' | to_time: 'UTC' + assign accepted_at = now_time | strftime: "%Y-%m-%dT%H:%M:%S%Z" + graphql _ = 'modules/user_invites/user_invites/update', id: object.user_invite_id, accepted_at: accepted_at + + function _ = 'modules/user/commands/session/create', user_id: object.user_id, validate_password: false + + assign user_invite_accepted_object = null | hash_merge: email: object.email, user_id: object.user_id, user_invite_id: object.user_invite_id, app_host: object.app_host + function _ = 'modules/core/commands/events/publish', type: 'user_invite_accepted', object: user_invite_accepted_object + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create.liquid new file mode 100644 index 00000000..a8604132 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create.liquid @@ -0,0 +1,12 @@ +{% liquid + assign object = '{}' | parse_json | hash_merge: email: email, first_name: first_name, last_name: last_name + + function object = 'modules/user_invites/commands/user_invites/create/build', object: object + function object = 'modules/user_invites/commands/user_invites/create/check', object: object + + if object.valid + function object = 'modules/user_invites/commands/user_invites/create/execute', object: object + endif + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/build.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/build.liquid new file mode 100644 index 00000000..a0b068a8 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/build.liquid @@ -0,0 +1,4 @@ +{% liquid + assign data = null | hash_merge: email: object.email, first_name: object.first_name, last_name: object.last_name + return data +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/check.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/check.liquid new file mode 100644 index 00000000..59357ee0 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/check.liquid @@ -0,0 +1,17 @@ +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email' + + if object.email != blank + graphql emails_count = 'modules/user/user/emails_count', email: object.email | dig: 'users', 'total_entries' + if emails_count > 0 + assign message = 'app.errors.taken' | t + function c = 'modules/core/helpers/register_error', contract: c, field_name: 'email', message: message + endif + endif + + assign object = object | hash_merge: c + + return object +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/execute.liquid b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/execute.liquid new file mode 100644 index 00000000..5a89dad8 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/commands/user_invites/create/execute.liquid @@ -0,0 +1,25 @@ +{% liquid + assign password = 12 | random_string | append: 'Az3!/' + assign email_prefix = object.email | split: '@' | first + assign first_name = object.first_name | default: email_prefix + assign last_name = object.last_name | default: email_prefix + + function user = 'modules/user/commands/user/create', email: object.email, password: password, first_name: first_name, last_name: last_name + assign user_id = user.id + + if user_id == blank + return user + endif + + graphql user_invite = 'modules/user_invites/user_invites/create', user_id: user_id + + if user_invite.record_create.id == blank + return false + endif + + assign user_invited_object = null | hash_merge: email: object.email, user_id: user_id, user_invite_id: user_invite.record_create.id, app_host: context.location.host + + function _ = 'modules/core/commands/events/publish', type: 'user_invited', object: user_invited_object + + return user_invite +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/consumers/user_invited/send_invite_email.liquid b/pos-module-user-invites/modules/user_invites/public/lib/consumers/user_invited/send_invite_email.liquid new file mode 100644 index 00000000..0227d227 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/consumers/user_invited/send_invite_email.liquid @@ -0,0 +1,23 @@ +{% background delay: 0.1, user_id: event.user_id, email: event.email, user_invite_id: event.user_invite_id, app_host: event.app_host, max_attempts: 0 %} + {% liquid + graphql g = 'modules/user/user/find', id: user_id, with_token: true, valid_for: 4380, expires_in: 4380 + + assign user_invite_token = g.users.results.first.token + + assign object = '{}' | parse_json + hash_assign object['email'] = email + hash_assign object['user_id'] = user_id + hash_assign object['sign_up_url'] = "https://" | append: app_host | append: "/user_invites/" | append: user_invite_id | append: "/edit" | append: "?token=" | append: user_invite_token + + assign now_time = 'now' | to_time: 'UTC' + assign sent_at = now_time | strftime: "%Y-%m-%dT%H:%M:%S%Z" + assign expires_at_time = now_time | add_to_time: 182, 'days' + assign expires_at = expires_at_time | strftime: "%Y-%m-%dT%H:%M:%S%Z" + + graphql g = 'modules/user_invites/user_invites/update', id: user_invite_id, expires_at: expires_at, sent_at: sent_at + + assign site_name = 'app.site_name' | t + assign from_email = 'app.from_email' | t + function email = 'modules/user_invites/commands/emails/user_invite', object: object, site_name: site_name, from: from_email + %} +{% endbackground %} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/events/user_invite_accepted.liquid b/pos-module-user-invites/modules/user_invites/public/lib/events/user_invite_accepted.liquid new file mode 100644 index 00000000..039fa382 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/events/user_invite_accepted.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + user_id + email + user_invite_id + app_host +--- +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'email' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_invite_id' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'app_host' + return c +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/events/user_invited.liquid b/pos-module-user-invites/modules/user_invites/public/lib/events/user_invited.liquid new file mode 100644 index 00000000..039fa382 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/events/user_invited.liquid @@ -0,0 +1,17 @@ +--- +metadata: + event: + user_id + email + user_invite_id + app_host +--- +{% liquid + assign c = '{ "errors": {}, "valid": true }' | parse_json + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'email' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_invite_id' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'app_host' + return c +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/helpers/current_profile.liquid b/pos-module-user-invites/modules/user_invites/public/lib/helpers/current_profile.liquid new file mode 100644 index 00000000..c7781d31 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/helpers/current_profile.liquid @@ -0,0 +1,4 @@ +{% liquid + function results = 'modules/core/commands/hook/fire', hook: 'user_invites_current_profile' + return results | first +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/find.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/find.liquid new file mode 100644 index 00000000..2d8c5280 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/find.liquid @@ -0,0 +1,8 @@ +{% doc %} + Finds an invite_csv record by id. + @param id {string} - invite_csv record id +{% enddoc %} +{% liquid + graphql found = 'modules/user_invites/invite_csvs/find', id: id + return found.records.results.first +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/parse.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/parse.liquid new file mode 100644 index 00000000..9bfefe65 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/parse.liquid @@ -0,0 +1,57 @@ +{% doc %} + Parses an invite CSV string and discovers the email/first_name/last_name columns + (case-insensitive). Returns parsed_rows (rows with a non-blank email), + csv_emails (downcased), invalid (rows missing email), header, and email_index. + @param csv {string} - raw CSV text +{% enddoc %} +{% liquid + assign rows = csv | parse_csv + assign header = rows | first + + assign email_index = -1 + assign first_name_index = -1 + assign last_name_index = -1 + + for column in header + assign column_name = column | strip | downcase + if column_name == 'email' + assign email_index = forloop.index0 + elsif column_name == 'first_name' + assign first_name_index = forloop.index0 + elsif column_name == 'last_name' + assign last_name_index = forloop.index0 + endif + endfor + + assign parsed_rows = '[]' | parse_json + assign csv_emails = '[]' | parse_json + assign invalid = '[]' | parse_json + + if email_index >= 0 + for cols in rows offset: 1 + assign email = cols[email_index] | strip | downcase + + if email == blank + assign invalid_row = null | hash_merge: cols: cols + assign invalid = invalid | array_add: invalid_row + continue + endif + + assign first_name = blank + assign last_name = blank + if first_name_index >= 0 + assign first_name = cols[first_name_index] | strip + endif + if last_name_index >= 0 + assign last_name = cols[last_name_index] | strip + endif + + assign row = null | hash_merge: email: email, first_name: first_name, last_name: last_name + assign parsed_rows = parsed_rows | array_add: row + assign csv_emails = csv_emails | array_add: email + endfor + endif + + assign result = null | hash_merge: email_index: email_index, header: header, parsed_rows: parsed_rows, csv_emails: csv_emails, invalid: invalid + return result +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/preview.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/preview.liquid new file mode 100644 index 00000000..50265dfd --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/preview.liquid @@ -0,0 +1,31 @@ +{% doc %} + Returns a full preview of an invite CSV: parsed rows split into to_invite vs + skipped (already-existing emails), plus invalid (no-email rows). Performs a + single batched profile lookup against modules/user/profiles/search. + @param csv {string} - raw CSV text +{% enddoc %} +{% liquid + function parsed = 'modules/user_invites/queries/invite_csvs/parse', csv: csv + + assign existing_lookup = '{}' | parse_json + if parsed.csv_emails.size > 0 + graphql existing = 'modules/user/profiles/search', emails: parsed.csv_emails, limit: parsed.csv_emails.size + for profile in existing.records.results + assign existing_email = profile.email | downcase + hash_assign existing_lookup[existing_email] = true + endfor + endif + + assign to_invite = '[]' | parse_json + assign skipped = '[]' | parse_json + for row in parsed.parsed_rows + if existing_lookup[row.email] + assign skipped = skipped | array_add: row + else + assign to_invite = to_invite | array_add: row + endif + endfor + + assign result = parsed | hash_merge: to_invite: to_invite, skipped: skipped + return result +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/search.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/search.liquid new file mode 100644 index 00000000..f7c0d657 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/invite_csvs/search.liquid @@ -0,0 +1,10 @@ +{% doc %} + Returns a paginated list of invite_csv records. + @param page {integer} - page number (1-based) + @param limit {integer} - per-page count + @param status {string} - optional status filter ('pending' | 'sent') +{% enddoc %} +{% liquid + graphql result = 'modules/user_invites/invite_csvs/search', page: page, limit: limit, status: status + return result.invite_csvs +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invite_fields/load.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invite_fields/load.liquid new file mode 100644 index 00000000..2266ce51 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invite_fields/load.liquid @@ -0,0 +1,28 @@ +{% parse_json fields %} +[ + { + "name": "first_name", + "required": true, + "type": "text", + "weight": 0, + "label": "First name" + }, + { + "name": "last_name", + "required": true, + "type": "text", + "weight": 1, + "label": "Last name" + }, + { + "name": "password", + "required": true, + "type": "password", + "weight": 2, + "label": "Password" + } +] +{% endparse_json %} +{% liquid + return fields +%} diff --git a/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invites/find.liquid b/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invites/find.liquid new file mode 100644 index 00000000..c0657da9 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/lib/queries/user_invites/find.liquid @@ -0,0 +1,8 @@ +{% doc %} + Finds a user_invite record by id. + @param id {string} - user_invite record id +{% enddoc %} +{% liquid + graphql found = 'modules/user_invites/user_invites/find', id: id + return found.records.results.first +%} diff --git a/pos-module-user-invites/modules/user_invites/public/schema/invite_csv.yml b/pos-module-user-invites/modules/user_invites/public/schema/invite_csv.yml new file mode 100644 index 00000000..e62a0725 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/schema/invite_csv.yml @@ -0,0 +1,14 @@ +name: invite_csv +properties: + - name: filename + type: string + - name: csv + type: text + - name: status + type: string + - name: created_by_id + type: string + - name: sent_at + type: datetime + - name: sent_count + type: integer diff --git a/pos-module-user-invites/modules/user_invites/public/schema/user_invite.yml b/pos-module-user-invites/modules/user_invites/public/schema/user_invite.yml new file mode 100644 index 00000000..8bee9010 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/schema/user_invite.yml @@ -0,0 +1,10 @@ +name: user_invite +properties: + - name: user_id + type: string + - name: sent_at + type: datetime + - name: accepted_at + type: datetime + - name: expires_at + type: datetime diff --git a/pos-module-user-invites/modules/user_invites/public/translations/en/admin.yml b/pos-module-user-invites/modules/user_invites/public/translations/en/admin.yml new file mode 100644 index 00000000..9a525826 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/translations/en/admin.yml @@ -0,0 +1,42 @@ +--- +en: + admin: + invite_users: + menu_title: "Invite users" + heading: "Invite users from CSV" + intro_columns: "Attach a CSV file to start a new bulk invitation. The first row should contain the column headers. The email, first_name, and last_name columns will be used — additional columns are ignored." + intro_summary: "You will see a summary of who will be invited before any emails go out. The claim link in each invitation is valid for six months." + file_label: "CSV file" + attach_and_preview: "Attach & preview" + empty_csv: "CSV file appears to be empty." + past_imports: "Past CSV imports" + no_imports: "No CSV imports yet." + column_filename: "Filename" + column_uploaded: "Uploaded" + column_status: "Status" + column_action: "Action" + action_resume: "Resume" + action_view: "View" + unnamed: "(unnamed)" + not_found_heading: "CSV not found" + back: "Back" + back_to_list: "Back to invite users" + already_sent_heading: "Already sent" + already_sent_message: "This CSV import has already been processed on %{date}." + missing_email_heading: "CSV is missing the email column" + missing_email_message: "The first row of the CSV must include a column called email." + sent_heading: "Sent — %{filename}" + sent_summary: "Invitations were sent to %{count} user(s) on %{date}." + preview_heading: "Preview — %{filename}" + preview_to_invite: "%{count} user(s) will be invited." + preview_skipped: "%{count} row(s) will be skipped (email already in use)." + preview_invalid: "%{count} row(s) without a valid email will be ignored." + send_button: "Send %{count} invitation(s)" + cancel: "Cancel" + users_to_invite: "Users to invite" + skipped_users: "Skipped (already exists)" + table_email: "Email" + table_first_name: "First name" + table_last_name: "Last name" + queued_heading: "Invitations queued" + queued_message: "Sending %{count} invitation(s) in the background. Emails will go out shortly." diff --git a/pos-module-user-invites/modules/user_invites/public/translations/en/emails.yml b/pos-module-user-invites/modules/user_invites/public/translations/en/emails.yml new file mode 100644 index 00000000..bb1afa0d --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/translations/en/emails.yml @@ -0,0 +1,10 @@ +--- +en: + emails: + invitation_subject: "You are invited to join %{site_name}" + invitation_title: You have an invitation waiting + invitation_content: An account has been created for you. Use the button + below to set your password and claim your account. + invitation_ignore: If you don't want to accept the invitation, please just + ignore this message. + invitation_claim: Claim account diff --git a/pos-module-user-invites/modules/user_invites/public/translations/en/user_invites.yml b/pos-module-user-invites/modules/user_invites/public/translations/en/user_invites.yml new file mode 100644 index 00000000..ced9f7b1 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/translations/en/user_invites.yml @@ -0,0 +1,7 @@ +--- +en: + user_invites: + form: + title: "Create a %{site_name} account" + errors: + registration_failed: "Could not complete registration. Please try again." diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users.liquid new file mode 100644 index 00000000..be419a87 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users.liquid @@ -0,0 +1,19 @@ +--- +layout: "{{ context.constants.USER_INVITES_ADMIN_LAYOUT }}" +metadata: + menu: + title: "Invite users" + permission: "profiles.manage.all" + relative_path: "/admin/community/invite_users" +--- +{% liquid + function current_profile = 'modules/user_invites/helpers/current_profile' + # platformos-check-disable UnreachableCode + include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: context.page.metadata.permission + # platformos-check-enable UnreachableCode + + assign page = context.params.page | default: 1 | plus: 0 + function invite_csvs = 'modules/user_invites/queries/invite_csvs/search', page: page, limit: 20, status: null + + render 'modules/user_invites/admin_pages/invite_users/index', invite_csvs: invite_csvs, page: page, context: context +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_preview.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_preview.liquid new file mode 100644 index 00000000..849034f8 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_preview.liquid @@ -0,0 +1,31 @@ +--- +layout: "{{ context.constants.USER_INVITES_ADMIN_LAYOUT }}" +slug: admin/community/invite_users/:id/preview +--- +{% liquid + function current_profile = 'modules/user_invites/helpers/current_profile' + # platformos-check-disable UnreachableCode + include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: 'profiles.manage.all' + # platformos-check-enable UnreachableCode + + function invite_csv = 'modules/user_invites/queries/invite_csvs/find', id: context.params.id + + if invite_csv == blank + render 'modules/user_invites/admin_pages/invite_users/not_found' + break + endif + + if invite_csv.status == 'sent' + render 'modules/user_invites/admin_pages/invite_users/sent', invite_csv: invite_csv + break + endif + + function preview = 'modules/user_invites/queries/invite_csvs/preview', csv: invite_csv.csv + + if preview.email_index < 0 + render 'modules/user_invites/admin_pages/invite_users/missing_email_column' + break + endif + + render 'modules/user_invites/admin_pages/invite_users/preview', invite_csv: invite_csv, preview: preview, context: context +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_send.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_send.liquid new file mode 100644 index 00000000..c1bfdf86 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_send.liquid @@ -0,0 +1,31 @@ +--- +layout: "{{ context.constants.USER_INVITES_ADMIN_LAYOUT }}" +method: post +slug: admin/community/invite_users/:id/send +--- +{% liquid + function current_profile = 'modules/user_invites/helpers/current_profile' + # platformos-check-disable UnreachableCode + include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: 'profiles.manage.all' + # platformos-check-enable UnreachableCode + + function invite_csv = 'modules/user_invites/queries/invite_csvs/find', id: context.params.id + + if invite_csv == blank + render 'modules/user_invites/admin_pages/invite_users/not_found' + break + endif + + if invite_csv.status == 'sent' + render 'modules/user_invites/admin_pages/invite_users/already_sent', invite_csv: invite_csv + break + endif + + function result = 'modules/user_invites/commands/invite_csvs/send', id: invite_csv.id, csv: invite_csv.csv + + if result.valid + render 'modules/user_invites/admin_pages/invite_users/queued', sent_count: result.sent_count + else + redirect_to '/admin/community/invite_users' + endif +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_upload.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_upload.liquid new file mode 100644 index 00000000..31a563e9 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/admin/community/invite_users_upload.liquid @@ -0,0 +1,24 @@ +--- +layout: "{{ context.constants.USER_INVITES_ADMIN_LAYOUT }}" +method: post +slug: admin/community/invite_users/upload +--- +{% liquid + function current_profile = 'modules/user_invites/helpers/current_profile' + # platformos-check-disable UnreachableCode + include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: 'profiles.manage.all' + # platformos-check-enable UnreachableCode + + assign filename = context.params.filename | default: 'upload.csv' + function result = 'modules/user_invites/commands/invite_csvs/create', csv: context.params.csv_content, filename: filename, created_by_id: current_profile.user_id + + if result.valid + assign preview_url = '/admin/community/invite_users/' | append: result.id | append: '/preview' + redirect_to preview_url + else + assign message = 'modules/user_invites/admin.invite_users.empty_csv' | t + assign flash = null | hash_merge: message: message, severity: 'error' + function _ = 'modules/core/commands/session/set', key: 'sflash', value: flash + redirect_to '/admin/community/invite_users' + endif +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/edit.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/edit.liquid new file mode 100644 index 00000000..492c845a --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/edit.liquid @@ -0,0 +1,22 @@ +--- +slug: user_invites/:id/edit +--- +{% liquid + function user_invite_record = 'modules/user_invites/queries/user_invites/find', id: context.params.id + assign user_invite_token = context.params.token + + assign requester_roles = '["invited"]' | parse_json + assign requester = null | hash_merge: roles: requester_roles + assign access_object = null | hash_merge: user_invite_token: user_invite_token, user_invite: user_invite_record, user_id: user_invite_record.properties.user_id + include 'modules/user/helpers/can_do_or_redirect', entity: access_object, do: 'edit', requester: requester, access_callback: 'modules/user_invites/can/user_invites', return_url: '/' + + function user = 'modules/user/queries/user/find', id: user_invite_record.properties.user_id, email: null + function profile = 'modules/user/queries/profiles/find', user_id: user.id, id: null, uuid: null, first_name: null, last_name: null + + function registration_fields = 'modules/user_invites/queries/user_invite_fields/load' + + assign values = null | hash_merge: first_name: profile.first_name, last_name: profile.last_name + assign site_name = 'app.site_name' | t + + theme_render_rc 'modules/user_invites/user_invites/form', user_invite: user_invite_record, token: user_invite_token, registration_fields: registration_fields, values: values, context: context, site_name: site_name +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/update.liquid b/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/update.liquid new file mode 100644 index 00000000..4946f4fa --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/pages/user_invites/update.liquid @@ -0,0 +1,33 @@ +--- +slug: user_invites/:id/update +method: post +--- +{% liquid + function user_invite_record = 'modules/user_invites/queries/user_invites/find', id: context.params.id + assign user_invite_token = context.params.token + + assign requester_roles = '["invited"]' | parse_json + assign requester = null | hash_merge: roles: requester_roles + assign access_object = null | hash_merge: user_invite_token: user_invite_token, user_invite: user_invite_record, user_id: user_invite_record.properties.user_id + include 'modules/user/helpers/can_do_or_unauthorized', entity: access_object, do: 'update', requester: requester, access_callback: 'modules/user_invites/can/user_invites' + + assign user_id = user_invite_record.properties.user_id + function user = 'modules/user/queries/user/find', id: user_id, email: null + + assign accept_object = context.params | hash_merge: user_id: user_id, email: user.email, user_invite_id: user_invite_record.id, app_host: context.location.host + function accept = 'modules/user_invites/commands/user_invites/accept', object: accept_object + + if accept.valid + redirect_to '/onboarding' + else + log accept, type: 'ERROR: user_invites/accept' + assign message = 'modules/user_invites/user_invites.errors.registration_failed' | t + assign flash = null | hash_merge: message: message, severity: 'error' + function _ = 'modules/core/commands/session/set', key: 'sflash', value: flash + + function registration_fields = 'modules/user_invites/queries/user_invite_fields/load' + assign values = context.params | hash_merge: password: '' + assign site_name = 'app.site_name' | t + theme_render_rc 'modules/user_invites/user_invites/form', context: context, registration_fields: registration_fields, errors: accept.errors, values: values, token: user_invite_token, user_invite: user_invite_record, site_name: site_name + endif +%} diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/already_sent.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/already_sent.liquid new file mode 100644 index 00000000..bd1bc425 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/already_sent.liquid @@ -0,0 +1,12 @@ +{% comment %} + @prompt: Renders the "Already sent" minimal page (post-send view of an invite_csv). + Required: invite_csv (record with sent_at) +{% endcomment %} +{% liquid + assign sent_date = invite_csv.sent_at | localize: 'short' +%} +
    +

    {{ 'modules/user_invites/admin.invite_users.already_sent_heading' | t }}

    +

    {{ 'modules/user_invites/admin.invite_users.already_sent_message' | t: date: sent_date }}

    + {{ 'modules/user_invites/admin.invite_users.back' | t }} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/index.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/index.liquid new file mode 100644 index 00000000..7c56630f --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/index.liquid @@ -0,0 +1,76 @@ +{% comment %} + @prompt: Renders the admin "Invite users from CSV" index page with the upload form + and a paginated list of past CSV imports. + Required: invite_csvs (search result), page (current page number), context +{% endcomment %} +{% liquid + assign unnamed_label = 'modules/user_invites/admin.invite_users.unnamed' | t +%} +
    +

    {{ 'modules/user_invites/admin.invite_users.heading' | t }}

    + +
    +

    {{ 'modules/user_invites/admin.invite_users.intro_columns' | t }}

    +

    {{ 'modules/user_invites/admin.invite_users.intro_summary' | t }}

    + + {% render 'modules/user_invites/admin_pages/invite_users/upload_form', context: context %} +
    + +

    {{ 'modules/user_invites/admin.invite_users.past_imports' | t }}

    + +
    + {% if invite_csvs.results.size == 0 %} +

    {{ 'modules/user_invites/admin.invite_users.no_imports' | t }}

    + {% else %} + + + + + + + + + + + {% for record in invite_csvs.results %} + {% liquid + assign filename_label = record.filename | default: unnamed_label + assign uploaded_at = record.created_at | localize: 'short' + assign action_label = 'modules/user_invites/admin.invite_users.action_view' | t + if record.status == 'pending' + assign action_label = 'modules/user_invites/admin.invite_users.action_resume' | t + endif + %} + + + + + + + {% endfor %} + +
    {{ filename_label }}{{ uploaded_at }} + {% liquid + assign chip_variant = 'warning' + if record.status == 'sent' + assign chip_variant = 'success' + endif + theme_render_rc 'components/molecules/chip', variant: chip_variant, content: record.status + %} + + {{ action_label }} +
    + {% endif %} +
    + +
    + {% liquid + if invite_csvs.total_pages > 1 + assign url_params = null | hash_merge: page: '' + assign url_template = '/admin/community/invite_users{?page}' + assign pager_url = url_template | expand_url_template: url_params + theme_render_rc 'components/molecules/pagination', count: invite_csvs.total_pages, active: page, url: pager_url + endif + %} +
    +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/missing_email_column.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/missing_email_column.liquid new file mode 100644 index 00000000..bda8d0e6 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/missing_email_column.liquid @@ -0,0 +1,8 @@ +{% comment %} + @prompt: Renders the "missing email column" error for an uploaded CSV. +{% endcomment %} +
    +

    {{ 'modules/user_invites/admin.invite_users.missing_email_heading' | t }}

    +

    {{ 'modules/user_invites/admin.invite_users.missing_email_message' | t }}

    + {{ 'modules/user_invites/admin.invite_users.back' | t }} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/not_found.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/not_found.liquid new file mode 100644 index 00000000..c1bd52ba --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/not_found.liquid @@ -0,0 +1,7 @@ +{% comment %} + @prompt: Renders the "CSV not found" admin message with a back link. +{% endcomment %} +
    +

    {{ 'modules/user_invites/admin.invite_users.not_found_heading' | t }}

    + {{ 'modules/user_invites/admin.invite_users.back' | t }} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/preview.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/preview.liquid new file mode 100644 index 00000000..f5f18366 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/preview.liquid @@ -0,0 +1,42 @@ +{% comment %} + @prompt: Renders the pre-send preview of an invite_csv: counts, send button, + and tables of users-to-invite + skipped rows. + Required: invite_csv, preview (with to_invite, skipped, invalid), context +{% endcomment %} +{% liquid + assign unnamed_label = 'modules/user_invites/admin.invite_users.unnamed' | t + assign filename_label = invite_csv.filename | default: unnamed_label +%} +
    +

    {{ 'modules/user_invites/admin.invite_users.preview_heading' | t: filename: filename_label }}

    + +
    +

    {{ 'modules/user_invites/admin.invite_users.preview_to_invite' | t: count: preview.to_invite.size }}

    +

    {{ 'modules/user_invites/admin.invite_users.preview_skipped' | t: count: preview.skipped.size }}

    + {% if preview.invalid.size > 0 %} +

    {{ 'modules/user_invites/admin.invite_users.preview_invalid' | t: count: preview.invalid.size }}

    + {% endif %} +
    + + {% if preview.to_invite.size > 0 %} +
    + {% render 'modules/core/helpers/authenticity_token', context: context %} + + {{ 'modules/user_invites/admin.invite_users.cancel' | t }} +
    + {% else %} + {{ 'modules/user_invites/admin.invite_users.back' | t }} + {% endif %} + + {% if preview.to_invite.size > 0 %} +

    {{ 'modules/user_invites/admin.invite_users.users_to_invite' | t }}

    + {% render 'modules/user_invites/admin_pages/invite_users/row_table', rows: preview.to_invite %} + {% endif %} + + {% if preview.skipped.size > 0 %} +

    {{ 'modules/user_invites/admin.invite_users.skipped_users' | t }}

    + {% render 'modules/user_invites/admin_pages/invite_users/row_table', rows: preview.skipped %} + {% endif %} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/queued.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/queued.liquid new file mode 100644 index 00000000..30031466 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/queued.liquid @@ -0,0 +1,11 @@ +{% comment %} + @prompt: Renders the "invitations queued" confirmation after a send. + Required: sent_count (integer) +{% endcomment %} +
    +

    {{ 'modules/user_invites/admin.invite_users.queued_heading' | t }}

    +

    + {{ 'modules/user_invites/admin.invite_users.queued_message' | t: count: sent_count }} +

    + {{ 'modules/user_invites/admin.invite_users.back_to_list' | t }} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/row_table.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/row_table.liquid new file mode 100644 index 00000000..5f388cef --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/row_table.liquid @@ -0,0 +1,24 @@ +{% comment %} + @prompt: Renders a table of CSV rows (email / first_name / last_name). + Required: rows (array of {email, first_name, last_name}) +{% endcomment %} +
    + + + + + + + + + + {% for row in rows %} + + + + + + {% endfor %} + +
    {{ 'modules/user_invites/admin.invite_users.table_email' | t }}{{ 'modules/user_invites/admin.invite_users.table_first_name' | t }}{{ 'modules/user_invites/admin.invite_users.table_last_name' | t }}
    {{ row.email }}{{ row.first_name }}{{ row.last_name }}
    +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/sent.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/sent.liquid new file mode 100644 index 00000000..39690362 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/sent.liquid @@ -0,0 +1,18 @@ +{% comment %} + @prompt: Renders the post-send summary for a sent invite_csv, showing how many + users were invited and when. + Required: invite_csv (record with filename, sent_count, sent_at) +{% endcomment %} +{% liquid + assign unnamed_label = 'modules/user_invites/admin.invite_users.unnamed' | t + assign filename_label = invite_csv.filename | default: unnamed_label + assign sent_date = invite_csv.sent_at | localize: 'short' + assign sent_count = invite_csv.sent_count | default: 0 +%} +
    +

    {{ 'modules/user_invites/admin.invite_users.sent_heading' | t: filename: filename_label }}

    +
    +

    {{ 'modules/user_invites/admin.invite_users.sent_summary' | t: count: sent_count, date: sent_date }}

    +
    + {{ 'modules/user_invites/admin.invite_users.back_to_list' | t }} +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/upload_form.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/upload_form.liquid new file mode 100644 index 00000000..5a78c369 --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/admin_pages/invite_users/upload_form.liquid @@ -0,0 +1,47 @@ +{% comment %} + @prompt: Renders the file-upload form for the invite-users CSV. Reads the chosen + file in the browser, posts its contents to /admin/community/invite_users/upload. + Required: context (for authenticity_token) +{% endcomment %} +
    + {% render 'modules/core/helpers/authenticity_token', context: context %} + + + +
    + + +
    + + +
    + + diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/emails/user_invites/user_invite.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/emails/user_invites/user_invite.liquid new file mode 100644 index 00000000..af6fd8cf --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/emails/user_invites/user_invite.liquid @@ -0,0 +1,16 @@ +

    {{ 'modules/user_invites/emails.invitation_title' | t }}

    + +

    {{ 'modules/user_invites/emails.invitation_content' | t }}

    +

    {{ 'modules/user_invites/emails.invitation_ignore' | t }}

    + + + + + +
    + + + {{ 'modules/user_invites/emails.invitation_claim' | t }} + + +
    diff --git a/pos-module-user-invites/modules/user_invites/public/views/partials/user_invites/form.liquid b/pos-module-user-invites/modules/user_invites/public/views/partials/user_invites/form.liquid new file mode 100644 index 00000000..2748e4ff --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/public/views/partials/user_invites/form.liquid @@ -0,0 +1,42 @@ +{% doc %} + @param site_name {string} - site name shown in form title + @param user_invite {object} - user invite record + @param token {string} - signed invite token + @param registration_fields {array} - fields rendered in the form + @param values {object} - default values keyed by field name + @param errors {object} - per-field error messages + @param context {object} - request context (for authenticity_token) +{% enddoc %} +
    +

    {{ 'modules/user_invites/user_invites.form.title' | t: site_name: site_name }}

    + +
    +
    + {% render 'modules/core/helpers/authenticity_token', context: context %} + + + + {% for field in registration_fields %} + {% liquid + assign default_value = values[field.name] | raw_escape_string + assign error_messages = '[]' | parse_json + assign has_error = errors[field.name] + assign validation = null | hash_merge: messages: error_messages + if has_error + hash_assign validation['passed'] = false + hash_assign validation['messages'] = errors[field.name] + endif + assign input_params = field | hash_merge: value: default_value, classes: 'w-full' + assign label_params = null | hash_merge: content: field.label + assign field_params = null | hash_merge: validation: validation, input_params: input_params, label_params: label_params, classes: 'mb-6' + + theme_render_rc 'components/molecules/formfield', params: field_params + %} + {% endfor %} + +
    + {% theme_render_rc 'components/atoms/button', content: "Sign Up", type: 'submit' %} +
    +
    +
    +
    diff --git a/pos-module-user-invites/modules/user_invites/template-values.json b/pos-module-user-invites/modules/user_invites/template-values.json new file mode 100644 index 00000000..b54a6b4c --- /dev/null +++ b/pos-module-user-invites/modules/user_invites/template-values.json @@ -0,0 +1,11 @@ +{ + "name": "Pos Module User Invites", + "machine_name": "user_invites", + "type": "module", + "version": "1.0.0", + "dependencies": { + "core": "^2.0.0", + "user": "5.2.8", + "common-styling": "1.37.26" + } +} diff --git a/pos-module-user-invites/pos-module.json b/pos-module-user-invites/pos-module.json new file mode 100644 index 00000000..cf03beb3 --- /dev/null +++ b/pos-module-user-invites/pos-module.json @@ -0,0 +1,10 @@ +{ + "machine_name": "user_invites", + "version": "1.0.0", + "name": "Pos Module User Invites", + "dependencies": { + "core": "^2.0.0", + "user": "5.2.8", + "common-styling": "1.37.26" + } +} diff --git a/pos-module-user-invites/pos-module.lock.json b/pos-module-user-invites/pos-module.lock.json new file mode 100644 index 00000000..d9bc0fd0 --- /dev/null +++ b/pos-module-user-invites/pos-module.lock.json @@ -0,0 +1,15 @@ +{ + "dependencies": { + "user": "5.2.8", + "common-styling": "1.37.26", + "core": "2.1.8", + "oauth_github": "0.0.12" + }, + "devDependencies": {}, + "registries": { + "user": "https://partners.platformos.com", + "common-styling": "https://partners.platformos.com", + "core": "https://partners.platformos.com", + "oauth_github": "https://partners.platformos.com" + } +} \ No newline at end of file