diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6780193 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab +indent_size = 4 + +[*.{json,yml,md}] +indent_style = space +indent_size = 2 + +[{*.txt,wp-config-sample.php}] +end_of_line = crlf diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 0000000..50d5f47 --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,44 @@ +name: Prettier (JS) +on: + push: + branches: + - "master" + - "main" + paths-ignore: + - "**.md" + pull_request: + paths-ignore: + - "**.md" + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + prettier: + name: Prettier (JS) + runs-on: ubuntu-latest + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + steps: + - uses: actions/checkout@v4 + - name: Get changed js/vue files + id: changed-files-specific + uses: tj-actions/changed-files@v44 + with: + files: | + **.js + **.vue + - name: Prettify code + if: steps.changed-files-specific.outputs.any_changed == 'true' + env: + ALL_CHANGED_FILES: ${{ steps.changed-files-specific.outputs.all_changed_files }} + run: | + echo "Files that have changed: $ALL_CHANGED_FILES" + npx prettier --write $ALL_CHANGED_FILES + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Prettier: auto-formatting" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..a1ba12e --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,96 @@ +name: Continuous integration tests + +on: + push: + branches: + - "master" + - "main" + paths-ignore: + - "**.md" + pull_request: + paths-ignore: + - "**.md" + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + unit_tests: + name: "1️⃣ Unit tests" + runs-on: "ubuntu-latest" + continue-on-error: ${{ matrix.allowed_failure }} + strategy: + fail-fast: false + matrix: + php: [ '8.1', '8.2', '8.3' ] + allowed_failure: [ false ] + dependencies: + - "highest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php }}" + coverage: "xdebug" + + - name: "Checkout code" + uses: "actions/checkout@v4" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependencies }}" + custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F") + + - name: "Setup test suite" + run: "./vendor/bin/wp-pest setup plugin --plugin-slug=metorik-helper --skip-delete" + + - name: "Execute unit tests" + run: "./vendor/bin/pest --group=unit" + + integration_tests: + name: "2️⃣ Integration tests" + runs-on: "ubuntu-latest" + continue-on-error: ${{ matrix.allowed_failure }} + strategy: + fail-fast: false + matrix: + php: [ '8.1', '8.2', '8.3' ] + allowed_failure: [ false ] + dependencies: + - "highest" + steps: + - name: "Set up PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php }}" + coverage: "xdebug" + + - uses: "mirromutth/mysql-action@v1.1" + with: + mysql version: '5.6' + mysql database: 'mtk_test' + mysql root password: 'password' + + - name: "Checkout code" + uses: "actions/checkout@v4" + + - name: "Install dependencies" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependencies }}" + custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F") + + - name: "Add woocommerce plugin" + run: | + wget https://downloads.wordpress.org/plugin/woocommerce.zip + unzip woocommerce.zip + mv woocommerce ../ + + - name: "Setup test suite" + run: "./vendor/bin/wp-pest setup plugin --plugin-slug=metorik-helper --skip-delete --wp-version=6.4.3" + + - name: "Execute integration tests" + run: "./vendor/bin/pest --group=integration" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..827b82f --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/vendor/ +/node_modules/ +*.DS_Store +._* + +# Tests - local only +/wp-content +/wp +/tests/coverage +.phpunit.result.cache + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..64f1be3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +# Ignore built files: +vendor +node_modules +assets +composer.json +composer.lock +package.json +.github diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..6c7048a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "tabWidth": 4, + "useTabs": false, + "printWidth": 120, + "singleQuote": true, + "trailingComma": "es5", + "semi": true, + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "vueIndentScriptAndStyle": false, + "htmlWhitespaceSensitivity": "css" +} diff --git a/README.md b/README.md index a52f737..66a54bf 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,31 @@ gulp magic ``` To compile a minified JS file. + +--- + +## Testing + +As of v2 of the plugin, we now have some limited unit & integration testing in the plugin. + +In order to run the tests you'll first need to set up dependencies using `composer`: + +``` +composer install +``` + +Then you'll need to set up the test suite using `wp-pest`: + +``` +vendor/bin/wp-pest setup plugin --plugin-slug=metorik-helper --skip-delete --wp-version=6.4.2 +``` +(at the moment there is issues with installing WP 6.5+ with `wp-pest` so we are using 6.4.2) + +This will create the necessary files in your project to run the tests. + +Then you can run the tests using: + +``` +composer test:unit +composer test:integration +``` diff --git a/assets/css/metorik.css b/assets/css/metorik.css index 809a973..720ec2f 100644 --- a/assets/css/metorik.css +++ b/assets/css/metorik.css @@ -1,52 +1,83 @@ -/* Tippy Light Theme */ -.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme .tippy-arrow{border-top:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme .tippy-arrow{border-bottom:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme .tippy-arrow{border-left:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme .tippy-arrow{border-right:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-tooltip.light-theme{color:#26323d;box-shadow:0 0 20px 4px rgba(154,161,177,.15),0 4px 80px -8px rgba(36,40,47,.25),0 4px 4px -2px rgba(91,94,105,.15);background-color:#fff}.tippy-tooltip.light-theme .tippy-backdrop{background-color:#fff}.tippy-tooltip.light-theme .tippy-roundarrow{fill:#fff}.tippy-tooltip.light-theme[data-animatefill]{background-color:transparent} - /* Base styles for add to cart */ .metorik-add-cart-email-form { - max-width: 300px; - padding: 18px 15px 20px; - text-align: left; + max-width: 300px; + padding: 18px 15px 20px; + text-align: left; } .metorik-add-cart-email-form h3 { - font-weight: 600; - margin-bottom: 20px; + font-weight: 600; + margin: 0 0 20px; } .metorik-add-cart-email-form .close-button { - color: #bbb; - cursor: pointer; - font-size: 15px; - position: absolute; - right: 28px; - top: 28px; + color: #bbb; + cursor: pointer; + font-size: 15px; + position: absolute; + right: 28px; + top: 28px; } .metorik-add-cart-email-form .close-button:hover { - color: #888; + color: #888; } .metorik-add-cart-email-form .email-input-wrapper { - position: relative; + position: relative; } .metorik-add-cart-email-form .email-input-wrapper.loading { - opacity: 0.75; + opacity: 0.75; } .metorik-add-cart-email-form .email-input-wrapper.success:after { - color: rgb(55,178,77); - content: "\2713"; - font-size: 17px; - position: absolute; - right: 10px; - top: 10px; + color: rgb(55, 178, 77); + content: "\2713"; + font-size: 17px; + position: absolute; + right: 10px; + top: 10px; } .metorik-add-cart-email-form .email-input { - width: 100%; + width: calc(100% - 20px); + padding: 5px; } .metorik-add-cart-email-form .email-usage-notice { - padding: 5px 0 0; -} \ No newline at end of file + padding: 5px 0 0; +} + +/* tippy light theme */ +.tippy-box[data-theme~='light'] { + color: #26323d; + box-shadow: 0 0 20px 4px rgba(154, 161, 177, 0.15), + 0 4px 80px -8px rgba(36, 40, 47, 0.25), + 0 4px 4px -2px rgba(91, 94, 105, 0.15); + background-color: #fff; +} + +.tippy-box[data-theme~='light'] [data-placement^='top'] > .tippy-arrow::before { + border-top-color: #fff; +} + +.tippy-box[data-theme~='light'] [data-placement^='bottom'] > .tippy-arrow::before { + border-bottom-color: #fff; +} + +.tippy-box[data-theme~='light'] [data-placement^='left'] > .tippy-arrow::before { + border-left-color: #fff; +} + +.tippy-box[data-theme~='light'] [data-placement^='right'] > .tippy-arrow::before { + border-right-color: #fff; +} + +.tippy-box[data-theme~='light'] > .tippy-backdrop { + background-color: #fff; +} + +.tippy-box[data-theme~='light'] > .tippy-svg-arrow { + fill: #fff; +} diff --git a/assets/js/metorik.min.js b/assets/js/metorik.min.js index 4b2f17d..6b0e113 100644 --- a/assets/js/metorik.min.js +++ b/assets/js/metorik.min.js @@ -1 +1 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.sbjs=t()}}(function(){return function a(o,s,p){function c(r,t){if(!s[r]){if(!o[r]){var e="function"==typeof require&&require;if(!t&&e)return e(r,!0);if(l)return l(r,!0);var i=new Error("Cannot find module '"+r+"'");throw i.code="MODULE_NOT_FOUND",i}var n=s[r]={exports:{}};o[r][0].call(n.exports,function(t){var e=o[r][1][t];return c(e||t)},n,n.exports,a,o,s,p)}return s[r].exports}for(var l="function"==typeof require&&require,t=0;t=i.clientWidth&&r>=i.clientHeight}),l=0a,bottom:n-s.bottom>a,left:s.left-i>a,right:i-s.right>a};return"top"===p?l.top=s.top-n>c:"bottom"===p?l.bottom=n-s.bottom>c:"left"===p?l.left=s.left-i>c:"right"===p&&(l.right=i-s.right>c),l.top||l.bottom||l.left||l.right}(e,o.popper,o.options)&&(document.body.removeEventListener("mouseleave",a),document.removeEventListener("mousemove",t),J.call(o,t))})}J.call(o)}},onBlur:function(t){if(t.target===o.reference&&!mt.usingTouch){if(o.options.interactive){if(!t.relatedTarget)return;if(W(t.relatedTarget,ht.POPPER))return}J.call(o)}},onDelegateShow:function(t){W(t.target,o.options.target)&&V.call(o,t)},onDelegateHide:function(t){W(t.target,o.options.target)&&J.call(o)}}}function tt(){var t=this,e=this.popper,r=this.reference,i=this.options,n=g(e).tooltip,a=i.popperOptions,o="round"===i.arrowType?ht.ROUND_ARROW:ht.ARROW,s=n.querySelector(o),p=yt({placement:i.placement},a||{},{modifiers:yt({},a?a.modifiers:{},{arrow:yt({element:o},a&&a.modifiers?a.modifiers.arrow:{}),flip:yt({enabled:i.flip,padding:i.distance+5,behavior:i.flipBehavior},a&&a.modifiers?a.modifiers.flip:{}),offset:yt({offset:i.offset},a&&a.modifiers?a.modifiers.offset:{})}),onCreate:function(){n.style[M(e)]=z(i.distance),s&&i.arrowTransform&&B(e,s,i.arrowTransform)},onUpdate:function(){var t=n.style;t.top="",t.bottom="",t.left="",t.right="",t[M(e)]=z(i.distance),s&&i.arrowTransform&&B(e,s,i.arrowTransform)}});return it.call(this,{target:e,callback:function(){t.popperInstance.update()},options:{childList:!0,subtree:!0,characterData:!0}}),new Pt(r,e,p)}function et(){var t=this._(Nt),e=t.showTimeout,r=t.hideTimeout;clearTimeout(e),clearTimeout(r)}function rt(){var e=this;!function t(){e.popperInstance&&e.popperInstance.update(),e.popper.style[m("transitionDuration")]=e.options.updateDuration+"ms",e.state.visible?requestAnimationFrame(t):e.popper.style[m("transitionDuration")]=""}()}function it(t){var e=t.target,r=t.callback,i=t.options;if(window.MutationObserver){var n=new MutationObserver(r);n.observe(e,i),this._(Nt).mutationObservers.push(n)}}function nt(t,r){if(!t)return r();var i=g(this.popper).tooltip,n=function(t,e){e&&i[t+"EventListener"]("ontransitionend"in window?"transitionend":"webkitTransitionEnd",e)},e=function t(e){e.target===i&&(n("remove",t),r())};n("remove",this._(Nt).transitionendListener),n("add",e),this._(Nt).transitionendListener=e}function at(t,f){return t.reduce(function(t,r){var e,i,n,a,o,s=Ft,p=(e=r,(i=f.performance?f:(n=r,a=f,o=bt.reduce(function(t,e){var r=n.getAttribute("data-tippy-"+e.toLowerCase())||a[e];return"false"===r&&(r=!1),"true"===r&&(r=!0),isFinite(r)&&!isNaN(parseFloat(r))&&(r=parseFloat(r)),"target"!==e&&"string"==typeof r&&"["===r.trim().charAt(0)&&(r=JSON.parse(r)),t[e]=r,t},{}),yt({},a,o))).arrow&&(i.animateFill=!1),i.appendTo&&"function"==typeof i.appendTo&&(i.appendTo=i.appendTo()),"function"==typeof i.html&&(i.html=i.html(e)),i),c=r.getAttribute("title");if(!(c||p.target||p.html||p.dynamicTitle))return t;r.setAttribute(p.target?"data-tippy-delegate":"data-tippy",""),b(r);var l=function(t,e,r){var i=h();i.setAttribute("class","tippy-popper"),i.setAttribute("role","tooltip"),i.setAttribute("id","tippy-"+t),i.style.zIndex=r.zIndex,i.style.maxWidth=r.maxWidth;var n=h();n.setAttribute("class","tippy-tooltip"),n.setAttribute("data-size",r.size),n.setAttribute("data-animation",r.animation),n.setAttribute("data-state","hidden"),r.theme.split(" ").forEach(function(t){n.classList.add(t+"-theme")});var a=h();if(a.setAttribute("class","tippy-content"),r.arrow){var o=h();o.style[m("transform")]=r.arrowTransform,"round"===r.arrowType?(o.classList.add("tippy-roundarrow"),o.innerHTML=''):o.classList.add("tippy-arrow"),n.appendChild(o)}if(r.animateFill){n.setAttribute("data-animatefill","");var s=h();s.classList.add("tippy-backdrop"),s.setAttribute("data-state","hidden"),n.appendChild(s)}r.inertia&&n.setAttribute("data-inertia",""),r.interactive&&n.setAttribute("data-interactive","");var p,c=r.html;return c?(p=c instanceof Element?(a.appendChild(c),"#"+(c.id||"tippy-html-template")):(a.innerHTML=document.querySelector(c).innerHTML,c),i.setAttribute("data-html",""),n.setAttribute("data-template-id",p),r.interactive&&i.setAttribute("tabindex","-1")):a[r.allowTitleHTML?"innerHTML":"textContent"]=e,n.appendChild(a),i.appendChild(n),i}(s,c,p),u=new Mt({id:s,reference:r,popper:l,options:p,title:c,popperInstance:null});p.createPopperInstanceOnInit&&(u.popperInstance=tt.call(u),u.popperInstance.disableEventListeners());var d=Q.call(u);return u.listeners=p.trigger.trim().split(" ").reduce(function(t,e){return t.concat(function(t,r,e,i){var n=e.onTrigger,a=e.onMouseLeave,o=e.onBlur,s=e.onDelegateShow,p=e.onDelegateHide,c=[];if("manual"===t)return c;var l=function(t,e){r.addEventListener(t,e),c.push({event:t,handler:e})};return i.target?(mt.supportsTouch&&i.touchHold&&(l("touchstart",s),l("touchend",p)),"mouseenter"===t&&(l("mouseover",s),l("mouseout",p)),"focus"===t&&(l("focusin",s),l("focusout",p)),"click"===t&&l("click",s)):(l(t,n),mt.supportsTouch&&i.touchHold&&(l("touchstart",n),l("touchend",a)),"mouseenter"===t&&l("mouseleave",a),"focus"===t&&l(ft?"focusout":"blur",o)),c}(e,r,d,p))},[]),p.dynamicTitle&&it.call(u,{target:r,callback:function(){var t=g(l).content,e=r.getAttribute("title");e&&(t[p.allowTitleHTML?"innerHTML":"textContent"]=u.title=e,b(r))},options:{attributes:!0}}),r._tippy=u,l._tippy=u,l._reference=r,t.push(u),Ft++,t},[])}function ot(i){l(document.querySelectorAll(ht.POPPER)).forEach(function(t){var e=t._tippy;if(e){var r=e.options;(!0===r.hideOnClick||-1p[t]&&!i.escapeWithReference&&(r=pt(l[e],p[t]-("right"===t?l.width:l.height))),At({},e,r)}};return c.forEach(function(t){var e=-1===["left","top"].indexOf(t)?"secondary":"primary";l=It({},l,u[e](t))}),t.offsets.popper=l,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,r=e.popper,i=e.reference,n=t.placement.split("-")[0],a=lt,o=-1!==["top","bottom"].indexOf(n),s=o?"right":"bottom",p=o?"left":"top",c=o?"width":"height";return r[s]a(i[s])&&(t.offsets.popper[p]=a(i[s])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var r;if(!H(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var n=t.placement.split("-")[0],a=t.offsets,o=a.popper,s=a.reference,p=-1!==["left","right"].indexOf(n),c=p?"height":"width",l=p?"Top":"Left",u=l.toLowerCase(),d=p?"left":"top",f=p?"bottom":"right",m=C(i)[c];s[f]-mo[f]&&(t.offsets.popper[u]+=s[u]+m-o[f]),t.offsets.popper=T(t.offsets.popper);var h=s[u]+s[c]/2-m/2,g=w(t.instance.popper),b=parseFloat(g["margin"+l],10),v=parseFloat(g["border"+l+"Width"],10),y=h-t.offsets.popper[u]-b-v;return y=ut(pt(o[c]-m,y),0),t.arrowElement=i,t.offsets.arrow=(At(r={},u,ct(y)),At(r,d,""),r),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(m,h){if(t(m.instance.modifiers,"inner"))return m;if(m.flipped&&m.placement===m.originalPlacement)return m;var g=I(m.instance.popper,m.instance.reference,h.padding,h.boundariesElement,m.positionFixed),b=m.placement.split("-")[0],v=Y(b),y=m.placement.split("-")[1]||"",w=[];switch(h.behavior){case Dt:w=[b,v];break;case St:w=n(b);break;case jt:w=n(b,!0);break;default:w=h.behavior}return w.forEach(function(t,e){if(b!==t||w.length===e+1)return m;b=m.placement.split("-")[0],v=Y(b);var r,i=m.offsets.popper,n=m.offsets.reference,a=lt,o="left"===b&&a(i.right)>a(n.left)||"right"===b&&a(i.left)a(n.top)||"bottom"===b&&a(i.top)a(g.right),c=a(i.top)a(g.bottom),u="left"===b&&s||"right"===b&&p||"top"===b&&c||"bottom"===b&&l,d=-1!==["top","bottom"].indexOf(b),f=!!h.flipVariations&&(d&&"start"===y&&s||d&&"end"===y&&p||!d&&"start"===y&&c||!d&&"end"===y&&l);(o||u||f)&&(m.flipped=!0,(o||u)&&(b=w[e+1]),f&&(y="end"===(r=y)?"start":"start"===r?"end":r),m.placement=b+(y?"-"+y:""),m.offsets.popper=It({},m.offsets.popper,D(m.instance.popper,m.offsets.reference,m.placement)),m=j(m.instance.modifiers,m,"flip"))}),m},behavior:"flip",padding:5,boundariesElement:"viewport"},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,r=e.split("-")[0],i=t.offsets,n=i.popper,a=i.reference,o=-1!==["left","right"].indexOf(r),s=-1===["top","left"].indexOf(r);return n[o?"left":"top"]=a[r]-(s?n[o?"width":"height"]:0),t.placement=Y(e),t.offsets.popper=T(n),t}},hide:{order:800,enabled:!0,fn:function(t){if(!H(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,r=S(t.instance.modifiers,function(t){return"preventOverflow"===t.name}).boundaries;if(e.bottomr.right||e.top>r.bottom||e.rightp[O]&&(k=$(k)),$(k)),O=[];if(r&&O.push(T[w]<=0),i&&O.push(T[k]<=0,T[_]<=0),O.every(function(e){return e})){y=x,v=!1;break}u.set(x,O)}if(v)for(var E=h?3:1;0e,t=c-i.bottom-n>e,n=i.left-s+r>e,r=s-i.right-a>e,o)||t||n||r})&&(D(),R(e)))}function X(e){G(e)||0<=_.props.trigger.indexOf("click")&&h||(_.props.interactive?_.hideWithInteractivity(e):R(e))}function Z(e){_.props.trigger.indexOf("focusin")<0&&e.target!==O()||_.props.interactive&&e.relatedTarget&&u.contains(e.relatedTarget)||R(e)}function G(e){return ye.isTouch&&H()!==0<=e.type.indexOf("touch")}function J(){K();var e=_.props,t=e.popperOptions,n=e.placement,r=e.offset,i=e.getReferenceClientRect,e=e.moveTransition,o=k()?we(u).arrow:null,i=i?{getBoundingClientRect:i,contextElement:i.contextElement||O()}:a,r=[{name:"offset",options:{offset:r}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!e}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t,n=e.state;k()&&(t=E().box,["placement","reference-hidden","escaped"].forEach(function(e){"placement"===e?t.setAttribute("data-placement",n.placement):n.attributes.popper["data-popper-"+e]?t.setAttribute("data-"+e,""):t.removeAttribute("data-"+e)}),n.attributes.popper={})}}];k()&&o&&r.push({name:"arrow",options:{element:o,padding:3}}),r.push.apply(r,(null==t?void 0:t.modifiers)||[]),_.popperInstance=ee.createPopper(i,u,Object.assign({},t,{placement:n,onFirstUpdate:s,modifiers:r}))}function K(){_.popperInstance&&(_.popperInstance.destroy(),_.popperInstance=null)}function P(){return pe(u.querySelectorAll("[data-tippy-root]"))}function Q(e){_.clearDelayTimeouts(),e&&C("onTrigger",[_,e]),W();var e=q(!0),t=I(),n=t[0],t=t[1];(e=ye.isTouch&&"hold"===n&&t?t:e)?r=setTimeout(function(){_.show()},e):_.show()}function R(e){_.clearDelayTimeouts(),C("onUntrigger",[_,e]),_.state.isVisible?0<=_.props.trigger.indexOf("mouseenter")&&0<=_.props.trigger.indexOf("click")&&0<=["mouseleave","mousemove"].indexOf(e.type)&&h||((e=q(!1))?t=setTimeout(function(){_.state.isVisible&&_.hide()},e):n=requestAnimationFrame(function(){_.hide()})):S()}}function y(e,t){var n=be.plugins.concat((t=void 0===t?{}:t).plugins||[]),r=(document.addEventListener("touchstart",c,te),window.addEventListener("blur",p),Object.assign({},t,{plugins:n})),n=(o(t=e)?[t]:i(t,"NodeList")?pe(t):Array.isArray(t)?t:pe(document.querySelectorAll(t))).reduce(function(e,t){t=t&&g(t,r);return t&&e.push(t),e},[]);return o(e)?n[0]:n}y.defaultProps=be,y.setDefaultProps=function(t){Object.keys(t).forEach(function(e){be[e]=t[e]})},y.currentInput=ye;var b=Object.assign({},ee.applyStyles,{effect:function(e){var e=e.state,t={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(e.elements.popper.style,t.popper),e.styles=t,e.elements.arrow&&Object.assign(e.elements.arrow.style,t.arrow)}}),x={mouseover:"mouseenter",focusin:"focus",click:"click"},w={name:"animateFill",defaultValue:!1,fn:function(e){var n,r,i,t;return null!=(t=e.props.render)&&t.$$tippy?(t=we(e.popper),n=t.box,r=t.content,i=e.props.animateFill?((t=le()).className="tippy-backdrop",me([t],"hidden"),t):null,{onCreate:function(){i&&(n.insertBefore(i,n.firstElementChild),n.setAttribute("data-animatefill",""),n.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){var e,t;i&&(e=n.style.transitionDuration,t=Number(e.replace("ms","")),r.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,me([i],"visible"))},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&me([i],"hidden")}}):{}}},m={clientX:0,clientY:0},h=[];function _(e){var t=e.clientX,e=e.clientY;m={clientX:t,clientY:e}}var s,k,O={name:"followCursor",defaultValue:!1,fn:function(n){var u=n.reference,t=he(n.props.triggerTarget||u),r=!1,i=!1,e=!0,o=n.props;function a(){return"initial"===n.props.followCursor&&n.state.isVisible}function s(){t.addEventListener("mousemove",l)}function c(){t.removeEventListener("mousemove",l)}function p(){r=!0,n.setProps({getReferenceClientRect:null}),r=!1}function l(e){var t=!e.target||u.contains(e.target),o=n.props.followCursor,a=e.clientX,s=e.clientY,e=u.getBoundingClientRect(),c=a-e.left,p=s-e.top;!t&&n.props.interactive||n.setProps({getReferenceClientRect:function(){var e=u.getBoundingClientRect(),t=a,n=s,r=("initial"===o&&(t=e.left+c,n=e.top+p),"horizontal"===o?e.top:n),i="vertical"===o?e.right:t,n="horizontal"===o?e.bottom:n,e="vertical"===o?e.left:t;return{width:i-e,height:n-r,top:r,right:i,bottom:n,left:e}}})}function f(){n.props.followCursor&&(h.push({instance:n,doc:t}),t.addEventListener("mousemove",_))}function d(){0===(h=h.filter(function(e){return e.instance!==n})).filter(function(e){return e.doc===t}).length&&t.removeEventListener("mousemove",_)}return{onCreate:f,onDestroy:d,onBeforeUpdate:function(){o=n.props},onAfterUpdate:function(e,t){t=t.followCursor;r||void 0!==t&&o.followCursor!==t&&(d(),t?(f(),!n.state.isMounted||i||a()||s()):(c(),p()))},onMount:function(){n.props.followCursor&&!i&&(e&&(l(m),e=!1),a()||s())},onTrigger:function(e,t){fe(t)&&(m={clientX:t.clientX,clientY:t.clientY}),i="focus"===t.type},onHidden:function(){n.props.followCursor&&(p(),c(),e=!0)}}}},T={name:"inlinePositioning",defaultValue:!1,fn:function(i){var t,d=i.reference,m=-1,n=!1,r=[],o={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(e){var f=e.state;i.props.inlinePositioning&&(-1!==r.indexOf(f.placement)&&(r=[]),t!==f.placement&&-1===r.indexOf(f.placement)&&(r.push(f.placement),i.setProps({getReferenceClientRect:function(){var t=ce(f.placement),e=d.getBoundingClientRect(),n=pe(d.getClientRects()),r=m;if(n.length<2||null===t)return e;if(2===n.length&&0<=r&&n[0].left>n[1].right)return n[r]||e;switch(t){case"top":case"bottom":var i=n[0],o=n[n.length-1],a="top"===t,s=i.top,c=o.bottom,p=(a?i:o).left,a=(a?i:o).right;return{top:s,bottom:c,left:p,right:a,width:a-p,height:c-s};case"left":case"right":var u=Math.min.apply(Math,n.map(function(e){return e.left})),l=Math.max.apply(Math,n.map(function(e){return e.right})),i=n.filter(function(e){return"left"===t?e.left===u:e.right===l}),o=i[0].top,a=i[i.length-1].bottom;return{top:o,bottom:a,left:u,right:l,width:l-u,height:a-o};default:return e}}})),t=f.placement)}};function e(){var e,t;n||(e=i.props,t=o,e={popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(e=e.popperOptions)?void 0:e.modifiers)||[]).filter(function(e){return e.name!==t.name}),[t])})},n=!0,i.setProps(e),n=!1)}return{onCreate:e,onAfterUpdate:e,onTrigger:function(e,t){var n,r;fe(t)&&(n=(r=pe(i.reference.getClientRects())).find(function(e){return e.left-2<=t.clientX&&e.right+2>=t.clientX&&e.top-2<=t.clientY&&e.bottom+2>=t.clientY}),r=r.indexOf(n),m=-1.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}',e.setAttribute("data-tippy-stylesheet",""),s=document.head,(k=document.querySelector("head>style,head>link"))?s.insertBefore(e,k):s.appendChild(e)),y.setDefaultProps({plugins:[w,O,T,E],render:d}),y.createSingleton=function(e,t){var i,o=e,r=[],a=[],s=(t=void 0===t?{}:t).overrides,n=[],c=!1;function p(){a=o.map(function(e){return ae(e.props.triggerTarget||e.reference)}).reduce(function(e,t){return e.concat(t)},[])}function u(){r=o.map(function(e){return e.reference})}function l(t){o.forEach(function(e){t?e.enable():e.disable()})}function f(r){return o.map(function(t){var n=t.setProps;return t.setProps=function(e){n(e),t.reference===i&&r.setProps(e)},function(){t.setProps=n}})}function d(e,t){var n=a.indexOf(t);t!==i&&(i=t,t=(s||[]).concat("content").reduce(function(e,t){return e[t]=o[n].props[t],e},{}),e.setProps(Object.assign({},t,{getReferenceClientRect:"function"==typeof t.getReferenceClientRect?t.getReferenceClientRect:function(){var e;return null==(e=r[n])?void 0:e.getBoundingClientRect()}})))}l(!1),u(),p();var e={fn:function(){return{onDestroy:function(){l(!0)},onHidden:function(){i=null},onClickOutside:function(e){e.props.showOnCreate&&!c&&(c=!0,i=null)},onShow:function(e){e.props.showOnCreate&&!c&&(c=!0,d(e,r[0]))},onTrigger:function(e,t){d(e,t.currentTarget)}}}},m=y(le(),Object.assign({},v(t,["overrides"]),{plugins:[e].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(e=t.popperOptions)?void 0:e.modifiers)||[],[b])})})),h=m.show,g=(m.show=function(e){var t;return h(),i||null!=e?i&&null==e?void 0:"number"==typeof e?r[e]&&d(m,r[e]):0<=o.indexOf(e)?(t=e.reference,d(m,t)):0<=r.indexOf(e)?d(m,e):void 0:d(m,r[0])},m.showNext=function(){var e=r[0];if(!i)return m.show(0);var t=r.indexOf(i);m.show(r[t+1]||e)},m.showPrevious=function(){var e=r[r.length-1];if(!i)return m.show(e);var t=r.indexOf(i),t=r[t-1]||e;m.show(t)},m.setProps);return m.setProps=function(e){s=e.overrides||s,g(e)},m.setInstances=function(e){l(!0),n.forEach(function(e){return e()}),o=e,l(!1),u(),p(),n=f(m),m.setProps({triggerTarget:a})},n=f(m),m},y.delegate=function(e,r){var i=[],o=[],a=!1,s=r.target,t=v(r,["target"]),n=Object.assign({},t,{trigger:"manual",touch:!1}),c=Object.assign({touch:be.touch},t,{showOnCreate:!0}),t=y(e,n);function p(e){var t,n;e.target&&!a&&(t=e.target.closest(s))&&(n=t.getAttribute("data-tippy-trigger")||r.trigger||be.trigger,t._tippy||"touchstart"===e.type&&"boolean"==typeof c.touch||"touchstart"!==e.type&&n.indexOf(x[e.type])<0||(n=y(t,c))&&(o=o.concat(n)))}function u(e,t,n,r){e.addEventListener(t,n,r=void 0===r?!1:r),i.push({node:e,eventType:t,handler:n,options:r})}return ae(t).forEach(function(e){var t=e.destroy,n=e.enable,r=e.disable;e.destroy=function(e){(e=void 0===e?!0:e)&&o.forEach(function(e){e.destroy()}),o=[],i.forEach(function(e){var t=e.node,n=e.eventType,r=e.handler,e=e.options;t.removeEventListener(n,r,e)}),i=[],t()},e.enable=function(){n(),o.forEach(function(e){return e.enable()}),a=!1},e.disable=function(){r(),o.forEach(function(e){return e.disable()}),a=!0},u(e=e.reference,"touchstart",p,te),u(e,"mouseover",p),u(e,"focusin",p),u(e,"click",p)}),t},y.hideAll=function(e){var e=void 0===e?{}:e,n=e.exclude,r=e.duration;ke.forEach(function(e){var t=!1;(t=n?a(n)?e.reference===n:e.popper===n.popper:t)||(t=e.props.duration,e.setProps({duration:r}),e.hide(),e.state.isDestroyed)||e.setProps({duration:t})})},y.roundArrow='',y}),function(o){var e=new class{sourceTrackingParams={lifetime:metorik_params.source_tracking.cookie_lifetime,session_length:metorik_params.source_tracking.session_length,timezone_offset:"0"};init(){!metorik_params.source_tracking.enabled||this.cookieExists()||(metorik_params.source_tracking.sbjs_domain&&(this.sourceTrackingParams.domain=metorik_params.source_tracking.sbjs_domain),sbjs.init(this.sourceTrackingParams),this.setSourceTrackingCookie())}cookieExists(){return document.cookie.split("; ").find(e=>e.startsWith(metorik_params.source_tracking.cookie_name))}cookieContent(){var e={type:sbjs.get.current.typ,url:sbjs.get.current_add.rf,mtke:sbjs.get.current.mtke,utm_campaign:sbjs.get.current.cmp,utm_source:sbjs.get.current.src,utm_medium:sbjs.get.current.mdm,utm_content:sbjs.get.current.cnt,utm_id:sbjs.get.current.id,utm_term:sbjs.get.current.trm,session_entry:sbjs.get.current_add.ep,session_start_time:sbjs.get.current_add.fd,session_pages:sbjs.get.session.pgs,session_count:sbjs.get.udata.vst};return JSON.stringify(e)}cookieExpiration(){var e=new Date;return e.setTime(e.getTime()+1e3*metorik_params.source_tracking.cookie_lifetime*60*60*24*30),e.toUTCString()}setSourceTrackingCookie(){sbjs.get&&(document.cookie=metorik_params.source_tracking.cookie_name+"="+this.cookieContent()+"; expires="+this.cookieExpiration()+"; Secure")}},t=new class{timers={customer_data:null,email_field:null,checkout_field:null,add_cart:null};addToCartEmailWrapper=o(".add-cart-email-wrapper");addToCartSeen=!1;addToCartShouldMarkAsSeen=metorik_params.cart_tracking.add_to_cart_should_mark_as_seen;selectors=metorik_params.cart_tracking.add_to_cart_form_selectors;init(){metorik_params.cart_tracking.enabled&&(this.initAddToCartPopup(),this.initOptOutListener(),this.captureDataListeners())}initAddToCartPopup(){this.addToCartEmailWrapper.length&&(this.selectors.forEach(this.initiateTippyForElement.bind(this)),o(document.body).on("wc_fragments_refreshed",this.showTippyOnAddToCart.bind(this)),o(document).on("click",".metorik-add-cart-email-form .close-button",this.closeTippyAndMarkAsSeen.bind(this)),o(document).on("input",".metorik-add-cart-email-form .email-input",this.captureEmailFromAddCart.bind(this)),metorik_params.cart_tracking.item_was_added_to_cart)&&this.showTippyOnAddToCart()}initOptOutListener(){o(document).on("click",".metorik-email-usage-notice-link",this.optOutAndFadeNotice.bind(this)),o(document).on("change","#contact-metorik\\/opt-in, #contact-metorik-opt-in",this.toggleOptInOptOut.bind(this))}initiateTippyForElement(e){tippy(e,{content:this.addToCartEmailWrapper.html(),allowHTML:!0,theme:"light",trigger:".ajax_add_to_cart"==e?"click":"manual",hideOnClick:!0,interactive:!0,arrow:!0,offset:[0,15],placement:metorik_params.cart_tracking.add_cart_popup_placement,onShow:()=>{if(this.addToCartSeen)return!1},onShown:()=>{this.addToCartShouldMarkAsSeen&&this.markAddToCartAsSeen()}})}showTippyOnAddToCart(e){var t;metorik_params.cart_tracking.cart_items_count<1||(t=o(".single_add_to_cart_button, .wc-block-components-product-button__button.add_to_cart_button")).length&&t[0]._tippy.show()}closeTippyAndMarkAsSeen(e){this.closeTippy(e),this.markAddToCartAsSeen()}closeTippy(e){e.preventDefault();e=e.target.closest("[data-tippy-root]");e&&e._tippy&&e._tippy.hide()}markAddToCartAsSeen(){this.addToCartSeen||(this.addToCartSeen=!0,o.post(metorik_params.cart_tracking.wc_ajax_seen_add_to_cart_form_url,{security:metorik_params.nonce}))}captureDataListeners(){document.querySelectorAll(".metorik-capture-email, #billing_email").forEach(e=>{e&&e.addEventListener("input",this.captureEmail.bind(this))}),document.querySelectorAll("#billing_first_name, #billing_phone").forEach(e=>{e&&e.addEventListener("input",this.captureCheckoutField.bind(this))})}captureEmailFromAddCart(e){var t=o(e.target);const n=t.parent(),r=t.val();n.removeClass("success"),clearTimeout(this.timers.add_cart),this.timers.add_cart=setTimeout(()=>{this.isValidEmail(r)&&(n.addClass("success"),this.captureCustomerData(r),setTimeout(()=>{this.closeTippyAndMarkAsSeen(e)},1500))},500)}captureEmail(e){const t=e.target.value;clearTimeout(this.timers.email_field),this.timers.email_field=setTimeout(()=>{this.isValidEmail(t)&&this.captureCustomerData(t)},500)}captureCheckoutField(e){clearTimeout(this.timers.checkout_field),this.timers.checkout_field=setTimeout(()=>{this.captureCustomerData()},500)}captureCustomerData(i){clearTimeout(this.timers.customer_data),this.timers.customer_data=setTimeout(()=>{let e=null;this.isValidEmail(i)?e=i:(t=o("#billing_email").val(),this.isValidEmail(t)&&(e=t));var t=o("#billing_first_name").val(),n=o("#billing_last_name").val(),r=o("#billing_phone").val(),t={email:e,first_name:t,last_name:n,phone:r,security:metorik_params.nonce};o.post(metorik_params.cart_tracking.wc_ajax_capture_customer_data_url,t)},1e3)}optOutAndFadeNotice(e){e.preventDefault();const t=o(".metorik-email-usage-notice");t.css({opacity:"0.5","pointer-events":"none"}),this.optOut(()=>{t.hide(),this.closeTippy(e)})}toggleOptInOptOut(e){e.preventDefault(),e.target.checked?this.optIn():this.optOut()}optOut(e=null){o.post(metorik_params.cart_tracking.wc_ajax_email_opt_out_url,{security:metorik_params.nonce},e)}optIn(e=null){o.post(metorik_params.cart_tracking.wc_ajax_email_opt_in_url,{security:metorik_params.nonce},e)}isValidEmail(e){return/[^\s@]+@[^\s@]+\.[^\s@]+/.test(e)}};e.init(),t.init()}(jQuery); \ No newline at end of file diff --git a/assets/js/src/metorik.js b/assets/js/src/metorik.js index f9d3b4c..a68bece 100644 --- a/assets/js/src/metorik.js +++ b/assets/js/src/metorik.js @@ -1,322 +1,344 @@ (function($) { - var params = { - lifetime: metorik_params.lifetime, - session_length: metorik_params.session, - timezone_offset: '0', // utc - } - - if (metorik_params.sbjs_domain) { - params.domain = metorik_params.sbjs_domain; - } - - /** - * Initialize sourcebuster.js. - */ - sbjs.init(params); - - /** - * Set values. - */ - var setFields = function() { - if (sbjs.get) { - $('input[name="metorik_source_type"]').val(sbjs.get.current.typ); - $('input[name="metorik_source_url"]').val(sbjs.get.current_add.rf); - $('input[name="metorik_source_mtke"]').val(sbjs.get.current.mtke); - - $('input[name="metorik_source_utm_campaign"]').val(sbjs.get.current.cmp); - $('input[name="metorik_source_utm_source"]').val(sbjs.get.current.src); - $('input[name="metorik_source_utm_medium"]').val(sbjs.get.current.mdm); - $('input[name="metorik_source_utm_content"]').val(sbjs.get.current.cnt); - $('input[name="metorik_source_utm_id"]').val(sbjs.get.current.id); - $('input[name="metorik_source_utm_term"]').val(sbjs.get.current.trm); - - $('input[name="metorik_source_session_entry"]').val(sbjs.get.current_add.ep); - $('input[name="metorik_source_session_start_time"]').val(sbjs.get.current_add.fd); - $('input[name="metorik_source_session_pages"]').val(sbjs.get.session.pgs); - $('input[name="metorik_source_session_count"]').val(sbjs.get.udata.vst); - } - }; - - /** - * Add source values to checkout. - */ - $(document.body).on('init_checkout', function(event) { - setFields(); - }); - - /** - * Add source values to register. - */ - if ($('.woocommerce form.register').length) { - setFields(); - } - - /** - * Cart functionality - only if cart tracking enabled. - */ - if (metorik_params.cart_tracking) { - /** - * Send cart data. - * @todo Only if cart token set up. - */ - var cartTimer; - var sendCartData = function(customEmail) { - clearTimeout(cartTimer); - cartTimer = setTimeout(function () { - var email = isValidEmail($('#billing_email').val()) ? $('#billing_email').val() : null; - if (customEmail) { - email = customEmail; - } - - var name = $('#billing_first_name').val(); - var phone = $('#billing_phone').val(); - - var data = { - action: 'metorik_send_cart', - email: email, - name: name, - phone: phone, - }; - - $.post(metorik_params.ajaxurl, data, function (response) { - // - }); - }, 1000); - }; - - /** - * Function to check if an email is valid. - * @param {*} email - */ - var isValidEmail = function(email) { - return /[^\s@]+@[^\s@]+\.[^\s@]+/.test(email); - }; - - /** - * Listen for cart change events then send cart data. - */ - $(document.body).on( - metorik_params.send_cart_events, - function (event) { - sendCartData(); - } - ); - - /** - * Watch for fragments separate and determine if have data to send. - * As this event may trigger with no items in cart (initial page - * load) but no need to send cart then. So we check for items. - */ - if (metorik_params.send_cart_fragments) { - $(document.body).on( - 'wc_fragments_refreshed', - function(event) { - // Only continue if wc_cart_fragments_params defined - if (typeof wc_cart_fragments_params !== 'undefined' && wc_cart_fragments_params) { - // Get cart hash key from wc_cart_fragments_params variable - var cart_hash_key = wc_cart_fragments_params.cart_hash_key; - - try { - // Get local storage and session storage for cart dash - var localStorageItem = localStorage.getItem(cart_hash_key) - var sessionStorageItem = sessionStorage.getItem(cart_hash_key) - - // Check if have local storage or session storage - if (localStorageItem || sessionStorageItem) { - // Have items so we'll send the cart data now - sendCartData(); - } - } catch (e) { - - } - } - } - ); - } - - /** - * Watch for email input changes. - */ - var email_input_timer; - - var emailCartHandler = function(e) { - var val = e.target.value; - - clearTimeout(email_input_timer); - email_input_timer = setTimeout(function() { - if (isValidEmail(val)) { - sendCartData(val); - } - }, 500); - }; - - var billingEmailInput = document.getElementById('billing_email'); - if (billingEmailInput) { - billingEmailInput.addEventListener('input', emailCartHandler); - } - - var captureGuestEmailInput = document.querySelector('.metorik-capture-guest-email'); - if (captureGuestEmailInput) { - captureGuestEmailInput.addEventListener('input', emailCartHandler); - } - - /** - * Watch for name input changes. - */ - var name_input_timer; - - var checkoutFieldHandler = function(e) { - clearTimeout(name_input_timer); - name_input_timer = setTimeout(function () { - sendCartData(); - }, 500); - } - - var billingNameInput = document.getElementById('billing_first_name'); - if (billingNameInput) { - billingNameInput.addEventListener('input', checkoutFieldHandler); - } - - var billingPhoneInput = document.getElementById('billing_phone'); - if (billingPhoneInput) { - billingPhoneInput.addEventListener('input', checkoutFieldHandler); - } - - /** - * Popup to capture email when added to cart (if wrapper class exists/output on page). - */ - var addToCartSeen = false; - - if ($('.add-cart-email-wrapper').length) { - // classes/buttons that we're targeting - var classes = [ - '.button.ajax_add_to_cart', - '.single_add_to_cart_button', - ]; - - // add cart checkout button if enabled (filterable) - if (metorik_params.cart_checkout_button) { - classes.push('.button.checkout-button'); - } - - // listen for page reloads after products added to the cart - $(document.body).on( - 'wc_fragments_refreshed', - function (e) { - // only if cart items 1 or more - if (metorik_params.cart_items >= 1) { - // show tippy on add cart button - var singleButton = $('.single_add_to_cart_button'); - if (singleButton.length) { - singleButton[0]._tippy.show(); - } - - // show tippy on cart update button (if cart checkout button enabled) - if (metorik_params.cart_checkout_button) { - var cartButton = $('.button.checkout-button'); - if (cartButton.length) { - cartButton[0]._tippy.show(); - } - } - } - } - ); - - // add tippy for each class - classes.forEach(function(c) { - tippy(c, { - html: '.add-cart-email-wrapper', - theme: 'light', - trigger: (c == '.button.ajax_add_to_cart') ? 'click' : 'manual', - hideOnClick: true, - interactive: true, - arrow: true, - distance: 15, - placement: metorik_params.add_cart_popup_placement, - wait: function(show) { - // Only show if add to cart seen not true. Delay 100ms - if(!addToCartSeen) { - setTimeout(function() { - show(); - }, 250); - } - }, - onShow: function () { - // Set the add to cart fomr as having been senen so it doesn't get shown again. - addToCartSeen = true; - - // Make an AJAX request to set the add cart form as 'seen'. - var data = { - action: 'metorik_add_cart_form_seen', - }; - - $.post(metorik_params.ajaxurl, data, function (response) { - // - }); - }, - }); - }); - } - - /** - * Listen for closing the add cart email form tippy. - */ - $(document).on('click', '.metorik-add-cart-email-form .close-button', function (e) { - e.preventDefault(); - - // close/hide tippy if have - var button = $('.tippy-active'); - if (button.length && button[0]._tippy) { - button[0]._tippy.hide(); - } - }); - - /** - * Listen for add cart email input changes. - */ - var addCartTimer; - $(document).on('input', '.metorik-add-cart-email-form .email-input', function(e) { - var _this = $(this); - var _wrapper = _this.parent(); - - // clear classes on input change - _wrapper.removeClass('success'); - - clearTimeout(addCartTimer); - addCartTimer = setTimeout(function() { - if (isValidEmail(_this.val())) { - _wrapper.addClass('success'); - sendCartData(_this.val()); - } - }, 500); - }); - - /** - * Listen for email usage opt-out clicks and send AJAX request to do so. - */ - $(document).on('click', '.metorik-email-usage-notice-link', function(e) { - e.preventDefault(); - - // loading - $('.metorik-email-usage-notice').css({ opacity: '0.5', 'pointer-events': 'none' }); - - var data = { - action: 'metorik_email_opt_out', - }; - - $.post(metorik_params.ajaxurl, data, function(response) { - // hide email usage notice - $('.metorik-email-usage-notice').css('display', 'none'); - - // close/hide tippy if have - var button = $('.tippy-active'); - if (button.length && button[0]._tippy) { - button[0]._tippy.hide(); - } - - // send cart so we can send email opted out - sendCartData(); - }); - }); - } + + class MetorikSourceTracking { + + sourceTrackingParams = { + lifetime: metorik_params.source_tracking.cookie_lifetime, + session_length: metorik_params.source_tracking.session_length, + timezone_offset: '0', // utc + }; + + init() { + + // bail if source tracking is disabled + if (!metorik_params.source_tracking.enabled) { + return; + } + + // bail if cookie already set + if (this.cookieExists()) { + return; + } + + // set domain if overwritten via metorik_sbjs_domain filter + if (metorik_params.source_tracking.sbjs_domain) { + this.sourceTrackingParams.domain = metorik_params.source_tracking.sbjs_domain; + } + + // Initialize sourcebuster.js + sbjs.init(this.sourceTrackingParams); + + // set the cookie + this.setSourceTrackingCookie(); + } + + cookieExists() { + return document.cookie + .split('; ') + .find((row) => row.startsWith(metorik_params.source_tracking.cookie_name)); + } + + cookieContent() { + const cookieContent = { + type: sbjs.get.current.typ, + url: sbjs.get.current_add.rf, + mtke: sbjs.get.current.mtke, + + utm_campaign: sbjs.get.current.cmp, + utm_source: sbjs.get.current.src, + utm_medium: sbjs.get.current.mdm, + utm_content: sbjs.get.current.cnt, + utm_id: sbjs.get.current.id, + utm_term: sbjs.get.current.trm, + + session_entry: sbjs.get.current_add.ep, + session_start_time: sbjs.get.current_add.fd, + session_pages: sbjs.get.session.pgs, + session_count: sbjs.get.udata.vst, + }; + + return JSON.stringify(cookieContent); + } + + cookieExpiration() { + const date = new Date(); + // cookie_lifetime is in months + // milliseconds x seconds x minutes x hours x day x month + date.setTime(date.getTime() + (metorik_params.source_tracking.cookie_lifetime * 1000 * 60 * 60 * 24 * 30)); + return date.toUTCString(); + } + + setSourceTrackingCookie() { + if (!sbjs.get) { + return; + } + + document.cookie = metorik_params.source_tracking.cookie_name + '=' + + this.cookieContent() + '; expires=' + this.cookieExpiration() + '; Secure'; + } + } + + class MetorikCartTracking { + + timers = { + customer_data: null, + email_field: null, + checkout_field: null, + add_cart: null, + }; + + addToCartEmailWrapper = $('.add-cart-email-wrapper'); + addToCartSeen = false; + + // by default, we only show the add to cart form once, and then mark it as seen + // this can be disabled via the metorik_acp_should_mark_as_seen filter + addToCartShouldMarkAsSeen = metorik_params.cart_tracking.add_to_cart_should_mark_as_seen; + + // classes/buttons that we're targeting for the popup + // see metorik-helper.php where add_to_cart_button_classes is set and filterable + selectors = metorik_params.cart_tracking.add_to_cart_form_selectors; + + init() { + // bail if cart tracking is disabled + if (!metorik_params.cart_tracking.enabled) { + return; + } + + this.initAddToCartPopup(); + + this.initOptOutListener(); + + this.captureDataListeners(); + } + + initAddToCartPopup() { + // bail if not rendered (means it's disabled) + if (!this.addToCartEmailWrapper.length) { + return; + } + + // add tippy for each class + this.selectors.forEach(this.initiateTippyForElement.bind(this)); + + // listen for cart reloads after products added to the cart + $(document.body).on('wc_fragments_refreshed', this.showTippyOnAddToCart.bind(this)); + + // Listen for closing the add cart email form/tippy + $(document).on('click', '.metorik-add-cart-email-form .close-button', this.closeTippyAndMarkAsSeen.bind(this)); + + // Listen for add cart email input changes + $(document).on('input', '.metorik-add-cart-email-form .email-input', this.captureEmailFromAddCart.bind(this)); + + // if an item was just added to the cart (from a product page), show the popup + if (metorik_params.cart_tracking.item_was_added_to_cart) { + this.showTippyOnAddToCart(); + } + + } + + initOptOutListener() { + // Listen for email usage opt-out clicks + $(document).on('click', '.metorik-email-usage-notice-link', this.optOutAndFadeNotice.bind(this)); + + $(document).on('change', '#contact-metorik\\/opt-in, #contact-metorik-opt-in', this.toggleOptInOptOut.bind(this)); + } + + initiateTippyForElement(selector) { + tippy(selector, { + content: this.addToCartEmailWrapper.html(), + allowHTML: true, + theme: 'light', + trigger: (selector == '.ajax_add_to_cart') ? 'click' : 'manual', + hideOnClick: true, + interactive: true, + arrow: true, + offset: [0, 15], + placement: metorik_params.cart_tracking.add_cart_popup_placement, + onShow: () => { + // hide the tippy if the form has been seen already + if (this.addToCartSeen) { + return false; + } + }, + onShown: () => { + if (this.addToCartShouldMarkAsSeen) { + this.markAddToCartAsSeen(); + } + }, + }); + } + + showTippyOnAddToCart(e) { + // bail if there's no cart items + if (metorik_params.cart_tracking.cart_items_count < 1) { + return; + } + + // show tippy on add cart button + var singleButton = $('.single_add_to_cart_button, .wc-block-components-product-button__button.add_to_cart_button'); + if (singleButton.length) { + singleButton[0]._tippy.show(); + } + } + + closeTippyAndMarkAsSeen(e) { + this.closeTippy(e); + this.markAddToCartAsSeen(); + } + + closeTippy(e) { + e.preventDefault(); + + // close/hide tippy if active + const tippyRoot = e.target.closest('[data-tippy-root]'); + if (tippyRoot && tippyRoot._tippy) { + tippyRoot._tippy.hide(); + } + } + + markAddToCartAsSeen() { + // bail if already marked as seen + if (this.addToCartSeen) { + return; + } + + // Set the add to cart form as having been seen, so it doesn't get shown again. + this.addToCartSeen = true; + $.post(metorik_params.cart_tracking.wc_ajax_seen_add_to_cart_form_url, { security: metorik_params.nonce }); + } + + captureDataListeners() { + const emailFields = document.querySelectorAll('.metorik-capture-email, #billing_email'); + emailFields.forEach((field) => { + if (field) { + field.addEventListener('input', this.captureEmail.bind(this)); + } + }); + + const checkoutFields = document.querySelectorAll('#billing_first_name, #billing_phone'); + checkoutFields.forEach((field) => { + if (field) { + field.addEventListener('input', this.captureCheckoutField.bind(this)); + } + }); + } + + captureEmailFromAddCart(e) { + const emailField = $(e.target); + const emailWrapper = emailField.parent(); + const email = emailField.val(); + + // clear classes on input change + emailWrapper.removeClass('success'); + + clearTimeout(this.timers.add_cart); + this.timers.add_cart = setTimeout(() => { + if (this.isValidEmail(email)) { + emailWrapper.addClass('success'); + this.captureCustomerData(email); + + // close the tippy & mark as seen after a short delay + setTimeout(() => { + this.closeTippyAndMarkAsSeen(e); + }, 1500); + } + }, 500); + } + + captureEmail(e) { + const email = e.target.value; + clearTimeout(this.timers.email_field); + this.timers.email_field = setTimeout(() => { + if (this.isValidEmail(email)) { + this.captureCustomerData(email); + } + }, 500); + } + + captureCheckoutField(e) { + clearTimeout(this.timers.checkout_field); + this.timers.checkout_field = setTimeout(() => { + this.captureCustomerData(); + }, 500); + } + + captureCustomerData(customEmail) { + clearTimeout(this.timers.customer_data); + this.timers.customer_data = setTimeout(() => { + let email = null; + if (this.isValidEmail(customEmail)) { + email = customEmail; + } else { + const billingEmail = $('#billing_email').val(); + if (this.isValidEmail(billingEmail)) { + email = billingEmail; + } + } + + const firstName = $('#billing_first_name').val(); + const lastName = $('#billing_last_name').val(); + const phone = $('#billing_phone').val(); + + const data = { + email: email, + first_name: firstName, + last_name: lastName, + phone: phone, + security: metorik_params.nonce, + }; + + $.post(metorik_params.cart_tracking.wc_ajax_capture_customer_data_url, data); + }, 1000); + } + + optOutAndFadeNotice(e) { + e.preventDefault(); + const emailUsageNotice = $('.metorik-email-usage-notice'); + + // loading + emailUsageNotice.css({ opacity: '0.5', 'pointer-events': 'none' }); + + this.optOut(() => { + emailUsageNotice.hide(); + this.closeTippy(e); + }); + } + + toggleOptInOptOut(e) { + e.preventDefault(); + const optIn = e.target.checked; + + if (optIn) { + this.optIn(); + } else { + this.optOut(); + } + } + + optOut(callback = null) { + $.post( + metorik_params.cart_tracking.wc_ajax_email_opt_out_url, + { security: metorik_params.nonce }, + callback, + ); + } + + optIn(callback = null) { + $.post( + metorik_params.cart_tracking.wc_ajax_email_opt_in_url, + { security: metorik_params.nonce }, + callback, + ); + } + + isValidEmail(email) { + return /[^\s@]+@[^\s@]+\.[^\s@]+/.test(email); + } + } + + + var metorikSourceTracking = new MetorikSourceTracking(); + var metorikCartTracking = new MetorikCartTracking(); + metorikSourceTracking.init(); + metorikCartTracking.init(); })(jQuery); diff --git a/assets/js/src/tippy.min.js b/assets/js/src/tippy.min.js index 8a46239..5dc4bf7 100644 --- a/assets/js/src/tippy.min.js +++ b/assets/js/src/tippy.min.js @@ -1 +1,11 @@ -(function(t,e){'object'==typeof exports&&'undefined'!=typeof module?module.exports=e():'function'==typeof define&&define.amd?define(e):t.tippy=e()})(this,function(){'use strict';function t(t){return'[object Object]'==={}.toString.call(t)}function a(t){return[].slice.call(t)}function o(e){if(e instanceof Element||t(e))return[e];if(e instanceof NodeList)return a(e);if(Array.isArray(e))return e;try{return a(document.querySelectorAll(e))}catch(t){return[]}}function r(t){t.refObj=!0,t.attributes=t.attributes||{},t.setAttribute=function(e,a){t.attributes[e]=a},t.getAttribute=function(e){return t.attributes[e]},t.removeAttribute=function(e){delete t.attributes[e]},t.hasAttribute=function(e){return e in t.attributes},t.addEventListener=function(){},t.removeEventListener=function(){},t.classList={classNames:{},add:function(e){return t.classList.classNames[e]=!0},remove:function(e){return delete t.classList.classNames[e],!0},contains:function(e){return e in t.classList.classNames}}}function p(t){for(var e=['','webkit'],a=t.charAt(0).toUpperCase()+t.slice(1),o=0;o'):s.classList.add('tippy-arrow'),o.appendChild(s)}if(a.animateFill){o.setAttribute('data-animatefill','');var l=n();l.classList.add('tippy-backdrop'),l.setAttribute('data-state','hidden'),o.appendChild(l)}a.inertia&&o.setAttribute('data-inertia',''),a.interactive&&o.setAttribute('data-interactive','');var d=a.html;if(d){var c;d instanceof Element?(r.appendChild(d),c='#'+(d.id||'tippy-html-template')):(r.innerHTML=document.querySelector(d).innerHTML,c=d),i.setAttribute('data-html',''),o.setAttribute('data-template-id',c),a.interactive&&i.setAttribute('tabindex','-1')}else r[a.allowTitleHTML?'innerHTML':'textContent']=e;return o.appendChild(r),i.appendChild(o),i}function l(t,e,a,i){var o=a.onTrigger,r=a.onMouseLeave,p=a.onBlur,n=a.onDelegateShow,s=a.onDelegateHide,l=[];if('manual'===t)return l;var d=function(t,a){e.addEventListener(t,a),l.push({event:t,handler:a})};return i.target?(qt.supportsTouch&&i.touchHold&&(d('touchstart',n),d('touchend',s)),'mouseenter'===t&&(d('mouseover',n),d('mouseout',s)),'focus'===t&&(d('focusin',n),d('focusout',s)),'click'===t&&d('click',n)):(d(t,o),qt.supportsTouch&&i.touchHold&&(d('touchstart',o),d('touchend',r)),'mouseenter'===t&&d('mouseleave',r),'focus'===t&&d(Ft?'focusout':'blur',p)),l}function d(t,e){var a=Gt.reduce(function(a,i){var o=t.getAttribute('data-tippy-'+i.toLowerCase())||e[i];return'false'===o&&(o=!1),'true'===o&&(o=!0),isFinite(o)&&!isNaN(parseFloat(o))&&(o=parseFloat(o)),'target'!==i&&'string'==typeof o&&'['===o.trim().charAt(0)&&(o=JSON.parse(o)),a[i]=o,a},{});return Jt({},e,a)}function c(t,e){return e.arrow&&(e.animateFill=!1),e.appendTo&&'function'==typeof e.appendTo&&(e.appendTo=e.appendTo()),'function'==typeof e.html&&(e.html=e.html(t)),e}function m(t){var e=function(e){return t.querySelector(e)};return{tooltip:e(jt.TOOLTIP),backdrop:e(jt.BACKDROP),content:e(jt.CONTENT),arrow:e(jt.ARROW)||e(jt.ROUND_ARROW)}}function f(t){var e=t.getAttribute('title');e&&t.setAttribute('data-original-title',e),t.removeAttribute('title')}function h(t){return t&&'[object Function]'==={}.toString.call(t)}function b(t,e){if(1!==t.nodeType)return[];var a=getComputedStyle(t,null);return e?a[e]:a}function u(t){return'HTML'===t.nodeName?t:t.parentNode||t.host}function y(t){if(!t)return document.body;switch(t.nodeName){case'HTML':case'BODY':return t.ownerDocument.body;case'#document':return t.body;}var e=b(t),a=e.overflow,i=e.overflowX,o=e.overflowY;return /(auto|scroll|overlay)/.test(a+o+i)?t:y(u(t))}function g(t){return 11===t?ie:10===t?oe:ie||oe}function w(t){if(!t)return document.documentElement;for(var e=g(10)?document.body:null,a=t.offsetParent;a===e&&t.nextElementSibling;)a=(t=t.nextElementSibling).offsetParent;var i=a&&a.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TD','TABLE'].indexOf(a.nodeName)&&'static'===b(a,'position')?w(a):a:t?t.ownerDocument.documentElement:document.documentElement}function x(t){var e=t.nodeName;return'BODY'!==e&&('HTML'===e||w(t.firstElementChild)===t)}function v(t){return null===t.parentNode?t:v(t.parentNode)}function k(t,e){if(!t||!t.nodeType||!e||!e.nodeType)return document.documentElement;var a=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=a?t:e,o=a?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var p=r.commonAncestorContainer;if(t!==p&&e!==p||i.contains(o))return x(p)?p:w(p);var n=v(t);return n.host?k(n.host,e):k(t,v(e).host)}function E(t){var e=1=a.clientWidth&&i>=a.clientHeight}),d=0r,bottom:o-n.bottom>r,left:n.left-i>r,right:i-n.right>r};return'top'===s?d.top=n.top-o>l:'bottom'===s?d.bottom=o-n.bottom>l:'left'===s?d.left=n.left-i>l:'right'===s?d.right=i-n.right>l:void 0,d.top||d.bottom||d.left||d.right}function ft(t,e,a,i){if(!e.length)return'';var o={scale:function(){return 1===e.length?''+e[0]:a?e[0]+', '+e[1]:e[1]+', '+e[0]}(),translate:function(){return 1===e.length?i?-e[0]+'px':e[0]+'px':a?i?e[0]+'px, '+-e[1]+'px':e[0]+'px, '+e[1]+'px':i?-e[1]+'px, '+e[0]+'px':e[1]+'px, '+e[0]+'px'}()};return o[t]}function ht(t,e){if(!t)return'';return e?t:{X:'Y',Y:'X'}[t]}function bt(t,e,a){var i=ct(t),o='top'===i||'bottom'===i,r='right'===i||'bottom'===i,n=function(t){var e=a.match(t);return e?e[1]:''},s=function(t){var e=a.match(t);return e?e[1].split(',').map(parseFloat):[]},l={translate:/translateX?Y?\(([^)]+)\)/,scale:/scaleX?Y?\(([^)]+)\)/},d={translate:{axis:n(/translate([XY])/),numbers:s(l.translate)},scale:{axis:n(/scale([XY])/),numbers:s(l.scale)}},c=a.replace(l.translate,'translate'+ht(d.translate.axis,o)+'('+ft('translate',d.translate.numbers,o,r)+')').replace(l.scale,'scale'+ht(d.scale.axis,o)+'('+ft('scale',d.scale.numbers,o,r)+')');e.style[p('transform')]=c}function ut(t){return-(t-Kt.distance)+'px'}function yt(t){requestAnimationFrame(function(){setTimeout(t,1)})}function gt(t,a){var i=Element.prototype.closest||function(t){for(var a=this;a;){if(e.call(a,t))return a;a=a.parentElement}};return i.call(t,a)}function wt(t,e){return Array.isArray(t)?t[e]:t}function xt(t,e){t.forEach(function(t){t&&t.setAttribute('data-state',e)})}function vt(t,e){t.filter(Boolean).forEach(function(t){t.style[p('transitionDuration')]=e+'ms'})}function kt(t){var e=window.scrollX||window.pageXOffset,a=window.scrollY||window.pageYOffset;t.focus(),scroll(e,a)}function Et(){var t=this._(be).lastTriggerEvent;return this.options.followCursor&&!qt.usingTouch&&t&&'focus'!==t.type}function Tt(t){var e=gt(t.target,this.options.target);if(e&&!e._tippy){var a=e.getAttribute('title')||this.title;a&&(e.setAttribute('title',a),Ht(e,Jt({},this.options,{target:null})),Lt.call(e._tippy,t))}}function Lt(t){var e=this,a=this.options;if(Yt.call(this),!this.state.visible){if(a.target)return void Tt.call(this,t);if(this._(be).isPreparingToShow=!0,a.wait)return void a.wait.call(this.popper,this.show.bind(this),t);if(Et.call(this)){this._(be).followCursorListener||Pt.call(this);var i=m(this.popper),o=i.arrow;o&&(o.style.margin='0'),document.addEventListener('mousemove',this._(be).followCursorListener)}var r=wt(a.delay,0);r?this._(be).showTimeout=setTimeout(function(){e.show()},r):this.show()}}function Ot(){var t=this;if(Yt.call(this),!!this.state.visible){this._(be).isPreparingToShow=!1;var e=wt(this.options.delay,1);e?this._(be).hideTimeout=setTimeout(function(){t.state.visible&&t.hide()},e):this.hide()}}function At(){var t=this;return{onTrigger:function(e){if(t.state.enabled){var a=qt.supportsTouch&&qt.usingTouch&&-1<['mouseenter','mouseover','focus'].indexOf(e.type);a&&t.options.touchHold||(t._(be).lastTriggerEvent=e,'click'===e.type&&'persistent'!==t.options.hideOnClick&&t.state.visible?Ot.call(t):Lt.call(t,e),a&&qt.iOS&&t.reference.click&&t.reference.click())}},onMouseLeave:function(e){if(!(-1<['mouseleave','mouseout'].indexOf(e.type)&&qt.supportsTouch&&qt.usingTouch&&t.options.touchHold)){if(t.options.interactive){var a=Ot.bind(t),i=function e(i){var o=gt(i.target,jt.REFERENCE),r=gt(i.target,jt.POPPER)===t.popper,p=o===t.reference;r||p||mt(i,t.popper,t.options)&&(document.body.removeEventListener('mouseleave',a),document.removeEventListener('mousemove',e),Ot.call(t,e))};return document.body.addEventListener('mouseleave',a),void document.addEventListener('mousemove',i)}Ot.call(t)}},onBlur:function(e){if(!(e.target!==t.reference||qt.usingTouch)){if(t.options.interactive){if(!e.relatedTarget)return;if(gt(e.relatedTarget,jt.POPPER))return}Ot.call(t)}},onDelegateShow:function(e){gt(e.target,t.options.target)&&Lt.call(t,e)},onDelegateHide:function(e){gt(e.target,t.options.target)&&Ot.call(t)}}}function Ct(){var t=this,e=this.popper,a=this.reference,i=this.options,o=m(e),r=o.tooltip,p=i.popperOptions,n='round'===i.arrowType?jt.ROUND_ARROW:jt.ARROW,s=r.querySelector(n),l=Jt({placement:i.placement},p||{},{modifiers:Jt({},p?p.modifiers:{},{arrow:Jt({element:n},p&&p.modifiers?p.modifiers.arrow:{}),flip:Jt({enabled:i.flip,padding:i.distance+5,behavior:i.flipBehavior},p&&p.modifiers?p.modifiers.flip:{}),offset:Jt({offset:i.offset},p&&p.modifiers?p.modifiers.offset:{})}),onCreate:function(){r.style[ct(e)]=ut(i.distance),s&&i.arrowTransform&&bt(e,s,i.arrowTransform)},onUpdate:function(){var t=r.style;t.top='',t.bottom='',t.left='',t.right='',t[ct(e)]=ut(i.distance),s&&i.arrowTransform&&bt(e,s,i.arrowTransform)}});return Dt.call(this,{target:e,callback:function(){t.popperInstance.update()},options:{childList:!0,subtree:!0,characterData:!0}}),new me(a,e,l)}function St(t){var e=this.options;if(this.popperInstance?(this.popperInstance.scheduleUpdate(),e.livePlacement&&!Et.call(this)&&this.popperInstance.enableEventListeners()):(this.popperInstance=Ct.call(this),!e.livePlacement&&this.popperInstance.disableEventListeners()),!Et.call(this)){var a=m(this.popper),i=a.arrow;i&&(i.style.margin=''),this.popperInstance.reference=this.reference}dt(this.popperInstance,t,!0),e.appendTo.contains(this.popper)||e.appendTo.appendChild(this.popper)}function Yt(){var t=this._(be),e=t.showTimeout,a=t.hideTimeout;clearTimeout(e),clearTimeout(a)}function Pt(){var t=this;this._(be).followCursorListener=function(e){var a=t._(be).lastMouseMoveEvent=e,i=a.clientX,o=a.clientY;t.popperInstance&&(t.popperInstance.reference={getBoundingClientRect:function(){return{width:0,height:0,top:o,left:i,right:i,bottom:o}},clientWidth:0,clientHeight:0},t.popperInstance.scheduleUpdate())}}function Xt(){var t=this,e=function(){t.popper.style[p('transitionDuration')]=t.options.updateDuration+'ms'},a=function(){t.popper.style[p('transitionDuration')]=''};(function i(){t.popperInstance&&t.popperInstance.update(),e(),t.state.visible?requestAnimationFrame(i):a()})()}function Dt(t){var e=t.target,a=t.callback,i=t.options;if(window.MutationObserver){var o=new MutationObserver(a);o.observe(e,i),this._(be).mutationObservers.push(o)}}function It(t,a){if(!t)return a();var e=m(this.popper),i=e.tooltip,o=function(t,e){e&&i[t+'EventListener']('ontransitionend'in window?'transitionend':'webkitTransitionEnd',e)},r=function t(r){r.target===i&&(o('remove',t),a())};o('remove',this._(be).transitionendListener),o('add',r),this._(be).transitionendListener=r}function _t(t,e){return t.reduce(function(t,a){var i=ge,o=c(a,e.performance?e:d(a,e)),r=a.getAttribute('title');if(!r&&!o.target&&!o.html&&!o.dynamicTitle)return t;a.setAttribute(o.target?'data-tippy-delegate':'data-tippy',''),f(a);var p=s(i,r,o),n=new ye({id:i,reference:a,popper:p,options:o,title:r,popperInstance:null});o.createPopperInstanceOnInit&&(n.popperInstance=Ct.call(n),n.popperInstance.disableEventListeners());var h=At.call(n);return n.listeners=o.trigger.trim().split(' ').reduce(function(t,e){return t.concat(l(e,a,h,o))},[]),o.dynamicTitle&&Dt.call(n,{target:a,callback:function(){var t=m(p),e=t.content,i=a.getAttribute('title');i&&(e[o.allowTitleHTML?'innerHTML':'textContent']=n.title=i,f(a))},options:{attributes:!0}}),a._tippy=n,p._tippy=n,p._reference=a,t.push(n),ge++,t},[])}function Rt(t){var e=a(document.querySelectorAll(jt.POPPER));e.forEach(function(e){var a=e._tippy;if(a){var i=a.options;(!0===i.hideOnClick||-1e-t&&(qt.usingTouch=!1,document.removeEventListener('mousemove',i),!qt.iOS&&document.body.classList.remove('tippy-touch'),qt.onUserInputChange('mouse')),t=e}}();document.addEventListener('click',function(t){if(!(t.target instanceof Element))return Rt();var e=gt(t.target,jt.REFERENCE),a=gt(t.target,jt.POPPER);if(!(a&&a._tippy&&a._tippy.options.interactive)){if(e&&e._tippy){var i=e._tippy.options,o=-1s[t]&&!e.escapeWithReference&&(i=Mt(d[a],s[t]-('right'===t?d.width:d.height))),ne({},a,i)}};return l.forEach(function(t){var e=-1===['left','top'].indexOf(t)?'secondary':'primary';d=se({},d,c[e](t))}),t.offsets.popper=d,t},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,a=e.popper,i=e.reference,o=t.placement.split('-')[0],r=Wt,p=-1!==['top','bottom'].indexOf(o),n=p?'right':'bottom',s=p?'left':'top',l=p?'width':'height';return a[n]r(i[n])&&(t.offsets.popper[s]=r(i[n])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var a;if(!it(t.instance.modifiers,'arrow','keepTogether'))return t;var i=e.element;if('string'==typeof i){if(i=t.instance.popper.querySelector(i),!i)return t;}else if(!t.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),t;var o=t.placement.split('-')[0],r=t.offsets,p=r.popper,n=r.reference,s=-1!==['left','right'].indexOf(o),l=s?'height':'width',d=s?'Top':'Left',c=d.toLowerCase(),m=s?'left':'top',f=s?'bottom':'right',h=H(i)[l];n[f]-hp[f]&&(t.offsets.popper[c]+=n[c]+h-p[f]),t.offsets.popper=C(t.offsets.popper);var u=n[c]+n[l]/2-h/2,y=b(t.instance.popper),g=parseFloat(y['margin'+d],10),w=parseFloat(y['border'+d+'Width'],10),x=u-t.offsets.popper[c]-g-w;return x=Ut(Mt(p[l]-h,x),0),t.arrowElement=i,t.offsets.arrow=(a={},ne(a,c,Bt(x)),ne(a,m,''),a),t},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(t,e){if(q(t.instance.modifiers,'inner'))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var a=I(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split('-')[0],o=M(i),r=t.placement.split('-')[1]||'',p=[];switch(e.behavior){case ce.FLIP:p=[i,o];break;case ce.CLOCKWISE:p=rt(i);break;case ce.COUNTERCLOCKWISE:p=rt(i,!0);break;default:p=e.behavior;}return p.forEach(function(n,s){if(i!==n||p.length===s+1)return t;i=t.placement.split('-')[0],o=M(i);var l=t.offsets.popper,d=t.offsets.reference,c=Wt,m='left'===i&&c(l.right)>c(d.left)||'right'===i&&c(l.left)c(d.top)||'bottom'===i&&c(l.top)c(a.right),b=c(l.top)c(a.bottom),y='left'===i&&f||'right'===i&&h||'top'===i&&b||'bottom'===i&&u,g=-1!==['top','bottom'].indexOf(i),w=!!e.flipVariations&&(g&&'start'===r&&f||g&&'end'===r&&h||!g&&'start'===r&&b||!g&&'end'===r&&u);(m||y||w)&&(t.flipped=!0,(m||y)&&(i=p[s+1]),w&&(r=ot(r)),t.placement=i+(r?'-'+r:''),t.offsets.popper=se({},t.offsets.popper,B(t.instance.popper,t.offsets.reference,t.placement)),t=z(t.instance.modifiers,t,'flip'))}),t},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,a=e.split('-')[0],i=t.offsets,o=i.popper,r=i.reference,p=-1!==['left','right'].indexOf(a),n=-1===['top','left'].indexOf(a);return o[p?'left':'top']=r[a]-(n?o[p?'width':'height']:0),t.placement=M(e),t.offsets.popper=C(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!it(t.instance.modifiers,'hide','preventOverflow'))return t;var e=t.offsets.reference,a=W(t.instance.modifiers,function(t){return'preventOverflow'===t.name}).boundaries;if(e.bottoma.right||e.top>a.bottom||e.right0&&s(a.width)/e.offsetWidth||1,p=e.offsetHeight>0&&s(a.height)/e.offsetHeight||1);var u=(n(e)?t(e):window).visualViewport,l=!c()&&i,d=(a.left+(l&&u?u.offsetLeft:0))/f,h=(a.top+(l&&u?u.offsetTop:0))/p,m=a.width/f,v=a.height/p;return{width:m,height:v,top:h,right:d+m,bottom:h+v,left:d,x:d,y:h}}function u(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function l(e){return e?(e.nodeName||"").toLowerCase():null}function d(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function h(e){return p(d(e)).left+u(e).scrollLeft}function m(e){return t(e).getComputedStyle(e)}function v(e){var t=m(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function y(e,n,o){void 0===o&&(o=!1);var i,a,f=r(n),c=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),m=d(n),y=p(e,c,o),g={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(f||!f&&!o)&&(("body"!==l(n)||v(m))&&(g=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:u(i)),r(n)?((b=p(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):m&&(b.x=h(m))),{x:y.left+g.scrollLeft-b.x,y:y.top+g.scrollTop-b.y,width:y.width,height:y.height}}function g(e){var t=p(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function b(e){return"html"===l(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||d(e)}function x(e){return["html","body","#document"].indexOf(l(e))>=0?e.ownerDocument.body:r(e)&&v(e)?e:x(b(e))}function w(e,n){var r;void 0===n&&(n=[]);var o=x(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],v(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(w(b(s)))}function O(e){return["table","td","th"].indexOf(l(e))>=0}function j(e){return r(e)&&"fixed"!==m(e).position?e.offsetParent:null}function E(e){for(var n=t(e),i=j(e);i&&O(i)&&"static"===m(i).position;)i=j(i);return i&&("html"===l(i)||"body"===l(i)&&"static"===m(i).position)?n:i||function(e){var t=/firefox/i.test(f());if(/Trident/i.test(f())&&r(e)&&"fixed"===m(e).position)return null;var n=b(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(l(n))<0;){var i=m(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var D="top",A="bottom",L="right",P="left",M="auto",k=[D,A,L,P],W="start",B="end",H="viewport",T="popper",R=k.reduce((function(e,t){return e.concat([t+"-"+W,t+"-"+B])}),[]),S=[].concat(k,[M]).reduce((function(e,t){return e.concat([t,t+"-"+W,t+"-"+B])}),[]),V=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function q(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function N(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function I(e,r,o){return r===H?N(function(e,n){var r=t(e),o=d(e),i=r.visualViewport,a=o.clientWidth,s=o.clientHeight,f=0,p=0;if(i){a=i.width,s=i.height;var u=c();(u||!u&&"fixed"===n)&&(f=i.offsetLeft,p=i.offsetTop)}return{width:a,height:s,x:f+h(e),y:p}}(e,o)):n(r)?function(e,t){var n=p(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(r,o):N(function(e){var t,n=d(e),r=u(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+h(e),c=-r.scrollTop;return"rtl"===m(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:c}}(d(e)))}function _(e,t,o,s){var f="clippingParents"===t?function(e){var t=w(b(e)),o=["absolute","fixed"].indexOf(m(e).position)>=0&&r(e)?E(e):e;return n(o)?t.filter((function(e){return n(e)&&C(e,o)&&"body"!==l(e)})):[]}(e):[].concat(t),c=[].concat(f,[o]),p=c[0],u=c.reduce((function(t,n){var r=I(e,n,s);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),I(e,p,s));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function F(e){return e.split("-")[0]}function U(e){return e.split("-")[1]}function z(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function X(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?F(o):null,a=o?U(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case D:t={x:s,y:n.y-r.height};break;case A:t={x:s,y:n.y+n.height};break;case L:t={x:n.x+n.width,y:f};break;case P:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?z(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case W:t[c]=t[c]-(n[p]/2-r[p]/2);break;case B:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function Y(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function G(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function J(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.strategy,s=void 0===a?e.strategy:a,f=r.boundary,c=void 0===f?"clippingParents":f,u=r.rootBoundary,l=void 0===u?H:u,h=r.elementContext,m=void 0===h?T:h,v=r.altBoundary,y=void 0!==v&&v,g=r.padding,b=void 0===g?0:g,x=Y("number"!=typeof b?b:G(b,k)),w=m===T?"reference":T,O=e.rects.popper,j=e.elements[y?w:m],E=_(n(j)?j:j.contextElement||d(e.elements.popper),c,l,s),P=p(e.elements.reference),M=X({reference:P,element:O,strategy:"absolute",placement:i}),W=N(Object.assign({},O,M)),B=m===T?W:P,R={top:E.top-B.top+x.top,bottom:B.bottom-E.bottom+x.bottom,left:E.left-B.left+x.left,right:B.right-E.right+x.right},S=e.modifiersData.offset;if(m===T&&S){var V=S[i];Object.keys(R).forEach((function(e){var t=[L,A].indexOf(e)>=0?1:-1,n=[D,A].indexOf(e)>=0?"y":"x";R[e]+=V[n]*t}))}return R}var K={placement:"bottom",modifiers:[],strategy:"absolute"};function Q(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[P,L].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},se={left:"right",right:"left",bottom:"top",top:"bottom"};function fe(e){return e.replace(/left|right|bottom|top/g,(function(e){return se[e]}))}var ce={start:"end",end:"start"};function pe(e){return e.replace(/start|end/g,(function(e){return ce[e]}))}function ue(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?S:f,p=U(r),u=p?s?R:R.filter((function(e){return U(e)===p})):k,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=J(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[F(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var le={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,y=F(v),g=f||(y===v||!h?[fe(v)]:function(e){if(F(e)===M)return[];var t=fe(e);return[pe(e),t,pe(t)]}(v)),b=[v].concat(g).reduce((function(e,n){return e.concat(F(n)===M?ue(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,j=!0,E=b[0],k=0;k=0,S=R?"width":"height",V=J(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),q=R?T?L:P:T?A:D;x[S]>w[S]&&(q=fe(q));var C=fe(q),N=[];if(i&&N.push(V[H]<=0),s&&N.push(V[q]<=0,V[C]<=0),N.every((function(e){return e}))){E=B,j=!1;break}O.set(B,N)}if(j)for(var I=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return E=t,"break"},_=h?3:1;_>0;_--){if("break"===I(_))break}t.placement!==E&&(t.modifiersData[r]._skip=!0,t.placement=E,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function de(e,t,n){return i(e,a(t,n))}var he={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,v=n.tetherOffset,y=void 0===v?0:v,b=J(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=F(t.placement),w=U(t.placement),O=!w,j=z(x),M="x"===j?"y":"x",k=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,V={x:0,y:0};if(k){if(s){var q,C="y"===j?D:P,N="y"===j?A:L,I="y"===j?"height":"width",_=k[j],X=_+b[C],Y=_-b[N],G=m?-H[I]/2:0,K=w===W?B[I]:H[I],Q=w===W?-H[I]:-B[I],Z=t.elements.arrow,$=m&&Z?g(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[C],ne=ee[N],re=de(0,B[I],$[I]),oe=O?B[I]/2-G-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=O?-B[I]/2+G+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&E(t.elements.arrow),se=ae?"y"===j?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(q=null==S?void 0:S[j])?q:0,ce=_+ie-fe,pe=de(m?a(X,_+oe-fe-se):X,_,m?i(Y,ce):Y);k[j]=pe,V[j]=pe-_}if(c){var ue,le="x"===j?D:P,he="x"===j?A:L,me=k[M],ve="y"===M?"height":"width",ye=me+b[le],ge=me-b[he],be=-1!==[D,P].indexOf(x),xe=null!=(ue=null==S?void 0:S[M])?ue:0,we=be?ye:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ge,je=m&&be?function(e,t,n){var r=de(e,t,n);return r>n?n:r}(we,me,Oe):de(m?we:ye,me,m?Oe:ge);k[M]=je,V[M]=je-me}t.modifiersData[r]=V}},requiresIfExists:["offset"]};var me={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=F(n.placement),f=z(s),c=[P,L].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return Y("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:G(e,k))}(o.padding,n),u=g(i),l="y"===f?D:P,d="y"===f?A:L,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],v=E(i),y=v?"y"===f?v.clientHeight||0:v.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],O=y/2-u[c]/2+b,j=de(x,O,w),M=f;n.modifiersData[r]=((t={})[M]=j,t.centerOffset=j-O,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&C(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ve(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function ye(e){return[D,L,A,P].some((function(t){return e[t]>=0}))}var ge={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=J(t,{elementContext:"reference"}),s=J(t,{altBoundary:!0}),f=ve(a,r),c=ve(s,o,i),p=ye(f),u=ye(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},be=Z({defaultModifiers:[ee,te,oe,ie]}),xe=[ee,te,oe,ie,ae,le,he,me,ge],we=Z({defaultModifiers:xe});e.applyStyles=ie,e.arrow=me,e.computeStyles=oe,e.createPopper=we,e.createPopperLite=be,e.defaultModifiers=xe,e.detectOverflow=J,e.eventListeners=ee,e.flip=le,e.hide=ge,e.offset=ae,e.popperGenerator=Z,e.popperOffsets=te,e.preventOverflow=he,Object.defineProperty(e,"__esModule",{value:!0})})); +//# sourceMappingURL=popper.min.js.map + +/** + * @tippy.js - version 6.3.7 + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],e):(t=t||self).tippy=e(t.Popper)}(this,(function(t){"use strict";var e="undefined"!=typeof window&&"undefined"!=typeof document,n=!!e&&!!window.msCrypto,r={passive:!0,capture:!0},o=function(){return document.body};function i(t,e,n){if(Array.isArray(t)){var r=t[e];return null==r?Array.isArray(n)?n[e]:n:r}return t}function a(t,e){var n={}.toString.call(t);return 0===n.indexOf("[object")&&n.indexOf(e+"]")>-1}function s(t,e){return"function"==typeof t?t.apply(void 0,e):t}function u(t,e){return 0===e?t:function(r){clearTimeout(n),n=setTimeout((function(){t(r)}),e)};var n}function p(t,e){var n=Object.assign({},t);return e.forEach((function(t){delete n[t]})),n}function c(t){return[].concat(t)}function f(t,e){-1===t.indexOf(e)&&t.push(e)}function l(t){return t.split("-")[0]}function d(t){return[].slice.call(t)}function v(t){return Object.keys(t).reduce((function(e,n){return void 0!==t[n]&&(e[n]=t[n]),e}),{})}function m(){return document.createElement("div")}function g(t){return["Element","Fragment"].some((function(e){return a(t,e)}))}function h(t){return a(t,"MouseEvent")}function b(t){return!(!t||!t._tippy||t._tippy.reference!==t)}function y(t){return g(t)?[t]:function(t){return a(t,"NodeList")}(t)?d(t):Array.isArray(t)?t:d(document.querySelectorAll(t))}function w(t,e){t.forEach((function(t){t&&(t.style.transitionDuration=e+"ms")}))}function x(t,e){t.forEach((function(t){t&&t.setAttribute("data-state",e)}))}function E(t){var e,n=c(t)[0];return null!=n&&null!=(e=n.ownerDocument)&&e.body?n.ownerDocument:document}function O(t,e,n){var r=e+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(e){t[r](e,n)}))}function C(t,e){for(var n=e;n;){var r;if(t.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var T={isTouch:!1},A=0;function L(){T.isTouch||(T.isTouch=!0,window.performance&&document.addEventListener("mousemove",D))}function D(){var t=performance.now();t-A<20&&(T.isTouch=!1,document.removeEventListener("mousemove",D)),A=t}function k(){var t=document.activeElement;if(b(t)){var e=t._tippy;t.blur&&!e.state.isVisible&&t.blur()}}var R=Object.assign({appendTo:o,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),P=Object.keys(R);function j(t){var e=(t.plugins||[]).reduce((function(e,n){var r,o=n.name,i=n.defaultValue;o&&(e[o]=void 0!==t[o]?t[o]:null!=(r=R[o])?r:i);return e}),{});return Object.assign({},t,e)}function M(t,e){var n=Object.assign({},e,{content:s(e.content,[t])},e.ignoreAttributes?{}:function(t,e){return(e?Object.keys(j(Object.assign({},R,{plugins:e}))):P).reduce((function(e,n){var r=(t.getAttribute("data-tippy-"+n)||"").trim();if(!r)return e;if("content"===n)e[n]=r;else try{e[n]=JSON.parse(r)}catch(t){e[n]=r}return e}),{})}(t,e.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?e.interactive:n.aria.expanded,content:"auto"===n.aria.content?e.interactive?null:"describedby":n.aria.content},n}function V(t,e){t.innerHTML=e}function I(t){var e=m();return!0===t?e.className="tippy-arrow":(e.className="tippy-svg-arrow",g(t)?e.appendChild(t):V(e,t)),e}function S(t,e){g(e.content)?(V(t,""),t.appendChild(e.content)):"function"!=typeof e.content&&(e.allowHTML?V(t,e.content):t.textContent=e.content)}function B(t){var e=t.firstElementChild,n=d(e.children);return{box:e,content:n.find((function(t){return t.classList.contains("tippy-content")})),arrow:n.find((function(t){return t.classList.contains("tippy-arrow")||t.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(t){return t.classList.contains("tippy-backdrop")}))}}function N(t){var e=m(),n=m();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=m();function o(n,r){var o=B(e),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||S(a,t.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(I(r.arrow))):i.appendChild(I(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),S(r,t.props),e.appendChild(n),n.appendChild(r),o(t.props,t.props),{popper:e,onUpdate:o}}N.$$tippy=!0;var H=1,U=[],_=[];function z(e,a){var p,g,b,y,A,L,D,k,P=M(e,Object.assign({},R,j(v(a)))),V=!1,I=!1,S=!1,N=!1,z=[],F=u(wt,P.interactiveDebounce),W=H++,X=(k=P.plugins).filter((function(t,e){return k.indexOf(t)===e})),Y={id:W,reference:e,popper:m(),popperInstance:null,props:P,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:X,clearDelayTimeouts:function(){clearTimeout(p),clearTimeout(g),cancelAnimationFrame(b)},setProps:function(t){if(Y.state.isDestroyed)return;at("onBeforeUpdate",[Y,t]),bt();var n=Y.props,r=M(e,Object.assign({},n,v(t),{ignoreAttributes:!0}));Y.props=r,ht(),n.interactiveDebounce!==r.interactiveDebounce&&(pt(),F=u(wt,r.interactiveDebounce));n.triggerTarget&&!r.triggerTarget?c(n.triggerTarget).forEach((function(t){t.removeAttribute("aria-expanded")})):r.triggerTarget&&e.removeAttribute("aria-expanded");ut(),it(),J&&J(n,r);Y.popperInstance&&(Ct(),At().forEach((function(t){requestAnimationFrame(t._tippy.popperInstance.forceUpdate)})));at("onAfterUpdate",[Y,t])},setContent:function(t){Y.setProps({content:t})},show:function(){var t=Y.state.isVisible,e=Y.state.isDestroyed,n=!Y.state.isEnabled,r=T.isTouch&&!Y.props.touch,a=i(Y.props.duration,0,R.duration);if(t||e||n||r)return;if(et().hasAttribute("disabled"))return;if(at("onShow",[Y],!1),!1===Y.props.onShow(Y))return;Y.state.isVisible=!0,tt()&&($.style.visibility="visible");it(),dt(),Y.state.isMounted||($.style.transition="none");if(tt()){var u=rt(),p=u.box,c=u.content;w([p,c],0)}L=function(){var t;if(Y.state.isVisible&&!N){if(N=!0,$.offsetHeight,$.style.transition=Y.props.moveTransition,tt()&&Y.props.animation){var e=rt(),n=e.box,r=e.content;w([n,r],a),x([n,r],"visible")}st(),ut(),f(_,Y),null==(t=Y.popperInstance)||t.forceUpdate(),at("onMount",[Y]),Y.props.animation&&tt()&&function(t,e){mt(t,e)}(a,(function(){Y.state.isShown=!0,at("onShown",[Y])}))}},function(){var t,e=Y.props.appendTo,n=et();t=Y.props.interactive&&e===o||"parent"===e?n.parentNode:s(e,[n]);t.contains($)||t.appendChild($);Y.state.isMounted=!0,Ct()}()},hide:function(){var t=!Y.state.isVisible,e=Y.state.isDestroyed,n=!Y.state.isEnabled,r=i(Y.props.duration,1,R.duration);if(t||e||n)return;if(at("onHide",[Y],!1),!1===Y.props.onHide(Y))return;Y.state.isVisible=!1,Y.state.isShown=!1,N=!1,V=!1,tt()&&($.style.visibility="hidden");if(pt(),vt(),it(!0),tt()){var o=rt(),a=o.box,s=o.content;Y.props.animation&&(w([a,s],r),x([a,s],"hidden"))}st(),ut(),Y.props.animation?tt()&&function(t,e){mt(t,(function(){!Y.state.isVisible&&$.parentNode&&$.parentNode.contains($)&&e()}))}(r,Y.unmount):Y.unmount()},hideWithInteractivity:function(t){nt().addEventListener("mousemove",F),f(U,F),F(t)},enable:function(){Y.state.isEnabled=!0},disable:function(){Y.hide(),Y.state.isEnabled=!1},unmount:function(){Y.state.isVisible&&Y.hide();if(!Y.state.isMounted)return;Tt(),At().forEach((function(t){t._tippy.unmount()})),$.parentNode&&$.parentNode.removeChild($);_=_.filter((function(t){return t!==Y})),Y.state.isMounted=!1,at("onHidden",[Y])},destroy:function(){if(Y.state.isDestroyed)return;Y.clearDelayTimeouts(),Y.unmount(),bt(),delete e._tippy,Y.state.isDestroyed=!0,at("onDestroy",[Y])}};if(!P.render)return Y;var q=P.render(Y),$=q.popper,J=q.onUpdate;$.setAttribute("data-tippy-root",""),$.id="tippy-"+Y.id,Y.popper=$,e._tippy=Y,$._tippy=Y;var G=X.map((function(t){return t.fn(Y)})),K=e.hasAttribute("aria-expanded");return ht(),ut(),it(),at("onCreate",[Y]),P.showOnCreate&&Lt(),$.addEventListener("mouseenter",(function(){Y.props.interactive&&Y.state.isVisible&&Y.clearDelayTimeouts()})),$.addEventListener("mouseleave",(function(){Y.props.interactive&&Y.props.trigger.indexOf("mouseenter")>=0&&nt().addEventListener("mousemove",F)})),Y;function Q(){var t=Y.props.touch;return Array.isArray(t)?t:[t,0]}function Z(){return"hold"===Q()[0]}function tt(){var t;return!(null==(t=Y.props.render)||!t.$$tippy)}function et(){return D||e}function nt(){var t=et().parentNode;return t?E(t):document}function rt(){return B($)}function ot(t){return Y.state.isMounted&&!Y.state.isVisible||T.isTouch||y&&"focus"===y.type?0:i(Y.props.delay,t?0:1,R.delay)}function it(t){void 0===t&&(t=!1),$.style.pointerEvents=Y.props.interactive&&!t?"":"none",$.style.zIndex=""+Y.props.zIndex}function at(t,e,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[t]&&n[t].apply(n,e)})),n)&&(r=Y.props)[t].apply(r,e)}function st(){var t=Y.props.aria;if(t.content){var n="aria-"+t.content,r=$.id;c(Y.props.triggerTarget||e).forEach((function(t){var e=t.getAttribute(n);if(Y.state.isVisible)t.setAttribute(n,e?e+" "+r:r);else{var o=e&&e.replace(r,"").trim();o?t.setAttribute(n,o):t.removeAttribute(n)}}))}}function ut(){!K&&Y.props.aria.expanded&&c(Y.props.triggerTarget||e).forEach((function(t){Y.props.interactive?t.setAttribute("aria-expanded",Y.state.isVisible&&t===et()?"true":"false"):t.removeAttribute("aria-expanded")}))}function pt(){nt().removeEventListener("mousemove",F),U=U.filter((function(t){return t!==F}))}function ct(t){if(!T.isTouch||!S&&"mousedown"!==t.type){var n=t.composedPath&&t.composedPath()[0]||t.target;if(!Y.props.interactive||!C($,n)){if(c(Y.props.triggerTarget||e).some((function(t){return C(t,n)}))){if(T.isTouch)return;if(Y.state.isVisible&&Y.props.trigger.indexOf("click")>=0)return}else at("onClickOutside",[Y,t]);!0===Y.props.hideOnClick&&(Y.clearDelayTimeouts(),Y.hide(),I=!0,setTimeout((function(){I=!1})),Y.state.isMounted||vt())}}}function ft(){S=!0}function lt(){S=!1}function dt(){var t=nt();t.addEventListener("mousedown",ct,!0),t.addEventListener("touchend",ct,r),t.addEventListener("touchstart",lt,r),t.addEventListener("touchmove",ft,r)}function vt(){var t=nt();t.removeEventListener("mousedown",ct,!0),t.removeEventListener("touchend",ct,r),t.removeEventListener("touchstart",lt,r),t.removeEventListener("touchmove",ft,r)}function mt(t,e){var n=rt().box;function r(t){t.target===n&&(O(n,"remove",r),e())}if(0===t)return e();O(n,"remove",A),O(n,"add",r),A=r}function gt(t,n,r){void 0===r&&(r=!1),c(Y.props.triggerTarget||e).forEach((function(e){e.addEventListener(t,n,r),z.push({node:e,eventType:t,handler:n,options:r})}))}function ht(){var t;Z()&&(gt("touchstart",yt,{passive:!0}),gt("touchend",xt,{passive:!0})),(t=Y.props.trigger,t.split(/\s+/).filter(Boolean)).forEach((function(t){if("manual"!==t)switch(gt(t,yt),t){case"mouseenter":gt("mouseleave",xt);break;case"focus":gt(n?"focusout":"blur",Et);break;case"focusin":gt("focusout",Et)}}))}function bt(){z.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,o=t.options;e.removeEventListener(n,r,o)})),z=[]}function yt(t){var e,n=!1;if(Y.state.isEnabled&&!Ot(t)&&!I){var r="focus"===(null==(e=y)?void 0:e.type);y=t,D=t.currentTarget,ut(),!Y.state.isVisible&&h(t)&&U.forEach((function(e){return e(t)})),"click"===t.type&&(Y.props.trigger.indexOf("mouseenter")<0||V)&&!1!==Y.props.hideOnClick&&Y.state.isVisible?n=!0:Lt(t),"click"===t.type&&(V=!n),n&&!r&&Dt(t)}}function wt(t){var e=t.target,n=et().contains(e)||$.contains(e);"mousemove"===t.type&&n||function(t,e){var n=e.clientX,r=e.clientY;return t.every((function(t){var e=t.popperRect,o=t.popperState,i=t.props.interactiveBorder,a=l(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,p="top"===a?s.bottom.y:0,c="right"===a?s.left.x:0,f="left"===a?s.right.x:0,d=e.top-r+u>i,v=r-e.bottom-p>i,m=e.left-n+c>i,g=n-e.right-f>i;return d||v||m||g}))}(At().concat($).map((function(t){var e,n=null==(e=t._tippy.popperInstance)?void 0:e.state;return n?{popperRect:t.getBoundingClientRect(),popperState:n,props:P}:null})).filter(Boolean),t)&&(pt(),Dt(t))}function xt(t){Ot(t)||Y.props.trigger.indexOf("click")>=0&&V||(Y.props.interactive?Y.hideWithInteractivity(t):Dt(t))}function Et(t){Y.props.trigger.indexOf("focusin")<0&&t.target!==et()||Y.props.interactive&&t.relatedTarget&&$.contains(t.relatedTarget)||Dt(t)}function Ot(t){return!!T.isTouch&&Z()!==t.type.indexOf("touch")>=0}function Ct(){Tt();var n=Y.props,r=n.popperOptions,o=n.placement,i=n.offset,a=n.getReferenceClientRect,s=n.moveTransition,u=tt()?B($).arrow:null,p=a?{getBoundingClientRect:a,contextElement:a.contextElement||et()}:e,c=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(t){var e=t.state;if(tt()){var n=rt().box;["placement","reference-hidden","escaped"].forEach((function(t){"placement"===t?n.setAttribute("data-placement",e.placement):e.attributes.popper["data-popper-"+t]?n.setAttribute("data-"+t,""):n.removeAttribute("data-"+t)})),e.attributes.popper={}}}}];tt()&&u&&c.push({name:"arrow",options:{element:u,padding:3}}),c.push.apply(c,(null==r?void 0:r.modifiers)||[]),Y.popperInstance=t.createPopper(p,$,Object.assign({},r,{placement:o,onFirstUpdate:L,modifiers:c}))}function Tt(){Y.popperInstance&&(Y.popperInstance.destroy(),Y.popperInstance=null)}function At(){return d($.querySelectorAll("[data-tippy-root]"))}function Lt(t){Y.clearDelayTimeouts(),t&&at("onTrigger",[Y,t]),dt();var e=ot(!0),n=Q(),r=n[0],o=n[1];T.isTouch&&"hold"===r&&o&&(e=o),e?p=setTimeout((function(){Y.show()}),e):Y.show()}function Dt(t){if(Y.clearDelayTimeouts(),at("onUntrigger",[Y,t]),Y.state.isVisible){if(!(Y.props.trigger.indexOf("mouseenter")>=0&&Y.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(t.type)>=0&&V)){var e=ot(!1);e?g=setTimeout((function(){Y.state.isVisible&&Y.hide()}),e):b=requestAnimationFrame((function(){Y.hide()}))}}else vt()}}function F(t,e){void 0===e&&(e={});var n=R.plugins.concat(e.plugins||[]);document.addEventListener("touchstart",L,r),window.addEventListener("blur",k);var o=Object.assign({},e,{plugins:n}),i=y(t).reduce((function(t,e){var n=e&&z(e,o);return n&&t.push(n),t}),[]);return g(t)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(t){Object.keys(t).forEach((function(e){R[e]=t[e]}))},F.currentInput=T;var W=Object.assign({},t.applyStyles,{effect:function(t){var e=t.state,n={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(e.elements.popper.style,n.popper),e.styles=n,e.elements.arrow&&Object.assign(e.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(t){var e;if(null==(e=t.props.render)||!e.$$tippy)return{};var n=B(t.popper),r=n.box,o=n.content,i=t.props.animateFill?function(){var t=m();return t.className="tippy-backdrop",x([t],"hidden"),t}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",t.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var t=r.style.transitionDuration,e=Number(t.replace("ms",""));o.style.transitionDelay=Math.round(e/10)+"ms",i.style.transitionDuration=t,x([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&x([i],"hidden")}}}};var q={clientX:0,clientY:0},$=[];function J(t){var e=t.clientX,n=t.clientY;q={clientX:e,clientY:n}}var G={name:"followCursor",defaultValue:!1,fn:function(t){var e=t.reference,n=E(t.props.triggerTarget||e),r=!1,o=!1,i=!0,a=t.props;function s(){return"initial"===t.props.followCursor&&t.state.isVisible}function u(){n.addEventListener("mousemove",f)}function p(){n.removeEventListener("mousemove",f)}function c(){r=!0,t.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||e.contains(n.target),o=t.props.followCursor,i=n.clientX,a=n.clientY,s=e.getBoundingClientRect(),u=i-s.left,p=a-s.top;!r&&t.props.interactive||t.setProps({getReferenceClientRect:function(){var t=e.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=t.left+u,r=t.top+p);var s="horizontal"===o?t.top:r,c="vertical"===o?t.right:n,f="horizontal"===o?t.bottom:r,l="vertical"===o?t.left:n;return{width:c-l,height:f-s,top:s,right:c,bottom:f,left:l}}})}function l(){t.props.followCursor&&($.push({instance:t,doc:n}),function(t){t.addEventListener("mousemove",J)}(n))}function d(){0===($=$.filter((function(e){return e.instance!==t}))).filter((function(t){return t.doc===n})).length&&function(t){t.removeEventListener("mousemove",J)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=t.props},onAfterUpdate:function(e,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!t.state.isMounted||o||s()||u()):(p(),c()))},onMount:function(){t.props.followCursor&&!o&&(i&&(f(q),i=!1),s()||u())},onTrigger:function(t,e){h(e)&&(q={clientX:e.clientX,clientY:e.clientY}),o="focus"===e.type},onHidden:function(){t.props.followCursor&&(c(),p(),i=!0)}}}};var K={name:"inlinePositioning",defaultValue:!1,fn:function(t){var e,n=t.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;t.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),e!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),t.setProps({getReferenceClientRect:function(){return function(t){return function(t,e,n,r){if(n.length<2||null===t)return e;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||e;switch(t){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===t,s=o.top,u=i.bottom,p=a?o.left:i.left,c=a?o.right:i.right;return{top:s,bottom:u,left:p,right:c,width:c-p,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(t){return t.left}))),l=Math.max.apply(Math,n.map((function(t){return t.right}))),d=n.filter((function(e){return"left"===t?e.left===f:e.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return e}}(l(t),n.getBoundingClientRect(),d(n.getClientRects()),r)}(a.placement)}})),e=a.placement)}};function s(){var e;o||(e=function(t,e){var n;return{popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat(((null==(n=t.popperOptions)?void 0:n.modifiers)||[]).filter((function(t){return t.name!==e.name})),[e])})}}(t.props,a),o=!0,t.setProps(e),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(e,n){if(h(n)){var o=d(t.reference.getClientRects()),i=o.find((function(t){return t.left-2<=n.clientX&&t.right+2>=n.clientX&&t.top-2<=n.clientY&&t.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var Q={name:"sticky",defaultValue:!1,fn:function(t){var e=t.reference,n=t.popper;function r(e){return!0===t.props.sticky||t.props.sticky===e}var o=null,i=null;function a(){var s=r("reference")?(t.popperInstance?t.popperInstance.state.elements.reference:e).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Z(o,s)||u&&Z(i,u))&&t.popperInstance&&t.popperInstance.update(),o=s,i=u,t.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){t.props.sticky&&a()}}}};function Z(t,e){return!t||!e||(t.top!==e.top||t.right!==e.right||t.bottom!==e.bottom||t.left!==e.left)}return e&&function(t){var e=document.createElement("style");e.textContent=t,e.setAttribute("data-tippy-stylesheet","");var n=document.head,r=document.querySelector("head>style,head>link");r?n.insertBefore(e,r):n.appendChild(e)}('.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}'),F.setDefaultProps({plugins:[Y,G,K,Q],render:N}),F.createSingleton=function(t,e){var n;void 0===e&&(e={});var r,o=t,i=[],a=[],s=e.overrides,u=[],f=!1;function l(){a=o.map((function(t){return c(t.props.triggerTarget||t.reference)})).reduce((function(t,e){return t.concat(e)}),[])}function d(){i=o.map((function(t){return t.reference}))}function v(t){o.forEach((function(e){t?e.enable():e.disable()}))}function g(t){return o.map((function(e){var n=e.setProps;return e.setProps=function(o){n(o),e.reference===r&&t.setProps(o)},function(){e.setProps=n}}))}function h(t,e){var n=a.indexOf(e);if(e!==r){r=e;var u=(s||[]).concat("content").reduce((function(t,e){return t[e]=o[n].props[e],t}),{});t.setProps(Object.assign({},u,{getReferenceClientRect:"function"==typeof u.getReferenceClientRect?u.getReferenceClientRect:function(){var t;return null==(t=i[n])?void 0:t.getBoundingClientRect()}}))}}v(!1),d(),l();var b={fn:function(){return{onDestroy:function(){v(!0)},onHidden:function(){r=null},onClickOutside:function(t){t.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(t){t.props.showOnCreate&&!f&&(f=!0,h(t,i[0]))},onTrigger:function(t,e){h(t,e.currentTarget)}}}},y=F(m(),Object.assign({},p(e,["overrides"]),{plugins:[b].concat(e.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat((null==(n=e.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(t){if(w(),!r&&null==t)return h(y,i[0]);if(!r||null!=t){if("number"==typeof t)return i[t]&&h(y,i[t]);if(o.indexOf(t)>=0){var e=t.reference;return h(y,e)}return i.indexOf(t)>=0?h(y,t):void 0}},y.showNext=function(){var t=i[0];if(!r)return y.show(0);var e=i.indexOf(r);y.show(i[e+1]||t)},y.showPrevious=function(){var t=i[i.length-1];if(!r)return y.show(t);var e=i.indexOf(r),n=i[e-1]||t;y.show(n)};var x=y.setProps;return y.setProps=function(t){s=t.overrides||s,x(t)},y.setInstances=function(t){v(!0),u.forEach((function(t){return t()})),o=t,v(!1),d(),l(),u=g(y),y.setProps({triggerTarget:a})},u=g(y),y},F.delegate=function(t,e){var n=[],o=[],i=!1,a=e.target,s=p(e,["target"]),u=Object.assign({},s,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},s,{showOnCreate:!0}),l=F(t,u);function d(t){if(t.target&&!i){var n=t.target.closest(a);if(n){var r=n.getAttribute("data-tippy-trigger")||e.trigger||R.trigger;if(!n._tippy&&!("touchstart"===t.type&&"boolean"==typeof f.touch||"touchstart"!==t.type&&r.indexOf(X[t.type])<0)){var s=F(n,f);s&&(o=o.concat(s))}}}}function v(t,e,r,o){void 0===o&&(o=!1),t.addEventListener(e,r,o),n.push({node:t,eventType:e,handler:r,options:o})}return c(l).forEach((function(t){var e=t.destroy,a=t.enable,s=t.disable;t.destroy=function(t){void 0===t&&(t=!0),t&&o.forEach((function(t){t.destroy()})),o=[],n.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,o=t.options;e.removeEventListener(n,r,o)})),n=[],e()},t.enable=function(){a(),o.forEach((function(t){return t.enable()})),i=!1},t.disable=function(){s(),o.forEach((function(t){return t.disable()})),i=!0},function(t){var e=t.reference;v(e,"touchstart",d,r),v(e,"mouseover",d),v(e,"focusin",d),v(e,"click",d)}(t)})),l},F.hideAll=function(t){var e=void 0===t?{}:t,n=e.exclude,r=e.duration;_.forEach((function(t){var e=!1;if(n&&(e=b(n)?t.reference===n:t.popper===n.popper),!e){var o=t.props.duration;t.setProps({duration:r}),t.hide(),t.state.isDestroyed||t.setProps({duration:o})}}))},F.roundArrow='',F})); +//# sourceMappingURL=tippy-bundle.umd.min.js.map diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..de13b7a --- /dev/null +++ b/composer.json @@ -0,0 +1,52 @@ +{ + "name": "metorikhq/metorik-helper", + "type": "wordpress-plugin", + "description": "The WordPress helper plugin for Metorik. Metorik provides reports, integrations, automatic emails, and cart tracking for WooCommerce stores.", + "keywords": ["plugin", "WordPress", "WooCommerce", "Metorik", "stats", "email", "engage", "store", "ecommerce"], + "homepage": "https://github.com/metorikhq/metorik-helper", + "license": "GPL-2.0-or-later", + "authors": [ + { + "name": "Metorik", + "homepage": "https://metorik.com" + }, + { + "name": "Bryce Adams", + "email": "bryce@metorik.com" + }, + { + "name": "Joey Kudish", + "email": "joey@metorik.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/metorikhq/metorik-helper/graphs/contributors" + } + ], + "require-dev": { + "dingo-d/wp-pest": "^2.0.0-alpha" + }, + "minimum-stability": "dev", + "config": { + "sort-packages": true, + "optimize-autoloader": true, + "allow-plugins": { + "composer/installers": true, + "pestphp/pest-plugin": true + } + }, + "scripts": { + "test:unit": "@php ./vendor/bin/pest --group=unit", + "test:integration": "@php ./vendor/bin/pest --group=integration" + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "support": { + "issues": "https://github.com/metorikhq/metorik-helper/issues", + "wiki": "https://help.metorik.com/", + "source": "https://github.com/metorikhq/metorik-helper" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..ef65e82 --- /dev/null +++ b/composer.lock @@ -0,0 +1,4892 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b91428a6278ffb06a59e69fb41b1ff96", + "packages": [], + "packages-dev": [ + { + "name": "aaemnnosttv/wp-sqlite-db", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/aaemnnosttv/wp-sqlite-db.git", + "reference": "1c52157e2e75693efc94fcd7a9ac36bf5d2f6012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aaemnnosttv/wp-sqlite-db/zipball/1c52157e2e75693efc94fcd7a9ac36bf5d2f6012", + "reference": "1c52157e2e75693efc94fcd7a9ac36bf5d2f6012", + "shasum": "" + }, + "require": { + "composer/installers": "^1.0 || ^2.0", + "ext-pdo": "*", + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6 || ^7 || ^8 || ^9", + "roots/wordpress": "^6", + "wp-cli/core-command": "^2", + "wp-phpunit/wp-phpunit": "^6", + "yoast/phpunit-polyfills": "^1" + }, + "type": "wordpress-dropin", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Evan Mattson", + "email": "me@aaemnnost.tv", + "role": "Developer" + }, + { + "name": "Kojima Toshiyasu", + "homepage": "https://profiles.wordpress.org/kjmtsh", + "role": "Author of SQLite Integration" + } + ], + "description": "SQLite drop-in database driver for WordPress", + "support": { + "issues": "https://github.com/aaemnnosttv/wp-sqlite-db/issues", + "source": "https://github.com/aaemnnosttv/wp-sqlite-db/tree/v1.3.1" + }, + "time": "2023-02-05T16:42:38+00:00" + }, + { + "name": "antecedent/patchwork", + "version": "2.1.28", + "source": { + "type": "git", + "url": "https://github.com/antecedent/patchwork.git", + "reference": "6b30aff81ebadf0f2feb9268d3e08385cebcc08d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/6b30aff81ebadf0f2feb9268d3e08385cebcc08d", + "reference": "6b30aff81ebadf0f2feb9268d3e08385cebcc08d", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "homepage": "https://antecedent.github.io/patchwork/", + "keywords": [ + "aop", + "aspect", + "interception", + "monkeypatching", + "redefinition", + "runkit", + "testing" + ], + "support": { + "issues": "https://github.com/antecedent/patchwork/issues", + "source": "https://github.com/antecedent/patchwork/tree/2.1.28" + }, + "time": "2024-02-06T09:26:11+00:00" + }, + { + "name": "brain/monkey", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Brain-WP/BrainMonkey.git", + "reference": "560355db29e7acef0a9f2ae591dbd4e9bf590b50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Brain-WP/BrainMonkey/zipball/560355db29e7acef0a9f2ae591dbd4e9bf590b50", + "reference": "560355db29e7acef0a9f2ae591dbd4e9bf590b50", + "shasum": "" + }, + "require": { + "antecedent/patchwork": "^2.1.17", + "mockery/mockery": "^1.3.5 || ^1.4.4", + "php": ">=5.6.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", + "phpcompatibility/php-compatibility": "^9.3.0", + "phpunit/phpunit": "^5.7.26 || ^6.0 || ^7.0 || >=8.0 <8.5.12 || ^8.5.14 || ^9.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-version/1": "1.x-dev", + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "inc/api.php" + ], + "psr-4": { + "Brain\\Monkey\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Giuseppe Mazzapica", + "email": "giuseppe.mazzapica@gmail.com", + "homepage": "https://gmazzap.me", + "role": "Developer" + } + ], + "description": "Mocking utility for PHP functions and WordPress plugin API", + "keywords": [ + "Monkey Patching", + "interception", + "mock", + "mock functions", + "mockery", + "patchwork", + "redefinition", + "runkit", + "test", + "testing" + ], + "support": { + "issues": "https://github.com/Brain-WP/BrainMonkey/issues", + "source": "https://github.com/Brain-WP/BrainMonkey" + }, + "time": "2024-03-05T08:04:04+00:00" + }, + { + "name": "brianium/paratest", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "551f46f52a93177d873f3be08a1649ae886b4a30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/551f46f52a93177d873f3be08a1649ae886b4a30", + "reference": "551f46f52a93177d873f3be08a1649ae886b4a30", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^0.5.1 || ^1.0.0", + "jean85/pretty-package-versions": "^2.0.5", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "phpunit/php-code-coverage": "^10.1.7", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-timer": "^6.0", + "phpunit/phpunit": "^10.4.2", + "sebastian/environment": "^6.0.1", + "symfony/console": "^6.3.4 || ^7.0.0", + "symfony/process": "^6.3.4 || ^7.0.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "infection/infection": "^0.27.6", + "phpstan/phpstan": "^1.10.40", + "phpstan/phpstan-deprecation-rules": "^1.1.4", + "phpstan/phpstan-phpunit": "^1.3.15", + "phpstan/phpstan-strict-rules": "^1.5.2", + "squizlabs/php_codesniffer": "^3.7.2", + "symfony/filesystem": "^6.3.1 || ^7.0.0" + }, + "bin": [ + "bin/paratest", + "bin/paratest.bat", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2023-10-31T09:24:17+00:00" + }, + { + "name": "composer/installers", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "2a9170263fcd9cc4fd0b50917293c21d6c1a5bfe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/2a9170263fcd9cc4fd0b50917293c21d6c1a5bfe", + "reference": "2a9170263fcd9cc4fd0b50917293c21d6c1a5bfe", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "composer/composer": "1.6.* || ^2.0", + "composer/semver": "^1 || ^3", + "phpstan/phpstan": "^0.12.55", + "phpstan/phpstan-phpunit": "^0.12.16", + "symfony/phpunit-bridge": "^5.3", + "symfony/process": "^5" + }, + "default-branch": true, + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-main": "2.x-dev" + }, + "plugin-modifies-install-path": true + }, + "autoload": { + "psr-4": { + "Composer\\Installers\\": "src/Composer/Installers" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "https://composer.github.io/installers/", + "keywords": [ + "Dolibarr", + "Eliasis", + "Hurad", + "ImageCMS", + "Kanboard", + "Lan Management System", + "MODX Evo", + "MantisBT", + "Mautic", + "Maya", + "OXID", + "Plentymarkets", + "Porto", + "RadPHP", + "SMF", + "Starbug", + "Thelia", + "Whmcs", + "WolfCMS", + "agl", + "annotatecms", + "attogram", + "bitrix", + "cakephp", + "chef", + "cockpit", + "codeigniter", + "concrete5", + "croogo", + "dokuwiki", + "drupal", + "eZ Platform", + "elgg", + "expressionengine", + "fuelphp", + "grav", + "installer", + "itop", + "known", + "kohana", + "laravel", + "lavalite", + "lithium", + "magento", + "majima", + "mako", + "matomo", + "mediawiki", + "miaoxing", + "modulework", + "modx", + "moodle", + "osclass", + "pantheon", + "phpbb", + "piwik", + "ppi", + "processwire", + "puppet", + "pxcms", + "reindex", + "roundcube", + "shopware", + "silverstripe", + "sydes", + "sylius", + "tastyigniter", + "wordpress", + "yawik", + "zend", + "zikula" + ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/main" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-10-12T12:07:30+00:00" + }, + { + "name": "dingo-d/wp-pest", + "version": "2.0.0-alpha", + "source": { + "type": "git", + "url": "https://github.com/dingo-d/wp-pest.git", + "reference": "e265c4232027802040b39798faab5812262bcdbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dingo-d/wp-pest/zipball/e265c4232027802040b39798faab5812262bcdbd", + "reference": "e265c4232027802040b39798faab5812262bcdbd", + "shasum": "" + }, + "require": { + "aaemnnosttv/wp-sqlite-db": "^1.3", + "ext-json": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^7.4", + "pestphp/pest": "^2.18.0", + "php": "^8.1", + "symfony/filesystem": "^6.3", + "yoast/wp-test-utils": "dev-JRF/update-for-polyfills-2.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^v1.0.0", + "phpcompatibility/php-compatibility": "^9", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-symfony": "^1.3", + "squizlabs/php_codesniffer": "^3.7.0", + "zenstruck/console-test": "^v1.4.0" + }, + "bin": [ + "bin/wp-pest" + ], + "type": "library", + "autoload": { + "psr-4": { + "MadeByDenis\\WpPestIntegrationTestSetup\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Denis Žoljom", + "email": "denis.zoljom@gmail.com" + } + ], + "description": "A package that will add WordPress integration test suite with Pest framework", + "keywords": [ + "framework", + "integration", + "pest", + "php", + "test", + "testing", + "wordpress" + ], + "support": { + "issues": "https://github.com/dingo-d/wp-pest/issues", + "source": "https://github.com/dingo-d/wp-pest/tree/2.0.0-alpha" + }, + "time": "2023-09-20T09:02:07+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-02-07T09:43:46+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.15.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2023-11-03T12:00:00+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.x-dev", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "default-branch": true, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.x-dev", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "default-branch": true, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "696163addf28bb4e01455254e055a9a75e0ba6c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/696163addf28bb4e01455254e055a9a75e0ba6c4", + "reference": "696163addf28bb4e01455254e055a9a75e0ba6c4", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/master" + }, + "time": "2023-12-14T11:00:58+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "29cc5722729c0916743088fe474b04792a2ae944" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/29cc5722729c0916743088fe474b04792a2ae944", + "reference": "29cc5722729c0916743088fe474b04792a2ae944", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A library to get pretty versions strings of installed dependencies", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.x" + }, + "time": "2024-03-17T17:58:00+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.7.x-dev", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "3f8d3ff1ffe4c552d45c5690c6d825e9310769bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/3f8d3ff1ffe4c552d45c5690c6d825e9310769bf", + "reference": "3f8d3ff1ffe4c552d45c5690c6d825e9310769bf", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": ">=9.6.11 <10.4" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2023-10-01T17:31:30+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "2f5294676c802a62b0549f6bc8983f14294ce369" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/2f5294676c802a62b0549f6bc8983f14294ce369", + "reference": "2f5294676c802a62b0549f6bc8983f14294ce369", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "default-branch": true, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-02-10T11:10:03+00:00" + }, + { + "name": "nikic/php-parser", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/46be4560c4cd4bab2b74882c0da39a4548a5cfbe", + "reference": "46be4560c4cd4bab2b74882c0da39a4548a5cfbe", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "default-branch": true, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/master" + }, + "time": "2024-03-17T10:24:36+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v7.x-dev", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.3", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.3.4" + }, + "conflict": { + "laravel/framework": ">=11.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.3.0", + "laravel/framework": "^10.28.0", + "laravel/pint": "^1.13.3", + "laravel/sail": "^1.25.0", + "laravel/sanctum": "^3.3.1", + "laravel/tinker": "^2.8.2", + "nunomaduro/larastan": "^2.6.4", + "orchestra/testbench-core": "^8.13.0", + "pestphp/pest": "^2.23.2", + "phpunit/phpunit": "^10.4.1", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.3.1" + }, + "default-branch": true, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2023-10-11T15:45:01+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "642f96d31019f59573d5c0b92206042cac5a0514" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/642f96d31019f59573d5c0b92206042cac5a0514", + "reference": "642f96d31019f59573d5c0b92206042cac5a0514", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0|^10.0", + "illuminate/support": "^8.0|^9.0|^10.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/1.x" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2023-10-10T08:56:15+00:00" + }, + { + "name": "pestphp/pest", + "version": "2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "d519e40b9541af6618b49773be5aa008d72b6e64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/d519e40b9541af6618b49773be5aa008d72b6e64", + "reference": "d519e40b9541af6618b49773be5aa008d72b6e64", + "shasum": "" + }, + "require": { + "brianium/paratest": "^7.3.1", + "nunomaduro/collision": "^7.10.0|^8.1.1", + "nunomaduro/termwind": "^1.15.1|^2.0.1", + "pestphp/pest-plugin": "^2.1.1", + "pestphp/pest-plugin-arch": "^2.7.0", + "php": "^8.1.0", + "phpunit/phpunit": "^10.5.13" + }, + "conflict": { + "phpunit/phpunit": ">10.5.13", + "sebastian/exporter": "<5.1.0", + "webmozart/assert": "<1.11.0" + }, + "require-dev": { + "pestphp/pest-dev-tools": "^2.16.0", + "pestphp/pest-plugin-type-coverage": "^2.8.1", + "symfony/process": "^6.4.0|^7.0.4" + }, + "default-branch": true, + "bin": [ + "bin/pest" + ], + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Plugins\\Bail", + "Pest\\Plugins\\Cache", + "Pest\\Plugins\\Coverage", + "Pest\\Plugins\\Init", + "Pest\\Plugins\\Environment", + "Pest\\Plugins\\Help", + "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", + "Pest\\Plugins\\Printer", + "Pest\\Plugins\\ProcessIsolation", + "Pest\\Plugins\\Profile", + "Pest\\Plugins\\Retry", + "Pest\\Plugins\\Snapshot", + "Pest\\Plugins\\Verbose", + "Pest\\Plugins\\Version", + "Pest\\Plugins\\Parallel" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php", + "src/Pest.php" + ], + "psr-4": { + "Pest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "The elegant PHP Testing Framework.", + "keywords": [ + "framework", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest/issues", + "source": "https://github.com/pestphp/pest/tree/2.x" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-03-15T21:14:22+00:00" + }, + { + "name": "pestphp/pest-plugin", + "version": "2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin.git", + "reference": "52cfb1311d462ceeb58fc72b24c8b8314afdf7f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/52cfb1311d462ceeb58fc72b24c8b8314afdf7f0", + "reference": "52cfb1311d462ceeb58fc72b24c8b8314afdf7f0", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.0", + "composer-runtime-api": "^2.2.2", + "php": "^8.1" + }, + "conflict": { + "pestphp/pest": "<2.2.3" + }, + "require-dev": { + "composer/composer": "^2.6.6", + "pestphp/pest": "^2.30.0", + "pestphp/pest-dev-tools": "^2.16.0" + }, + "default-branch": true, + "type": "composer-plugin", + "extra": { + "class": "Pest\\Plugin\\Manager" + }, + "autoload": { + "psr-4": { + "Pest\\Plugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest plugin manager", + "keywords": [ + "framework", + "manager", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin/tree/2.x" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-01-05T11:07:45+00:00" + }, + { + "name": "pestphp/pest-plugin-arch", + "version": "2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-arch.git", + "reference": "d23b2d7498475354522c3818c42ef355dca3fcda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/d23b2d7498475354522c3818c42ef355dca3fcda", + "reference": "d23b2d7498475354522c3818c42ef355dca3fcda", + "shasum": "" + }, + "require": { + "nunomaduro/collision": "^7.10.0|^8.1.0", + "pestphp/pest-plugin": "^2.1.1", + "php": "^8.1", + "ta-tikoma/phpunit-architecture-test": "^0.8.4" + }, + "require-dev": { + "pestphp/pest": "^2.33.0", + "pestphp/pest-dev-tools": "^2.16.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Arch\\Plugin" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Arch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Arch plugin for Pest PHP.", + "keywords": [ + "arch", + "architecture", + "framework", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.7.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-01-26T09:46:42+00:00" + }, + { + "name": "phar-io/manifest", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "a0eeab580cbdf4414fef6978732510a36ed0a9d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/a0eeab580cbdf4414fef6978732510a36ed0a9d6", + "reference": "a0eeab580cbdf4414fef6978732510a36ed0a9d6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + }, + "time": "2021-06-25T13:47:51+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.x-dev", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "f359e4f8ef7e9705a3bfea2c6b7df6090bfc5744" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f359e4f8ef7e9705a3bfea2c6b7df6090bfc5744", + "reference": "f359e4f8ef7e9705a3bfea2c6b7df6090bfc5744", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.x" + }, + "time": "2024-03-20T21:40:18+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + }, + "time": "2024-02-23T11:10:43+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.27.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/86e4d5a4b036f8f0be1464522f4c6b584c452757", + "reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.27.0" + }, + "time": "2024-03-21T13:14:53+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "598f700ccfdad63d683ec86e276c7e294a8883c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/598f700ccfdad63d683ec86e276c7e294a8883c4", + "reference": "598f700ccfdad63d683ec86e276c7e294a8883c4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-13T12:30:36+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "ca60822068f8ab8b9cc857fa506a5099c6c07c18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/ca60822068f8ab8b9cc857fa506a5099c6c07c18", + "reference": "ca60822068f8ab8b9cc857fa506a5099c6c07c18", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:12:29+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "9afb552ced751c6c01e0f54ed6155c76c548bf96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/9afb552ced751c6c01e0f54ed6155c76c548bf96", + "reference": "9afb552ced751c6c01e0f54ed6155c76c548bf96", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:13:12+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "c317d65c5650d67de881ca62d21c0db7d80b0616" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/c317d65c5650d67de881ca62d21c0db7d80b0616", + "reference": "c317d65c5650d67de881ca62d21c0db7d80b0616", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:13:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "db15469e18881c5d2b7fcf24d0fd89922d4001b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/db15469e18881c5d2b7fcf24d0fd89922d4001b2", + "reference": "db15469e18881c5d2b7fcf24d0fd89922d4001b2", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:14:24+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.13", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7", + "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-03-12T15:37:41+00:00" + }, + { + "name": "psr/container", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container" + }, + "time": "2023-09-22T11:11:30+00:00" + }, + { + "name": "psr/http-client", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/7037f4b0950474e9d1350e8df89b15f1842085f6", + "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2023-09-22T11:16:44+00:00" + }, + { + "name": "psr/http-message", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2fff79395e71555cadad02394463015450a9147f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2fff79395e71555cadad02394463015450a9147f", + "reference": "2fff79395e71555cadad02394463015450a9147f", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:01:01+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "29dbfc7958b829fb56031dfd02107fa3ca4dd548" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/29dbfc7958b829fb56031dfd02107fa3ca4dd548", + "reference": "29dbfc7958b829fb56031dfd02107fa3ca4dd548", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:02:20+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "8b3986ecfd56c4508ba5905a7de4727a0ab469c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/8b3986ecfd56c4508ba5905a7de4727a0ab469c2", + "reference": "8b3986ecfd56c4508ba5905a7de4727a0ab469c2", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:03:37+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "9d98e1cbe917afaffe1d3afbd486c6c722fb08bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/9d98e1cbe917afaffe1d3afbd486c6c722fb08bb", + "reference": "9d98e1cbe917afaffe1d3afbd486c6c722fb08bb", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:04:30+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "a4702f9eb606338d2bce634ca9935633782e5ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/a4702f9eb606338d2bce634ca9935633782e5ace", + "reference": "a4702f9eb606338d2bce634ca9935633782e5ace", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:05:15+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "fb01f9026246179dbd640be6a2fe95d76d008e38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fb01f9026246179dbd640be6a2fe95d76d008e38", + "reference": "fb01f9026246179dbd640be6a2fe95d76d008e38", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:06:35+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "69e9e6af221a910d572fc107c5a358383922d889" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/69e9e6af221a910d572fc107c5a358383922d889", + "reference": "69e9e6af221a910d572fc107c5a358383922d889", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:07:17+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "83e9f903f06941e784a851ee565f2b60a3408a43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/83e9f903f06941e784a851ee565f2b60a3408a43", + "reference": "83e9f903f06941e784a851ee565f2b60a3408a43", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:07:58+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "6541f1399f09a6674757205c8a5767354f358866" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/6541f1399f09a6674757205c8a5767354f358866", + "reference": "6541f1399f09a6674757205c8a5767354f358866", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:08:32+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e2274576303f7d09f9c281479505b08a52b1a213" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e2274576303f7d09f9c281479505b08a52b1a213", + "reference": "e2274576303f7d09f9c281479505b08a52b1a213", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:09:04+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "24d1bee29be5e78269f35fb762ae7b2330c1b1fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/24d1bee29be5e78269f35fb762ae7b2330c1b1fa", + "reference": "24d1bee29be5e78269f35fb762ae7b2330c1b1fa", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:09:44+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b04fd2a2f80bb15fc61601d6e5c3dd8865078c47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b04fd2a2f80bb15fc61601d6e5c3dd8865078c47", + "reference": "b04fd2a2f80bb15fc61601d6e5c3dd8865078c47", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:11:37+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "530b50542f39dabd1b0f78a317f37deeaf43416b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/530b50542f39dabd1b0f78a317f37deeaf43416b", + "reference": "530b50542f39dabd1b0f78a317f37deeaf43416b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:15:02+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "3e8331d7e9ab5d4901ff754c00b701d7a44620be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3e8331d7e9ab5d4901ff754c00b701d7a44620be", + "reference": "3e8331d7e9ab5d4901ff754c00b701d7a44620be", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/4.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:15:33+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "434676ec33623a6934bd2b6ed09bf823f3f33674" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/434676ec33623a6934bd2b6ed09bf823f3f33674", + "reference": "434676ec33623a6934bd2b6ed09bf823f3f33674", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/4.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-11T06:16:26+00:00" + }, + { + "name": "symfony/console", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/6.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-22T20:27:10+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/2c438b99bb2753c1628c1e6f523991edea5b03a4", + "reference": "2c438b99bb2753c1628c1e6f523991edea5b03a4", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/main" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-02T14:07:37+00:00" + }, + { + "name": "symfony/filesystem", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9919b5509ada52cc7f66f9a35c86a4a29955c9d3", + "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/6.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-03-21T19:36:20+00:00" + }, + { + "name": "symfony/finder", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/6.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-10-31T17:30:12+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "e5e7ddb00b859dbdf5ad8f3bbe4cd29a3a37aa34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e5e7ddb00b859dbdf5ad8f3bbe4cd29a3a37aa34", + "reference": "e5e7ddb00b859dbdf5ad8f3bbe4cd29a3a37aa34", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/1.x" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-03-14T13:49:05+00:00" + }, + { + "name": "symfony/process", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "710e27879e9be3395de2b98da3f52a946039f297" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297", + "reference": "710e27879e9be3395de2b98da3f52a946039f297", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/6.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-20T12:31:00+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", + "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/main" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-02T14:07:37+00:00" + }, + { + "name": "symfony/string", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/6.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-01T13:16:41+00:00" + }, + { + "name": "ta-tikoma/phpunit-architecture-test", + "version": "0.8.4", + "source": { + "type": "git", + "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18.0 || ^5.0.0", + "php": "^8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0", + "symfony/finder": "^6.4.0 || ^7.0.0" + }, + "require-dev": { + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.52" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPUnit\\Architecture\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ni Shi", + "email": "futik0ma011@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Methods for testing application architecture", + "keywords": [ + "architecture", + "phpunit", + "stucture", + "test", + "testing" + ], + "support": { + "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.4" + }, + "time": "2024-01-05T14:10:56+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "yoast/phpunit-polyfills", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", + "reference": "c758753e8f9dac251fed396a73c8305af3f17922" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/c758753e8f9dac251fed396a73c8305af3f17922", + "reference": "c758753e8f9dac251fed396a73c8305af3f17922", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0" + }, + "require-dev": { + "yoast/yoastcs": "^2.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "files": [ + "phpunitpolyfills-autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Team Yoast", + "email": "support@yoast.com", + "homepage": "https://yoast.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors" + } + ], + "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills", + "keywords": [ + "phpunit", + "polyfill", + "testing" + ], + "support": { + "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "source": "https://github.com/Yoast/PHPUnit-Polyfills" + }, + "time": "2023-06-06T20:28:24+00:00" + }, + { + "name": "yoast/wp-test-utils", + "version": "dev-JRF/update-for-polyfills-2.0", + "source": { + "type": "git", + "url": "https://github.com/Yoast/wp-test-utils.git", + "reference": "04d0e29b0373da159deeafb1c30764da2e1318cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Yoast/wp-test-utils/zipball/04d0e29b0373da159deeafb1c30764da2e1318cd", + "reference": "04d0e29b0373da159deeafb1c30764da2e1318cd", + "shasum": "" + }, + "require": { + "brain/monkey": "^2.6.1", + "php": ">=5.6", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0" + }, + "require-dev": { + "yoast/yoastcs": "^2.3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "1.x-dev", + "dev-main": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "exclude-from-classmap": [ + "/src/WPIntegration/TestCase.php", + "/src/WPIntegration/TestCaseNoPolyfills.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Team Yoast", + "email": "support@yoast.com", + "homepage": "https://yoast.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Yoast/wp-test-utils/graphs/contributors" + } + ], + "description": "PHPUnit cross-version compatibility layer for testing plugins and themes build for WordPress", + "homepage": "https://github.com/Yoast/wp-test-utils/", + "keywords": [ + "brainmonkey", + "integration-testing", + "phpunit", + "testing", + "unit-testing", + "wordpress" + ], + "support": { + "issues": "https://github.com/Yoast/wp-test-utils/issues", + "source": "https://github.com/Yoast/wp-test-utils" + }, + "time": "2023-09-27T10:30:09+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/gulpfile.js b/gulpfile.js index 6839e92..abdb5b5 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,9 +6,10 @@ var uglify = require('gulp-uglify'); var jsDest = 'assets/js'; gulp.task('magic', function () { - return gulp.src(['assets/js/src/sourcebuster.js', 'assets/js/src/tippy.min.js', 'assets/js/src/metorik.js']) + return gulp + .src(['assets/js/src/sourcebuster.js', 'assets/js/src/tippy.min.js', 'assets/js/src/metorik.js']) .pipe(concat('metorik.min.js')) .pipe(gulp.dest(jsDest)) .pipe(uglify()) .pipe(gulp.dest(jsDest)); -}); \ No newline at end of file +}); diff --git a/inc/admin-ui.php b/inc/admin-ui.php new file mode 100644 index 0000000..783ed07 --- /dev/null +++ b/inc/admin-ui.php @@ -0,0 +1,176 @@ +'; + + foreach ( $ids as $id ) { + echo ' + #' . $id . ' button { display: none; } + #' . $id . ' h2 { display: none; } + #' . $id . ' .postbox-header { border-bottom: none; } + #' . $id . ' .inside { padding: 0; margin: 0; } + #' . $id . ' .inside a { display: block; font-weight: bold; padding: 12px; text-decoration: none; vertical-align: middle; } + #' . $id . ' .inside a:hover { background: #fafafa; } + #' . $id . ' .inside a img { display: inline-block; margin: -4px 5px 0 0; vertical-align: middle; width: 20px; } + #' . $id . ' .inside a span { float: right; } + '; + } + + echo '.metorik-notice.notice button.notice-dismiss { display: none; }'; + echo '.metorik-notice.notice a.notice-dismiss { text-decoration: none; }'; + + echo ''; + } + + /** + * Register Metorik meta boxes + * + * @return void + */ + public function register_meta_boxes() { + $orderScreen = class_exists( \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class ) && wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() + ? wc_get_page_screen_id( 'shop-order' ) + : 'shop_order'; + + add_meta_box( 'metorik-product-box', __( 'Metorik', 'metorik' ), [ + $this, + 'product_box_display' + ], 'product', 'side', 'high' ); + add_meta_box( 'metorik-order-box', __( 'Metorik', 'metorik' ), [ + $this, + 'order_box_display' + ], $orderScreen, 'side', 'high' ); + + $subscriptionScreen = class_exists( \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class ) && wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() + ? wc_get_page_screen_id( 'shop-subscription' ) + : 'shop_subscription'; + + if ( $subscriptionScreen ) { + add_meta_box( 'metorik-subscription-box', __( 'Metorik', 'metorik' ), [ + $this, + 'subscription_box_display' + ], $subscriptionScreen, 'side', 'high' ); + } + } + + /** + * Product meta box + * + * @param WP_Post $post + * + * @return void + */ + public function product_box_display( $post ) { + $shopUrl = str_replace( [ 'http://', 'https://' ], '', home_url() ); + echo ' + View in Metorik + '; + } + + /** + * Order meta box + * + * @param WP_Post $post + * + * @return void + */ + public function order_box_display( $post ) { + $orderID = ( $post instanceof WP_Post ) ? $post->ID : $post->get_id(); + $shopUrl = str_replace( [ 'http://', 'https://' ], '', home_url() ); + + echo ' + View in Metorik + '; + } + + /** + * Subscription meta box + * + * @param WP_Post $post + * + * @return void + */ + public function subscription_box_display( $post ) { + $orderID = ( $post instanceof WP_Post ) ? $post->ID : $post->get_id(); + $shopUrl = str_replace( [ 'http://', 'https://' ], '', home_url() ); + + echo ' + View in Metorik + '; + } + + /** + * Add column header to users table + * + * @param array $columns + * + * @return array the columns + */ + public function modify_user_table( $columns ) { + $columns['metorik'] = 'Metorik'; + + return $columns; + } + + /** + * Add column body to users table. + * + * @param string $val the column value + * @param string $column_name the column name + * @param int $user_id the user ID for the row + * + * @return string the column value + */ + public function add_user_table_column( $val, $column_name, $user_id ) { + if ( $column_name !== 'metorik' ) { + return $val; + } + + $shopUrl = str_replace( [ 'http://', 'https://' ], '', home_url() ); + $metorikUrl = 'https://app.metorik.com/woo-admin-link?resource=customers&shop=' . $shopUrl . '&id=' . $user_id; + + return 'View'; + } +} + +new Metorik_Admin_UI(); diff --git a/inc/api/customers.php b/inc/api/customers.php index 2463bdd..b56ccd7 100755 --- a/inc/api/customers.php +++ b/inc/api/customers.php @@ -163,7 +163,7 @@ public function customers_ids_callback() " SELECT user_id FROM $wpdb->usermeta - WHERE meta_key = 'wp_capabilities' + WHERE meta_key = 'wp_capabilities' AND meta_value LIKE '%customer%' " ); @@ -261,15 +261,15 @@ public function customers_updated_callback($request) // Query $customers = $wpdb->get_results($wpdb->prepare( " - SELECT + SELECT a.user_id as id, b.meta_value as last_updated FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b ON b.user_id = a.user_id AND b.meta_key = 'last_update' - AND b.meta_value > %d - WHERE a.meta_key = %s + AND b.meta_value > %s + WHERE a.meta_key = %s LIMIT %d, %d ", array( @@ -283,12 +283,12 @@ public function customers_updated_callback($request) // Not multisite $customers = $wpdb->get_results($wpdb->prepare( " - SELECT + SELECT user_id as id, meta_value as last_updated FROM $wpdb->usermeta - WHERE meta_key = 'last_update' - AND meta_value > %d + WHERE meta_key = 'last_update' + AND meta_value > %s LIMIT %d, %d ", array( diff --git a/inc/api/metorik.php b/inc/api/metorik.php index f782fa9..798ad87 100755 --- a/inc/api/metorik.php +++ b/inc/api/metorik.php @@ -187,14 +187,14 @@ public function update_metorik_auth_callback($request) /* * Update token. */ - update_option('metorik_auth_token', $token); + update_option( Metorik_Cart_Tracking::AUTH_TOKEN_OPTION, $token); /** * Prepare response. */ $data = array( 'updated' => true, - 'token' => get_option('metorik_auth_token'), + 'token' => Metorik_Cart_Tracking::get_auth_token(), ); /** diff --git a/inc/cart-data.php b/inc/cart-data.php new file mode 100755 index 0000000..782492d --- /dev/null +++ b/inc/cart-data.php @@ -0,0 +1,442 @@ +cart = WC()->cart->get_cart(); + $this->determine_customer_data(); + } + + public function determine_customer_data() { + $this->determine_customer_id(); + $this->determine_email(); + $this->determine_name(); + $this->determine_phone(); + } + + public function determine_customer_id() { + if ( is_user_logged_in() ) { + $this->customer_id = get_current_user_id(); + } elseif ( ! empty( WC()->session->get( 'customer' ) ) + && isset( WC()->session->get( 'customer' )['id'] ) + && absint( WC()->session->get( 'customer' )['id'] ) > 0 + ) { + $this->customer_id = absint( WC()->session->get( 'customer' )['id'] ); + } + } + + public function determine_email() { + if ( ! empty( WC()->customer ) + && is_email( WC()->customer->get_billing_email() ) + ) { + $this->email = sanitize_email( WC()->customer->get_billing_email() ); + } elseif ( ! empty( WC()->customer ) + && is_email( WC()->customer->get_email() ) + ) { + $this->email = sanitize_email( WC()->customer->get_email() ); + } elseif ( is_user_logged_in() && is_email( wp_get_current_user()->user_email ) ) { + $this->email = sanitize_email( wp_get_current_user()->user_email ); + } elseif ( ! empty( $_POST['email'] ) && is_email( $_POST['email'] ) ) { + $this->email = sanitize_email( $_POST['email'] ); + } + } + + public function determine_name() { + if ( ! empty( WC()->customer ) + && ! empty( WC()->customer->get_billing_first_name() ) + ) { + $this->name = WC()->customer->get_billing_first_name(); + } elseif ( ! empty( $_POST['first_name'] ) ) { + $this->name = sanitize_text_field( $_POST['first_name'] ); + } elseif ( is_user_logged_in() ) { + $this->name = wp_get_current_user()->first_name; + } + } + + public function determine_phone() { + if ( ! empty( WC()->customer ) + && ! empty( WC()->customer->get_billing_phone() ) + ) { + $this->phone = sanitize_text_field( WC()->customer->get_billing_phone() ); + } elseif ( ! empty( $_POST['phone'] ) ) { + $this->phone = sanitize_text_field( $_POST['phone'] ); + } + } + + public function to_array() { + if ( $this->cart_is_empty() ) { + return [ + 'token' => $this->get_cart_token(), + 'cart' => false, + ]; + } + + // ensure we have the latest customer data + $this->determine_customer_data(); + + return [ + 'token' => $this->get_cart_token(), + 'cart' => $this->cart, + 'started_at' => current_time( 'timestamp', true ), // utc timestamp + 'total' => $this->get_cart_total(), + 'subtotal' => $this->get_cart_subtotal(), + 'total_tax' => $this->get_cart_tax(), + 'total_discount' => $this->get_cart_discount(), + 'total_shipping' => $this->get_cart_shipping(), + 'total_fee' => $this->get_cart_fee(), + 'currency' => get_woocommerce_currency(), + 'customer_id' => $this->customer_id, + 'email' => $this->email, + 'name' => $this->name, + 'phone' => $this->phone, + 'locale' => determine_locale(), + 'email_opt_out' => $this->get_customer_email_opt_out(), + 'client_session' => $this->get_client_session_data(), + 'display_prices_including_tax' => WC()->cart->display_prices_including_tax(), + ]; + } + + /** + * Check if the cart is empty. + * + * @return bool + */ + public function cart_is_empty() { + return (bool) WC()->cart->is_empty(); + } + + /** + * Get the cart hash. + * Hash is composed of everything we would send to metorik + * except for the 'started_at' timestamp (since that is always set to now) + * This is used to determine if the cart data has changed since the last time we sent it + * + * @return string $hash + */ + public function get_hash() { + $cart_data_for_hash = $this->to_array(); + if ( isset( $cart_data_for_hash['started_at'] ) ) { + unset( $cart_data_for_hash['started_at'] ); + } + + return md5( json_encode( $cart_data_for_hash ) ); + } + + + /** + * Get the last cart hash that was sent to Metorik. + * This is stored in the WC session. + * + * @return null|string $hash The last cart hash or null if not set + */ + public function get_last_hash() { + return WC()->session->get( self::LAST_CART_HASH ); + } + + /** + * Save the current hash as the last hash. + * This is stored in the WC session. + * + * @return void + */ + public function save_last_hash() { + WC()->session->set( self::LAST_CART_HASH, $this->get_hash() ); + } + + + /** + * Get (and generate/set if needed) the cart token. + * The token is stored in the WC session + * If a user is logged in, it's also stored in user meta. + * + * @param int|bool $user_id + * + * @return string $token + */ + public function get_cart_token( $user_id = false ) { + $user_id = $user_id ?: get_current_user_id(); + $token = null; + $from_user_meta = false; + + if ( ! empty( $user_id ) ) { + $token = get_user_meta( $user_id, '_metorik_cart_token', true ); + $from_user_meta = true; + } + + if ( empty( $token ) && WC()->session ) { + $token = WC()->session->get( 'metorik_cart_token' ); + } + + if ( empty( $token ) ) { + $token = $this->generate_cart_token(); + } + + if ( ! empty( $user_id ) && ! $from_user_meta ) { + update_user_meta( $user_id, '_metorik_cart_token', $token ); + } + + WC()->session->set( 'metorik_cart_token', $token ); + + return $token; + } + + /** + * Generate a cart token. + * @return string $token + */ + public function generate_cart_token() { + // Generate a cart token (md5 of current time & random number). + return md5( time() . rand( 100, 10000 ) ); + } + + + /** + * Return if a user has seen the add to cart form before. + * + * @return bool + */ + public static function user_has_seen_add_to_cart_form() { + return (bool) ( WC()->session ) ? WC()->session->get( 'metorik_seen_add_to_cart_form', false ) : false; + } + + /** + * Set the add cart form to having been 'seen' in the session. + * + * @return void + */ + public static function set_user_has_seen_add_to_cart_form() { + WC()->session->set( 'metorik_seen_add_to_cart_form', true ); + } + + /** + * Get the customer email opt out setting. + * + * @param int|null $user_id optional user ID, otherwise will check session + * + * @return bool is the user opted out + */ + public static function get_customer_email_opt_out( $user_id = null ) { + $user_id = $user_id ?: get_current_user_id(); + $opt_out = false; + + if ( ! empty( $user_id ) ) { + $opt_out = get_user_meta( $user_id, '_metorik_customer_email_opt_out', true ); + } + + if ( empty( $token ) && WC()->session ) { + $opt_out = WC()->session->get( 'metorik_customer_email_opt_out' ); + } + + return (bool) $opt_out; + } + + /** + * Set the customer email opt out setting. + * + * @param bool $opt_out defaults to true + * + * @return bool the opt out setting + */ + public static function set_customer_email_opt_out( $opt_out = true ) { + WC()->session->set( 'metorik_customer_email_opt_out', $opt_out ); + + if ( $user_id = get_current_user_id() ) { + update_user_meta( $user_id, '_metorik_customer_email_opt_out', $opt_out ); + } + + return $opt_out; + } + + /** + * Get the customer email opt in setting. + * + * @param int|null $user_id optional user ID, otherwise will check session + * + * @return bool is the user opted out + */ + public static function get_customer_email_opt_in( $user_id = null ) { + return (bool) ! self::get_customer_email_opt_out( $user_id ); + } + + /** + * Set the customer email opt in setting. + * + * @param bool $opt_in defaults to true + * + * @return bool the opt in setting + */ + public static function set_customer_email_opt_in( $opt_in = true ) { + return self::set_customer_email_opt_out( ! $opt_in ); + } + + /** + * Cart total. + * If we're on a checkout page, WC will have calculated it already + * Otherwise, we need to get the calculation directly + * + * @return float $total + */ + protected function get_cart_total() { + if ( + is_checkout() || + is_cart() || + defined( 'WOOCOMMERCE_CHECKOUT' ) || + defined( 'WOOCOMMERCE_CART' ) + ) { + return (float) WC()->cart->total; + } else { + return (float) WC()->cart->get_total( false ); + } + } + + /** + * Get the cart subtotal (maybe inclusive of taxes). + * + * @return float $subtotal + */ + public function get_cart_subtotal() { + if ( 'excl' === WC()->cart->display_prices_including_tax() ) { + $subtotal = WC()->cart->subtotal_ex_tax; + } else { + $subtotal = WC()->cart->subtotal; + } + + return (float) $subtotal; + } + + /** + * Get the cart tax. + * + * @return float $tax + */ + public function get_cart_tax() { + return WC()->cart->get_total_tax(); + } + + /** + * Get the cart discount (maybe inclusive of taxes). + * + * @return float $discount + */ + public function get_cart_discount() { + $discount_total = WC()->cart->get_discount_total(); + $discount_tax = WC()->cart->get_discount_tax(); + + if ( 'excl' === WC()->cart->display_prices_including_tax() ) { + return $discount_total; + } else { + return $discount_total + $discount_tax; + } + } + + /** + * Get the cart shipping (maybe inclusive of taxes). + * + * @return float $shipping + */ + public function get_cart_shipping() { + $shipping_total = WC()->cart->get_shipping_total(); + $shipping_tax = WC()->cart->get_shipping_tax(); + + if ( 'excl' === WC()->cart->display_prices_including_tax() ) { + return $shipping_total; + } else { + return $shipping_total + $shipping_tax; + } + } + + /** + * Get the cart fee (maybe inclusive of taxes). + * + * @return float $fee + */ + public function get_cart_fee() { + $fee_total = (float) WC()->cart->get_fee_total(); + $fee_tax = (float) WC()->cart->get_fee_tax(); + + if ( 'excl' === WC()->cart->display_prices_including_tax() ) { + return $fee_total; + } else { + return $fee_total + $fee_tax; + } + } + + /** + * Get data about the client's current session - eg. coupons, shipping. + * + * @return array $session_data + */ + public function get_client_session_data() { + // No session? Stop + if ( ! WC()->session ) { + return; + } + + return [ + 'applied_coupons' => WC()->session->get( 'applied_coupons' ), + 'chosen_shipping_methods' => WC()->session->get( 'chosen_shipping_methods' ), + 'shipping_method_counts' => WC()->session->get( 'shipping_method_counts' ), + 'chosen_payment_method' => WC()->session->get( 'chosen_payment_method' ), + ]; + } + + /** + * Check if the cart is pending recovery. + * + * @param int|null $user_id + * + * @return bool + */ + public static function cart_is_pending_recovery( $user_id = null ) { + $user_id = $user_id ?: get_current_user_id(); + $pending_recovery = false; + + if ( ! empty( $user_id ) ) { + $pending_recovery = get_user_meta( $user_id, '_metorik_pending_recovery', true ); + } + + if ( empty( $pending_recovery ) && WC()->session ) { + $pending_recovery = WC()->session->get( 'metorik_pending_recovery' ); + } + + return (bool) $pending_recovery; + } + + /** + * Get a cart setting + * The settings are stored as a JSON string in the metorik_cart_settings option + * See api/metorik.php for more info + * + * @param string $key + * + * @return mixed + */ + public static function get_cart_setting( $key = false, $default = false ) { + $settings = get_option( 'metorik_cart_settings' ); + + // no key defined or settings saved? default + if ( ! $key || ! $settings ) { + return $default; + } + + // json decode + $settings = json_decode( $settings ); + + // not set? default + if ( ! isset( $settings->$key ) ) { + return $default; + } + + return $settings->$key; + } +} diff --git a/inc/cart-recovery.php b/inc/cart-recovery.php new file mode 100755 index 0000000..4da44ac --- /dev/null +++ b/inc/cart-recovery.php @@ -0,0 +1,381 @@ + 'GET', + 'callback' => [ $this, 'recover_cart_callback' ], + 'permission_callback' => '__return_true', + ] ); + } + + /** + * API route callback for recovering a cart. + * This is the endpoint that the recovery link will hit. + * It will restore the cart and redirect to the checkout page. + * It will also apply a coupon if one is provided in the URL. + * + * @param WP_REST_Request $request + * + * @return void + */ + public function recover_cart_callback( $request ) { + // bail if no token + $cart_token = isset( $request['token'] ) ? $request['token'] : null; + if ( empty( $cart_token ) ) { + return; + } + + // cart start + $this->check_prerequisites(); + + // set the checkout URL to use + $checkout_url = $this->get_checkout_url(); + + // forward along any UTM or metorik params or lang + foreach ( $request->get_params() as $key => $val ) { + if ( 0 === strpos( $key, 'utm_' ) || 0 === strpos( $key, 'mtk' ) || 0 === strpos( $key, 'lang' ) ) { + $checkout_url = add_query_arg( $key, $val, $checkout_url ); + } + } + + // no session? start so cart/notices work + if ( ! WC()->session->has_session() ) { + WC()->session->set_customer_session_cookie( true ); + } + + // try to restore the cart + try { + $this->restore_cart( $cart_token ); + + // check for coupon in recovery URL to apply before checkout redirect + if ( isset( $request['coupon'] ) && $coupon = rawurldecode( $request['coupon'] ) ) { + $checkout_url = add_query_arg( array( 'coupon' => wc_clean( $coupon ) ), $checkout_url ); + } + } catch ( Exception $e ) { + // add a notice + wc_add_notice( __( 'Sorry, we were not able to restore your cart. Please try adding your items to your cart again.', 'metorik' ), 'error' ); + } + + // redirect to the checkout url + wp_safe_redirect( $checkout_url ); + exit; + } + + /** + * Check any prerequisites required for our add to cart request. + * + * @return void + */ + private function check_prerequisites() { + if ( defined( 'WC_ABSPATH' ) ) { + // WC 3.6+ - Cart and notice functions are not included during a REST request. + include_once WC_ABSPATH . 'includes/wc-cart-functions.php'; + include_once WC_ABSPATH . 'includes/wc-notice-functions.php'; + } + + if ( null === WC()->session ) { + $session_class = apply_filters( 'woocommerce_session_handler', 'WC_Session_Handler' ); + + // Prefix session class with global namespace if not already namespaced + if ( false === strpos( $session_class, '\\' ) ) { + $session_class = '\\' . $session_class; + } + + WC()->session = new $session_class(); + WC()->session->init(); + } + + if ( null === WC()->customer ) { + WC()->customer = new \WC_Customer( get_current_user_id(), true ); + } + + if ( null === WC()->cart ) { + WC()->cart = new \WC_Cart(); + + // We need to force a refresh of the cart contents from session here (cart contents are normally refreshed on wp_loaded, which has already happened by this point). + WC()->cart->get_cart(); + } + } + + /** + * Determine the checkout URL to use + * + * @param WP_REST_Request|null $request the request object + * + * @return string the checkout URL + */ + public function get_checkout_url( $request = null ) { + // default + $checkout_url = wc_get_checkout_url(); + + // override via settings + $override_checkout_url = get_option( 'metorik_checkout_url' ); + if ( ! empty( $override_checkout_url ) ) { + $checkout_url = $override_checkout_url; + } + + // override via request + $redirect_url = isset( $request['redirect_url'] ) ? $request['redirect_url'] : null; + if ( ! empty( $redirect_url ) ) { + $checkout_url = $redirect_url; + } + + return apply_filters( 'metorik_recover_cart_url', $checkout_url ); + } + + /** + * Given a Cart Token, restore the cart from Metorik's API and put it back into the session. + * + * @param string $cart_token + * + * @return void + */ + public function restore_cart( $cart_token ) { + $auth_token = Metorik_Cart_Tracking::get_auth_token(); + if ( empty( $auth_token ) ) { + throw new Exception( 'Missing Metorik authentication token' ); + } + + // get cart + $response = wp_remote_get( Metorik_Cart_Tracking::metorik_api_url() . '/external/carts', array( + 'body' => array( + 'api_token' => $auth_token, + 'cart_token' => $cart_token, + ), + ) ); + + // Error during response? + if ( is_wp_error( $response ) ) { + throw new Exception( 'Error getting cart from Metorik' ); + } + + $body = wp_remote_retrieve_body( $response ); + + // no response body/cart? + if ( ! $body ) { + throw new Exception( 'Error getting cart from Metorik' ); + } + + // json decode + $body = json_decode( $body ); + + // no data/cart? stop + if ( ! isset( $body->data ) || ! isset( $body->data->cart ) ) { + throw new Exception( 'Error getting cart from Metorik' ); + } + + // get cart + $cart = $body->data->cart; + + // need to cast all to an array for putting back into the session + $cart = json_decode( json_encode( $cart ), true ); + + // Clear any existing cart, but don't trigger cart tracking + remove_action( 'woocommerce_cart_emptied', [ Metorik_Cart_Tracking::instance(), 'initiate_sync' ] ); + WC()->cart->empty_cart(); + + // set the variation to an empty array if it doesn't exist + // this is workaround for a php notice that can occur later when Woo pulls the cart + foreach ( $cart as $key => $cart_item ) { + if ( ! isset( $cart_item['variation'] ) ) { + $cart_item['variation'] = []; + $cart[ $key ] = $cart_item; + } + } + + // Restore cart + WC()->session->set( 'cart', $cart ); + + // Set the cart token and pending recovery in session + WC()->session->set( 'metorik_cart_token', $cart_token ); + WC()->session->set( 'metorik_pending_recovery', true ); + + // Set the cart token / pending recovery in user meta if this cart has a user + $user_id = $body->data->customer_id; + if ( $user_id ) { + update_user_meta( $user_id, '_metorik_cart_token', $cart_token ); + update_user_meta( $user_id, '_metorik_pending_recovery', true ); + } + + // restore customer email + if ( ! empty( $body->data->email ) ) { + WC()->customer->set_email( sanitize_email( $body->data->email ) ); + WC()->customer->set_billing_email( sanitize_email( $body->data->email ) ); + } + + // restore customer name + if ( ! empty( $body->data->first_name ) ) { + $first_name = $body->data->first_name; + WC()->customer->set_first_name( sanitize_text_field( $first_name ) ); + WC()->customer->set_billing_first_name( sanitize_text_field( $first_name ) ); + WC()->customer->set_shipping_first_name( sanitize_text_field( $first_name ) ); + } + + // Customer phone + if ( ! empty( $body->data->phone ) ) { + WC()->customer->set_billing_phone( sanitize_text_field( $body->data->phone ) ); + } + + WC()->customer->save(); + + // Client session + $session = $body->data->client_session; + if ( $session ) { + if ( isset( $session->applied_coupons ) ) { + $applied_coupons = (array) $session->applied_coupons; + WC()->session->set( 'applied_coupons', $this->valid_coupons( $applied_coupons ) ); + } + + if ( isset( $session->chosen_shipping_methods ) ) { + $chosen_shipping_methods = (array) $session->chosen_shipping_methods; + WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); + } + + if ( isset( $session->shipping_method_counts ) ) { + $shipping_method_counts = (array) $session->shipping_method_counts; + WC()->session->set( 'shipping_method_counts', $shipping_method_counts ); + } + + if ( isset( $session->chosen_payment_method ) ) { + $chosen_payment_method = $session->chosen_payment_method; + WC()->session->set( 'chosen_payment_method', $chosen_payment_method ); + } + } + + // don't show add to cart restore when cart was recovered + WC()->session->set( 'metorik_seen_add_to_cart_form', true ); + } + + /** + * Maybe apply the recovery coupon provided in the recovery URL. + * + * @return void + */ + public function maybe_apply_cart_recovery_coupon() { + if ( Metorik_Cart_data::cart_is_pending_recovery() && ! empty( $_REQUEST['coupon'] ) ) { + $coupon_code = wc_clean( rawurldecode( $_REQUEST['coupon'] ) ); + + if ( WC()->cart && ! WC()->cart->has_discount( $coupon_code ) ) { + WC()->cart->calculate_totals(); + WC()->cart->add_discount( $coupon_code ); + } + } + } + + + /** + * Checks the validity of coupons that we try to apply to the cart. + * + * @param array $coupons coupons to check + * + * @return array $coupons valid coupons + */ + private function valid_coupons( $coupons = [] ) { + $valid_coupons = []; + if ( empty( $coupons ) ) { + return $valid_coupons; + } + + $discounts = new WC_Discounts( WC()->cart ); + foreach ( $coupons as $coupon_code ) { + $coupon = new WC_Coupon( $coupon_code ); + $valid = $discounts->is_coupon_valid( $coupon ); + + if ( ! $valid ) { + continue; + } + + $valid_coupons[] = $coupon_code; + } + + return $valid_coupons; + } + + /** + * Add a coupon code to the cart session. + * + * @return void + */ + public function add_coupon_code_to_cart_session() { + // Stop if no code in URL + if ( empty( $_GET['mtkc'] ) ) { + return; + } + + // cart start + $this->check_prerequisites(); + + // no session? start so cart/notices work + if ( ! WC()->session || ( WC()->session && ! WC()->session->has_session() ) ) { + WC()->session->set_customer_session_cookie( true ); + } + + // Set code in session + $coupon_code = esc_attr( $_GET['mtkc'] ); + WC()->session->set( 'mtk_coupon', $coupon_code ); + + // If there is an existing non empty cart active session we apply the coupon + if ( WC()->cart && ! WC()->cart->is_empty() && ! WC()->cart->has_discount( $coupon_code ) ) { + WC()->cart->calculate_totals(); + WC()->cart->add_discount( $coupon_code ); + + // Unset the coupon from the session + WC()->session->__unset( 'mtk_coupon' ); + } + } + + /** + * Add the Metorik session coupon code to the cart when adding a product. + * + * @return void + */ + public function add_coupon_code_to_cart() { + $coupon_code = WC()->session ? WC()->session->get( 'mtk_coupon' ) : false; + + // no coupon code? stop + if ( ! $coupon_code || empty( $coupon_code ) ) { + return; + } + + // only if have a cart but not this discount yet + if ( WC()->cart && ! WC()->cart->has_discount( $coupon_code ) ) { + WC()->cart->calculate_totals(); + WC()->cart->add_discount( $coupon_code ); + + // Unset the coupon from the session + WC()->session->__unset( 'mtk_coupon' ); + } + } + + +} + +Metorik_Cart_Recovery::instance(); diff --git a/inc/cart-tracking.php b/inc/cart-tracking.php new file mode 100755 index 0000000..0c72191 --- /dev/null +++ b/inc/cart-tracking.php @@ -0,0 +1,614 @@ +initiate_sync_actions(); + + // Customer login - link existing cart token to user account + add_action( 'wp_login', [ $this, 'link_customer_existing_cart' ], 10, 2 ); + + // Unset cart when order completed + add_action( 'woocommerce_payment_complete', [ $this, 'unset_cart_token' ] ); + add_action( 'woocommerce_thankyou', [ $this, 'unset_cart_token' ] ); + + // Render the add cart email form (that shows up when adding to cart) + add_action( 'wp_footer', [ $this, 'add_cart_email_form' ] ); + + // seen add to cart form + add_action( 'wc_ajax_metorik_seen_add_to_cart_form', [ $this, 'set_seen_add_to_cart_form' ] ); + + // opt out + add_action( 'wc_ajax_metorik_email_opt_out', [ $this, 'opt_out' ] ); + + // opt in + add_action( 'wc_ajax_metorik_email_opt_in', [ $this, 'opt_in' ] ); + + + // ================ + // Blocks Support + // ================ + + // register block checkout fields + add_action( 'woocommerce_blocks_loaded', [ $this, 'register_block_checkout_fields' ] ); + + // Checkout + add_action( 'woocommerce_store_api_checkout_order_processed', [ $this, 'checkout_order_processed' ] ); + + + // ================ + // Legacy (before blocks) Fields & Actions + // ================ + + // Move legacy email checkout field + add_filter( 'woocommerce_checkout_fields', [ $this, 'move_checkout_email_field' ], 5 ); + + // Add usage notice to legacy email field + add_filter( 'woocommerce_form_field_email', [ $this, 'checkout_add_email_usage_notice' ], 100, 2 ); + + // Capture email, name, phone from legacy checkout form + add_action( 'wc_ajax_metorik_capture_customer_data', [ $this, 'capture_customer_data' ] ); + + // Checkout + add_action( 'woocommerce_checkout_order_processed', [ $this, 'checkout_order_processed' ] ); + } + + /** + * Add hooks to WooCommerce events, and trigger a cart sync + * whenever cart is updated (add, remove, update, etc) + * + * @return void + */ + protected function initiate_sync_actions() { + $woo_cart_actions = apply_filters( + 'metorik_initate_cart_sync_events', + [ + 'woocommerce_add_to_cart', + 'woocommerce_applied_coupon', + 'woocommerce_cart_item_removed', + 'woocommerce_cart_item_restored', + 'woocommerce_cart_item_set_quantity', + 'woocommerce_after_calculate_totals', + ] + ); + + foreach ( $woo_cart_actions as $action ) { + add_action( $action, [ $this, 'initiate_sync' ] ); + } + } + + /** + * Get the auth token from the settings + * + * @return string + */ + public static function get_auth_token() { + self::$auth_token = self::$auth_token ?: get_option( self::AUTH_TOKEN_OPTION ); + + return self::$auth_token; + } + + /** + * Reset the static auth token and enabled status + * when the metorik auth token is updated + * + * @return void + */ + public static function reload_auth_token() { + self::$auth_token = null; + self::$enabled = null; + self::$dispatched_sync = false; + } + + /** + * Determine if cart tracking is enabled + * This is determined by the auth token being present + * and can be filtered for finer control + * + * @return bool + */ + public static function cart_tracking_enabled() { + self::$enabled = self::$enabled ?: (bool) self::get_auth_token(); + + return (bool) apply_filters( 'metorik_cart_tracking_enabled', self::$enabled ); + } + + /** + * Get the Metorik API URL + * This can be filtered if needed + * + * @return string + */ + public static function metorik_api_url() { + return apply_filters( 'metorik_carts_api_url', self::API_URL ); + } + + /** + * Initiate a cart sync on cart actions. + * e.g. add to cart, remove from cart, update cart, etc. + * The actual sync happens on shutdown for performance reasons + * + * @return void + */ + public function initiate_sync() { + // stop if already dispatched + if ( self::$dispatched_sync ) { + return; + } + + // stop if metorik cart tracking disabled + if ( ! self::cart_tracking_enabled() ) { + return; + } + + // this will only fire once per page load + add_action( 'shutdown', [ $this, 'sync_cart' ] ); + self::$dispatched_sync = true; + } + + /** + * Sync cart data with Metorik. + * + * @return void + */ + public function sync_cart() { + // stop if metorik cart tracking disabled + if ( ! self::cart_tracking_enabled() ) { + return; + } + + // currently checking out? don't sync + // we don't want to sync the cart when checking out, otherwise we end up with an empty cart sync + // instead, the cart will get updated when the order is synced to Metorik + if ( defined( 'WOOCOMMERCE_CHECKOUT' ) && WOOCOMMERCE_CHECKOUT === true ) { + return; + } + + $cart_data = ( new Metorik_Cart_Data() ); + + // bail if no customer id, no email, and not pending recovery + // since we don't store anonymous carts + // the cart will be rejected at Metorik's end otherwise + if ( empty( $cart_data->customer_id ) + && empty( $cart_data->email ) + && ! $cart_data->cart_is_pending_recovery() + ) { + return; + } + + // don't send if the cart hasn't changed since last hash was sent to metorik + if ( ! empty( $cart_data->get_last_hash() ) && $cart_data->get_last_hash() === $cart_data->get_hash() ) { + return; + } + + $this->send_cart_data( [ + 'api_token' => self::get_auth_token(), + 'data' => $cart_data->to_array(), + ] ); + $cart_data->save_last_hash(); + do_action( 'metorik_synced_cart', $cart_data->to_array() ); + + if ( $cart_data->cart_is_empty() ) { + $this->unset_cart_token(); + } + } + + /** + * Send cart data to Metorik. + * + * @param array $cart_data + * + * @return WP_Error|array + */ + public function send_cart_data( $cart_data ) { + return wp_remote_post( self::metorik_api_url() . '/incoming/carts', [ + 'body' => $cart_data, + ] ); + } + + /** + * Link a customer's existing cart when logging in. + * + * @param string $user_login + * @param WP_User $user + * + * @return void + */ + public function link_customer_existing_cart( $user_login, $user ) { + $session_token = ( WC()->session ) ? WC()->session->get( 'metorik_cart_token' ) : ''; + + // if session token and user, set in user meta + if ( $session_token && $user ) { + update_user_meta( $user->ID, '_metorik_cart_token', $session_token ); + } + + // trigger a sync + $this->initiate_sync(); + } + + /** + * This is called once the checkout has been processed and an order has been created. + * We save the cart token to the order meta so we can link the order to the cart. + * + * @param int $order + * + * @return void + */ + public function checkout_order_processed( $order ) { + // stop if metorik cart tracking disabled + if ( ! self::cart_tracking_enabled() ) { + return; + } + + $cart_data = ( new Metorik_Cart_Data() ); + $cart_token = $cart_data->get_cart_token(); + + // save cart token to order meta + if ( $cart_token ) { + $order = wc_get_order( $order ); + + if ( ! $order instanceof WC_Order ) { + return; + } + + $order->update_meta_data( '_metorik_cart_token', $cart_token ); + $order->save(); + } + + // check if pending recovery - if so, set in order meta + if ( Metorik_Cart_Data::cart_is_pending_recovery() ) { + $this->mark_order_as_recovered( $order ); + } + } + + /** + * Mark an order as recovered by Metorik. + * + * @param int|WC_Order $order will be the order object or order ID + * + * @return void + */ + public function mark_order_as_recovered( $order ) { + $order = $order instanceof WC_Order ? $order : wc_get_order( $order ); + if ( ! $order instanceof WC_Order ) { + return; + } + + $order->update_meta_data( '_metorik_cart_recovered', true ); + $order->add_order_note( __( 'Order cart recovered by Metorik.', 'metorik' ) ); + $order->save(); + } + + /** + * Unset a cart token/recovery status. + * This should be performed when checking out after payment or when a cart is cleared + * + * @return void + */ + public function unset_cart_token() { + if ( WC()->session ) { + unset( WC()->session->metorik_cart_token, WC()->session->metorik_pending_recovery ); + } + + if ( $user_id = get_current_user_id() ) { + delete_user_meta( $user_id, '_metorik_cart_token' ); + delete_user_meta( $user_id, '_metorik_pending_recovery' ); + } + } + + /** + * Register block checkout fields + * + * @return void + * @throws Exception + */ + public function register_block_checkout_fields() { + if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) { + return; + } + + if ( ! apply_filters( 'metorik_cart_tracking_opt_in_checkbox_enabled', Metorik_Cart_Data::get_cart_setting( 'opt_in_checkbox_enabled', true ) ) ) { + return; + } + + woocommerce_register_additional_checkout_field( [ + 'id' => 'metorik/opt-in', + 'label' => apply_filters( 'metorik_cart_tracking_opt_in_checkbox_label', Metorik_Cart_Data::get_cart_setting( 'opt_in_checkbox_label', __( 'Opt-in to receive cart reminders e-mails from this store', 'metorik' ) ) ), + 'location' => 'contact', + 'type' => 'checkbox', + ] ); + + // get the value from cart data + add_filter( + "woocommerce_get_default_value_for_metorik/opt-in", + function ( $value ) { + if ( is_null( $value ) ) { + $value = Metorik_Cart_Data::get_customer_email_opt_in(); + } + + return $value; + } ); + + // don't set the value if in the admin + if ( is_admin() ) { + return; + } + + // set the value to cart data + add_action( + 'woocommerce_set_additional_field_value', + function ( $key, $value, $group, $wc_object ) { + if ( 'metorik/opt-in' !== $key ) { + return; + } + + Metorik_Cart_Data::set_customer_email_opt_in( (bool) $value ); + }, + 10, + 4 + ); + } + + /** + * Render the add to cart email form into the footer (hidden) + * It is shown via JS via tippy.js: + * - when a user adds to cart + * - is not logged in + * - has not seen/dismissed the form before + * + * It can be disabled via cart settings or via filter + * + * @return void + */ + public function add_cart_email_form() { + // bail if metorik cart tracking disabled + if ( ! metorik_cart_tracking_enabled() ) { + return; + } + + // bail if setting not enabled + if ( ! Metorik_Cart_Data::get_cart_setting( 'add_cart_popup' ) ) { + return; + } + + // bail if user is logged in + if ( is_user_logged_in() ) { + return; + } + + // bail if user has seen the form before + if ( Metorik_Cart_Data::user_has_seen_add_to_cart_form() ) { + return; + } + + // Title + $title = Metorik_Cart_Data::get_cart_setting( 'add_cart_popup_title' ); + if ( ! $title ) { + $title = 'Save your cart?'; + } + + // Email usage notice + $email_usage_notice = false; + if ( Metorik_Cart_Data::get_cart_setting( 'email_usage_notice' ) && ! Metorik_Cart_Data::get_customer_email_opt_out() ) { + $email_usage_notice = $this->render_email_usage_notice(); + } + + // Variables + $args = [ + 'title' => $title, + 'email_usage_notice' => $email_usage_notice, + ]; + + // Output template wrapped in 'add-cart-email-wrapper' div (used by JS) + echo ''; + } + + /** + * Move the email field to the top of the checkout billing form + * (WC 3.0+ but when no block support only). + * + * @param array $fields the checkout fields + * + * @return array $fields the modified fields + */ + public function move_checkout_email_field( $fields ) { + // bail if metorik cart tracking disabled + if ( ! metorik_cart_tracking_enabled() ) { + return $fields; + } + + // bail if setting disabled + if ( ! Metorik_Cart_Data::get_cart_setting( 'move_email_field_top_checkout' ) ) { + return $fields; + } + + // bail if WC below 3 + if ( ! version_compare( WC()->version, '3.0.0', '>=' ) ) { + return $fields; + } + + // bail if field doesn't exist + if ( ! isset( $fields['billing']['billing_email']['priority'] ) ) { + return $fields; + } + + $fields['billing']['billing_email']['priority'] = 5; + $fields['billing']['billing_email']['class'] = [ 'form-row-wide' ]; + $fields['billing']['billing_email']['autofocus'] = true; + + // adjust layout of postcode/phone fields + if ( isset( $fields['billing']['billing_postcode'], $fields['billing']['billing_phone'] ) ) { + $fields['billing']['billing_postcode']['class'] = [ 'form-row-first', 'address-field' ]; + $fields['billing']['billing_phone']['class'] = [ 'form-row-last' ]; + } + + // remove autofocus from billing first name (set to email above) + if ( isset( $fields['billing']['billing_first_name'] ) && ! empty( $fields['billing']['billing_first_name']['autofocus'] ) ) { + $fields['billing']['billing_first_name']['autofocus'] = false; + } + + return $fields; + } + + /** + * Add the email usage notice to the email checkout field + * (WC 3.4+ but when no block support only). + * + * @param string $field the field being rendered + * @param string $key the key of the field being rendered + * + * @return string the field being rendered + */ + public function checkout_add_email_usage_notice( $field, $key ) { + // bail if this isn't the email field + if ( 'billing_email' !== $key ) { + return $field; + } + + // bail if metorik cart tracking disabled + if ( ! metorik_cart_tracking_enabled() ) { + return $field; + } + + // bail if setting disabled + if ( ! Metorik_Cart_Data::get_cart_setting( 'email_usage_notice' ) ) { + return $field; + } + + // bail if WC below 3.4 + if ( ! version_compare( WC()->version, '3.4.0', '>=' ) ) { + return $field; + } + + // bail if customer has opted out already + if ( Metorik_Cart_Data::get_customer_email_opt_out() ) { + return $field; + } + + // find the trailing

tag to replace with our notice +

+ $pos = strrpos( $field, '

' ); + $replace = $this->render_email_usage_notice() . '

'; + + if ( false !== $pos ) { + $field = substr_replace( $field, $replace, $pos, strlen( '

' ) ); + } + + return $field; + } + + + /** + * Render the email usage notice. + * + * @return string the email usage notice + */ + public function render_email_usage_notice() { + /* translators: Placeholders: %1$s - opening HTML link tag, %2$s - closing HTML link tag */ + $notice = sprintf( + __( 'We save your email and cart so we can send you reminders - %1$sdon\'t email me%2$s.', 'metorik' ), + '', + '' + ); + + /** + * Filters the email usage notice contents. + */ + $notice = (string) apply_filters( 'metorik_cart_email_usage_notice', $notice ); + + return '' . $notice . ''; + } + + /** + * Capture customer data from checkout form (WC AJAX endpoint) + * This is used to update the customer's email, name, phone + * in the session and trigger a sync + * + * @return void + */ + public function capture_customer_data() { + check_ajax_referer( 'metorik', 'security' ); + + if ( ! empty( $_POST['email'] ) && is_email( $_POST['email'] ) ) { + WC()->customer->set_email( sanitize_email( $_POST['email'] ) ); + WC()->customer->set_billing_email( sanitize_email( $_POST['email'] ) ); + } + + // Customer first name. + if ( isset( $_POST['first_name'] ) ) { + WC()->customer->set_first_name( sanitize_text_field( $_POST['first_name'] ) ); + WC()->customer->set_billing_first_name( sanitize_text_field( $_POST['first_name'] ) ); + } + + // Customer last name. + if ( isset( $_POST['last_name'] ) ) { + WC()->customer->set_last_name( sanitize_text_field( $_POST['last_name'] ) ); + WC()->customer->set_billing_last_name( sanitize_text_field( $_POST['last_name'] ) ); + } + + // Customer phone + if ( isset( $_POST['phone'] ) ) { + WC()->customer->set_billing_phone( sanitize_text_field( $_POST['phone'] ) ); + } + + WC()->customer->save(); + $this->initiate_sync(); + } + + /** + * Process WC ajax function to mark cart form as seen + * + * @return void + */ + public function set_seen_add_to_cart_form() { + check_ajax_referer( 'metorik', 'security' ); + + Metorik_Cart_Data::set_user_has_seen_add_to_cart_form(); + } + + /** + * Process WC ajax function to opt out of cart tracking + * + * @return void + */ + public function opt_out() { + check_ajax_referer( 'metorik', 'security' ); + + Metorik_Cart_Data::set_customer_email_opt_out(); + Metorik_Cart_Data::set_user_has_seen_add_to_cart_form(); + $this->initiate_sync(); + } + + public function opt_in() { + check_ajax_referer( 'metorik', 'security' ); + + Metorik_Cart_Data::set_customer_email_opt_in(); + $this->initiate_sync(); + } +} + +Metorik_Cart_Tracking::instance(); diff --git a/inc/carts.php b/inc/carts.php deleted file mode 100755 index feaf742..0000000 --- a/inc/carts.php +++ /dev/null @@ -1,979 +0,0 @@ -apiUrl; - - return apply_filters('metorik_carts_api_url', $url); - } - - /** - * Check any prerequisites required for our add to cart request. - * From https://barn2.co.uk/managing-cart-rest-api-woocommerce-3-6/. - */ - private function check_prerequisites() - { - if (defined('WC_ABSPATH')) { - // WC 3.6+ - Cart and notice functions are not included during a REST request. - include_once WC_ABSPATH.'includes/wc-cart-functions.php'; - include_once WC_ABSPATH.'includes/wc-notice-functions.php'; - } - - if (null === WC()->session) { - $session_class = apply_filters('woocommerce_session_handler', 'WC_Session_Handler'); - - //Prefix session class with global namespace if not already namespaced - if (false === strpos($session_class, '\\')) { - $session_class = '\\'.$session_class; - } - - WC()->session = new $session_class(); - WC()->session->init(); - } - - if (null === WC()->customer) { - WC()->customer = new \WC_Customer(get_current_user_id(), true); - } - - if (null === WC()->cart) { - WC()->cart = new \WC_Cart(); - - // We need to force a refresh of the cart contents from session here (cart contents are normally refreshed on wp_loaded, which has already happened by this point). - WC()->cart->get_cart(); - } - } - - /** - * Generate a cart token (md5 of current time & random number). - * - * @todo improve. - */ - public function generate_cart_token() - { - $token = md5(time().rand(100, 10000)); - - return $token; - } - - /** - * Get or set the cart token. - */ - public function get_or_set_cart_token() - { - if (!$token = $this->get_cart_token()) { - $token = $this->set_cart_token(); - } - - return $token; - } - - /** - * Get cart token from session / user meta. - */ - public function get_cart_token($user_id = false) - { - if ($user_id || ($user_id = get_current_user_id())) { - $token = get_user_meta($user_id, '_metorik_cart_token', true); - - // if no user meta token, check session cart token first and use that - if (!$token && WC()->session && WC()->session->get('metorik_cart_token')) { - $token = WC()->session->get('metorik_cart_token'); - update_user_meta($user_id, '_metorik_cart_token', $token); - } - - return $token; - } else { - return (WC()->session) ? WC()->session->get('metorik_cart_token') : ''; - } - } - - /** - * Set the cart token in session/user meta. - */ - public function set_cart_token() - { - $token = $this->generate_cart_token(); - - WC()->session->set('metorik_cart_token', $token); - - if ($user_id = get_current_user_id()) { - update_user_meta($user_id, '_metorik_cart_token', $token); - } - - return $token; - } - - /** - * Return if a user has seen the add to cart form before. - */ - public function seen_add_cart_form() - { - return (bool) (WC()->session) ? WC()->session->get('metorik_seen_add_to_cart_form') : false; - } - - /** - * Ajax set the add cart form to having been 'seen' in the session. - */ - public function ajax_set_seen_add_cart_form() - { - WC()->session->set('metorik_seen_add_to_cart_form', true); - } - - /** - * Ajax email opt out. - */ - public function ajax_email_opt_out() - { - $this->set_customer_email_opt_out(true); - } - - /** - * Get the customer email opt out setting. - */ - public function get_customer_email_opt_out($user_id = false) - { - if ($user_id || ($user_id = get_current_user_id())) { - return (bool) get_user_meta($user_id, '_metorik_customer_email_opt_out', true); - } elseif (isset(WC()->session)) { - return (bool) WC()->session->metorik_customer_email_opt_out; - } - } - - /** - * Set the customer email opt out setting. - */ - public function set_customer_email_opt_out($opt_out = true) - { - WC()->session->set('metorik_customer_email_opt_out', $opt_out); - - if ($user_id = get_current_user_id()) { - update_user_meta($user_id, '_metorik_customer_email_opt_out', $opt_out); - } - - return $opt_out; - } - - /** - * Unset a cart token/recovery status. - * Done when checking out after payment. - */ - public function unset_cart_token() - { - if (WC()->session) { - unset(WC()->session->metorik_cart_token, WC()->session->metorik_pending_recovery); - } - - if ($user_id = get_current_user_id()) { - delete_user_meta($user_id, '_metorik_cart_token'); - delete_user_meta($user_id, '_metorik_pending_recovery'); - } - } - - /** - * Was the current cart/checkout created by a Metorik recovery URL? - * - * @return bool - */ - public static function cart_is_pending_recovery($user_id = null) - { - if ($user_id || ($user_id = get_current_user_id())) { - return (bool) get_user_meta($user_id, '_metorik_pending_recovery', true); - } elseif (isset(WC()->session)) { - return (bool) WC()->session->metorik_pending_recovery; - } - - return false; - } - - /** - * Send cart ajax. Only if have cart! - * Only if metorik auth token set up. - * - * @return void - */ - public function ajax_send_cart() - { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return; - } - - $metorik_auth_token = get_option('metorik_auth_token'); - - // variables - $cart = WC()->cart->get_cart(); - $token = $this->get_or_set_cart_token(); - $customer_id = get_current_user_id(); - $email = isset($_POST['email']) && $_POST['email'] ? sanitize_email($_POST['email']) : null; - $name = isset($_POST['name']) && $_POST['name'] ? sanitize_text_field($_POST['name']) : null; - $phone = isset($_POST['phone']) && $_POST['phone'] ? sanitize_text_field($_POST['phone']) : null; - - // if no cart, stop (empty cart clearing is handled with separate action/method in this class) - if (!$cart) { - return; - } - - $data = array( - 'api_token' => $metorik_auth_token, - 'data' => array( - 'token' => $token, - 'cart' => $cart, - 'started_at' => current_time('timestamp', true), // utc timestamp - 'total' => (float) $this->get_cart_total(), - 'subtotal' => (float) $this->get_cart_subtotal(), - 'total_tax' => (float) $this->get_cart_tax(), - 'total_discount' => (float) $this->get_cart_discount(), - 'total_shipping' => (float) $this->get_cart_shipping(), - 'total_fee' => (float) $this->get_cart_fee(), - 'currency' => get_woocommerce_currency(), - 'customer_id' => $customer_id, - 'email' => $email, - 'name' => $name, - 'phone' => $phone, - 'locale' => get_user_locale(), - 'email_opt_out' => $this->get_customer_email_opt_out(), - 'client_session' => $this->get_client_session_data(), - 'display_prices_including_tax' => WC()->cart->display_prices_including_tax(), - ), - ); - - $response = wp_remote_post($this->getMetorikApiUrl().'/incoming/carts', array( - 'body' => $data, - )); - - wp_die(); - } - - /** - * Hooks into a cart item being removed action. - * Checks if the cart is empty. If so, sends the - * empty cart to Metorik (and clears token). - * - * @return void - */ - public function check_cart_empty_and_send() - { - // only continue if the cart is empty - if (WC()->cart->is_empty()) { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return; - } - - $metorik_auth_token = get_option('metorik_auth_token'); - - // clear cart remotely by sending empty cart - $token = $this->get_or_set_cart_token(); - - $response = wp_remote_post($this->getMetorikApiUrl().'/incoming/carts', array( - 'body' => array( - 'api_token' => $metorik_auth_token, - 'data' => array( - 'token' => $token, - 'cart' => false, - ), - ), - )); - - // clear the cart token/data from the session/user - $this->unset_cart_token(); - } - } - - /** - * Cart total. - * Since WC won't calculate total unless on cart/checkout, - * we need an alternative method to do it manually. - */ - protected function get_cart_total() - { - if ( - is_checkout() || - is_cart() || - defined('WOOCOMMERCE_CHECKOUT') || - defined('WOOCOMMERCE_CART') - ) { - return WC()->cart->total; - } else { - // product page, etc. - total not calculated but can get here - $total = WC()->cart->get_total(false); - - return $total; - } - } - - /** - * Get the cart subtotal (maybe inclusive of taxes). - */ - public function get_cart_subtotal() - { - if ('excl' === WC()->cart->display_prices_including_tax()) { - $subtotal = WC()->cart->subtotal_ex_tax; - } else { - $subtotal = WC()->cart->subtotal; - } - - return $subtotal; - } - - /** - * Get the cart tax. - */ - public function get_cart_tax() - { - //(WC()->cart->tax_total + WC()->cart->shipping_tax_total) - $total_tax = WC()->cart->get_total_tax(); - - return $total_tax; - } - - /** - * Get the cart discount (maybe inclusive of taxes). - */ - public function get_cart_discount() - { - // @todo check which version get_totals introduced to woo - $discount_total = WC()->cart->get_discount_total(); - $discount_tax = WC()->cart->get_discount_tax(); - - if ('excl' === WC()->cart->display_prices_including_tax()) { - return $discount_total; - } else { - return $discount_total + $discount_tax; - } - } - - /** - * Get the cart shipping (maybe inclusive of taxes). - */ - public function get_cart_shipping() - { - // @todo limit wc v3+ or set new wc min required version? - $shipping_total = WC()->cart->get_shipping_total(); - $shipping_tax = WC()->cart->get_shipping_tax(); - - if ('excl' === WC()->cart->display_prices_including_tax()) { - return $shipping_total; - } else { - return $shipping_total + $shipping_tax; - } - } - - /** - * Get the cart fee (maybe inclusive of taxes). - */ - public function get_cart_fee() - { - $fee_total = (float) WC()->cart->get_fee_total(); - $fee_tax = (float) WC()->cart->get_fee_tax(); - - if ('excl' === WC()->cart->display_prices_including_tax()) { - return $fee_total; - } else { - return $fee_total + $fee_tax; - } - } - - /** - * Get data about the client's current session - eg. coupons, shipping. - * Later maybe more customer info like addresses. - */ - public function get_client_session_data() - { - // No session? Stop - if (!WC()->session) { - return; - } - - return array( - 'applied_coupons' => WC()->session->get('applied_coupons'), - 'chosen_shipping_methods' => WC()->session->get('chosen_shipping_methods'), - 'shipping_method_counts' => WC()->session->get('shipping_method_counts'), - 'chosen_payment_method' => WC()->session->get('chosen_payment_method'), - ); - } - - /** - * Link a customer's existing cart when logging in. - */ - public function link_customer_existing_cart($user_login, $user) - { - $session_token = (WC()->session) ? WC()->session->get('metorik_cart_token') : ''; - - // if session token and user, set in user meta - if ($session_token && $user) { - update_user_meta($user->ID, '_metorik_cart_token', $session_token); - } - } - - /** - * This is called once the checkout has been processed and an order has been created. - */ - public function checkout_order_processed($order_id) - { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return; - } - - $cart_token = $this->get_cart_token(); - - // save cart token to order meta - if ($cart_token) { - $order = wc_get_order($order_id); - - if (!$order instanceof WC_Order) { - return; - } - - $order->update_meta_data('_metorik_cart_token', $cart_token); - $order->save(); - } - - // check if pending recovery - if so, set in order meta - if ($this->cart_is_pending_recovery()) { - $this->mark_order_as_recovered($order_id); - } - } - - /** - * Mark an order as recovered by Metorik. - */ - public function mark_order_as_recovered($order_id) - { - $order = wc_get_order($order_id); - - if (!$order instanceof WC_Order) { - return; - } - - $order->update_meta_data('_metorik_cart_recovered', true); - $order->add_order_note(__('Order cart recovered by Metorik.', 'metorik')); - $order->save(); - } - - /** - * Maybe apply the recovery coupon provided in the recovery URL. - */ - public function maybe_apply_cart_recovery_coupon() - { - if ($this->cart_is_pending_recovery() && !empty($_REQUEST['coupon'])) { - $coupon_code = wc_clean(rawurldecode($_REQUEST['coupon'])); - - if (WC()->cart && !WC()->cart->has_discount($coupon_code)) { - WC()->cart->calculate_totals(); - WC()->cart->add_discount($coupon_code); - } - } - } - - /** - * Rest API route for recovering a cart. - * - * @return void - */ - public function api_recover_cart_route() - { - register_rest_route('metorik/v1', '/recover-cart', array( - 'methods' => 'GET', - 'callback' => array($this, 'recover_cart_callback'), - 'permission_callback' => '__return_true', - )); - } - - /** - * API route callback for recovering a cart. - */ - public function recover_cart_callback($request) - { - // Check token is set and has a value before continuing. - if (isset($request['token']) && $cart_token = $request['token']) { - // cart start - $this->check_prerequisites(); - - // base checkout url - default is the woo checkout url - $checkout_url = wc_get_checkout_url(); - - // if setting for it, use that - if ($this->get_cart_setting('checkout_url')) { - $checkout_url = $this->get_cart_setting('checkout_url'); - } - - // if request param for custom redirect url, use that - if (isset($request['redirect_url']) && $redirect_url = $request['redirect_url']) { - $checkout_url = $redirect_url; - } - - // finally, allow the url to be filtered for more advanced customising - $checkout_url = apply_filters('metorik_recover_cart_url', $checkout_url); - - // forward along any UTM or metorik params or lang - foreach ($request->get_params() as $key => $val) { - if (0 === strpos($key, 'utm_') || 0 === strpos($key, 'mtk') || 0 === strpos($key, 'lang')) { - $checkout_url = add_query_arg($key, $val, $checkout_url); - } - } - - // no session? start so cart/notices work - if (!WC()->session || (WC()->session && !WC()->session->has_session())) { - WC()->session->set_customer_session_cookie(true); - } - - // try restore the cart - try { - $this->restore_cart($cart_token); - - // check for coupon in recovery URL to apply before checkout redirect - if (isset($request['coupon']) && $coupon = rawurldecode($request['coupon'])) { - $checkout_url = add_query_arg(array('coupon' => wc_clean($coupon)), $checkout_url); - } - } catch (Exception $e) { - // add a notice - wc_add_notice(__('Sorry, we were not able to restore your cart. Please try adding your items to your cart again.', 'metorik'), 'error'); - } - - // redirect checkout url - wp_safe_redirect($checkout_url); - exit; - } - } - - /** - * Restore an actual cart. - */ - public function restore_cart($cart_token) - { - // metorik auth token - $metorik_auth_token = get_option('metorik_auth_token'); - if (!$metorik_auth_token) { - throw new Exception('Missing Metorik authentication token'); - } - - // get cart - $response = wp_remote_get($this->getMetorikApiUrl().'/external/carts', array( - 'body' => array( - 'api_token' => $metorik_auth_token, - 'cart_token' => $cart_token, - ), - )); - - // Error during response? - if (is_wp_error($response)) { - throw new Exception('Error getting cart from Metorik'); - } - - $body = wp_remote_retrieve_body($response); - - // no response body/cart? - if (!$body) { - throw new Exception('Error getting cart from Metorik'); - } - - // json decode - $body = json_decode($body); - - // no data/cart? stop - if (!isset($body->data->cart)) { - throw new Exception('Error getting cart from Metorik'); - } - - // get cart - $cart = $body->data->cart; - - // need to cast all to an array for putting back into the session - $cart = json_decode(json_encode($cart), true); - - // Clear any existing cart - WC()->cart->empty_cart(); - - // Restore cart - WC()->session->set('cart', $cart); - - // Set the cart token and pending recovery in session - WC()->session->set('metorik_cart_token', $cart_token); - WC()->session->set('metorik_pending_recovery', true); - - // Set the cart token / pending recovery in user meta if this cart has a user - $user_id = $body->data->customer_id; - if ($user_id) { - update_user_meta($user_id, '_metorik_cart_token', $cart_token); - update_user_meta($user_id, '_metorik_pending_recovery', true); - } - - // Client session - $session = $body->data->client_session; - if ($session) { - if (isset($session->applied_coupons)) { - $applied_coupons = (array) $session->applied_coupons; - WC()->session->set('applied_coupons', $this->return_valid_coupons($applied_coupons)); - } - - if (isset($session->chosen_shipping_methods)) { - $chosen_shipping_methods = (array) $session->chosen_shipping_methods; - WC()->session->set('chosen_shipping_methods', $chosen_shipping_methods); - } - - if (isset($session->shipping_method_counts)) { - $shipping_method_counts = (array) $session->shipping_method_counts; - WC()->session->set('shipping_method_counts', $shipping_method_counts); - } - - if (isset($session->chosen_payment_method)) { - $chosen_payment_method = $session->chosen_payment_method; - WC()->session->set('chosen_payment_method', $chosen_payment_method); - } - } - } - - /** - * Returns valid coupons for applying above. - */ - private function return_valid_coupons($coupons) - { - $valid_coupons = array(); - - if ($coupons) { - foreach ($coupons as $coupon_code) { - $the_coupon = new WC_Coupon($coupon_code); - - if (!$the_coupon->is_valid()) { - continue; - } - - $valid_coupons[] = $coupon_code; - } - } - - return $valid_coupons; - } - - /** - * Get a cart setting (stored in metorik.php over API). - */ - public function get_cart_setting($key = false) - { - $settings = get_option('metorik_cart_settings'); - - // no key defined or settings saved? false - if (!$key || !$settings) { - return false; - } - - // json decode - $settings = json_decode($settings); - - // not set? false - if (!isset($settings->$key)) { - return false; - } - - return $settings->$key; - } - - /** - * Add the email usage notice to checkout. - * Method required due to WC < 3.4 html handling. - */ - public function checkout_add_email_usage_notice($field, $key) - { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return $field; - } - - // only if 3.4+, setting enabled, customer hasn't already opted out and billing email field exists - if ( - $key === 'billing_email' && - $this->get_cart_setting('email_usage_notice') && - !$this->get_customer_email_opt_out() - ) { - // find the trailing

tag to replace with our notice +

- $pos = strrpos($field, '

'); - $replace = $this->render_email_usage_notice().'

'; - - if (false !== $pos) { - $field = substr_replace($field, $replace, $pos, strlen('

')); - } - } - - return $field; - } - - /** - * Move the email field to the top of the checkout billing form (3.0+ only). - */ - public function move_checkout_email_field($fields) - { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return $fields; - } - - // Oonly if setting is enabled and WC 3.0+) - if ( - $this->get_cart_setting('move_email_field_top_checkout') && - version_compare(WC()->version, '3.0.0', '>=') && - isset($fields['billing']['billing_email']['priority']) - ) { - $fields['billing']['billing_email']['priority'] = 5; - $fields['billing']['billing_email']['class'] = array('form-row-wide'); - $fields['billing']['billing_email']['autofocus'] = true; - - // adjust layout of postcode/phone fields - if (isset($fields['billing']['billing_postcode'], $fields['billing']['billing_phone'])) { - $fields['billing']['billing_postcode']['class'] = array('form-row-first', 'address-field'); - $fields['billing']['billing_phone']['class'] = array('form-row-last'); - } - - // remove autofocus from billing first name (set to email above) - if (isset($fields['billing']['billing_first_name']) && !empty($fields['billing']['billing_first_name']['autofocus'])) { - $fields['billing']['billing_first_name']['autofocus'] = false; - } - } - - return $fields; - } - - /** - * Render an email usage notice. - */ - public function render_email_usage_notice() - { - /* translators: Placeholders: %1$s - opening HTML link tag, %2$s - closing HTML link tag */ - $notice = sprintf( - __('We save your email and cart so we can send you reminders - %1$sdon\'t email me%2$s.', 'metorik'), - '', - '' - ); - - /** - * Filters the email usage notice contents. - */ - $notice = (string) apply_filters('metorik_cart_email_usage_notice', $notice); - - return ''.$notice.''; - } - - /** - * Add cart email form (end of DOM in WP footer). JS loads it. - */ - public function add_cart_email_form() - { - // stop if metorik cart tracking disabled - if (!metorik_cart_tracking_enabled()) { - return; - } - - // Only if setting enabled, user not logged in, and never seen before - if ($this->get_cart_setting('add_cart_popup') - && !get_current_user_id() - && !$this->seen_add_cart_form()) { - // Title - $title = $this->get_cart_setting('add_cart_popup_title'); - if (!$title) { - $title = 'Save your cart?'; - } - - // Email usage notice - $email_usage_notice = false; - if ($this->get_cart_setting('email_usage_notice') && !$this->get_customer_email_opt_out()) { - $email_usage_notice = $this->render_email_usage_notice(); - } - - // Variables - $args = array( - 'title' => $title, - 'email_usage_notice' => $email_usage_notice, - ); - - // Output template wrapped in 'add-cart-email-wrapper' div (used by JS) - echo ''; - } - } - - /** - * Get template. - * - * Search for the template and include the file. - * - * @author https://jeroensormani.com/how-to-add-template-files-in-your-plugin/ - * - * @see $this->locate_template() - * - * @param string $template_name Template to load. - * @param array $args Args passed for the template file. - * @param string $string $template_path Path to templates. - * @param string $default_path Default path to template files. - */ - public function get_template($template_name, $args = array(), $tempate_path = '', $default_path = '') - { - if (is_array($args) && isset($args)) { - extract($args); - } - - $template_file = $this->locate_template($template_name, $tempate_path, $default_path); - - if (!file_exists($template_file)) { - _doing_it_wrong(__FUNCTION__, sprintf('%s does not exist.', $template_file), '1.0.0'); - - return; - } - - include $template_file; - } - - /** - * Locate template. - * - * Locate the called template. - * Search Order: - * 1. /themes/theme/metorik/$template_name - * 2. /themes/theme/$template_name - * 3. /plugins/metorik/templates/$template_name. - * - * @author https://jeroensormani.com/how-to-add-template-files-in-your-plugin/ - * - * @param string $template_name Template to load. - * @param string $string $template_path Path to templates. - * @param string $default_path Default path to template files. - * - * @return string Path to the template file. - */ - public function locate_template($template_name, $template_path = '', $default_path = '') - { - // Set variable to search in metorik folder of theme. - if (!$template_path) { - $template_path = 'metorik/'; - } - - // Set default plugin templates path. - if (!$default_path) { - $default_path = plugin_dir_path(dirname(__FILE__)).'templates/'; // Path to the template folder - } - - // Search template file in theme folder. - $template = locate_template(array( - $template_path.$template_name, - $template_name, - )); - - // Get plugins template file. - if (!$template) { - $template = $default_path.$template_name; - } - - return apply_filters('metorik_locate_template', $template, $template_name, $template_path, $default_path); - } - - /** - * Add a coupon code to the cart session. - * - * @return void - */ - public function add_coupon_code_to_cart_session() - { - // Stop if no code in URL - if (empty($_GET['mtkc'])) { - return; - } - - // cart start - $this->check_prerequisites(); - - // no session? start so cart/notices work - if (!WC()->session || (WC()->session && !WC()->session->has_session())) { - WC()->session->set_customer_session_cookie(true); - } - - // Set code in session - $coupon_code = esc_attr($_GET['mtkc']); - WC()->session->set('mtk_coupon', $coupon_code); - - // If there is an existing non empty cart active session we apply the coupon - if (WC()->cart && !WC()->cart->is_empty() && !WC()->cart->has_discount($coupon_code)) { - WC()->cart->calculate_totals(); - WC()->cart->add_discount($coupon_code); - - // Unset the coupon from the session - WC()->session->__unset('mtk_coupon'); - } - } - - /** - * Add the Metorik session coupon code to the cart when adding a product. - */ - public function add_coupon_code_to_cart() - { - $coupon_code = WC()->session ? WC()->session->get('mtk_coupon') : false; - - // no coupon code? stop - if (!$coupon_code || empty($coupon_code)) { - return; - } - - // only if have a cart but not this discount yet - if (WC()->cart && !WC()->cart->has_discount($coupon_code)) { - WC()->cart->calculate_totals(); - WC()->cart->add_discount($coupon_code); - - // Unset the coupon from the session - WC()->session->__unset('mtk_coupon'); - } - } -} - -new Metorik_Helper_Carts(); diff --git a/inc/custom.php b/inc/custom.php deleted file mode 100644 index 3c499f2..0000000 --- a/inc/custom.php +++ /dev/null @@ -1,219 +0,0 @@ -version, true); - - /* - * Enqueue styles. - */ - wp_enqueue_style('metorik-css', plugins_url('assets/css/metorik.css', dirname(__FILE__)), '', $this->version); - - /* - * Prepare cart items - possible to disable through a filter. - */ - $cart_items = 0; - if (apply_filters('metorik_cart_items', true)) { - $cart_items = WC()->cart ? WC()->cart->get_cart_contents_count() : 0; - } - - /** - * Pass parameters to Metorik JS. - */ - $params = array( - 'lifetime' => (int) apply_filters('metorik_cookie_lifetime', 6), // 6 months - 'session' => (int) apply_filters('metorik_session_length', 30), // 30 minutes - 'ajaxurl' => admin_url('admin-ajax.php'), - 'cart_tracking' => metorik_cart_tracking_enabled(), - 'cart_items' => $cart_items, - 'cart_checkout_button' => apply_filters('metorik_acp_checkout_button', true), - 'add_cart_popup_placement' => apply_filters('metorik_acp_placement', 'bottom'), - 'send_cart_events' => apply_filters('metorik_send_cart_events', 'added_to_cart removed_from_cart updated_cart_totals updated_shipping_method applied_coupon removed_coupon updated_checkout'), - 'sbjs_domain' => apply_filters('metorik_sbjs_domain', false), - 'send_cart_fragments' => apply_filters('metorik_send_cart_fragments', true), - ); - wp_localize_script('metorik-js', 'metorik_params', $params); - } - - /** - * Add Metorik hidden input fields for checkout & customer register froms. - */ - public function source_form_fields() - { - /* - * Hidden field for each possible field. - */ - foreach ($this->fields as $field) { - echo ''; - } - } - - /** - * Set the source data in the order post meta. - */ - public function set_order_source($order_id) - { - $this->set_source_data($order_id, 'order'); - } - - /** - * Set the source data in the customer user meta. - */ - public function set_customer_source($customer_id) - { - $this->set_source_data($customer_id, 'customer'); - } - - /** - * Set source data. - */ - public function set_source_data($id, $resource) - { - /** - * Values. - */ - $values = array(); - - /* - * Get each field if POSTed. - */ - foreach ($this->fields as $field) { - // default empty - $values[$field] = ''; - - // set if have - if (isset($_POST[$this->fieldPrefix.$field]) && $_POST[$this->fieldPrefix.$field]) { - $values[$field] = sanitize_text_field($_POST[$this->fieldPrefix.$field]); - } - } - - /** - * Now parse values to set in meta. - */ - - // by default order should NOT save - $orderShouldSave = false; - - // if orders, need to get the order object - if ($resource == 'order') { - $order = wc_get_order($id); - - if (!$order instanceof WC_Order) { - return; - } - } - - // metorik engage - if ($values['mtke'] && $values['mtke'] !== '(none)') { - if ($resource == 'order') { - $order->update_meta_data('_metorik_engage', $values['mtke']); - $orderShouldSave = true; - } else { - update_user_meta($id, '_metorik_engage', $values['mtke']); - } - } - unset($values['mtke']); - - // only set next fields if filter not set to false - if (apply_filters('metorik_source_tracking_enabled', true)) { - // type - if ($values['type'] && $values['type'] !== '(none)') { - if ($resource == 'order') { - $order->update_meta_data('_metorik_source_type', $values['type']); - $orderShouldSave = true; - } else { - update_user_meta($id, '_metorik_source_type', $values['type']); - } - } - unset($values['type']); - - // referer url - if ($values['url'] && $values['url'] !== '(none)') { - if ($resource == 'order') { - $order->update_meta_data('_metorik_referer', $values['url']); - $orderShouldSave = true; - } else { - update_user_meta($id, '_metorik_referer', $values['url']); - } - } - unset($values['url']); - - // rest of fields - UTMs & sessions (if not '(none)') - foreach ($values as $key => $value) { - if ($value && $value !== '(none)') { - if ($resource == 'order') { - $order->update_meta_data('_metorik_'.$key, $value); - $orderShouldSave = true; - } else { - update_user_meta($id, '_metorik_'.$key, $value); - } - } - } - } - - // now save for orders (regardless filter) if SHOULD save (at least one meta updated above) - if ($resource == 'order' && $orderShouldSave) { - $order->save(); - } - } -} - -new Metorik_Custom(); diff --git a/inc/functions.php b/inc/functions.php index 94dc639..1e5f5db 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -36,19 +36,12 @@ function metorik_check_headers_agent($headers) } /** - * Function to check if Metorik cart tracking is enabled. - * First checks the option, but can be overridden by a filter. + * Check if Metorik cart tracking is enabled. + * @see Metorik_Cart_Tracking::cart_tracking_enabled * - * @return void + * @return bool */ function metorik_cart_tracking_enabled() { - // check if cart tracking is enabled - $cart_tracking = get_option('metorik_auth_token') ? true : false; - - // run through metorik filter - must be bool - $cart_tracking = (bool) apply_filters('metorik_cart_tracking_enabled', $cart_tracking); - - // return - return $cart_tracking; + return Metorik_Cart_Tracking::cart_tracking_enabled(); } diff --git a/inc/source-tracking.php b/inc/source-tracking.php new file mode 100755 index 0000000..59ef087 --- /dev/null +++ b/inc/source-tracking.php @@ -0,0 +1,190 @@ +set_source_data( $order_id, 'order' ); + } + + /** + * Set the source data in the customer user meta. + */ + public function set_customer_source( $customer_id ) { + $this->set_source_data( $customer_id, 'customer' ); + } + + /** + * Set source data. + */ + public function set_source_data( $id, $resource ) { + /** + * Values. + */ + $values = array(); + + /* + * Get each field if in the cookie + */ + $cookie_name = self::source_tracking_cookie_name(); + $cookie = isset( $_COOKIE[ $cookie_name ] ) && is_string( $_COOKIE[ $cookie_name ] ) ? $_COOKIE[ $cookie_name ] : ''; + $cookie = json_decode( stripslashes( $cookie ), true ); + + // if no/invalid cookie, bail + if ( ! is_array( $cookie ) ) { + return; + } + + foreach ( self::FIELDS as $field ) { + // default is empty + $values[ $field ] = ''; + + // if field is set in POST, sanitize and set + if ( ! empty( $cookie[ $field ] ) ) { + $values[ $field ] = sanitize_text_field( $cookie[ $field ] ); + } + } + + + // by default order should NOT save + $orderShouldSave = false; + + // if orders, need to get the order object + if ( $resource == 'order' ) { + $order = wc_get_order( $id ); + + if ( ! $order instanceof WC_Order ) { + return; + } + } + + // metorik engage + if ( $values['mtke'] && $values['mtke'] !== '(none)' ) { + if ( $resource == 'order' ) { + $order->update_meta_data( '_metorik_engage', $values['mtke'] ); + $orderShouldSave = true; + } else { + update_user_meta( $id, '_metorik_engage', $values['mtke'] ); + } + } + unset( $values['mtke'] ); + + // only set next fields if filter not set to false + // type + if ( $values['type'] && $values['type'] !== '(none)' ) { + if ( $resource == 'order' ) { + $order->update_meta_data( '_metorik_source_type', $values['type'] ); + $orderShouldSave = true; + } else { + update_user_meta( $id, '_metorik_source_type', $values['type'] ); + } + } + unset( $values['type'] ); + + // referer url + if ( $values['url'] && $values['url'] !== '(none)' ) { + if ( $resource == 'order' ) { + $order->update_meta_data( '_metorik_referer', $values['url'] ); + $orderShouldSave = true; + } else { + update_user_meta( $id, '_metorik_referer', $values['url'] ); + } + } + unset( $values['url'] ); + + // rest of fields - UTMs & sessions (if not '(none)') + foreach ( $values as $key => $value ) { + if ( $value && $value !== '(none)' ) { + if ( $resource == 'order' ) { + $order->update_meta_data( '_metorik_' . $key, $value ); + $orderShouldSave = true; + } else { + update_user_meta( $id, '_metorik_' . $key, $value ); + } + } + } + + // now save for orders (regardless filter) if SHOULD save (at least one meta updated above) + if ( $resource == 'order' && $orderShouldSave ) { + $order->save(); + } + } +} + +Metorik_Source_Tracking::instance(); diff --git a/inc/ui.php b/inc/ui.php deleted file mode 100644 index 98f5155..0000000 --- a/inc/ui.php +++ /dev/null @@ -1,140 +0,0 @@ -'; - - foreach ($ids as $id) { - echo ' - #'.$id.' button { display: none; } - #'.$id.' h2 { display: none; } - #'.$id.' .postbox-header { border-bottom: none; } - #'.$id.' .inside { padding: 0; margin: 0; } - #'.$id.' .inside a { display: block; font-weight: bold; padding: 12px; text-decoration: none; vertical-align: middle; } - #'.$id.' .inside a:hover { background: #fafafa; } - #'.$id.' .inside a img { display: inline-block; margin: -4px 5px 0 0; vertical-align: middle; width: 20px; } - #'.$id.' .inside a span { float: right; } - '; - } - - echo '.metorik-notice.notice button.notice-dismiss { display: none; }'; - echo '.metorik-notice.notice a.notice-dismiss { text-decoration: none; }'; - - echo ''; - } - - /** - * Register meta box(es). - */ - public function register_meta_boxes() - { - $orderScreen = class_exists(\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class) && wc_get_container()->get(\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class)->custom_orders_table_usage_is_enabled() - ? wc_get_page_screen_id('shop-order') - : 'shop_order'; - - add_meta_box('metorik-product-box', __('Metorik', 'metorik'), array($this, 'product_box_display'), 'product', 'side', 'high'); - add_meta_box('metorik-order-box', __('Metorik', 'metorik'), array($this, 'order_box_display'), $orderScreen, 'side', 'high'); - - $subscriptionScreen = class_exists(\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class) && wc_get_container()->get(\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class)->custom_orders_table_usage_is_enabled() - ? wc_get_page_screen_id('shop-subscription') - : 'shop_subscription'; - - if ($subscriptionScreen) { - add_meta_box('metorik-subscription-box', __('Metorik', 'metorik'), array($this, 'subscription_box_display'), $subscriptionScreen, 'side', 'high'); - } - } - - /** - * Product meta box display callback. - */ - public function product_box_display($post) - { - $shopUrl = str_replace(array('http://', 'https://'), '', home_url()); - echo ' - View in Metorik - '; - } - - /** - * Order meta box display callback. - */ - public function order_box_display($post) - { - $orderID = ($post instanceof WP_Post) ? $post->ID : $post->get_id(); - $shopUrl = str_replace(array('http://', 'https://'), '', home_url()); - - echo ' - View in Metorik - '; - } - - /** - * Subscription meta box display callback. - */ - public function subscription_box_display($post) - { - $orderID = ($post instanceof WP_Post) ? $post->ID : $post->get_id(); - $shopUrl = str_replace(array('http://', 'https://'), '', home_url()); - - echo ' - View in Metorik - '; - } - - /** - * Add column header to users table. - */ - public function modify_user_table($column) - { - $column['metorik'] = 'Metorik'; - - return $column; - } - - /** - * Add column body to users table. - */ - public function add_user_table_column($val, $column_name, $user_id) - { - $shopUrl = str_replace(array('http://', 'https://'), '', home_url()); - - switch ($column_name) { - case 'metorik': - return 'View'; - break; - default: - } - - return $val; - } -} - -new Metorik_UI(); diff --git a/metorik-helper.php b/metorik-helper.php old mode 100644 new mode 100755 index e1b97a5..be89249 --- a/metorik-helper.php +++ b/metorik-helper.php @@ -1,132 +1,264 @@ url = plugin_dir_url(__FILE__); - } - - /** - * Start plugin. - */ - public function init() - { - if (class_exists('WooCommerce')) { - // Woo HPOS compatibility - add_action('before_woocommerce_init', function () { - if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) { - \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true); - } - }); - - // Activate notice (shown once) - add_action('admin_notices', array($this, 'activate_notice')); - - // Require files for the plugin - require_once 'inc/functions.php'; - require_once 'inc/import.php'; - require_once 'inc/api.php'; - require_once 'inc/ui.php'; - require_once 'inc/custom.php'; - require_once 'inc/carts.php'; - } else { - add_action('admin_notices', array($this, 'no_wc')); - } - - // Plugin textdomain - load_plugin_textdomain('metorik', false, basename(dirname(__FILE__)).'/languages/'); - } - - /** - * No WC notice. - */ - public function no_wc() - { - echo '

'.sprintf(__('Metorik Helper requires %s to be installed and active.', 'metorik'), 'WooCommerce').'

'; - } - - /** - * Run on activation. - */ - public static function activate() - { - // Set Metorik's show activation notice option to true if it isn't already false (only first time) - if (get_option('metorik_show_activation_notice', true)) { - update_option('metorik_show_activation_notice', true); - } - } - - /** - * Activate notice (if we should). - */ - public function activate_notice() - { - if (get_option('metorik_show_activation_notice', false)) { - echo '

'.sprintf(__('The Metorik Helper is active! Go back to %s to complete the connection.', 'metorik'), 'Metorik').'

'; - - // Disable notice option - update_option('metorik_show_activation_notice', false); - } - } +class Metorik_Helper { + /** + * Current version of Metorik. + */ + public $version = '2.0.0'; + + /** + * URL dir for plugin. + */ + public $url; + + /** + * The single instance of the class. + */ + protected static $_instance = null; + + /** + * Main Metorik Helper Instance. + * + * Ensures only one instance of the Metorik Helper is loaded or can be loaded. + * + * @return Metorik Helper - Main instance. + */ + public static function instance() { + if ( is_null( self::$_instance ) ) { + self::$_instance = new self(); + } + + return self::$_instance; + } + + /** + * Constructor. + */ + public function __construct() { + add_action( 'plugins_loaded', [ $this, 'init' ] ); + + // Set URL + $this->url = plugin_dir_url( __FILE__ ); + } + + /** + * Start plugin. + */ + public function init() { + if ( class_exists( 'WooCommerce' ) ) { + // Woo HPOS compatibility + add_action( 'before_woocommerce_init', function () { + if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); + } + + // Woo Blocks Support + if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, true ); + } + } ); + + // Activate notice (shown once) + add_action( 'admin_notices', [ $this, 'activate_notice' ] ); + + // Require files for the plugin + require_once 'inc/functions.php'; + require_once 'inc/import.php'; + require_once 'inc/api.php'; + require_once 'inc/admin-ui.php'; + require_once 'inc/source-tracking.php'; + require_once 'inc/cart-data.php'; + require_once 'inc/cart-tracking.php'; + require_once 'inc/cart-recovery.php'; + + // enqueue scripts & styles + add_action( 'wp_enqueue_scripts', [ $this, 'scripts_styles' ] ); + } else { + add_action( 'admin_notices', [ $this, 'no_wc' ] ); + } + + // Plugin textdomain + load_plugin_textdomain( 'metorik', false, basename( dirname( __FILE__ ) ) . '/languages/' ); + } + + /** + * Scripts & styles for Metorik's custom source tracking and cart tracking. + */ + public function scripts_styles() { + /* + * Enqueue scripts. + */ + wp_enqueue_script( 'metorik-js', plugins_url( 'assets/js/metorik.min.js', __FILE__ ), [ 'jquery' ], $this->version, true ); + + /* + * Enqueue styles. + */ + wp_enqueue_style( 'metorik-css', plugins_url( 'assets/css/metorik.css', __FILE__ ), '', $this->version ); + + /* + * Prepare cart items - possible to disable through a filter. + */ + $cart_items_count = 0; + if ( apply_filters( 'metorik_cart_items', true ) ) { + $cart_items_count = WC()->cart ? WC()->cart->get_cart_contents_count() : 0; + } + + /** + * Pass parameters to Metorik JS. + */ + $params = [ + 'source_tracking' => [ + 'enabled' => Metorik_Source_Tracking::source_tracking_enabled(), + 'cookie_lifetime' => (int) apply_filters( 'metorik_cookie_lifetime', 6 ), // 6 months + 'session_length' => (int) apply_filters( 'metorik_session_length', 30 ), // 30 minutes + 'sbjs_domain' => apply_filters( 'metorik_sbjs_domain', false ), + 'cookie_name' => Metorik_Source_Tracking::source_tracking_cookie_name(), + ], + 'cart_tracking' => [ + 'enabled' => metorik_cart_tracking_enabled(), + 'cart_items_count' => $cart_items_count, + 'item_was_added_to_cart' => isset( $_REQUEST['add-to-cart'] ) && is_numeric( $_REQUEST['add-to-cart'] ), + 'wc_ajax_capture_customer_data_url' => WC_AJAX::get_endpoint( 'metorik_capture_customer_data' ), + 'wc_ajax_email_opt_out_url' => WC_AJAX::get_endpoint( 'metorik_email_opt_out' ), + 'wc_ajax_email_opt_in_url' => WC_AJAX::get_endpoint( 'metorik_email_opt_in' ), + 'wc_ajax_seen_add_to_cart_form_url' => WC_AJAX::get_endpoint( 'metorik_seen_add_to_cart_form' ), + 'add_cart_popup_placement' => apply_filters( 'metorik_acp_placement', 'bottom' ), + 'add_to_cart_should_mark_as_seen' => apply_filters( 'metorik_acp_should_mark_as_seen', true ), + 'add_to_cart_form_selectors' => apply_filters( 'metorik_acp_form_selectors', [ + '.ajax_add_to_cart', + '.single_add_to_cart_button', + ] ), + ], + 'nonce' => wp_create_nonce( 'metorik' ), + ]; + wp_localize_script( 'metorik-js', 'metorik_params', $params ); + } + + /** + * No WC notice. + */ + public function no_wc() { + echo '

' . sprintf( __( 'Metorik Helper requires %s to be installed and active.', 'metorik' ), 'WooCommerce' ) . '

'; + } + + /** + * Run on activation. + */ + public static function activate() { + // Set Metorik's show activation notice option to true if it isn't already false (only first time) + if ( get_option( 'metorik_show_activation_notice', true ) ) { + update_option( 'metorik_show_activation_notice', true ); + } + } + + /** + * Activate notice (if we should). + */ + public function activate_notice() { + if ( get_option( 'metorik_show_activation_notice', false ) ) { + echo '

' . sprintf( __( 'The Metorik Helper is active! Go back to %s to complete the connection.', 'metorik' ), 'Metorik' ) . '

'; + + // Disable notice option + update_option( 'metorik_show_activation_notice', false ); + } + } + + /** + * Get & render template file + * + * Search for the template and include the file. + * + * @author https://jeroensormani.com/how-to-add-template-files-in-your-plugin/ + * + * @see $this->locate_template() + * + * @param string $template_name Template to load. + * @param array $args Args passed for the template file. + * @param string $tempate_path Path to templates. + * @param string $default_path Default path to template files. + */ + public static function get_template( $template_name, $args = [], $tempate_path = '', $default_path = '' ) { + if ( is_array( $args ) && isset( $args ) ) { + extract( $args ); + } + + $template_file = self::locate_template( $template_name, $tempate_path, $default_path ); + + if ( ! file_exists( $template_file ) ) { + _doing_it_wrong( __FUNCTION__, sprintf( '%s does not exist.', $template_file ), '1.0.0' ); + + return; + } + + include $template_file; + } + + + /** + * Locate template. + * + * Locate the called template. + * Search Order: + * 1. /themes/theme/metorik/$template_name + * 2. /themes/theme/$template_name + * 3. /plugins/metorik/templates/$template_name. + * + * @author https://jeroensormani.com/how-to-add-template-files-in-your-plugin/ + * + * @param string $template_name Template to load. + * @param string $template_path Path to template. + * @param string $default_path Default path to template files. + * + * @return string Path to the template file. + */ + public static function locate_template( $template_name, $template_path = '', $default_path = '' ) { + // Set variable to search in metorik folder of theme. + if ( ! $template_path ) { + $template_path = 'metorik/'; + } + + // Set default plugin templates path. + if ( ! $default_path ) { + $default_path = plugin_dir_path( __FILE__ ) . 'templates/'; // Path to the template folder + } + + // Search template file in theme folder. + $template = locate_template( [ + $template_path . $template_name, + $template_name, + ] ); + + // Get plugins template file. + if ( ! $template ) { + $template = $default_path . $template_name; + } + + return apply_filters( 'metorik_locate_template', $template, $template_name, $template_path, $default_path ); + } } // Notice after it's been activated -register_activation_hook(__FILE__, array('Metorik_Helper', 'activate')); +register_activation_hook( __FILE__, [ 'Metorik_Helper', 'activate' ] ); /** * For plugin-wide access to initial instance. */ -function Metorik_Helper() -{ - return Metorik_Helper::instance(); +function Metorik_Helper() { + return Metorik_Helper::instance(); } Metorik_Helper(); diff --git a/package.json b/package.json index d8c4fd5..f0d544f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,8 @@ "devDependencies": { "gulp": "^4.0.0", "gulp-concat": "^2.6.1", - "gulp-uglify": "^3.0.1" + "gulp-uglify": "^3.0.1", + "uglify-js": "^3.17.4", + "prettier": "^3.2.5" } } diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..b97068a --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./tests/Unit/ + + + ./tests/Integration/ + + + + + + + + + + + diff --git a/readme.txt b/readme.txt old mode 100644 new mode 100755 index 0ac5f96..34d48be --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === Metorik - Reports & Email Automation for WooCommerce === -Contributors: bryceadams, metorik -Tags: woocommerce, woocommerce reports, woocommerce emails, woocommerce abandoned carts, woocommerce carts, woocommerce filtering, woocommerce google analytics, woocommerce zendesk, woocommerce help scout, woocommerce freshdesk, woocommerce support, woocommerce analytics, subscription reports, woo reports, woocommerce email, woocommerce email automation, woocommerce cart emails, woocommerce export, woocommerce csv -Requires at least: 4.4.0 -Requires PHP: 5.6.20 -Tested up to: 6.6.0 -Stable tag: trunk +Contributors: bryceadams, jkudish, metorik +Tags: woocommerce, woocommerce reports, woocommerce emails, woocommerce carts, woocommerce export +Requires at least: 5.0 +Requires PHP: 7.4 +Tested up to: 6.6.1 +Stable tag: 2.0.0 License: MIT License URI: https://opensource.org/licenses/MIT @@ -141,6 +141,15 @@ To hide the links from individual orders/products, you can click the 'Screen Opt To get them back, go to http://yoursite.com/wp-admin?show-metorik-notices=yes while logged in as an administrator. == Changelog == += 2.0.0 = +* We've overhauled the cart tracking feature in the Metorik Helper. The new method is faster and more reliable, making use of WooCommerce internal hooks instead of front-end javascript. This significantly improves the performance of the feature and improves compatibility with different checkout setups and third-party plugins. + * We've added WooCommerce Blocks support for all features of the Metorik Helper plugin, including prompting to save a cart when adding an item to cart as well as during the checkout (via a new opt-in/opt-out checkbox), cart restoration and source tracking. To take full advantage of Woo Blocks support with Metorik, please make sure to upgrade to WooCommerce 9.1 or higher. Additionally, make sure to visit your Metorik dashboard's Cart Settings page to enable some new settings for WooCommerce blocks integration. +* Cart restoration will now restore the customer's first name and e-mail into the checkout flow when possible. +* We've made several improvements to the source tracking system. We've removed the reliance on hidden fields in the checkout process, which makes the system more performant and improves compatibility with different checkout setups and third-party plugins. +* We've added several action hooks and filters to allow for further customization of the Metorik Helper's behaviour. +* We've bundled in several other minor improvements around performance and reliability into the new version of the Metorik Helper. +* For a full breakdown of the changes please see the [Metorik Help Docs](https://help.metorik.com/article/243-metorik-helper-v2) + = 1.7.2 = * Removed ability to enable cart tracking by admins through URL in admin (fixes a potential security issue where cart tracking could be disabled by an admin unintentionally). @@ -343,4 +352,4 @@ To get them back, go to http://yoursite.com/wp-admin?show-metorik-notices=yes wh * Override WC customers endpoint to make faster during imports = 0.1.0 = -* Initial beta release. \ No newline at end of file +* Initial beta release. diff --git a/templates/add-cart-email-form.php b/templates/add-cart-email-form.php index e60a1ea..fac3146 100644 --- a/templates/add-cart-email-form.php +++ b/templates/add-cart-email-form.php @@ -12,31 +12,31 @@ * * @version 1.0.4 */ -if (!defined('ABSPATH')) { - exit; +if ( ! defined( 'ABSPATH' ) ) { + exit; } // Don't allow direct access ?>
- -

+ +

- -
x
+ +
x
- - + + - - - - -
\ No newline at end of file + + + + + diff --git a/tests/Integration/CartTrackingTest.php b/tests/Integration/CartTrackingTest.php new file mode 100644 index 0000000..651c13c --- /dev/null +++ b/tests/Integration/CartTrackingTest.php @@ -0,0 +1,251 @@ +toBeTrue(); + + update_option( \Metorik_Cart_Tracking::AUTH_TOKEN_OPTION, false ); + expect( metorik_cart_tracking_enabled() )->toBeFalse(); + + update_option( \Metorik_Cart_Tracking::AUTH_TOKEN_OPTION, 'token-1234' ); + expect( metorik_cart_tracking_enabled() )->toBeTrue(); + + delete_option( \Metorik_Cart_Tracking::AUTH_TOKEN_OPTION ); + expect( metorik_cart_tracking_enabled() )->toBeFalse(); +} ); + +test( 'cart tracking is enabled based on filter', function () { + update_option( \Metorik_Cart_Tracking::AUTH_TOKEN_OPTION, 'test' ); + add_filter( 'metorik_cart_tracking_enabled', '__return_false' ); + expect( metorik_cart_tracking_enabled() )->toBeFalse(); + + remove_filter( 'metorik_cart_tracking_enabled', '__return_false' ); + expect( metorik_cart_tracking_enabled() )->toBeTrue(); + + delete_option( \Metorik_Cart_Tracking::AUTH_TOKEN_OPTION ); + expect( metorik_cart_tracking_enabled() )->toBeFalse(); + + add_filter( 'metorik_cart_tracking_enabled', '__return_true' ); + expect( metorik_cart_tracking_enabled() )->toBeTrue(); +} ); + +describe( 'cart sync tests', function () { + beforeEach( function () { + // enable cart tracking + \Metorik_Test_WC_Helpers::clear_cart_tracking_enabled(); + add_filter( 'metorik_cart_tracking_enabled', '__return_true' ); + } ); + + afterEach( function () { + // clear the cart between tests + \Metorik_Test_WC_Helpers::clear_wc_data(); + + // clear actions and filters between tests + \Metorik_Test_WC_Helpers::clear_cart_actions_and_filters(); + } ); + + test( 'no cart sync when tracking is disabled', function () { + // disable cart tracking + add_filter( 'metorik_cart_tracking_enabled', '__return_false' ); + + // Create dummy product && add to cart + $product = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + \Metorik_Test_WC_Helpers::check_cart_did_not_sync(); + } ); + + test( 'no cart sync when no customer info provided', function () { + // Create dummy product && add to cart + $product = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product->get_id() ); + + \Metorik_Test_WC_Helpers::check_cart_did_not_sync(); + } ); + + test( 'initiates cart sync when email provided and item added to cart', function () { + // Create dummy product && add to cart + $product = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 1 ); + + $cart_item = array_pop( $data['cart'] ); + expect( $cart_item['product_id'] )->toEqual( $product->get_id() ); + expect( $cart_item['quantity'] )->toEqual( 1 ); + expect( $cart_item['line_subtotal'] )->toEqual( 1 * $product->get_price() ); + expect( $data['subtotal'] )->toEqual( 1 * $product->get_price() ); + } ); + + } ); + + test( 'initiates cart sync when cart quantity modified', function () { + // Create dummy product && add to cart + $product = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + // check it synced once + \Metorik_Test_WC_Helpers::check_cart_synced_once(); + + // reset so that we can test again + \Metorik_Test_WC_Helpers::clear_between_cart_syncs(); + + $cart_contents = WC()->cart->get_cart_contents(); + $cart_item = array_pop( $cart_contents ); + WC()->cart->set_quantity( $cart_item['key'], 3 ); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 1 ); + + $cart_item = array_pop( $data['cart'] ); + expect( $cart_item['product_id'] )->toEqual( $product->get_id() ); + expect( $cart_item['quantity'] )->toEqual( 3 ); + expect( $cart_item['line_subtotal'] )->toEqual( 3 * $product->get_price() ); + expect( $data['subtotal'] )->toEqual( 3 * $product->get_price() ); + } ); + } ); + + test( 'initiates cart sync when multiple items added', function () { + // Create dummy product && add to cart + $product1 = \Metorik_Test_WC_Helpers::create_product(); + $product2 = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product1->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + // check it synced once + \Metorik_Test_WC_Helpers::check_cart_synced_once(); + + // reset so that we can test again + \Metorik_Test_WC_Helpers::clear_between_cart_syncs(); + + WC()->cart->add_to_cart( $product2->get_id() ); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product1, $product2 ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 2 ); + + $cart_item1 = array_pop( $data['cart'] ); + $cart_item2 = array_pop( $data['cart'] ); + expect( $cart_item2['product_id'] )->toEqual( $product1->get_id() ); + expect( $cart_item2['quantity'] )->toEqual( 1 ); + expect( $cart_item1['product_id'] )->toEqual( $product2->get_id() ); + expect( $cart_item1['quantity'] )->toEqual( 1 ); + expect( $data['subtotal'] )->toEqual( $product1->get_price() + $product2->get_price() ); + } ); + } ); + + test( 'initiates cart sync when cart items removed', function () { + // Create dummy product && add to cart + $product1 = \Metorik_Test_WC_Helpers::create_product(); + $product2 = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product1->get_id() ); + WC()->cart->add_to_cart( $product2->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + // check it synced once + \Metorik_Test_WC_Helpers::check_cart_synced_once(); + + // reset so that we can test again + \Metorik_Test_WC_Helpers::clear_between_cart_syncs(); + + $cart_contents = WC()->cart->get_cart_contents(); + $cart_item = array_pop( $cart_contents ); + WC()->cart->remove_cart_item( $cart_item['key'] ); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product1 ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 1 ); + + $cart_item = array_pop( $data['cart'] ); + expect( $cart_item['product_id'] )->toEqual( $product1->get_id() ); + expect( $cart_item['quantity'] )->toEqual( 1 ); + expect( $data['subtotal'] )->toEqual( $product1->get_price() ); + } ); + } ); + + test( 'initiates cart sync when coupon added and removed', function () { + // Create dummy product && add to cart + $product = \Metorik_Test_WC_Helpers::create_product(); + WC()->cart->add_to_cart( $product->get_id() ); + + // set customer email + \Metorik_Test_WC_Helpers::capture_customer_email(); + + // check it synced once + \Metorik_Test_WC_Helpers::check_cart_synced_once(); + + // reset so that we can test again + \Metorik_Test_WC_Helpers::clear_between_cart_syncs(); + + // create & add coupon + $coupon = \Metorik_Test_WC_Helpers::create_coupon(); + WC()->cart->add_discount( $coupon->get_code() ); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product, $coupon ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 1 ); + + $cart_item = array_pop( $data['cart'] ); + expect( $cart_item['product_id'] )->toEqual( $product->get_id() ); + expect( $cart_item['quantity'] )->toEqual( 1 ); + expect( $cart_item['line_subtotal'] )->toEqual( $product->get_price() ); + expect( $cart_item['line_total'] )->toEqual( $product->get_price() - $coupon->get_amount() ); + expect( $data['total'] )->toEqual( $product->get_price() - $coupon->get_amount() ); + expect( $data['total_discount'] )->toEqual( $coupon->get_amount() ); + } ); + + // reset so that we can test again + \Metorik_Test_WC_Helpers::clear_between_cart_syncs(); + + // remove coupon + WC()->cart->remove_coupon( $coupon->get_code() ); + WC()->cart->calculate_totals(); + + \Metorik_Test_WC_Helpers::check_cart_sync_outgoing_request_data( function ( $data ) use ( $product, $coupon ) { + expect( $data['email'] )->toEqual( \Metorik_Test_WC_Helpers::DEFAULT_CUSTOMER_EMAIL ); + expect( $data['cart'] )->toHaveCount( 1 ); + + $cart_item = array_pop( $data['cart'] ); + expect( $cart_item['product_id'] )->toEqual( $product->get_id() ); + expect( $cart_item['quantity'] )->toEqual( 1 ); + expect( $cart_item['line_subtotal'] )->toEqual( $product->get_price() ); + expect( $cart_item['line_total'] )->toEqual( $product->get_price() ); + expect( $data['total'] )->toEqual( $product->get_price() ); + expect( $data['total_discount'] )->toEqual( 0 ); + } ); + } ); +} ); diff --git a/tests/Integration/RestApiTest.php b/tests/Integration/RestApiTest.php new file mode 100644 index 0000000..bb47d40 --- /dev/null +++ b/tests/Integration/RestApiTest.php @@ -0,0 +1,35 @@ +server = $wp_rest_server = new \WP_REST_Server(); + do_action( 'rest_api_init', $this->server ); +} ); + +afterEach( function () { + global $wp_rest_server; + $wp_rest_server = null; + + parent::tearDown(); +} ); + +test( 'Metorik Rest API endpoints are loaded', function () { + $routes = $this->server->get_routes(); + + expect( $routes ) + ->toBeArray() + ->toHaveKey( '/wc/v1/metorik/info' ) + ->toHaveKey( '/wc/v1/metorik/importing' ) + ->toHaveKey( '/wc/v1/metorik/auth' ) + ->toHaveKey( '/wc/v1/metorik/cart-settings' ); +} ); diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..d36bcd5 --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,14 @@ +group( 'integration' )->in( 'Integration' ); +uses()->group( 'unit' )->in( 'Unit' ); + +uses( TestCase::class )->in( 'Unit', 'Integration' ); + +require_once 'helpers/wc-helpers.php'; + +function isUnitTest() { + return ! empty( $GLOBALS['argv'] ) && $GLOBALS['argv'][1] === '--group=unit'; +} diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php new file mode 100644 index 0000000..4cd2ad7 --- /dev/null +++ b/tests/Unit/ExampleTest.php @@ -0,0 +1,5 @@ +toBeTrue(); +} ); diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..82f6a31 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,54 @@ +cart->cart_contents = []; + WC()->cart->removed_cart_contents = []; + WC()->cart->shipping_methods = []; + WC()->cart->coupon_discount_totals = []; + WC()->cart->coupon_discount_tax_totals = []; + WC()->cart->applied_coupons = []; + WC()->cart->totals = WC()->cart->default_totals; + + WC()->customer->delete( true ); + WC()->session->set( 'customer', null ); + WC()->session->destroy_session(); + WC()->customer->set_defaults(); + + // reset auth token & enabled/disabled + Metorik_Cart_Tracking::reload_auth_token(); + } + + public static function clear_between_cart_syncs() { + self::clear_cart_actions_and_filters(); + WC()->session->set( Metorik_Cart_Data::LAST_CART_HASH, null ); + Metorik_Cart_Tracking::reload_auth_token(); + } + + public static function clear_cart_tracking_enabled() { + remove_all_filters( 'metorik_cart_tracking_enabled' ); + } + + public static function clear_cart_actions_and_filters() { + global $wp_actions; + unset( $wp_actions['metorik_synced_cart'] ); + remove_all_actions( 'pre_http_request' ); + remove_all_actions( 'metorik_synced_cart' ); + } + + // props WooCommerce testing suite + // https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-product.php#L35 + public static function create_product( $save = true, $props = [] ) { + $product = new WC_Product_Simple(); + $default_props = [ + 'name' => 'Dummy Product', + 'regular_price' => rand( 10, 50 ), + 'price' => rand( 10, 50 ), + 'sku' => 'DUMMY SKU ' . rand( 1, 999 ), + 'manage_stock' => false, + 'tax_status' => 'taxable', + 'downloadable' => false, + 'virtual' => false, + 'stock_status' => 'instock', + 'weight' => '1.1', + ]; + + $product->set_props( array_merge( $default_props, $props ) ); + + if ( $save ) { + $product->save(); + + return wc_get_product( $product->get_id() ); + } else { + return $product; + } + } + + // props WooCommerce testing suite + // https://github.com/woocommerce/woocommerce/blob/f2cf6b56aa762cb36eb9496b878c5c295376f16d/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-coupon.php#L20C2-L59C40 + public static function create_coupon( $coupon_code = 'mtk_coupon', $save = true, $meta = [] ) { + // Insert post + $coupon_id = wp_insert_post( [ + 'post_title' => $coupon_code, + 'post_type' => 'shop_coupon', + 'post_status' => 'publish', + 'post_excerpt' => 'This is a dummy coupon', + ] ); + + $meta = wp_parse_args( $meta, [ + 'discount_type' => 'fixed_cart', + 'coupon_amount' => '1', + 'individual_use' => 'no', + 'product_ids' => '', + 'exclude_product_ids' => '', + 'usage_limit' => '', + 'usage_limit_per_user' => '', + 'limit_usage_to_x_items' => '', + 'expiry_date' => '', + 'free_shipping' => 'no', + 'exclude_sale_items' => 'no', + 'product_categories' => [], + 'exclude_product_categories' => [], + 'minimum_amount' => '', + 'maximum_amount' => '', + 'customer_email' => [], + 'usage_count' => '0', + ] ); + + // Update meta. + foreach ( $meta as $key => $value ) { + update_post_meta( $coupon_id, $key, $value ); + } + + $coupon = new WC_Coupon( $coupon_code ); + if ( $save ) { + $coupon->save(); + } + + return $coupon; + } + + // props WooCommerce testing suite + // https://github.com/woocommerce/woocommerce/blob/f2cf6b56aa762cb36eb9496b878c5c295376f16d/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-shipping.php#L22C2-L37C1 + public static function create_flat_rate_shipping_zone( $cost = 10 ) { + $flat_rate_settings = array( + 'enabled' => 'yes', + 'title' => 'Flat rate (' . $cost . ')', + 'availability' => 'all', + 'countries' => '', + 'tax_status' => 'taxable', + 'cost' => $cost, + ); + + update_option( 'woocommerce_flat_rate_settings', $flat_rate_settings ); + update_option( 'woocommerce_flat_rate', array() ); + WC_Cache_Helper::get_transient_version( 'shipping', true ); + WC()->shipping()->load_shipping_methods(); + } + + public static function capture_customer_email( $email = self::DEFAULT_CUSTOMER_EMAIL ) { + // set customer email + WC()->customer->set_email( sanitize_email( $email ) ); + WC()->customer->set_billing_email( sanitize_email( $email ) ); + WC()->customer->save(); + } + + public static function check_cart_sync_outgoing_request_data( $callback ) { + // check the outgoing HTTP request + // returning true prevents the request from actually going out + add_action( 'pre_http_request', function ( $pre, $parsed_args, $url ) use ( $callback ) { + // only check metorik requests + if ( ! str_contains( $url, 'metorik' ) ) { + return false; + } + + expect( str_contains( $url, 'api/store/incoming/carts' ) )->toBeTrue(); + expect( $parsed_args['method'] )->toEqual( 'POST' ); + + $data = $parsed_args['body']['data']; + + $callback( $data ); + + // this prevents the request from firing off + return true; + }, 10, 3 ); + + self::simulateShutdownActionToFireOffSync(); + + // check if the action was fired but should only happen once + expect( did_action( 'metorik_synced_cart' ) )->toEqual( 1 ); + } + + public static function check_cart_synced_once() { + add_action( 'pre_http_request', function ( $pre, $parsed_args, $url ) { + // only check metorik requests + if ( ! str_contains( $url, 'metorik' ) ) { + return false; + } + + // prevent the request from firing + return true; + }, 10, 3 ); + + self::simulateShutdownActionToFireOffSync(); + + // check if the action was fired but should only happen once + expect( did_action( 'metorik_synced_cart' ) )->toEqual( 1 ); + } + + public static function check_cart_did_not_sync() { + self::simulateShutdownActionToFireOffSync(); + + // check that the action was never fired + expect( did_action( 'metorik_synced_cart' ) )->toEqual( 0 ); + } + + protected static function simulateShutdownActionToFireOffSync(): void { + // simulate the shutdown action to fire off the sync + // remove wp_ob_end_flush_all to prevent buffer error + remove_action( 'shutdown', 'wp_ob_end_flush_all', 1 ); + do_action( 'shutdown' ); + } + +} diff --git a/yarn.lock b/yarn.lock index e200682..f5d7f0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,16 +12,19 @@ ansi-colors@^1.0.1: ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw== dependencies: ansi-wrap "0.1.0" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw== anymatch@^2.0.0: version "2.0.0" @@ -34,48 +37,53 @@ anymatch@^2.0.0: append-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + integrity sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA== dependencies: buffer-equal "^1.0.0" archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== arr-filter@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" - integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= + integrity sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA== dependencies: make-iterator "^1.0.0" arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-map@^2.0.0, arr-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" - integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= + integrity sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw== dependencies: make-iterator "^1.0.0" arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== array-each@^1.0.0, array-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA== array-initial@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" - integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= + integrity sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw== dependencies: array-slice "^1.0.0" is-number "^4.0.0" @@ -90,6 +98,7 @@ array-last@^1.1.1: array-slice@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== array-sort@^1.0.0: version "1.0.0" @@ -103,10 +112,12 @@ array-sort@^1.0.0: array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== async-done@^1.2.0, async-done@^1.2.2: version "1.3.2" @@ -119,25 +130,26 @@ async-done@^1.2.0, async-done@^1.2.2: stream-exhaust "^1.0.1" async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" + integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== async-settle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" - integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= + integrity sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw== dependencies: async-done "^1.2.2" -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== bach@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" - integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= + integrity sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg== dependencies: arr-filter "^1.1.1" arr-flatten "^1.0.1" @@ -150,12 +162,14 @@ bach@^1.0.0: now-and-later "^2.0.0" balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -188,6 +202,7 @@ brace-expansion@^1.1.7: braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -201,18 +216,19 @@ braces@^2.3.1, braces@^2.3.2: to-regex "^3.0.1" buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90" + integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg== buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -224,10 +240,21 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== chokidar@^2.0.0: version "2.1.8" @@ -251,6 +278,7 @@ chokidar@^2.0.0: class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -260,7 +288,7 @@ class-utils@^0.3.5: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -269,18 +297,22 @@ cliui@^3.2.0: clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g== clone-stats@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag== clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== cloneable-readable@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + version "1.1.3" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== dependencies: inherits "^2.0.1" process-nextick-args "^2.0.0" @@ -289,12 +321,12 @@ cloneable-readable@^1.0.0: code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== collection-map@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" - integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= + integrity sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA== dependencies: arr-map "^2.0.2" for-own "^1.0.0" @@ -303,6 +335,7 @@ collection-map@^1.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -310,18 +343,17 @@ collection-visit@^1.0.0: color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + version "1.3.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.6.0: version "1.6.2" @@ -336,54 +368,57 @@ concat-stream@^1.6.0: concat-with-sourcemaps@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== dependencies: source-map "^0.6.1" convert-source-map@^1.5.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== copy-props@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" - integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== + version "2.0.5" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.5.tgz#03cf9ae328d4ebb36f8f1d804448a6af9ee3f2d2" + integrity sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw== dependencies: - each-props "^1.3.0" - is-plain-object "^2.0.1" + each-props "^1.3.2" + is-plain-object "^5.0.0" core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== dependencies: - es5-ext "^0.10.50" - type "^1.0.1" + es5-ext "^0.10.64" + type "^2.7.2" debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== default-compare@^1.0.0: version "1.0.0" @@ -395,30 +430,44 @@ default-compare@^1.0.0: default-resolution@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" - integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= + integrity sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ== -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: - object-keys "^1.0.12" + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -426,6 +475,7 @@ define-property@^2.0.2: detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== duplexify@^3.6.0: version "3.7.1" @@ -437,7 +487,7 @@ duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" -each-props@^1.3.0: +each-props@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== @@ -459,31 +509,44 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.1, es6-iterator@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== dependencies: d "1" es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== dependencies: - d "^1.0.1" - ext "^1.1.2" + d "^1.0.2" + ext "^1.7.0" es6-weak-map@^2.0.1: version "2.0.3" @@ -495,9 +558,28 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -510,25 +592,28 @@ expand-brackets@^2.1.4: expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== dependencies: homedir-polyfill "^1.0.1" -ext@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" - integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== dependencies: - type "^2.0.0" + type "^2.7.2" extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -536,10 +621,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -560,6 +647,11 @@ fancy-log@^1.3.2: parse-node-version "^1.0.0" time-stamp "^1.0.0" +fast-levenshtein@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9" + integrity sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw== + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -568,6 +660,7 @@ file-uri-to-path@1.0.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -577,7 +670,7 @@ fill-range@^4.0.0: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -585,6 +678,7 @@ find-up@^1.0.0: findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g== dependencies: detect-file "^1.0.0" is-glob "^3.1.0" @@ -602,8 +696,9 @@ findup-sync@^3.0.0: resolve-dir "^1.0.1" fined@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" + version "1.2.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" + integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== dependencies: expand-tilde "^2.0.2" is-plain-object "^2.0.3" @@ -612,8 +707,9 @@ fined@^1.0.1: parse-filepath "^1.0.1" flagged-respawn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" + version "1.0.1" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" + integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== flush-write-stream@^1.0.2: version "1.1.1" @@ -626,23 +722,26 @@ flush-write-stream@^1.0.2: for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== for-own@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg== dependencies: for-in "^1.0.1" fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + integrity sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ== dependencies: graceful-fs "^4.1.11" through2 "^2.0.3" @@ -650,34 +749,46 @@ fs-mkdirp-stream@^1.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^1.2.7: - version "1.2.11" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" - integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" nan "^2.12.1" -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -685,7 +796,7 @@ glob-parent@^3.1.0: glob-stream@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + integrity sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw== dependencies: extend "^3.0.0" glob "^7.1.1" @@ -699,32 +810,34 @@ glob-stream@^6.1.0: unique-stream "^2.0.2" glob-watcher@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" - integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + version "5.0.5" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.5.tgz#aa6bce648332924d9a8489be41e3e5c52d4186dc" + integrity sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw== dependencies: anymatch "^2.0.0" async-done "^1.2.0" chokidar "^2.0.0" is-negated-glob "^1.0.0" just-debounce "^1.0.0" + normalize-path "^3.0.0" object.defaults "^1.1.0" glob@^7.1.1: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" is-windows "^1.0.1" @@ -733,6 +846,7 @@ global-modules@^1.0.0: global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== dependencies: expand-tilde "^2.0.2" homedir-polyfill "^1.0.1" @@ -741,20 +855,28 @@ global-prefix@^1.0.1: which "^1.2.14" glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== dependencies: sparkles "^1.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== gulp-cli@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.2.0.tgz#5533126eeb7fe415a7e3e84a297d334d5cf70ebc" - integrity sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f" + integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A== dependencies: ansi-colors "^1.0.1" archy "^1.0.0" @@ -764,7 +886,7 @@ gulp-cli@^2.2.0: copy-props "^2.0.1" fancy-log "^1.3.2" gulplog "^1.0.0" - interpret "^1.1.0" + interpret "^1.4.0" isobject "^3.0.1" liftoff "^3.1.0" matchdep "^2.0.0" @@ -772,24 +894,28 @@ gulp-cli@^2.2.0: pretty-hrtime "^1.0.0" replace-homedir "^1.0.0" semver-greatest-satisfied-range "^1.1.0" - v8flags "^3.0.1" + v8flags "^3.2.0" yargs "^7.1.0" gulp-concat@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" + integrity sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg== dependencies: concat-with-sourcemaps "^1.0.0" through2 "^2.0.0" vinyl "^2.0.0" gulp-uglify@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + version "3.0.2" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.2.tgz#5f5b2e8337f879ca9dec971feb1b82a5a87850b0" + integrity sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg== dependencies: + array-each "^1.0.1" + extend-shallow "^3.0.2" gulplog "^1.0.0" has-gulplog "^0.1.0" - lodash "^4.13.1" + isobject "^3.0.1" make-error-cause "^1.1.1" safe-buffer "^5.1.2" through2 "^2.0.0" @@ -809,23 +935,38 @@ gulp@^4.0.0: gulplog@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw== dependencies: glogg "^1.0.0" has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw== dependencies: sparkles "^1.0.0" -has-symbols@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -834,6 +975,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -842,161 +984,172 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inherits@^2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ini@^1.3.4: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" - integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -interpret@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== dependencies: is-relative "^1.0.0" is-windows "^1.0.1" -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" +is-accessor-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz#3223b10628354644b86260db29b3e693f5ceedd4" + integrity sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA== dependencies: - kind-of "^6.0.0" + hasown "^2.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - kind-of "^3.0.2" + hasown "^2.0.0" -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" +is-data-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz#2109164426166d32ea38c405c1e0945d9e6a4eeb" + integrity sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw== dependencies: - kind-of "^6.0.0" + hasown "^2.0.0" is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + version "0.1.7" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.7.tgz#2727eb61fd789dcd5bdf0ed4569f551d2fe3be33" + integrity sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg== dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.3.tgz#92d27cb3cd311c4977a4db47df457234a13cb306" + integrity sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw== dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + integrity sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug== is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" @@ -1008,109 +1161,126 @@ is-number@^4.0.0: is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-relative@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== dependencies: is-unc-path "^1.0.0" is-unc-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== dependencies: unc-path-regex "^0.1.2" is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== is-valid-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + integrity sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA== is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== just-debounce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" - integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= + version "1.1.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf" + integrity sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ== kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0, kind-of@^5.0.2: +kind-of@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== last-run@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" - integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= + integrity sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ== dependencies: default-resolution "^2.0.0" es6-weak-map "^2.0.1" lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + version "1.0.1" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" + integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== dependencies: readable-stream "^2.0.5" lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== dependencies: invert-kv "^1.0.0" lead@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + integrity sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow== dependencies: flush-write-stream "^1.0.2" @@ -1131,7 +1301,7 @@ liftoff@^3.1.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -1139,41 +1309,41 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -lodash@^4.13.1: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - make-error-cause@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + integrity sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg== dependencies: make-error "^1.2.0" make-error@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== dependencies: kind-of "^6.0.2" map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" matchdep@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" - integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= + integrity sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA== dependencies: findup-sync "^2.0.0" micromatch "^3.0.4" @@ -1199,16 +1369,17 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -1216,6 +1387,7 @@ mixin-deep@^1.2.0: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== mute-stdout@^1.0.0: version "1.0.1" @@ -1223,13 +1395,14 @@ mute-stdout@^1.0.0: integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + version "2.19.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" + integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -1243,10 +1416,10 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== normalize-package-data@^2.3.2: version "2.5.0" @@ -1261,7 +1434,7 @@ normalize-package-data@^2.3.2: normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" @@ -1280,17 +1453,18 @@ now-and-later@^2.0.0: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11, object-keys@^1.0.12: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -1298,22 +1472,24 @@ object-keys@^1.0.11, object-keys@^1.0.12: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" -object.assign@^4.0.4: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.0.4, object.assign@^4.1.0: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" + object-keys "^1.1.1" object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA== dependencies: array-each "^1.0.1" array-slice "^1.0.0" @@ -1323,6 +1499,7 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: object.map@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w== dependencies: for-own "^1.0.0" make-iterator "^1.0.0" @@ -1330,13 +1507,14 @@ object.map@^1.0.0: object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" object.reduce@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" - integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= + integrity sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw== dependencies: for-own "^1.0.0" make-iterator "^1.0.0" @@ -1344,27 +1522,28 @@ object.reduce@^1.0.0: once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" ordered-read-streams@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + integrity sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw== dependencies: readable-stream "^2.0.1" os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== dependencies: lcid "^1.0.0" parse-filepath@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q== dependencies: is-absolute "^1.0.0" map-cache "^0.2.0" @@ -1373,7 +1552,7 @@ parse-filepath@^1.0.1: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== dependencies: error-ex "^1.2.0" @@ -1385,46 +1564,51 @@ parse-node-version@^1.0.0: parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== dependencies: pinkie-promise "^2.0.0" path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-parse@^1.0.5, path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-root-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ== path-root@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg== dependencies: path-root-regex "^0.1.0" path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -1433,31 +1617,39 @@ path-type@^1.0.0: pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-hrtime@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== pump@^2.0.0: version "2.0.1" @@ -1479,7 +1671,7 @@ pumpify@^1.3.5: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -1487,28 +1679,25 @@ read-pkg-up@^1.0.1: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" path-type "^1.0.0" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== +readable-stream@3: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" -readable-stream@^2.1.5, readable-stream@^2.3.5: - version "2.3.6" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -1530,12 +1719,14 @@ readdirp@^2.2.1: rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== dependencies: resolve "^1.1.6" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -1551,7 +1742,7 @@ remove-bom-buffer@^3.0.0: remove-bom-stream@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + integrity sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA== dependencies: remove-bom-buffer "^3.0.0" safe-buffer "^5.1.0" @@ -1560,23 +1751,27 @@ remove-bom-stream@^1.2.0: remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + version "1.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" + integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== replace-homedir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" - integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= + integrity sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg== dependencies: homedir-polyfill "^1.0.1" is-absolute "^1.0.0" @@ -1585,16 +1780,17 @@ replace-homedir@^1.0.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== dependencies: expand-tilde "^2.0.0" global-modules "^1.0.0" @@ -1602,75 +1798,79 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + integrity sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A== dependencies: value-or-function "^3.0.0" resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve@^1.1.6, resolve@^1.1.7: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.4.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - path-parse "^1.0.5" - -resolve@^1.10.0, resolve@^1.4.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== - dependencies: - path-parse "^1.0.6" + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -safe-buffer@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" semver-greatest-satisfied-range@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" - integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= + integrity sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ== dependencies: sver-compat "^1.5.0" "semver@2 || 3 || 4 || 5": - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -1680,6 +1880,7 @@ set-value@^2.0.0: snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -1688,12 +1889,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -1705,71 +1908,78 @@ snapdragon@^0.8.1: use "^3.1.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@^0.5.1, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sparkles@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" stack-trace@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -1780,62 +1990,68 @@ stream-exhaust@^1.0.1: integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== dependencies: is-utf8 "^0.2.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + sver-compat@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" - integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + integrity sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg== dependencies: es6-iterator "^2.0.1" es6-symbol "^3.1.1" through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.1.0.tgz#4a1b45d2b76b3ac93ec137951e372c268efc1a4e" + integrity sha512-VhZsTsfrIJjyUi6GeecnwcOJlmoqgIdGFDjqnV5ape+F1DN8GejfPO66XyIhoinxmxGImiUTrq9RwpTN5yszGA== dependencies: - through2 "~2.0.0" - xtend "~4.0.0" + through2 "^4.0.2" -through2@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^2.0.3, through2@~2.0.0: +through2@^2.0.0, through2@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -1843,14 +2059,22 @@ through2@^2.0.3, through2@~2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" +through2@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" + integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== + dependencies: + readable-stream "3" + time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw== to-absolute-glob@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + integrity sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA== dependencies: is-absolute "^1.0.0" is-negated-glob "^1.0.0" @@ -1858,12 +2082,14 @@ to-absolute-glob@^2.0.0: to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -1871,6 +2097,7 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -1880,64 +2107,60 @@ to-regex@^3.0.1, to-regex@^3.0.2: to-through@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + integrity sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q== dependencies: through2 "^2.0.3" -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -uglify-js@^3.0.5: - version "3.4.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - dependencies: - commander "~2.17.1" - source-map "~0.6.1" +uglify-js@^3.0.5, uglify-js@^3.17.4: + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== undertaker-registry@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" - integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= + integrity sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw== undertaker@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" - integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.3.0.tgz#363a6e541f27954d5791d6fa3c1d321666f86d18" + integrity sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg== dependencies: arr-flatten "^1.0.1" arr-map "^2.0.0" bach "^1.0.0" collection-map "^1.0.0" es6-weak-map "^2.0.1" + fast-levenshtein "^1.0.0" last-run "^1.1.0" object.defaults "^1.0.0" object.reduce "^1.0.0" undertaker-registry "^1.0.0" union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" - set-value "^0.4.3" + set-value "^2.0.1" unique-stream@^2.0.2: version "2.3.1" @@ -1950,6 +2173,7 @@ unique-stream@^2.0.2: unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -1962,19 +2186,22 @@ upath@^1.1.1: urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -v8flags@^3.0.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" - integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w== +v8flags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" + integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== dependencies: homedir-polyfill "^1.0.1" @@ -1989,7 +2216,7 @@ validate-npm-package-license@^3.0.1: value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + integrity sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg== vinyl-fs@^3.0.0: version "3.0.3" @@ -2017,7 +2244,7 @@ vinyl-fs@^3.0.0: vinyl-sourcemap@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + integrity sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA== dependencies: append-buffer "^1.0.2" convert-source-map "^1.5.0" @@ -2030,12 +2257,14 @@ vinyl-sourcemap@^1.1.0: vinyl-sourcemaps-apply@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + integrity sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw== dependencies: source-map "^0.5.1" vinyl@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + version "2.2.1" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== dependencies: clone "^2.1.1" clone-buffer "^1.0.0" @@ -2047,18 +2276,19 @@ vinyl@^2.0.0: which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== which@^1.2.14: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -2066,32 +2296,30 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -xtend@~4.0.0: +xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= +yargs-parser@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394" + integrity sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA== dependencies: camelcase "^3.0.0" + object.assign "^4.1.0" yargs@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= + version "7.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db" + integrity sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA== dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -2105,4 +2333,4 @@ yargs@^7.1.0: string-width "^1.0.2" which-module "^1.0.0" y18n "^3.2.1" - yargs-parser "^5.0.0" + yargs-parser "^5.0.1"