diff --git a/readthedocsext/theme/static/readthedocsext/theme/js/site.js b/readthedocsext/theme/static/readthedocsext/theme/js/site.js index dee208eb..978fa3dd 100644 --- a/readthedocsext/theme/static/readthedocsext/theme/js/site.js +++ b/readthedocsext/theme/static/readthedocsext/theme/js/site.js @@ -1,4 +1,4 @@ -(()=>{"use strict";var e,t,n,r,o,i={286:()=>{},8488:e=>{if("undefined"==typeof moment){var t=new Error("Cannot find module 'moment'");throw t.code="MODULE_NOT_FOUND",t}e.exports=moment},738:(e,t,n)=>{var r=n(9755),o=n(8527),i=n(2152),a=n(5142);function c(e){return c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c(e)}function s(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:"body";console.debug("Attaching application to selector:",e),o.applyBindings(this,r(e)[0])}},{key:"show_modal",value:function(e){return function(t,n){var o="[data-modal-id="+e+"]";console.debug("Showing modal:",o),0===r(o).modal("show").length&&console.debug("Modal not found:",o)}}},{key:"post_child_form",value:function(e,t){var n=t.currentTarget.querySelector(":scope > form");return n&&n.submit(),!1}}],n&&s(t.prototype,n),i&&s(t,i),Object.defineProperty(t,"prototype",{writable:!1}),e}();globalThis.jQuery=r;var f=n(2876),d=(n(4238),n(7239),n(8105),n(7030),n(83),n(4567),n(1714),n(5082),n(8225),n(4696),n(5812),n(2208),n(3441),n(4671),n(9610),n(4115),n(2445),n(6426),n(3150),n(8329),n(1307),n(8182),n(9755));function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],s=!0,u=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;s=!1}else for(;!(s=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);s=!0);}catch(e){u=!0,o=e}finally{try{if(!s&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return b(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1?o-1:0),c=1;c1&&void 0!==arguments[1]&&arguments[1])&&(t.trackLocalhost=!0);var n=(0,f.Z)(t).trackEvent;return(0,(0,f.Z)(t).trackPageview)(),this.each((function(e,t){var o,i,a=r(t).data(),c=(null===(o=a.analyticsEvents)||void 0===o?void 0:o.split(/,/))||(null===(i=a.analytics)||void 0===i?void 0:i.split(/,/))||[],s={};function u(e){var r=null!=t.tagName&&"a"==t.tagName.toLowerCase(),o="auxclick"==e.type&&2==e.which,i="click"==e.type,a=r&&i&&!t.target&&!(e.ctrlKey||e.metaKey||e.shiftKey);if((o||i)&&Promise.all(c.map((function(e){return new Promise((function(t,r){n(e,{callback:t,props:s}),setTimeout((function(){r()}),1e3)}))}))).catch((function(e){console.debug("Plausible didn't receive a response for one or more event")})).finally((function(){console.debug("Plausible tracked events:",c,s),a&&t.href&&"#"!=t.href&&(console.debug("Plausible replaying click event",t.href),window.location=t.href)})),a)return e.preventDefault(),!1}Object.keys(a).forEach((function(e){var t=e.match(/analyticsProperty(.*)/);if(t){var n=p(t,2),r=(n[0],n[1]);s[r.toLowerCase()]=a[e]}})),t.addEventListener("click",u),t.addEventListener("auxclick",u)}))}function E(e){return this.each((function(t,n){d(n).find(".item").tab(e)}))}function j(e){return j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},j(e)}function P(e,t,n){return P=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&x(o,n.prototype),o},P.apply(null,arguments)}function x(e,t){return x=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},x(e,t)}function A(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],s=!0,u=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;s=!1}else for(;!(s=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);s=!0);}catch(e){u=!0,o=e}finally{try{if(!s&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return N(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return N(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function N(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){c=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(c)throw i}}}}function q(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&n.is_expanded(!0)})),this.output=o.observable(),this.output_lines=o.computed((function(){return n.output().split(/\n/).map((function(e,t){return new J({command:n,output:e,line_number:t+1})}))}),null,{deferEvaluation:!0}),this.output(t.output)}return V(e,[{key:"color_output",value:function(e){return n.e("ansi_up").then(n.t.bind(n,4431,19)).then((function(t){var n=new(0,t.default);return n.use_classes=!0,e=n.ansi_to_html(e)}))}},{key:"toggle_expanded",value:function(){return this.is_expanded(!this.is_expanded()),!1}}]),e}(),K=function(){function e(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1?arguments[1]:void 0,a=arguments.length>2?arguments[2]:void 0;Y(this,e),this.id=n.id,this.url_api_build=i,this.url_api_notifications=a,this.success=o.observable(n.success),this.error=o.observable(n.error),this.notifications=o.observableArray(),this.has_notifications=o.computed((function(){return t.notifications().length>0})),this.state=o.observable(n.state),this.state_display=o.observable(n.state_display),this.is_finished=o.observable(!1),this.is_loading=o.observable(!0),this.can_cancel=o.observable(!1),this.can_retry=o.observable(!1),this.can_view_docs=o.observable(!1),this.is_wrapped=o.observable(!0),this.state.subscribe((function(e){t.update_state(e)})),this.progress_config=o.computed((function(){var e=t.state(),n=["triggered","queued","cloning","installing","building","uploading","finished"];if(o.computedContext.isInitial())return{autoSuccess:!1,value:n.indexOf(e),total:n.length-1,label:t.state_display()};if(t.is_finished()){var r="cancelled"===e,i=t.error()||!1===t.success();return r?function(e){e("set warning","Build cancelled")}:i?function(e){e("set error","Build failed")}:function(e){e("set success","Build succeeded")}}return function(r){r("set progress",n.indexOf(e)),r("set label",t.state_display())}})).extend({deferred:!0}),this.date=o.observable(n.date),this.length=o.observable(n.length),this.date_display=o.observable(),this.date_display_since=o.observable(),this.length_display=o.observable(),this.date.subscribe((function(e){var n=U(e);t.date_display(n.format("llll")),t.date_display_since(n.fromNow())})),this.length.subscribe((function(e){var n;if(e)n=U.duration(e,"seconds");else{var r=U(),o=U(t.date());n=U.duration(r.diff(o))}var i=["s[s]"];n.minutes()&&i.unshift("m[m]"),n.hours()&&i.unshift("H[h]"),t.length_display(n.format(i.join(" ")))})),this.config=o.observable(),this.builder=o.observable(n.builder),this.commands=o.observableArray(n.commands),this.commit=o.observable(n.commit),this.commit_short=o.computed((function(){var e=t.commit();if(e)return e.substring(0,8)})),this.docs_url=o.observable(n.docs_url),this.commit_url=o.observable(n.commit_url),this.legacy_output=o.observable(!1),this.selected_hash=o.observable(r(location).attr("hash")),this.selected_hash.subscribe((function(e){r(location).attr("hash",e)})),this.selected_line=o.observable(),this.selected_line.subscribe((function(e){e&&e.is_selected(!1)}),this,"beforeChange"),this.selected_line.subscribe((function(e){e.command.is_debug()&&t.show_debug(!0),e.command.is_expanded(!0),e.is_selected(!0),t.selected_hash(e.anchor_id())})),this.show_debug=o.observable(!1),this.is_polling=o.observable(!0),this.is_polling.subscribe((function(e){e||t.set_selected_line_from_hash(t.selected_hash())})),this.url_api_build&&this.poll_api_build(),this.url_api_notifications&&this.poll_api_notifications()}return V(e,[{key:"poll_api_build",value:function(){var e=this;r.getJSON(this.url_api_build).then((function(t){e.date(t.date),e.success(t.success),e.error(t.error),e.length(t.length),e.commit(t.commit),e.docs_url(t.docs_url),e.commit_url(t.commit_url),e.builder(t.builder),e.config(t.config),e.state(t.state),e.state_display(t.state_display),e.date.valueHasMutated(),e.length.valueHasMutated(),e.add_command({id:0,command:"readthedocs-build --show-config",output:JSON.stringify(t.config,null," "),exit_code:0,run_time:0,is_debug:!0});var n,r=W(t.commands);try{for(r.s();!(n=r.n()).done;){var o=n.value;e.add_command(o)}}catch(e){r.e(e)}finally{r.f()}e.is_loading(!1)})).then((function(){e.is_finished()?e.is_polling(!1):setTimeout((function(){e.poll_api_build(),e.poll_api_notifications()}),2e3)}))}},{key:"poll_api_notifications",value:function(){var e=this;r.getJSON(this.url_api_notifications,{state__in:"read,unread"}).then((function(t){t.results&&e.notifications(t.results)}))}},{key:"add_command",value:function(e){var t=o.utils.arrayFirst(this.commands(),(function(t){return t.id()===e.id}));t?(t.output(e.output),t.exit_code(e.exit_code||0),t.run_time(e.run_time),t.end_time(e.end_time)):this.commands.push(new X(e))}},{key:"set_selected_line",value:function(e){this.selected_line(e);var t=document.querySelector("[data-selected=true]");return t&&(t.scrollIntoView?t.scrollIntoView({behavior:"auto",block:"center",inline:"center"}):r(t).focus()),!1}},{key:"set_selected_line_from_hash",value:function(e){if(e){var t=e.match(/^#(\d+)--(\d+)$/);if(!t)return;var n=o.utils.arrayFirst(this.commands(),(function(e){return e.id()==t[1]}));if(n){var r=o.utils.arrayFirst(n.output_lines(),(function(e){return e.line_number()==t[2]}));r&&this.set_selected_line(r)}}}},{key:"show_legacy_output",value:function(){this.legacy_output(!0)}},{key:"toggle_debug",value:function(){var e=this.show_debug();this.show_debug(!e)}},{key:"update_state",value:function(e){["finished","cancelled"].includes(e)?(this.is_finished(!0),this.can_cancel(!1),this.can_retry(!0),this.success()&&this.can_view_docs(!0)):this.can_cancel(!0)}}]),e}();function Z(e){return Z="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Z(e)}function Q(e,t){for(var n=0;n=re[o];t.device[o](i)}}));var n=r(window),i=function(){t.viewport_width(n.width())};n.on("resize",i),i()})),ie=function(){function e(t){ne(this,e),this.id=t.id,this.url=t.url,this.loaded=o.observable(!1),this.loading=o.observable(!1),this.promise=null,this.data=o.observable()}return ee(e,[{key:"fetch",value:function(){var e=this;if(this.promise)return this.promise;this.promise=new Promise((function(t,n){if(e.loaded())return t(e.data());e.loading(!0),r.getJSON(e.url).then((function(n){return e.data(n),e.loaded(!0),e.loading(!1),t(n)}))}))}}]),e}(),ae=ee((function e(){var t=this;ne(this,e),this.config=o.observable(),this.search_project_config=o.observable(),this.config.subscribe((function(e){if(void 0!==e){var n=new URL(e.api_projects_list_url,window.location.origin);n.search="?name={query}",t.search_project_config({type:"category",apiSettings:{url:n.href,onResponse:function(e){return{results:{"category-projects":{name:"Projects",results:e.results.map((function(e,t){var n=e.slug;e.subproject_of?n="Subproject of "+e.subproject_of.name:e.translation_of&&(n=e.language.name+" translation of "+e.translation_of.name);var r=new URL(e.urls.home),o=new URL(window.location.href);return r.hostname!=o.hostname&&(r.hostname=o.hostname),{title:e.name,description:n,url:r.toString()}}))}}}}},minCharacters:2})}}))}));!function(e,t,n){(t=te(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}(ae,"view_name","HeaderView"),M.add_view(ae);var ce=n(6566);function se(e){return se="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},se(e)}function ue(e,t){for(var n=0;n"])))}},{key:"updated",value:function(e){if(e.has("seed")&&this.seed){var t=pe.ZP.xoroshiro128plus(this.seed),n=pe.ZP.unsafeUniformIntDistribution(0,99,t),r=pe.ZP.unsafeUniformIntDistribution(0,99,t);this.style.setProperty("--avatar-x",n),this.style.setProperty("--avatar-y",r)}e.has("url")&&this.url&&this.style.setProperty("--avatar-background-image",'url("'.concat(this.url,'")'))}}])&&Ee(t.prototype,n),r&&Ee(t,r),Object.defineProperty(t,"prototype",{writable:!1}),i}(de.oi);function Ce(e){return Ce="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ce(e)}function Ie(e,t){for(var n=0;n div {\n background-image: var(--avatar-background-image);\n background-repeat: no-repeat;\n background-size: calc(100 * -1 * var(--avatar-scale))\n calc(100 * -1 * var(--avatar-scale));\n background-position-x: calc(var(--avatar-x) * var(--avatar-scale));\n background-position-y: calc(var(--avatar-y) * var(--avatar-scale));\n image-rendering: pixelated;\n width: calc(var(--avatar-scale) * -4);\n height: calc(var(--avatar-scale) * -4);\n }\n "])))),customElements.define("readthedocs-avatar",Re);var De=function(){function e(){var t=this,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.is_collapsed=o.observable(n),this.dropdown_class=o.computed((function(){return t.is_collapsed()?"fa-caret-down":"fa-caret-up"}))}var t,n,r;return t=e,n=[{key:"toggle_collapsed",value:function(){var e=this.is_collapsed();this.is_collapsed(!e)}}],n&&Ie(t.prototype,n),r&&Ie(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function Me(e){return Me="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Me(e)}function Ue(e,t){for(var n=0;n\n \n \n '])),(0,Qe.$)({disabled:this.disabled,loading:!this.disabled&&this.state===yt.LOADING}),(null===(e=this.data)||void 0===e||null===(e=e.urls)||void 0===e?void 0:e.documentation)||"#",this.queueEvent,t,t,(0,et.g)(!this.disabled,(function(){return(0,de.dy)(We||(We=nt(["0"])))}),(function(){return(0,de.dy)(qe||(qe=nt(["-1"])))})))}}]),n}(_t);customElements.define("readthedocs-item-docs",wt);var St=function(e){at(n,e);var t=st(n);function n(){return rt(this,n),t.apply(this,arguments)}return it(n,[{key:"render",value:function(){var e,t,n,r,o,i,a=this.label||(0,Ze.WI)("Offline formats");return(0,de.dy)(Ge||(Ge=nt(['\n \n \n \n \n "])),(0,Qe.$)({disabled:this.disabled}),a,a,(0,et.g)(this.disabled,(function(){return(0,de.dy)(Ve||(Ve=nt(["0"])))}),(function(){return(0,de.dy)($e||($e=nt(["-1"])))})),(0,Ze.WI)("Offline formats"),null===(e=this.data)||void 0===e||null===(e=e.downloads)||void 0===e?void 0:e.pdf,(0,Qe.$)({disabled:!(null!==(t=this.data)&&void 0!==t&&null!==(t=t.downloads)&&void 0!==t&&t.pdf)}),(0,Ze.WI)("PDF file"),null===(n=this.data)||void 0===n||null===(n=n.downloads)||void 0===n?void 0:n.epub,(0,Qe.$)({disabled:!(null!==(r=this.data)&&void 0!==r&&null!==(r=r.downloads)&&void 0!==r&&r.epub)}),(0,Ze.WI)("ePUB file"),null===(o=this.data)||void 0===o||null===(o=o.downloads)||void 0===o?void 0:o.htmlzip,(0,Qe.$)({disabled:!(null!==(i=this.data)&&void 0!==i&&null!==(i=i.downloads)&&void 0!==i&&i.htmlzip)}),(0,Ze.WI)("HTML archive"))}}]),n}(_t);customElements.define("readthedocs-item-downloads",St);var Ot=function(e){at(n,e);var t=st(n);function n(){return rt(this,n),t.apply(this,arguments)}return it(n,[{key:"render",value:function(){var e,t,n=null===(e=this.data)||void 0===e||null===(e=e.permissions)||void 0===e?void 0:e.admin,r=(null===(t=this.data)||void 0===t||null===(t=t.urls)||void 0===t?void 0:t.settings)||this.urlSettings;return(0,de.dy)(Ye||(Ye=nt(['\n
','
\n \n \n ',"\n \n "])),(0,Ze.WI)("Admin"),(0,Qe.$)({disabled:!n}),r,(0,Ze.WI)("Configure project"))}}],[{key:"properties",get:function(){var e=_t.properties;return e.urlSettings={type:String,attribute:"url-settings"},e}}]),n}(_t);customElements.define("readthedocs-menu-project-admin",Ot);var Tt=n(2386),kt=n(3011); +(()=>{"use strict";var e,t,n,r,o,i={286:()=>{},8488:e=>{if("undefined"==typeof moment){var t=new Error("Cannot find module 'moment'");throw t.code="MODULE_NOT_FOUND",t}e.exports=moment},6099:(e,t,n)=>{var r=n(9755),o=n(8527),i=n(2152),a=n(5142);function c(e){return c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c(e)}function u(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return s(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){c=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(c)throw i}}}}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:"body";console.debug("Attaching application to selector:",e),o.applyBindings(this,r(e)[0])}},{key:"show_modal",value:function(e){return function(t,n){var o="[data-modal-id="+e+"]";console.debug("Showing modal:",o),0===r(o).modal("show").length&&console.debug("Modal not found:",o);var i,a=u(document.querySelectorAll(".button.ui"));try{for(a.s();!(i=a.n()).done;){var c=i.value;if(c.dataset.variation){var s=c.dataset.variation.split(" ");s.pop("visible"),c.dataset.variation=s.join(" ")}}}catch(e){a.e(e)}finally{a.f()}}}},{key:"post_child_form",value:function(e,t){var n=t.currentTarget.querySelector(":scope > form");return n&&n.submit(),!1}}],n&&l(t.prototype,n),i&&l(t,i),Object.defineProperty(t,"prototype",{writable:!1}),e}();globalThis.jQuery=r;var p=n(2876),b=(n(4238),n(7239),n(8105),n(7030),n(83),n(4567),n(1714),n(5082),n(8225),n(4696),n(5812),n(2208),n(3441),n(4671),n(9610),n(4115),n(2445),n(6426),n(3150),n(8329),n(1307),n(8182),n(9755));function m(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],u=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);u=!0);}catch(e){s=!0,o=e}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw o}}return c}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return h(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return h(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1?o-1:0),c=1;c1&&void 0!==arguments[1]&&arguments[1])&&(t.trackLocalhost=!0);var n=(0,p.Z)(t).trackEvent;return(0,(0,p.Z)(t).trackPageview)(),this.each((function(e,t){var o,i,a=r(t).data(),c=(null===(o=a.analyticsEvents)||void 0===o?void 0:o.split(/,/))||(null===(i=a.analytics)||void 0===i?void 0:i.split(/,/))||[],u={};function s(e){var r=null!=t.tagName&&"a"==t.tagName.toLowerCase(),o="auxclick"==e.type&&2==e.which,i="click"==e.type,a=r&&i&&!t.target&&!(e.ctrlKey||e.metaKey||e.shiftKey);if((o||i)&&Promise.all(c.map((function(e){return new Promise((function(t,r){n(e,{callback:t,props:u}),setTimeout((function(){r()}),1e3)}))}))).catch((function(e){console.debug("Plausible didn't receive a response for one or more event")})).finally((function(){console.debug("Plausible tracked events:",c,u),a&&t.href&&"#"!=t.href&&(console.debug("Plausible replaying click event",t.href),window.location=t.href)})),a)return e.preventDefault(),!1}Object.keys(a).forEach((function(e){var t=e.match(/analyticsProperty(.*)/);if(t){var n=m(t,2),r=(n[0],n[1]);u[r.toLowerCase()]=a[e]}})),t.addEventListener("click",s),t.addEventListener("auxclick",s)}))}function P(e){return this.each((function(t,n){b(n).find(".item").tab(e)}))}function A(e){return A="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},A(e)}function x(e,t,n){return x=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&N(o,n.prototype),o},x.apply(null,arguments)}function N(e,t){return N=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},N(e,t)}function R(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],u=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);u=!0);}catch(e){s=!0,o=e}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw o}}return c}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return C(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return C(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function C(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){c=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(c)throw i}}}}function X(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&n.is_expanded(!0)})),this.output=o.observable(),this.output_lines=o.computed((function(){return n.output().split(/\n/).map((function(e,t){return new te({command:n,output:e,line_number:t+1})}))}),null,{deferEvaluation:!0}),this.output(t.output)}return Z(e,[{key:"color_output",value:function(e){return n.e("ansi_up").then(n.t.bind(n,4431,19)).then((function(t){var n=new(0,t.default);return n.use_classes=!0,e=n.ansi_to_html(e)}))}},{key:"toggle_expanded",value:function(){return this.is_expanded(!this.is_expanded()),!1}}]),e}(),re=function(){function e(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1?arguments[1]:void 0,a=arguments.length>2?arguments[2]:void 0;ee(this,e),this.id=n.id,this.url_api_build=i,this.url_api_notifications=a,this.success=o.observable(n.success),this.error=o.observable(n.error),this.notifications=o.observableArray(),this.has_notifications=o.computed((function(){return t.notifications().length>0})),this.state=o.observable(n.state),this.state_display=o.observable(n.state_display),this.is_finished=o.observable(!1),this.is_loading=o.observable(!0),this.can_cancel=o.observable(!1),this.can_retry=o.observable(!1),this.can_view_docs=o.observable(!1),this.is_wrapped=o.observable(!0),this.state.subscribe((function(e){t.update_state(e)})),this.progress_config=o.computed((function(){var e=t.state(),n=["triggered","queued","cloning","installing","building","uploading","finished"];if(o.computedContext.isInitial())return{autoSuccess:!1,value:n.indexOf(e),total:n.length-1,label:t.state_display()};if(t.is_finished()){var r="cancelled"===e,i=t.error()||!1===t.success();return r?function(e){e("set warning","Build cancelled")}:i?function(e){e("set error","Build failed")}:function(e){e("set success","Build succeeded")}}return function(r){r("set progress",n.indexOf(e)),r("set label",t.state_display())}})).extend({deferred:!0}),this.date=o.observable(n.date),this.length=o.observable(n.length),this.date_display=o.observable(),this.date_display_since=o.observable(),this.length_display=o.observable(),this.date.subscribe((function(e){var n=q(e);t.date_display(n.format("llll")),t.date_display_since(n.fromNow())})),this.length.subscribe((function(e){var n;if(e)n=q.duration(e,"seconds");else{var r=q(),o=q(t.date());n=q.duration(r.diff(o))}var i=["s[s]"];n.minutes()&&i.unshift("m[m]"),n.hours()&&i.unshift("H[h]"),t.length_display(n.format(i.join(" ")))})),this.config=o.observable(),this.builder=o.observable(n.builder),this.commands=o.observableArray(n.commands),this.commit=o.observable(n.commit),this.commit_short=o.computed((function(){var e=t.commit();if(e)return e.substring(0,8)})),this.docs_url=o.observable(n.docs_url),this.commit_url=o.observable(n.commit_url),this.legacy_output=o.observable(!1),this.selected_hash=o.observable(r(location).attr("hash")),this.selected_hash.subscribe((function(e){r(location).attr("hash",e)})),this.selected_line=o.observable(),this.selected_line.subscribe((function(e){e&&e.is_selected(!1)}),this,"beforeChange"),this.selected_line.subscribe((function(e){e.command.is_debug()&&t.show_debug(!0),e.command.is_expanded(!0),e.is_selected(!0),t.selected_hash(e.anchor_id())})),this.show_debug=o.observable(!1),this.is_polling=o.observable(!0),this.is_polling.subscribe((function(e){e||t.set_selected_line_from_hash(t.selected_hash())})),this.url_api_build&&this.poll_api_build(),this.url_api_notifications&&this.poll_api_notifications()}return Z(e,[{key:"poll_api_build",value:function(){var e=this;r.getJSON(this.url_api_build).then((function(t){e.date(t.date),e.success(t.success),e.error(t.error),e.length(t.length),e.commit(t.commit),e.docs_url(t.docs_url),e.commit_url(t.commit_url),e.builder(t.builder),e.config(t.config),e.state(t.state),e.state_display(t.state_display),e.date.valueHasMutated(),e.length.valueHasMutated(),e.add_command({id:0,command:"readthedocs-build --show-config",output:JSON.stringify(t.config,null," "),exit_code:0,run_time:0,is_debug:!0});var n,r=J(t.commands);try{for(r.s();!(n=r.n()).done;){var o=n.value;e.add_command(o)}}catch(e){r.e(e)}finally{r.f()}e.is_loading(!1)})).then((function(){e.is_finished()?e.is_polling(!1):setTimeout((function(){e.poll_api_build(),e.poll_api_notifications()}),2e3)}))}},{key:"poll_api_notifications",value:function(){var e=this;r.getJSON(this.url_api_notifications,{state__in:"read,unread"}).then((function(t){t.results&&e.notifications(t.results)}))}},{key:"add_command",value:function(e){var t=o.utils.arrayFirst(this.commands(),(function(t){return t.id()===e.id}));t?(t.output(e.output),t.exit_code(e.exit_code||0),t.run_time(e.run_time),t.end_time(e.end_time)):this.commands.push(new ne(e))}},{key:"set_selected_line",value:function(e){this.selected_line(e);var t=document.querySelector("[data-selected=true]");return t&&(t.scrollIntoView?t.scrollIntoView({behavior:"auto",block:"center",inline:"center"}):r(t).focus()),!1}},{key:"set_selected_line_from_hash",value:function(e){if(e){var t=e.match(/^#(\d+)--(\d+)$/);if(!t)return;var n=o.utils.arrayFirst(this.commands(),(function(e){return e.id()==t[1]}));if(n){var r=o.utils.arrayFirst(n.output_lines(),(function(e){return e.line_number()==t[2]}));r&&this.set_selected_line(r)}}}},{key:"show_legacy_output",value:function(){this.legacy_output(!0)}},{key:"toggle_debug",value:function(){var e=this.show_debug();this.show_debug(!e)}},{key:"update_state",value:function(e){["finished","cancelled"].includes(e)?(this.is_finished(!0),this.can_cancel(!1),this.can_retry(!0),this.success()&&this.can_view_docs(!0)):this.can_cancel(!0)}}]),e}();function oe(e){return oe="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},oe(e)}function ie(e,t){for(var n=0;n=se[o];t.device[o](i)}}));var n=r(window),i=function(){t.viewport_width(n.width())};n.on("resize",i),i()})),fe=function(){function e(t){ue(this,e),this.id=t.id,this.url=t.url,this.loaded=o.observable(!1),this.loading=o.observable(!1),this.promise=null,this.data=o.observable()}return ae(e,[{key:"fetch",value:function(){var e=this;if(this.promise)return this.promise;this.promise=new Promise((function(t,n){if(e.loaded())return t(e.data());e.loading(!0),r.getJSON(e.url).then((function(n){return e.data(n),e.loaded(!0),e.loading(!1),t(n)}))}))}}]),e}(),de=ae((function e(){var t=this;ue(this,e),this.config=o.observable(),this.search_project_config=o.observable(),this.config.subscribe((function(e){if(void 0!==e){var n=new URL(e.api_projects_list_url,window.location.origin);n.search="?name={query}",t.search_project_config({type:"category",apiSettings:{url:n.href,onResponse:function(e){return{results:{"category-projects":{name:"Projects",results:e.results.map((function(e,t){var n=e.slug;e.subproject_of?n="Subproject of "+e.subproject_of.name:e.translation_of&&(n=e.language.name+" translation of "+e.translation_of.name);var r=new URL(e.urls.home),o=new URL(window.location.href);return r.hostname!=o.hostname&&(r.hostname=o.hostname),{title:e.name,description:n,url:r.toString()}}))}}}}},minCharacters:2})}}))}));!function(e,t,n){(t=ce(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}(de,"view_name","HeaderView"),z.add_view(de);var pe=n(6566);function be(e){return be="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},be(e)}function me(e,t){for(var n=0;n"])))}},{key:"updated",value:function(e){if(e.has("seed")&&this.seed){var t=ge.ZP.xoroshiro128plus(this.seed),n=ge.ZP.unsafeUniformIntDistribution(0,99,t),r=ge.ZP.unsafeUniformIntDistribution(0,99,t);this.style.setProperty("--avatar-x",n),this.style.setProperty("--avatar-y",r)}e.has("url")&&this.url&&this.style.setProperty("--avatar-background-image",'url("'.concat(this.url,'")'))}}])&&Re(t.prototype,n),r&&Re(t,r),Object.defineProperty(t,"prototype",{writable:!1}),i}(ye.oi);function ze(e){return ze="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ze(e)}function He(e,t){for(var n=0;n div {\n background-image: var(--avatar-background-image);\n background-repeat: no-repeat;\n background-size: calc(100 * -1 * var(--avatar-scale))\n calc(100 * -1 * var(--avatar-scale));\n background-position-x: calc(var(--avatar-x) * var(--avatar-scale));\n background-position-y: calc(var(--avatar-y) * var(--avatar-scale));\n image-rendering: pixelated;\n width: calc(var(--avatar-scale) * -4);\n height: calc(var(--avatar-scale) * -4);\n }\n "])))),customElements.define("readthedocs-avatar",Ue);var Fe=function(){function e(){var t=this,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.is_collapsed=o.observable(n),this.dropdown_class=o.computed((function(){return t.is_collapsed()?"fa-caret-down":"fa-caret-up"}))}var t,n,r;return t=e,n=[{key:"toggle_collapsed",value:function(){var e=this.is_collapsed();this.is_collapsed(!e)}}],n&&He(t.prototype,n),r&&He(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function We(e){return We="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},We(e)}function qe(e,t){for(var n=0;n\n \n \n '])),(0,it.$)({disabled:this.disabled,loading:!this.disabled&&this.state===Tt.LOADING}),(null===(e=this.data)||void 0===e||null===(e=e.urls)||void 0===e?void 0:e.documentation)||"#",this.queueEvent,t,t,(0,at.g)(!this.disabled,(function(){return(0,ye.dy)(Je||(Je=ut(["0"])))}),(function(){return(0,ye.dy)(Xe||(Xe=ut(["-1"])))})))}}]),n}(Et);customElements.define("readthedocs-item-docs",jt);var Pt=function(e){dt(n,e);var t=bt(n);function n(){return st(this,n),t.apply(this,arguments)}return ft(n,[{key:"render",value:function(){var e,t,n,r,o,i,a=this.label||(0,ot.WI)("Offline formats");return(0,ye.dy)(Ke||(Ke=ut(['\n \n \n \n \n "])),(0,it.$)({disabled:this.disabled}),a,a,(0,at.g)(this.disabled,(function(){return(0,ye.dy)(Ze||(Ze=ut(["0"])))}),(function(){return(0,ye.dy)(Qe||(Qe=ut(["-1"])))})),(0,ot.WI)("Offline formats"),null===(e=this.data)||void 0===e||null===(e=e.downloads)||void 0===e?void 0:e.pdf,(0,it.$)({disabled:!(null!==(t=this.data)&&void 0!==t&&null!==(t=t.downloads)&&void 0!==t&&t.pdf)}),(0,ot.WI)("PDF file"),null===(n=this.data)||void 0===n||null===(n=n.downloads)||void 0===n?void 0:n.epub,(0,it.$)({disabled:!(null!==(r=this.data)&&void 0!==r&&null!==(r=r.downloads)&&void 0!==r&&r.epub)}),(0,ot.WI)("ePUB file"),null===(o=this.data)||void 0===o||null===(o=o.downloads)||void 0===o?void 0:o.htmlzip,(0,it.$)({disabled:!(null!==(i=this.data)&&void 0!==i&&null!==(i=i.downloads)&&void 0!==i&&i.htmlzip)}),(0,ot.WI)("HTML archive"))}}]),n}(Et);customElements.define("readthedocs-item-downloads",Pt);var At=function(e){dt(n,e);var t=bt(n);function n(){return st(this,n),t.apply(this,arguments)}return ft(n,[{key:"render",value:function(){var e,t,n=null===(e=this.data)||void 0===e||null===(e=e.permissions)||void 0===e?void 0:e.admin,r=(null===(t=this.data)||void 0===t||null===(t=t.urls)||void 0===t?void 0:t.settings)||this.urlSettings;return(0,ye.dy)(et||(et=ut(['\n
','
\n \n \n ',"\n \n "])),(0,ot.WI)("Admin"),(0,it.$)({disabled:!n}),r,(0,ot.WI)("Configure project"))}}],[{key:"properties",get:function(){var e=Et.properties;return e.urlSettings={type:String,attribute:"url-settings"},e}}]),n}(Et);customElements.define("readthedocs-menu-project-admin",At);var xt=n(2386),Nt=n(3011); /*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */ -const{entries:Et,setPrototypeOf:jt,isFrozen:Pt,getPrototypeOf:xt,getOwnPropertyDescriptor:At}=Object;let{freeze:Nt,seal:Rt,create:Ct}=Object,{apply:It,construct:Lt}="undefined"!=typeof Reflect&&Reflect;Nt||(Nt=function(e){return e}),Rt||(Rt=function(e){return e}),It||(It=function(e,t,n){return e.apply(t,n)}),Lt||(Lt=function(e,t){return new e(...t)});const Dt=Jt(Array.prototype.forEach),Mt=Jt(Array.prototype.pop),Ut=Jt(Array.prototype.push),zt=Jt(String.prototype.toLowerCase),Ht=Jt(String.prototype.toString),Bt=Jt(String.prototype.match),Ft=Jt(String.prototype.replace),Wt=Jt(String.prototype.indexOf),qt=Jt(String.prototype.trim),Gt=Jt(Object.prototype.hasOwnProperty),Vt=Jt(RegExp.prototype.test),$t=(Yt=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),o=1;o2&&void 0!==arguments[2]?arguments[2]:zt;jt&&jt(e,null);let r=t.length;for(;r--;){let o=t[r];if("string"==typeof o){const e=n(o);e!==o&&(Pt(t)||(t[r]=e),o=e)}e[o]=!0}return e}function Kt(e){for(let t=0;t/gm),bn=Rt(/\${[\w\W]*}/gm),mn=Rt(/^data-[\-\w.\u00B7-\uFFFF]/),hn=Rt(/^aria-[\-\w]+$/),vn=Rt(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),yn=Rt(/^(?:\w+script|data):/i),gn=Rt(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),_n=Rt(/^html$/i),wn=Rt(/^[a-z][.\w]*(-[.\w]+)+$/i);var Sn=Object.freeze({__proto__:null,ARIA_ATTR:hn,ATTR_WHITESPACE:gn,CUSTOM_ELEMENT:wn,DATA_ATTR:mn,DOCTYPE_NAME:_n,ERB_EXPR:pn,IS_ALLOWED_URI:vn,IS_SCRIPT_OR_DATA:yn,MUSTACHE_EXPR:dn,TMPLIT_EXPR:bn});const On=1,Tn=3,kn=7,En=8,jn=9,Pn=function(){return"undefined"==typeof window?null:window};var xn,An,Nn=function e(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Pn();const n=t=>e(t);if(n.version="3.2.2",n.removed=[],!t||!t.document||t.document.nodeType!==jn)return n.isSupported=!1,n;let{document:r}=t;const o=r,i=o.currentScript,{DocumentFragment:a,HTMLTemplateElement:c,Node:s,Element:u,NodeFilter:l,NamedNodeMap:f=t.NamedNodeMap||t.MozNamedAttrMap,HTMLFormElement:d,DOMParser:p,trustedTypes:b}=t,m=u.prototype,h=Qt(m,"cloneNode"),v=Qt(m,"remove"),y=Qt(m,"nextSibling"),g=Qt(m,"childNodes"),_=Qt(m,"parentNode");if("function"==typeof c){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let w,S="";const{implementation:O,createNodeIterator:T,createDocumentFragment:k,getElementsByTagName:E}=r,{importNode:j}=o;let P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};n.isSupported="function"==typeof Et&&"function"==typeof _&&O&&void 0!==O.createHTMLDocument;const{MUSTACHE_EXPR:x,ERB_EXPR:A,TMPLIT_EXPR:N,DATA_ATTR:R,ARIA_ATTR:C,IS_SCRIPT_OR_DATA:I,ATTR_WHITESPACE:L,CUSTOM_ELEMENT:D}=Sn;let{IS_ALLOWED_URI:M}=Sn,U=null;const z=Xt({},[...en,...tn,...nn,...on,...cn]);let H=null;const B=Xt({},[...sn,...un,...ln,...fn]);let F=Object.seal(Ct(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),W=null,q=null,G=!0,V=!0,$=!1,Y=!0,J=!1,X=!0,K=!1,Z=!1,Q=!1,ee=!1,te=!1,ne=!1,re=!0,oe=!1,ie=!0,ae=!1,ce={},se=null;const ue=Xt({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let le=null;const fe=Xt({},["audio","video","img","source","image","track"]);let de=null;const pe=Xt({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),be="http://www.w3.org/1998/Math/MathML",me="http://www.w3.org/2000/svg",he="http://www.w3.org/1999/xhtml";let ve=he,ye=!1,ge=null;const _e=Xt({},[be,me,he],Ht);let we=Xt({},["mi","mo","mn","ms","mtext"]),Se=Xt({},["annotation-xml"]);const Oe=Xt({},["title","style","font","a","script"]);let Te=null;const ke=["application/xhtml+xml","text/html"];let Ee=null,je=null;const Pe=r.createElement("form"),xe=function(e){return e instanceof RegExp||e instanceof Function},Ae=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!je||je!==e){if(e&&"object"==typeof e||(e={}),e=Zt(e),Te=-1===ke.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,Ee="application/xhtml+xml"===Te?Ht:zt,U=Gt(e,"ALLOWED_TAGS")?Xt({},e.ALLOWED_TAGS,Ee):z,H=Gt(e,"ALLOWED_ATTR")?Xt({},e.ALLOWED_ATTR,Ee):B,ge=Gt(e,"ALLOWED_NAMESPACES")?Xt({},e.ALLOWED_NAMESPACES,Ht):_e,de=Gt(e,"ADD_URI_SAFE_ATTR")?Xt(Zt(pe),e.ADD_URI_SAFE_ATTR,Ee):pe,le=Gt(e,"ADD_DATA_URI_TAGS")?Xt(Zt(fe),e.ADD_DATA_URI_TAGS,Ee):fe,se=Gt(e,"FORBID_CONTENTS")?Xt({},e.FORBID_CONTENTS,Ee):ue,W=Gt(e,"FORBID_TAGS")?Xt({},e.FORBID_TAGS,Ee):{},q=Gt(e,"FORBID_ATTR")?Xt({},e.FORBID_ATTR,Ee):{},ce=!!Gt(e,"USE_PROFILES")&&e.USE_PROFILES,G=!1!==e.ALLOW_ARIA_ATTR,V=!1!==e.ALLOW_DATA_ATTR,$=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Y=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,J=e.SAFE_FOR_TEMPLATES||!1,X=!1!==e.SAFE_FOR_XML,K=e.WHOLE_DOCUMENT||!1,ee=e.RETURN_DOM||!1,te=e.RETURN_DOM_FRAGMENT||!1,ne=e.RETURN_TRUSTED_TYPE||!1,Q=e.FORCE_BODY||!1,re=!1!==e.SANITIZE_DOM,oe=e.SANITIZE_NAMED_PROPS||!1,ie=!1!==e.KEEP_CONTENT,ae=e.IN_PLACE||!1,M=e.ALLOWED_URI_REGEXP||vn,ve=e.NAMESPACE||he,we=e.MATHML_TEXT_INTEGRATION_POINTS||we,Se=e.HTML_INTEGRATION_POINTS||Se,F=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&xe(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(F.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&xe(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(F.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(F.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),J&&(V=!1),te&&(ee=!0),ce&&(U=Xt({},cn),H=[],!0===ce.html&&(Xt(U,en),Xt(H,sn)),!0===ce.svg&&(Xt(U,tn),Xt(H,un),Xt(H,fn)),!0===ce.svgFilters&&(Xt(U,nn),Xt(H,un),Xt(H,fn)),!0===ce.mathMl&&(Xt(U,on),Xt(H,ln),Xt(H,fn))),e.ADD_TAGS&&(U===z&&(U=Zt(U)),Xt(U,e.ADD_TAGS,Ee)),e.ADD_ATTR&&(H===B&&(H=Zt(H)),Xt(H,e.ADD_ATTR,Ee)),e.ADD_URI_SAFE_ATTR&&Xt(de,e.ADD_URI_SAFE_ATTR,Ee),e.FORBID_CONTENTS&&(se===ue&&(se=Zt(se)),Xt(se,e.FORBID_CONTENTS,Ee)),ie&&(U["#text"]=!0),K&&Xt(U,["html","head","body"]),U.table&&(Xt(U,["tbody"]),delete W.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw $t('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw $t('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');w=e.TRUSTED_TYPES_POLICY,S=w.createHTML("")}else void 0===w&&(w=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const r="data-tt-policy-suffix";t&&t.hasAttribute(r)&&(n=t.getAttribute(r));const o="dompurify"+(n?"#"+n:"");try{return e.createPolicy(o,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+o+" could not be created."),null}}(b,i)),null!==w&&"string"==typeof S&&(S=w.createHTML(""));Nt&&Nt(e),je=e}},Ne=Xt({},[...tn,...nn,...rn]),Re=Xt({},[...on,...an]),Ce=function(e){Ut(n.removed,{element:e});try{_(e).removeChild(e)}catch(t){v(e)}},Ie=function(e,t){try{Ut(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){Ut(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(ee||te)try{Ce(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Le=function(e){let t=null,n=null;if(Q)e=""+e;else{const t=Bt(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Te&&ve===he&&(e=''+e+"");const o=w?w.createHTML(e):e;if(ve===he)try{t=(new p).parseFromString(o,Te)}catch(e){}if(!t||!t.documentElement){t=O.createDocument(ve,"template",null);try{t.documentElement.innerHTML=ye?S:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),ve===he?E.call(t,K?"html":"body")[0]:K?t.documentElement:i},De=function(e){return T.call(e.ownerDocument||e,e,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT|l.SHOW_PROCESSING_INSTRUCTION|l.SHOW_CDATA_SECTION,null)},Me=function(e){return e instanceof d&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof f)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Ue=function(e){return"function"==typeof s&&e instanceof s};function ze(e,t,r){Dt(e,(e=>{e.call(n,t,r,je)}))}const He=function(e){let t=null;if(ze(P.beforeSanitizeElements,e,null),Me(e))return Ce(e),!0;const r=Ee(e.nodeName);if(ze(P.uponSanitizeElement,e,{tagName:r,allowedTags:U}),e.hasChildNodes()&&!Ue(e.firstElementChild)&&Vt(/<[/\w]/g,e.innerHTML)&&Vt(/<[/\w]/g,e.textContent))return Ce(e),!0;if(e.nodeType===kn)return Ce(e),!0;if(X&&e.nodeType===En&&Vt(/<[/\w]/g,e.data))return Ce(e),!0;if(!U[r]||W[r]){if(!W[r]&&Fe(r)){if(F.tagNameCheck instanceof RegExp&&Vt(F.tagNameCheck,r))return!1;if(F.tagNameCheck instanceof Function&&F.tagNameCheck(r))return!1}if(ie&&!se[r]){const t=_(e)||e.parentNode,n=g(e)||e.childNodes;if(n&&t){for(let r=n.length-1;r>=0;--r){const o=h(n[r],!0);o.__removalCount=(e.__removalCount||0)+1,t.insertBefore(o,y(e))}}}return Ce(e),!0}return e instanceof u&&!function(e){let t=_(e);t&&t.tagName||(t={namespaceURI:ve,tagName:"template"});const n=zt(e.tagName),r=zt(t.tagName);return!!ge[e.namespaceURI]&&(e.namespaceURI===me?t.namespaceURI===he?"svg"===n:t.namespaceURI===be?"svg"===n&&("annotation-xml"===r||we[r]):Boolean(Ne[n]):e.namespaceURI===be?t.namespaceURI===he?"math"===n:t.namespaceURI===me?"math"===n&&Se[r]:Boolean(Re[n]):e.namespaceURI===he?!(t.namespaceURI===me&&!Se[r])&&!(t.namespaceURI===be&&!we[r])&&!Re[n]&&(Oe[n]||!Ne[n]):!("application/xhtml+xml"!==Te||!ge[e.namespaceURI]))}(e)?(Ce(e),!0):"noscript"!==r&&"noembed"!==r&&"noframes"!==r||!Vt(/<\/no(script|embed|frames)/i,e.innerHTML)?(J&&e.nodeType===Tn&&(t=e.textContent,Dt([x,A,N],(e=>{t=Ft(t,e," ")})),e.textContent!==t&&(Ut(n.removed,{element:e.cloneNode()}),e.textContent=t)),ze(P.afterSanitizeElements,e,null),!1):(Ce(e),!0)},Be=function(e,t,n){if(re&&("id"===t||"name"===t)&&(n in r||n in Pe))return!1;if(V&&!q[t]&&Vt(R,t));else if(G&&Vt(C,t));else if(!H[t]||q[t]){if(!(Fe(e)&&(F.tagNameCheck instanceof RegExp&&Vt(F.tagNameCheck,e)||F.tagNameCheck instanceof Function&&F.tagNameCheck(e))&&(F.attributeNameCheck instanceof RegExp&&Vt(F.attributeNameCheck,t)||F.attributeNameCheck instanceof Function&&F.attributeNameCheck(t))||"is"===t&&F.allowCustomizedBuiltInElements&&(F.tagNameCheck instanceof RegExp&&Vt(F.tagNameCheck,n)||F.tagNameCheck instanceof Function&&F.tagNameCheck(n))))return!1}else if(de[t]);else if(Vt(M,Ft(n,L,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==Wt(n,"data:")||!le[e]){if($&&!Vt(I,Ft(n,L,"")));else if(n)return!1}else;return!0},Fe=function(e){return"annotation-xml"!==e&&Bt(e,D)},We=function(e){ze(P.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t)return;const r={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:H,forceKeepAttr:void 0};let o=t.length;for(;o--;){const i=t[o],{name:a,namespaceURI:c,value:s}=i,u=Ee(a);let l="value"===a?s:qt(s);if(r.attrName=u,r.attrValue=l,r.keepAttr=!0,r.forceKeepAttr=void 0,ze(P.uponSanitizeAttribute,e,r),l=r.attrValue,!oe||"id"!==u&&"name"!==u||(Ie(a,e),l="user-content-"+l),X&&Vt(/((--!?|])>)|<\/(style|title)/i,l)){Ie(a,e);continue}if(r.forceKeepAttr)continue;if(Ie(a,e),!r.keepAttr)continue;if(!Y&&Vt(/\/>/i,l)){Ie(a,e);continue}J&&Dt([x,A,N],(e=>{l=Ft(l,e," ")}));const f=Ee(e.nodeName);if(Be(f,u,l)){if(w&&"object"==typeof b&&"function"==typeof b.getAttributeType)if(c);else switch(b.getAttributeType(f,u)){case"TrustedHTML":l=w.createHTML(l);break;case"TrustedScriptURL":l=w.createScriptURL(l)}try{c?e.setAttributeNS(c,a,l):e.setAttribute(a,l),Me(e)?Ce(e):Mt(n.removed)}catch(e){}}}ze(P.afterSanitizeAttributes,e,null)},qe=function e(t){let n=null;const r=De(t);for(ze(P.beforeSanitizeShadowDOM,t,null);n=r.nextNode();)ze(P.uponSanitizeShadowNode,n,null),He(n)||(n.content instanceof a&&e(n.content),We(n));ze(P.afterSanitizeShadowDOM,t,null)};return n.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=null,i=null,c=null,u=null;if(ye=!e,ye&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Ue(e)){if("function"!=typeof e.toString)throw $t("toString is not a function");if("string"!=typeof(e=e.toString()))throw $t("dirty is not a string, aborting")}if(!n.isSupported)return e;if(Z||Ae(t),n.removed=[],"string"==typeof e&&(ae=!1),ae){if(e.nodeName){const t=Ee(e.nodeName);if(!U[t]||W[t])throw $t("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof s)r=Le("\x3c!----\x3e"),i=r.ownerDocument.importNode(e,!0),i.nodeType===On&&"BODY"===i.nodeName||"HTML"===i.nodeName?r=i:r.appendChild(i);else{if(!ee&&!J&&!K&&-1===e.indexOf("<"))return w&&ne?w.createHTML(e):e;if(r=Le(e),!r)return ee?null:ne?S:""}r&&Q&&Ce(r.firstChild);const l=De(ae?e:r);for(;c=l.nextNode();)He(c)||(c.content instanceof a&&qe(c.content),We(c));if(ae)return e;if(ee){if(te)for(u=k.call(r.ownerDocument);r.firstChild;)u.appendChild(r.firstChild);else u=r;return(H.shadowroot||H.shadowrootmode)&&(u=j.call(o,u,!0)),u}let f=K?r.outerHTML:r.innerHTML;return K&&U["!doctype"]&&r.ownerDocument&&r.ownerDocument.doctype&&r.ownerDocument.doctype.name&&Vt(_n,r.ownerDocument.doctype.name)&&(f="\n"+f),J&&Dt([x,A,N],(e=>{f=Ft(f,e," ")})),w&&ne?w.createHTML(f):f},n.setConfig=function(){Ae(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Z=!0},n.clearConfig=function(){je=null,Z=!1},n.isValidAttribute=function(e,t,n){je||Ae({});const r=Ee(e),o=Ee(t);return Be(r,o,n)},n.addHook=function(e,t){"function"==typeof t&&Ut(P[e],t)},n.removeHook=function(e){return Mt(P[e])},n.removeHooks=function(e){P[e]=[]},n.removeAllHooks=function(){P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},n}();function Rn(e){return Rn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Rn(e)}function Cn(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function In(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ln(e,t){for(var n=0;n\n ','\n
\n \n ',"\n
\n

","

\n \n "])),(0,Qe.$)(t),(0,et.g)(this.notification.dismissable,(function(){return(0,de.dy)(An||(An=Cn(['\n $lang',r='/$version';return"page"===e?"".concat(t).concat(r,"/"):"clean_url_to_html"===e?"".concat(t).concat(r,'/$file/'):"clean_url_without_trailing_slash_to_html"===e?"".concat(t).concat(r,'/$file'):"html_to_clean_url"===e?"".concat(t).concat(r,'/$file.html'):""})),this.redirect_from=o.computed((function(){var e=n.from_url(),t=n.redirect_type();return"prefix"===t?e+"faq.html":"page"===t?e.replace(/^\/+/,""):"exact"===t?e:""})),this.redirect_to_prefix=o.computed((function(){var e=n.redirect_type(),t='/$lang',r='/$version';return"prefix"===e?"".concat(t).concat(r,"/faq.html"):"page"===e?"".concat(t).concat(r,"/"):"clean_url_to_html"===e||"clean_url_without_trailing_slash_to_html"===e?"".concat(t).concat(r,'/$file.html'):"html_to_clean_url"===e?"".concat(t).concat(r,'/$file/'):""})),this.redirect_to=o.computed((function(){var e=n.to_url(),t=n.redirect_type();return"page"===t?e.replace(/^\/+/,""):"exact"===t?e:""})),this.redirect_type.subscribe((function(e){if(["prefix","page","exact"].includes(e)){n.is_example_disabled(!1);var t=!0;"prefix"==e&&(t=!1),n.is_from_url_visible(!0),n.is_to_url_visible(t)}else["clean_url_to_html","clean_url_without_trailing_slash_to_html","html_to_clean_url"].includes(e)?(n.is_example_disabled(!1),n.is_from_url_visible(!1),n.is_to_url_visible(!1)):(n.is_example_disabled(!0),n.is_from_url_visible(!1),n.is_to_url_visible(!1))}))}));fr(br,"view_name","ProjectRedirectView"),M.add_view(br);var mr=ur((function e(t){var n=this;lr(this,e),this.access_type=o.observable(),this.show_password_field=o.computed((function(){return"password"==n.access_type()})),this.allow_all=o.observable(t.allow_all),this.show_versions_list=o.computed((function(){return!1===n.allow_all()}))}));fr(mr,"view_name","ProjectTemporaryAccessView"),M.add_view(mr);var hr=ur((function e(){var t=this;lr(this,e),this.config=o.observable(),this.is_loading=o.observable(!0),this.config.subscribe((function(e){t.is_loading(!1)}))}));fr(hr,"view_name","ProjectSearchAnalyticsView"),M.add_view(hr);var vr=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&ir(e,t)}(n,e);var t=ar(n);function n(){return lr(this,n),t.apply(this,arguments)}return ur(n)}(hr);function yr(e){var t=r.Deferred(),n=e.url,o={csrfmiddlewaretoken:e.token};return r.ajax({method:"POST",url:n,data:o,success:function(e){(function(e){var t=r.Deferred(),n=5;return setTimeout((function o(){r.getJSON(e.url).done((function(e){e.finished?e.success?t.resolve():t.reject({message:e.error}):setTimeout(o,2e3)})).fail((function(e){if(console.error("Error polling task"),(n-=1)>0)setTimeout(o,2e3);else{var r=e.statusText;e.responseJSON&&(r=e.responseJSON.detail),t.reject({message:r})}}))}),2e3),t})(e).then((function(){t.resolve()})).fail((function(e){t.reject(e)}))},error:function(e){var n=e.responseJSON.detail||e.statusText;t.reject({message:n})}}),t}function gr(e){return gr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},gr(e)}function _r(e,t){return _r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},_r(e,t)}function wr(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,r=Sr(e);if(t){var o=Sr(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===gr(t)||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function Sr(e){return Sr=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},Sr(e)}function Or(e,t){for(var n=0;n0}))})),Nr=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&_r(e,t)}(n,e);var t=wr(n);function n(){var e;return Er(this,n),(e=t.call(this)).config=o.observable(),e.search_config=o.observable(),e.search_popup_config=o.observable(),e.search_modal_config=o.observable(void 0),e.selected=o.observable(),e.is_loading=o.observable(!1),e.is_syncing=o.observable(!1),e.is_synced=o.observable(!1),e.is_selected=o.computed((function(){return void 0!==e.selected()})),e.allow_private_repos=o.observable(!1),e.error=o.observable(),e.config.subscribe((function(t){void 0!==t&&(e.allow_private_repos(t.allow_private_repos),e.init_search())})),e}return Tr(n,[{key:"sync_remote_repos",value:function(){var e=this,t=this.config(),n={url:t.urls.api_sync_remote_repositories,token:t.csrf_token};return this.is_synced(!1),this.is_syncing(!0),this.is_loading(!0),yr(n).fail((function(t){console.error("Error syncing remote repositories:",t.message),e.error(t.message)})).always((function(){e.is_syncing(!1),e.is_loading(!1),e.is_synced(!0)}))}},{key:"init_search",value:function(){var e=this,t=this.config().urls.remoterepository_list+"?full_name={query}",n=3;this.search_popup_config({on:"manual",position:"top right",hoverable:!0,closable:!0,preserve:!0,onHidden:function(){n=3},delay:{hide:5e3}});var i="#repair"==r(location).attr("hash");this.search_modal_config({autoShow:i,centered:!1}),this.search_config({type:"knockout",templates:{knockout:function(e){var t=r("
");o.applyBindingsToNode(t[0],{template:{name:"remote-repo-results",data:{remote_repos:e.results.map((function(e){return new Ar(e)}))}}});var n=t.html();return t.remove(),n}},error:{noResultsHeader:"No matching repositories found"},apiSettings:{url:t},selector:{prompt:".ui.text",title:".title .text"},fullTextSearch:!0,onSelect:function(t,n){e.selected(new Ar(t))},onResults:function(t,r){(t&&0==t.count||n<=0)&&e.search_popup_config((function(e){return e("show")})),n--}})}},{key:"is_repository_supported",value:function(e){return!e.is_private()||this.allow_private_repos()}},{key:"show_modal",value:function(){this.search_popup_config((function(e){return e("hide")})),this.search_modal_config((function(e){return e("show")}))}}]),n}(oe);function Rr(e){return Rr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Rr(e)}function Cr(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Ir(e,t){for(var n=0;n\n ',"\n
\n "])),(0,rr.U)(e.results,(function(e){return(0,de.dy)(Pr||(Pr=Cr(['\n \n
\n
\n
\n ','\n \n ','\n
\n
\n ',"\n
\n
\n
\n "])),e.verbose_name,(0,Qe.$)({"fa-code-branch":"branch"===e.type,"fa-tag":"tag"===e.type}),(0,et.g)(e.active,(function(){return(0,de.dy)(xr||(xr=Cr(['\n \n \n Active\n \n '])))})),e.identifier)})));(0,de.sY)(n,t);var r=t.innerHTML;return t.remove(),r}}}}}]),e}();Br(qr,"view_name","ProjectVersionCreateView"),M.add_view(qr);var Gr=function(e){Mr(n,e);var t=zr(n);function n(e){var r;return Dr(this,n),(r=t.call(this,e)).url_pdf=o.observable(),r.url_epub=o.observable(),r.url_html=o.observable(),r.url_docs=o.observable(),r.is_built=o.observable(!0),r.data.subscribe((function(e){r.url_pdf(e.downloads.pdf),r.url_epub(e.downloads.epub),r.url_html(e.downloads.htmlzip),r.url_docs(e.urls.documentation),r.is_built(e.built)})),r}return Lr(n,[{key:"trigger_build",value:function(e,t){return function(n,o){r.ajax({type:"POST",url:e,data:{csrfmiddlewaretoken:t}}).then((function(e){e.build.urls.build?window.location.href=e.build.urls.build:console.debug("Redirect to new build failed")})).catch((function(e){console.error(e)}))}}}]),n}(ie);Br(Gr,"view_name","VersionListItemView"),M.add_view(Gr);var Vr=function(){function e(t){Dr(this,e),this.cache_key=t,this.prefix_key="announcements",this.storage_key="".concat(this.prefix_key,".").concat(this.cache_key),this.closed=o.observable(),localStorage.getItem(this.storage_key)?this.closed(!0):this.closed(!1)}return Lr(e,[{key:"close_announcement",value:function(){this.closed(!0),localStorage.setItem(this.storage_key,!0)}}]),e}();function $r(e){return $r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},$r(e)}function Yr(e,t){for(var n=0;n select").dropdown({placeholder:""}),r("[data-content]:not([data-semanticui-popup])").popup({position:"top center",delay:{show:500},variation:"small"}),r(".ui.menu > .item[data-tab]").tab(),new i("[data-clipboard-text], [data-clipboard-target]"),r("[data-clipboard-text], [data-clipboard-target]").popup({on:"click",hoverable:!1,content:"Copied!"}),r("[data-analytics], [data-analytics-events]").plausible(this.config.production_domain,this.config.debug)}}])&&Zr(t.prototype,c),s&&Zr(t,s),Object.defineProperty(t,"prototype",{writable:!1}),e}();r(document).ready((function(){(new eo).run()}))}},a={};function c(e){var t=a[e];if(void 0!==t)return t.exports;var n=a[e]={exports:{}};return i[e].call(n.exports,n,n.exports,c),n.exports}c.m=i,e=[],c.O=(t,n,r,o)=>{if(!n){var i=1/0;for(l=0;l=o)&&Object.keys(c.O).every((e=>c.O[e](n[s])))?n.splice(s--,1):(a=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1];e[l]=[n,r,o]},n=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var o=Object.create(null);c.r(o);var i={};t=t||[null,n({}),n([]),n(n)];for(var a=2&r&&e;"object"==typeof a&&!~t.indexOf(a);a=n(a))Object.getOwnPropertyNames(a).forEach((t=>i[t]=()=>e[t]));return i.default=()=>e,c.d(o,i),o},c.d=(e,t)=>{for(var n in t)c.o(t,n)&&!c.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((t,n)=>(c.f[n](e,t),t)),[])),c.u=e=>"js/vendors~"+e+".js?"+{chartjs:"9fe6b0464564451d1f1f",ansi_up:"c3b32875873781bca34e"}[e],c.miniCssF=e=>{},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r={},o="readthedocsext-theme:",c.l=(e,t,n,i)=>{if(r[e])r[e].push(t);else{var a,s;if(void 0!==n)for(var u=document.getElementsByTagName("script"),l=0;l{a.onerror=a.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(n))),t)return t(n)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=d.bind(null,a.onerror),a.onload=d.bind(null,a.onload),s&&document.head.appendChild(a)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="./",(()=>{var e={site:0};c.f.j=(t,n)=>{var r=c.o(e,t)?e[t]:void 0;if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(((n,o)=>r=e[t]=[n,o]));n.push(r[2]=o);var i=c.p+c.u(t),a=new Error;c.l(i,(n=>{if(c.o(e,t)&&(0!==(r=e[t])&&(e[t]=void 0),r)){var o=n&&("load"===n.type?"missing":n.type),i=n&&n.target&&n.target.src;a.message="Loading chunk "+t+" failed.\n("+o+": "+i+")",a.name="ChunkLoadError",a.type=o,a.request=i,r[1](a)}}),"chunk-"+t,t)}},c.O.j=t=>0===e[t];var t=(t,n)=>{var r,o,[i,a,s]=n,u=0;if(i.some((t=>0!==e[t]))){for(r in a)c.o(a,r)&&(c.m[r]=a[r]);if(s)var l=s(c)}for(t&&t(n);uc(286)));var s=c.O(void 0,["vendor"],(()=>c(738)));s=c.O(s)})(); -//# sourceMappingURL=site.js.map?a00831c90cf85db69618 \ No newline at end of file +const{entries:Rt,setPrototypeOf:Ct,isFrozen:It,getPrototypeOf:Lt,getOwnPropertyDescriptor:Dt}=Object;let{freeze:Mt,seal:Ut,create:zt}=Object,{apply:Ht,construct:Bt}="undefined"!=typeof Reflect&&Reflect;Mt||(Mt=function(e){return e}),Ut||(Ut=function(e){return e}),Ht||(Ht=function(e,t,n){return e.apply(t,n)}),Bt||(Bt=function(e,t){return new e(...t)});const Ft=tn(Array.prototype.forEach),Wt=tn(Array.prototype.pop),qt=tn(Array.prototype.push),Gt=tn(String.prototype.toLowerCase),Vt=tn(String.prototype.toString),$t=tn(String.prototype.match),Yt=tn(String.prototype.replace),Jt=tn(String.prototype.indexOf),Xt=tn(String.prototype.trim),Kt=tn(Object.prototype.hasOwnProperty),Zt=tn(RegExp.prototype.test),Qt=(en=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),o=1;o2&&void 0!==arguments[2]?arguments[2]:Gt;Ct&&Ct(e,null);let r=t.length;for(;r--;){let o=t[r];if("string"==typeof o){const e=n(o);e!==o&&(It(t)||(t[r]=e),o=e)}e[o]=!0}return e}function rn(e){for(let t=0;t/gm),_n=Ut(/\${[\w\W]*}/gm),wn=Ut(/^data-[\-\w.\u00B7-\uFFFF]/),Sn=Ut(/^aria-[\-\w]+$/),On=Ut(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Tn=Ut(/^(?:\w+script|data):/i),kn=Ut(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),En=Ut(/^html$/i),jn=Ut(/^[a-z][.\w]*(-[.\w]+)+$/i);var Pn=Object.freeze({__proto__:null,ARIA_ATTR:Sn,ATTR_WHITESPACE:kn,CUSTOM_ELEMENT:jn,DATA_ATTR:wn,DOCTYPE_NAME:En,ERB_EXPR:gn,IS_ALLOWED_URI:On,IS_SCRIPT_OR_DATA:Tn,MUSTACHE_EXPR:yn,TMPLIT_EXPR:_n});const An=1,xn=3,Nn=7,Rn=8,Cn=9,In=function(){return"undefined"==typeof window?null:window};var Ln,Dn,Mn=function e(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:In();const n=t=>e(t);if(n.version="3.2.2",n.removed=[],!t||!t.document||t.document.nodeType!==Cn)return n.isSupported=!1,n;let{document:r}=t;const o=r,i=o.currentScript,{DocumentFragment:a,HTMLTemplateElement:c,Node:u,Element:s,NodeFilter:l,NamedNodeMap:f=t.NamedNodeMap||t.MozNamedAttrMap,HTMLFormElement:d,DOMParser:p,trustedTypes:b}=t,m=s.prototype,h=an(m,"cloneNode"),v=an(m,"remove"),y=an(m,"nextSibling"),g=an(m,"childNodes"),_=an(m,"parentNode");if("function"==typeof c){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let w,S="";const{implementation:O,createNodeIterator:T,createDocumentFragment:k,getElementsByTagName:E}=r,{importNode:j}=o;let P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};n.isSupported="function"==typeof Rt&&"function"==typeof _&&O&&void 0!==O.createHTMLDocument;const{MUSTACHE_EXPR:A,ERB_EXPR:x,TMPLIT_EXPR:N,DATA_ATTR:R,ARIA_ATTR:C,IS_SCRIPT_OR_DATA:I,ATTR_WHITESPACE:L,CUSTOM_ELEMENT:D}=Pn;let{IS_ALLOWED_URI:M}=Pn,U=null;const z=nn({},[...cn,...un,...sn,...fn,...pn]);let H=null;const B=nn({},[...bn,...mn,...hn,...vn]);let F=Object.seal(zt(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),W=null,q=null,G=!0,V=!0,$=!1,Y=!0,J=!1,X=!0,K=!1,Z=!1,Q=!1,ee=!1,te=!1,ne=!1,re=!0,oe=!1,ie=!0,ae=!1,ce={},ue=null;const se=nn({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let le=null;const fe=nn({},["audio","video","img","source","image","track"]);let de=null;const pe=nn({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),be="http://www.w3.org/1998/Math/MathML",me="http://www.w3.org/2000/svg",he="http://www.w3.org/1999/xhtml";let ve=he,ye=!1,ge=null;const _e=nn({},[be,me,he],Vt);let we=nn({},["mi","mo","mn","ms","mtext"]),Se=nn({},["annotation-xml"]);const Oe=nn({},["title","style","font","a","script"]);let Te=null;const ke=["application/xhtml+xml","text/html"];let Ee=null,je=null;const Pe=r.createElement("form"),Ae=function(e){return e instanceof RegExp||e instanceof Function},xe=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!je||je!==e){if(e&&"object"==typeof e||(e={}),e=on(e),Te=-1===ke.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,Ee="application/xhtml+xml"===Te?Vt:Gt,U=Kt(e,"ALLOWED_TAGS")?nn({},e.ALLOWED_TAGS,Ee):z,H=Kt(e,"ALLOWED_ATTR")?nn({},e.ALLOWED_ATTR,Ee):B,ge=Kt(e,"ALLOWED_NAMESPACES")?nn({},e.ALLOWED_NAMESPACES,Vt):_e,de=Kt(e,"ADD_URI_SAFE_ATTR")?nn(on(pe),e.ADD_URI_SAFE_ATTR,Ee):pe,le=Kt(e,"ADD_DATA_URI_TAGS")?nn(on(fe),e.ADD_DATA_URI_TAGS,Ee):fe,ue=Kt(e,"FORBID_CONTENTS")?nn({},e.FORBID_CONTENTS,Ee):se,W=Kt(e,"FORBID_TAGS")?nn({},e.FORBID_TAGS,Ee):{},q=Kt(e,"FORBID_ATTR")?nn({},e.FORBID_ATTR,Ee):{},ce=!!Kt(e,"USE_PROFILES")&&e.USE_PROFILES,G=!1!==e.ALLOW_ARIA_ATTR,V=!1!==e.ALLOW_DATA_ATTR,$=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Y=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,J=e.SAFE_FOR_TEMPLATES||!1,X=!1!==e.SAFE_FOR_XML,K=e.WHOLE_DOCUMENT||!1,ee=e.RETURN_DOM||!1,te=e.RETURN_DOM_FRAGMENT||!1,ne=e.RETURN_TRUSTED_TYPE||!1,Q=e.FORCE_BODY||!1,re=!1!==e.SANITIZE_DOM,oe=e.SANITIZE_NAMED_PROPS||!1,ie=!1!==e.KEEP_CONTENT,ae=e.IN_PLACE||!1,M=e.ALLOWED_URI_REGEXP||On,ve=e.NAMESPACE||he,we=e.MATHML_TEXT_INTEGRATION_POINTS||we,Se=e.HTML_INTEGRATION_POINTS||Se,F=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&Ae(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(F.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&Ae(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(F.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(F.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),J&&(V=!1),te&&(ee=!0),ce&&(U=nn({},pn),H=[],!0===ce.html&&(nn(U,cn),nn(H,bn)),!0===ce.svg&&(nn(U,un),nn(H,mn),nn(H,vn)),!0===ce.svgFilters&&(nn(U,sn),nn(H,mn),nn(H,vn)),!0===ce.mathMl&&(nn(U,fn),nn(H,hn),nn(H,vn))),e.ADD_TAGS&&(U===z&&(U=on(U)),nn(U,e.ADD_TAGS,Ee)),e.ADD_ATTR&&(H===B&&(H=on(H)),nn(H,e.ADD_ATTR,Ee)),e.ADD_URI_SAFE_ATTR&&nn(de,e.ADD_URI_SAFE_ATTR,Ee),e.FORBID_CONTENTS&&(ue===se&&(ue=on(ue)),nn(ue,e.FORBID_CONTENTS,Ee)),ie&&(U["#text"]=!0),K&&nn(U,["html","head","body"]),U.table&&(nn(U,["tbody"]),delete W.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw Qt('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw Qt('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');w=e.TRUSTED_TYPES_POLICY,S=w.createHTML("")}else void 0===w&&(w=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const r="data-tt-policy-suffix";t&&t.hasAttribute(r)&&(n=t.getAttribute(r));const o="dompurify"+(n?"#"+n:"");try{return e.createPolicy(o,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+o+" could not be created."),null}}(b,i)),null!==w&&"string"==typeof S&&(S=w.createHTML(""));Mt&&Mt(e),je=e}},Ne=nn({},[...un,...sn,...ln]),Re=nn({},[...fn,...dn]),Ce=function(e){qt(n.removed,{element:e});try{_(e).removeChild(e)}catch(t){v(e)}},Ie=function(e,t){try{qt(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){qt(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(ee||te)try{Ce(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Le=function(e){let t=null,n=null;if(Q)e=""+e;else{const t=$t(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Te&&ve===he&&(e=''+e+"");const o=w?w.createHTML(e):e;if(ve===he)try{t=(new p).parseFromString(o,Te)}catch(e){}if(!t||!t.documentElement){t=O.createDocument(ve,"template",null);try{t.documentElement.innerHTML=ye?S:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),ve===he?E.call(t,K?"html":"body")[0]:K?t.documentElement:i},De=function(e){return T.call(e.ownerDocument||e,e,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT|l.SHOW_PROCESSING_INSTRUCTION|l.SHOW_CDATA_SECTION,null)},Me=function(e){return e instanceof d&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof f)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Ue=function(e){return"function"==typeof u&&e instanceof u};function ze(e,t,r){Ft(e,(e=>{e.call(n,t,r,je)}))}const He=function(e){let t=null;if(ze(P.beforeSanitizeElements,e,null),Me(e))return Ce(e),!0;const r=Ee(e.nodeName);if(ze(P.uponSanitizeElement,e,{tagName:r,allowedTags:U}),e.hasChildNodes()&&!Ue(e.firstElementChild)&&Zt(/<[/\w]/g,e.innerHTML)&&Zt(/<[/\w]/g,e.textContent))return Ce(e),!0;if(e.nodeType===Nn)return Ce(e),!0;if(X&&e.nodeType===Rn&&Zt(/<[/\w]/g,e.data))return Ce(e),!0;if(!U[r]||W[r]){if(!W[r]&&Fe(r)){if(F.tagNameCheck instanceof RegExp&&Zt(F.tagNameCheck,r))return!1;if(F.tagNameCheck instanceof Function&&F.tagNameCheck(r))return!1}if(ie&&!ue[r]){const t=_(e)||e.parentNode,n=g(e)||e.childNodes;if(n&&t){for(let r=n.length-1;r>=0;--r){const o=h(n[r],!0);o.__removalCount=(e.__removalCount||0)+1,t.insertBefore(o,y(e))}}}return Ce(e),!0}return e instanceof s&&!function(e){let t=_(e);t&&t.tagName||(t={namespaceURI:ve,tagName:"template"});const n=Gt(e.tagName),r=Gt(t.tagName);return!!ge[e.namespaceURI]&&(e.namespaceURI===me?t.namespaceURI===he?"svg"===n:t.namespaceURI===be?"svg"===n&&("annotation-xml"===r||we[r]):Boolean(Ne[n]):e.namespaceURI===be?t.namespaceURI===he?"math"===n:t.namespaceURI===me?"math"===n&&Se[r]:Boolean(Re[n]):e.namespaceURI===he?!(t.namespaceURI===me&&!Se[r])&&!(t.namespaceURI===be&&!we[r])&&!Re[n]&&(Oe[n]||!Ne[n]):!("application/xhtml+xml"!==Te||!ge[e.namespaceURI]))}(e)?(Ce(e),!0):"noscript"!==r&&"noembed"!==r&&"noframes"!==r||!Zt(/<\/no(script|embed|frames)/i,e.innerHTML)?(J&&e.nodeType===xn&&(t=e.textContent,Ft([A,x,N],(e=>{t=Yt(t,e," ")})),e.textContent!==t&&(qt(n.removed,{element:e.cloneNode()}),e.textContent=t)),ze(P.afterSanitizeElements,e,null),!1):(Ce(e),!0)},Be=function(e,t,n){if(re&&("id"===t||"name"===t)&&(n in r||n in Pe))return!1;if(V&&!q[t]&&Zt(R,t));else if(G&&Zt(C,t));else if(!H[t]||q[t]){if(!(Fe(e)&&(F.tagNameCheck instanceof RegExp&&Zt(F.tagNameCheck,e)||F.tagNameCheck instanceof Function&&F.tagNameCheck(e))&&(F.attributeNameCheck instanceof RegExp&&Zt(F.attributeNameCheck,t)||F.attributeNameCheck instanceof Function&&F.attributeNameCheck(t))||"is"===t&&F.allowCustomizedBuiltInElements&&(F.tagNameCheck instanceof RegExp&&Zt(F.tagNameCheck,n)||F.tagNameCheck instanceof Function&&F.tagNameCheck(n))))return!1}else if(de[t]);else if(Zt(M,Yt(n,L,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==Jt(n,"data:")||!le[e]){if($&&!Zt(I,Yt(n,L,"")));else if(n)return!1}else;return!0},Fe=function(e){return"annotation-xml"!==e&&$t(e,D)},We=function(e){ze(P.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t)return;const r={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:H,forceKeepAttr:void 0};let o=t.length;for(;o--;){const i=t[o],{name:a,namespaceURI:c,value:u}=i,s=Ee(a);let l="value"===a?u:Xt(u);if(r.attrName=s,r.attrValue=l,r.keepAttr=!0,r.forceKeepAttr=void 0,ze(P.uponSanitizeAttribute,e,r),l=r.attrValue,!oe||"id"!==s&&"name"!==s||(Ie(a,e),l="user-content-"+l),X&&Zt(/((--!?|])>)|<\/(style|title)/i,l)){Ie(a,e);continue}if(r.forceKeepAttr)continue;if(Ie(a,e),!r.keepAttr)continue;if(!Y&&Zt(/\/>/i,l)){Ie(a,e);continue}J&&Ft([A,x,N],(e=>{l=Yt(l,e," ")}));const f=Ee(e.nodeName);if(Be(f,s,l)){if(w&&"object"==typeof b&&"function"==typeof b.getAttributeType)if(c);else switch(b.getAttributeType(f,s)){case"TrustedHTML":l=w.createHTML(l);break;case"TrustedScriptURL":l=w.createScriptURL(l)}try{c?e.setAttributeNS(c,a,l):e.setAttribute(a,l),Me(e)?Ce(e):Wt(n.removed)}catch(e){}}}ze(P.afterSanitizeAttributes,e,null)},qe=function e(t){let n=null;const r=De(t);for(ze(P.beforeSanitizeShadowDOM,t,null);n=r.nextNode();)ze(P.uponSanitizeShadowNode,n,null),He(n)||(n.content instanceof a&&e(n.content),We(n));ze(P.afterSanitizeShadowDOM,t,null)};return n.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=null,i=null,c=null,s=null;if(ye=!e,ye&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Ue(e)){if("function"!=typeof e.toString)throw Qt("toString is not a function");if("string"!=typeof(e=e.toString()))throw Qt("dirty is not a string, aborting")}if(!n.isSupported)return e;if(Z||xe(t),n.removed=[],"string"==typeof e&&(ae=!1),ae){if(e.nodeName){const t=Ee(e.nodeName);if(!U[t]||W[t])throw Qt("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof u)r=Le("\x3c!----\x3e"),i=r.ownerDocument.importNode(e,!0),i.nodeType===An&&"BODY"===i.nodeName||"HTML"===i.nodeName?r=i:r.appendChild(i);else{if(!ee&&!J&&!K&&-1===e.indexOf("<"))return w&&ne?w.createHTML(e):e;if(r=Le(e),!r)return ee?null:ne?S:""}r&&Q&&Ce(r.firstChild);const l=De(ae?e:r);for(;c=l.nextNode();)He(c)||(c.content instanceof a&&qe(c.content),We(c));if(ae)return e;if(ee){if(te)for(s=k.call(r.ownerDocument);r.firstChild;)s.appendChild(r.firstChild);else s=r;return(H.shadowroot||H.shadowrootmode)&&(s=j.call(o,s,!0)),s}let f=K?r.outerHTML:r.innerHTML;return K&&U["!doctype"]&&r.ownerDocument&&r.ownerDocument.doctype&&r.ownerDocument.doctype.name&&Zt(En,r.ownerDocument.doctype.name)&&(f="\n"+f),J&&Ft([A,x,N],(e=>{f=Yt(f,e," ")})),w&&ne?w.createHTML(f):f},n.setConfig=function(){xe(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Z=!0},n.clearConfig=function(){je=null,Z=!1},n.isValidAttribute=function(e,t,n){je||xe({});const r=Ee(e),o=Ee(t);return Be(r,o,n)},n.addHook=function(e,t){"function"==typeof t&&qt(P[e],t)},n.removeHook=function(e){return Wt(P[e])},n.removeHooks=function(e){P[e]=[]},n.removeAllHooks=function(){P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},n}();function Un(e){return Un="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Un(e)}function zn(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Hn(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Bn(e,t){for(var n=0;n\n ','\n
\n \n ',"\n
\n

","

\n \n "])),(0,it.$)(t),(0,at.g)(this.notification.dismissable,(function(){return(0,ye.dy)(Dn||(Dn=zn(['\n $lang',r='/$version';return"page"===e?"".concat(t).concat(r,"/"):"clean_url_to_html"===e?"".concat(t).concat(r,'/$file/'):"clean_url_without_trailing_slash_to_html"===e?"".concat(t).concat(r,'/$file'):"html_to_clean_url"===e?"".concat(t).concat(r,'/$file.html'):""})),this.redirect_from=o.computed((function(){var e=n.from_url(),t=n.redirect_type();return"prefix"===t?e+"faq.html":"page"===t?e.replace(/^\/+/,""):"exact"===t?e:""})),this.redirect_to_prefix=o.computed((function(){var e=n.redirect_type(),t='/$lang',r='/$version';return"prefix"===e?"".concat(t).concat(r,"/faq.html"):"page"===e?"".concat(t).concat(r,"/"):"clean_url_to_html"===e||"clean_url_without_trailing_slash_to_html"===e?"".concat(t).concat(r,'/$file.html'):"html_to_clean_url"===e?"".concat(t).concat(r,'/$file/'):""})),this.redirect_to=o.computed((function(){var e=n.to_url(),t=n.redirect_type();return"page"===t?e.replace(/^\/+/,""):"exact"===t?e:""})),this.redirect_type.subscribe((function(e){if(["prefix","page","exact"].includes(e)){n.is_example_disabled(!1);var t=!0;"prefix"==e&&(t=!1),n.is_from_url_visible(!0),n.is_to_url_visible(t)}else["clean_url_to_html","clean_url_without_trailing_slash_to_html","html_to_clean_url"].includes(e)?(n.is_example_disabled(!1),n.is_from_url_visible(!1),n.is_to_url_visible(!1)):(n.is_example_disabled(!0),n.is_from_url_visible(!1),n.is_to_url_visible(!1))}))}));vr(_r,"view_name","ProjectRedirectView"),z.add_view(_r);var wr=mr((function e(t){var n=this;hr(this,e),this.access_type=o.observable(),this.show_password_field=o.computed((function(){return"password"==n.access_type()})),this.allow_all=o.observable(t.allow_all),this.show_versions_list=o.computed((function(){return!1===n.allow_all()}))}));vr(wr,"view_name","ProjectTemporaryAccessView"),z.add_view(wr);var Sr=mr((function e(){var t=this;hr(this,e),this.config=o.observable(),this.is_loading=o.observable(!0),this.config.subscribe((function(e){t.is_loading(!1)}))}));vr(Sr,"view_name","ProjectSearchAnalyticsView"),z.add_view(Sr);var Or=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&fr(e,t)}(n,e);var t=dr(n);function n(){return hr(this,n),t.apply(this,arguments)}return mr(n)}(Sr);function Tr(e){var t=r.Deferred(),n=e.url,o={csrfmiddlewaretoken:e.token};return r.ajax({method:"POST",url:n,data:o,success:function(e){(function(e){var t=r.Deferred(),n=5;return setTimeout((function o(){r.getJSON(e.url).done((function(e){e.finished?e.success?t.resolve():t.reject({message:e.error}):setTimeout(o,2e3)})).fail((function(e){if(console.error("Error polling task"),(n-=1)>0)setTimeout(o,2e3);else{var r=e.statusText;e.responseJSON&&(r=e.responseJSON.detail),t.reject({message:r})}}))}),2e3),t})(e).then((function(){t.resolve()})).fail((function(e){t.reject(e)}))},error:function(e){var n=e.responseJSON.detail||e.statusText;t.reject({message:n})}}),t}function kr(e){return kr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},kr(e)}function Er(e,t){return Er=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},Er(e,t)}function jr(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,r=Pr(e);if(t){var o=Pr(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===kr(t)||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function Pr(e){return Pr=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},Pr(e)}function Ar(e,t){for(var n=0;n0}))})),Mr=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&Er(e,t)}(n,e);var t=jr(n);function n(){var e;return Rr(this,n),(e=t.call(this)).config=o.observable(),e.search_config=o.observable(),e.search_popup_config=o.observable(),e.search_modal_config=o.observable(void 0),e.selected=o.observable(),e.is_loading=o.observable(!1),e.is_syncing=o.observable(!1),e.is_synced=o.observable(!1),e.is_selected=o.computed((function(){return void 0!==e.selected()})),e.allow_private_repos=o.observable(!1),e.error=o.observable(),e.config.subscribe((function(t){void 0!==t&&(e.allow_private_repos(t.allow_private_repos),e.init_search())})),e}return xr(n,[{key:"sync_remote_repos",value:function(){var e=this,t=this.config(),n={url:t.urls.api_sync_remote_repositories,token:t.csrf_token};return this.is_synced(!1),this.is_syncing(!0),this.is_loading(!0),Tr(n).fail((function(t){console.error("Error syncing remote repositories:",t.message),e.error(t.message)})).always((function(){e.is_syncing(!1),e.is_loading(!1),e.is_synced(!0)}))}},{key:"init_search",value:function(){var e=this,t=this.config().urls.remoterepository_list+"?full_name={query}",n=3;this.search_popup_config({on:"manual",position:"top right",hoverable:!0,closable:!0,preserve:!0,onHidden:function(){n=3},delay:{hide:5e3}});var i="#repair"==r(location).attr("hash");this.search_modal_config({autoShow:i,centered:!1}),this.search_config({type:"knockout",templates:{knockout:function(e){var t=r("
");o.applyBindingsToNode(t[0],{template:{name:"remote-repo-results",data:{remote_repos:e.results.map((function(e){return new Dr(e)}))}}});var n=t.html();return t.remove(),n}},error:{noResultsHeader:"No matching repositories found"},apiSettings:{url:t},selector:{prompt:".ui.text",title:".title .text"},fullTextSearch:!0,onSelect:function(t,n){e.selected(new Dr(t))},onResults:function(t,r){(t&&0==t.count||n<=0)&&e.search_popup_config((function(e){return e("show")})),n--}})}},{key:"is_repository_supported",value:function(e){return!e.is_private()||this.allow_private_repos()}},{key:"show_modal",value:function(){this.search_popup_config((function(e){return e("hide")})),this.search_modal_config((function(e){return e("show")}))}}]),n}(le);function Ur(e){return Ur="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ur(e)}function zr(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Hr(e,t){for(var n=0;n\n ',"\n
\n "])),(0,sr.U)(e.results,(function(e){return(0,ye.dy)(Ir||(Ir=zr(['\n \n
\n
\n
\n ','\n \n ','\n
\n
\n ',"\n
\n
\n
\n "])),e.verbose_name,(0,it.$)({"fa-code-branch":"branch"===e.type,"fa-tag":"tag"===e.type}),(0,at.g)(e.active,(function(){return(0,ye.dy)(Lr||(Lr=zr(['\n \n \n Active\n \n '])))})),e.identifier)})));(0,ye.sY)(n,t);var r=t.innerHTML;return t.remove(),r}}}}}]),e}();$r(Xr,"view_name","ProjectVersionCreateView"),z.add_view(Xr);var Kr=function(e){Wr(n,e);var t=Gr(n);function n(e){var r;return Fr(this,n),(r=t.call(this,e)).url_pdf=o.observable(),r.url_epub=o.observable(),r.url_html=o.observable(),r.url_docs=o.observable(),r.is_built=o.observable(!0),r.data.subscribe((function(e){r.url_pdf(e.downloads.pdf),r.url_epub(e.downloads.epub),r.url_html(e.downloads.htmlzip),r.url_docs(e.urls.documentation),r.is_built(e.built)})),r}return Br(n,[{key:"trigger_build",value:function(e,t){return function(n,o){r.ajax({type:"POST",url:e,data:{csrfmiddlewaretoken:t}}).then((function(e){e.build.urls.build?window.location.href=e.build.urls.build:console.debug("Redirect to new build failed")})).catch((function(e){console.error(e)}))}}}]),n}(fe);$r(Kr,"view_name","VersionListItemView"),z.add_view(Kr);var Zr=function(){function e(t){Fr(this,e),this.cache_key=t,this.prefix_key="announcements",this.storage_key="".concat(this.prefix_key,".").concat(this.cache_key),this.closed=o.observable(),localStorage.getItem(this.storage_key)?this.closed(!0):this.closed(!1)}return Br(e,[{key:"close_announcement",value:function(){this.closed(!0),localStorage.setItem(this.storage_key,!0)}}]),e}();function Qr(e){return Qr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Qr(e)}function eo(e,t){for(var n=0;n select").dropdown({placeholder:""}),r("[data-content]:not([data-semanticui-popup])").popup({position:"top center",delay:{show:500},variation:"small"}),r(".ui.menu > .item[data-tab]").tab(),new i("[data-clipboard-text], [data-clipboard-target]"),r("[data-clipboard-text], [data-clipboard-target]").popup({on:"click",hoverable:!1,content:"Copied!"}),r("[data-analytics], [data-analytics-events]").plausible(this.config.production_domain,this.config.debug)}}])&&oo(t.prototype,c),u&&oo(t,u),Object.defineProperty(t,"prototype",{writable:!1}),e}();r(document).ready((function(){(new ao).run()}))}},a={};function c(e){var t=a[e];if(void 0!==t)return t.exports;var n=a[e]={exports:{}};return i[e].call(n.exports,n,n.exports,c),n.exports}c.m=i,e=[],c.O=(t,n,r,o)=>{if(!n){var i=1/0;for(l=0;l=o)&&Object.keys(c.O).every((e=>c.O[e](n[u])))?n.splice(u--,1):(a=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1];e[l]=[n,r,o]},n=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var o=Object.create(null);c.r(o);var i={};t=t||[null,n({}),n([]),n(n)];for(var a=2&r&&e;"object"==typeof a&&!~t.indexOf(a);a=n(a))Object.getOwnPropertyNames(a).forEach((t=>i[t]=()=>e[t]));return i.default=()=>e,c.d(o,i),o},c.d=(e,t)=>{for(var n in t)c.o(t,n)&&!c.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((t,n)=>(c.f[n](e,t),t)),[])),c.u=e=>"js/vendors~"+e+".js?"+{chartjs:"9fe6b0464564451d1f1f",ansi_up:"c3b32875873781bca34e"}[e],c.miniCssF=e=>{},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r={},o="readthedocsext-theme:",c.l=(e,t,n,i)=>{if(r[e])r[e].push(t);else{var a,u;if(void 0!==n)for(var s=document.getElementsByTagName("script"),l=0;l{a.onerror=a.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(n))),t)return t(n)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=d.bind(null,a.onerror),a.onload=d.bind(null,a.onload),u&&document.head.appendChild(a)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="./",(()=>{var e={site:0};c.f.j=(t,n)=>{var r=c.o(e,t)?e[t]:void 0;if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(((n,o)=>r=e[t]=[n,o]));n.push(r[2]=o);var i=c.p+c.u(t),a=new Error;c.l(i,(n=>{if(c.o(e,t)&&(0!==(r=e[t])&&(e[t]=void 0),r)){var o=n&&("load"===n.type?"missing":n.type),i=n&&n.target&&n.target.src;a.message="Loading chunk "+t+" failed.\n("+o+": "+i+")",a.name="ChunkLoadError",a.type=o,a.request=i,r[1](a)}}),"chunk-"+t,t)}},c.O.j=t=>0===e[t];var t=(t,n)=>{var r,o,[i,a,u]=n,s=0;if(i.some((t=>0!==e[t]))){for(r in a)c.o(a,r)&&(c.m[r]=a[r]);if(u)var l=u(c)}for(t&&t(n);sc(286)));var u=c.O(void 0,["vendor"],(()=>c(6099)));u=c.O(u)})(); +//# sourceMappingURL=site.js.map?408af076a39d6983cbfa \ No newline at end of file diff --git a/readthedocsext/theme/static/readthedocsext/theme/js/site.js.map b/readthedocsext/theme/static/readthedocsext/theme/js/site.js.map index 98a224c4..85f6590c 100644 --- a/readthedocsext/theme/static/readthedocsext/theme/js/site.js.map +++ b/readthedocsext/theme/static/readthedocsext/theme/js/site.js.map @@ -1 +1 @@ -{"version":3,"file":"js/site.js?a00831c90cf85db69618","mappings":"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","sources":["webpack://readthedocsext-theme/webpack/runtime/chunk loaded","webpack://readthedocsext-theme/webpack/runtime/create fake namespace object","webpack://readthedocsext-theme/webpack/runtime/load script","webpack://readthedocsext-theme/external var \"moment\"","webpack://readthedocsext-theme/./src/js/application/views.js","webpack://readthedocsext-theme/./src/js/application/globals.js","webpack://readthedocsext-theme/./src/js/application/plugins.js","webpack://readthedocsext-theme/./src/js/application/registry.js","webpack://readthedocsext-theme/./src/js/build/detail.js","webpack://readthedocsext-theme/./src/js/core/views.js","webpack://readthedocsext-theme/./src/js/gold/index.js","webpack://readthedocsext-theme/./src/js/application/elements.js","webpack://readthedocsext-theme/./src/js/modules/avatar.js","webpack://readthedocsext-theme/./src/js/modules/header.js","webpack://readthedocsext-theme/./src/js/modules/filter.js","webpack://readthedocsext-theme/./src/js/modules/menus.js","webpack://readthedocsext-theme/./node_modules/dompurify/dist/purify.es.mjs","webpack://readthedocsext-theme/./src/js/modules/notifications.js","webpack://readthedocsext-theme/./src/js/modules/popupcards.js","webpack://readthedocsext-theme/./src/js/organization/index.js","webpack://readthedocsext-theme/./src/js/project/admin.js","webpack://readthedocsext-theme/./src/js/tasks/index.js","webpack://readthedocsext-theme/./src/js/project/create.js","webpack://readthedocsext-theme/./src/js/project/index.js","webpack://readthedocsext-theme/./src/js/profile/index.js","webpack://readthedocsext-theme/./src/js/application/index.js","webpack://readthedocsext-theme/./src/js/site.js","webpack://readthedocsext-theme/webpack/bootstrap","webpack://readthedocsext-theme/webpack/runtime/define property getters","webpack://readthedocsext-theme/webpack/runtime/ensure chunk","webpack://readthedocsext-theme/webpack/runtime/get javascript chunk filename","webpack://readthedocsext-theme/webpack/runtime/get mini-css chunk filename","webpack://readthedocsext-theme/webpack/runtime/hasOwnProperty shorthand","webpack://readthedocsext-theme/webpack/runtime/make namespace object","webpack://readthedocsext-theme/webpack/runtime/publicPath","webpack://readthedocsext-theme/webpack/runtime/jsonp chunk loading","webpack://readthedocsext-theme/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);\nvar leafPrototypes;\n// create a fake namespace object\n// mode & 1: value is a module id, require it\n// mode & 2: merge all properties of value into the ns\n// mode & 4: return value when already ns object\n// mode & 16: return value when it's Promise-like\n// mode & 8|1: behave like require\n__webpack_require__.t = function(value, mode) {\n\tif(mode & 1) value = this(value);\n\tif(mode & 8) return value;\n\tif(typeof value === 'object' && value) {\n\t\tif((mode & 4) && value.__esModule) return value;\n\t\tif((mode & 16) && typeof value.then === 'function') return value;\n\t}\n\tvar ns = Object.create(null);\n\t__webpack_require__.r(ns);\n\tvar def = {};\n\tleafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];\n\tfor(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {\n\t\tObject.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));\n\t}\n\tdef['default'] = () => (value);\n\t__webpack_require__.d(ns, def);\n\treturn ns;\n};","var inProgress = {};\nvar dataWebpackPrefix = \"readthedocsext-theme:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = (url, done, key, chunkId) => {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tscript.timeout = 120;\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tvar onScriptComplete = (prev, event) => {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tvar doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach((fn) => (fn(event)));\n\t\tif(prev) return prev(event);\n\t}\n\tvar timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","if(typeof moment === 'undefined') { var e = new Error(\"Cannot find module 'moment'\"); e.code = 'MODULE_NOT_FOUND'; throw e; }\n\nmodule.exports = moment;","import ko from \"knockout\";\n// Note: if debugging is needed, you can try this import instead.\n//import ko from \"knockout/build/output/knockout-latest.debug.js\";\nimport jquery from \"jquery\";\n\n/**\n * ``ApplicationView`` is the top-level view that is bound to ````, and is\n * what surfaces all registered view to templates. Registered views will be\n * available as attributes on this instance, and can be referenced directly, or\n * if the context is already in one of the views, can be referenced using\n * ``$root``:\n *\n * .. code:: html\n *\n * \n * \n *
\n * \n *
\n * \n *
\n *
\n * \n *\n * This view also has a few utility methods that templates use directly. This is\n * for a few quirks where Knockout or HTML required for SemanticUI need some\n * additional code.\n */\nexport class ApplicationView {\n /**\n * Attach application main view\n *\n * @param {string} selector - Selector string to use for view attachment\n */\n attach(selector = \"body\") {\n console.debug(\"Attaching application to selector:\", selector);\n ko.applyBindings(this, jquery(selector)[0]);\n }\n\n /**\n * Show a modal using an event callback. This is set up on\n * :class:`ApplicationView` so that this method is available as\n * ``$root.show_modal(123);``. This is required because the modal plugin ends\n * up altering ````, and this causes some havoc on the already attached\n * view on ````.\n *\n * This should be used from an element data-bind, such as:\n *\n * .. code:: html\n *\n * \n *
\n *\n * This method is executed when the view is attached and returns a callback.\n * The callback is finally executed from the ``click`` binding.\n *\n * @param {string} modal_id - Modal id, references `data-modal-id` attribute\n * @returns {knockout_click}\n */\n show_modal(modal_id) {\n return (data, event) => {\n const selector = \"[data-modal-id=\" + modal_id + \"]\";\n console.debug(\"Showing modal:\", selector);\n const found_modal = jquery(selector).modal(\"show\");\n if (found_modal.length === 0) {\n console.debug(\"Modal not found:\", selector);\n }\n };\n }\n\n /**\n * Submit a child form, useful for triggering a form POST with a link\n *\n * This could be used like:\n *\n * .. code:: html\n *\n * \n *\n * @param {Object} data - Context data\n * @param {Event} event - Click event\n * @returns {knockout_click}\n */\n post_child_form(data, event) {\n const elem = event.currentTarget;\n const form = elem.querySelector(\":scope > form\");\n if (form) {\n form.submit();\n }\n return false;\n }\n}\n","/**\n * Global imports workaround\n *\n * This import is used mostly during testing and for jQuery dependencies.\n * Because jQuery plugins and downstream libraries use jQuery as a\n * global/window object, we need to surface the library in the same way during\n * testing. In normal usage, jQuery is in our vendor library and Webpack knows\n * how to treat reference the external vendor library for instances of a\n * global/window jQuery variable.\n *\n * In testing, this accomplishes the same thing. It's defined in a separate\n * import as the import will be evaluated first, giving a chance to attach\n * `window.jQuery` before the other dependencies, like jQuery plugins and all\n * of FomanticUI's component, are imported.\n */\n\nimport jquery from \"jquery\";\nglobalThis.jQuery = jquery;\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\n\n// TODO this is only really needed while testing, it could be behind a\n// conditional\nimport \"./globals\";\n\nimport Plausible from \"plausible-tracker\";\n\n// Required for FUI tab module\nimport * as jqueryAddress from \"jquery-address\";\n\n/* CommonJS require instead of import syntax on purpose */\nimport * as fomanticVisibility from \"fomantic-ui-less/definitions/behaviors/visibility.js\";\nimport * as fomaticForm from \"fomantic-ui-less/definitions/behaviors/form.js\";\nimport * as fomaticState from \"fomantic-ui-less/definitions/behaviors/state.js\";\nimport * as fomaticAPI from \"fomantic-ui-less/definitions/behaviors/api.js\";\nimport * as fomaticTransition from \"fomantic-ui-less/definitions/modules/transition.js\";\nimport * as fomaticTab from \"fomantic-ui-less/definitions/modules/tab.js\";\nimport * as fomaticDropdown from \"fomantic-ui-less/definitions/modules/dropdown.js\";\nimport * as fomaticModal from \"fomantic-ui-less/definitions/modules/modal.js\";\nimport * as fomaticSearch from \"fomantic-ui-less/definitions/modules/search.js\";\nimport * as fomaticSticky from \"fomantic-ui-less/definitions/modules/sticky.js\";\nimport * as fomaticShape from \"fomantic-ui-less/definitions/modules/shape.js\";\nimport * as fomaticAccordian from \"fomantic-ui-less/definitions/modules/accordion.js\";\nimport * as fomaticSidebar from \"fomantic-ui-less/definitions/modules/sidebar.js\";\nimport * as fomaticDimmer from \"fomantic-ui-less/definitions/modules/dimmer.js\";\nimport * as fomaticCheckbox from \"fomantic-ui-less/definitions/modules/checkbox.js\";\nimport * as fomaticSlider from \"fomantic-ui-less/definitions/modules/slider.js\";\nimport * as fomaticPopup from \"fomantic-ui-less/definitions/modules/popup.js\";\nimport * as fomaticEmbed from \"fomantic-ui-less/definitions/modules/embed.js\";\nimport * as fomaticProgress from \"fomantic-ui-less/definitions/modules/progress.js\";\nimport * as fomaticToast from \"fomantic-ui-less/definitions/modules/toast.js\";\nimport * as fomaticSite from \"fomantic-ui-less/definitions/globals/site.js\";\n\n/**\n * Set up jQuery plugins. SemanticUI jQuery plugins are brought in piecemeal,\n * through separate dependencies. This allows for a smaller footprint.\n */\nexport function configure_jquery_plugins() {\n jquery.fn.site(\"normalize\");\n jquery.fn.tabs = jquery_tabmenu;\n // ``tabmenu`` was ported from our website, but ``tabs`` is nicer\n jquery.fn.tabmenu = jquery_tabmenu;\n jquery.fn.plausible = jqueryPlausible;\n}\n\n/**\n * Set up Knockout plugins for interacting with HTML templates\n */\nexport function configure_knockout_plugins() {\n ko.bindingHandlers.htmlInit = htmlInit;\n ko.bindingHandlers.textInit = textInit;\n ko.bindingHandlers.jsonInit = jsonInit;\n ko.bindingHandlers.valueInit = valueInit;\n ko.bindingHandlers.element = element;\n ko.bindingHandlers.chart = chart;\n ko.bindingHandlers.popup = popup;\n ko.bindingHandlers.semanticui = semanticui;\n ko.bindingHandlers.webcomponent = webcomponent;\n}\n\n/**\n * Binding for initializing an observable using the inner HTML of an element.\n */\nexport const htmlInit = add_init_handler(\n (element) => {\n return element.innerHTML;\n },\n (property) => {\n return { html: property };\n },\n);\n\n/**\n * Binding for initializing an observable using the inner text (the child text\n * nodes) of an element.\n */\nexport const textInit = add_init_handler(\n (element) => {\n return element.innerText;\n },\n (property) => {\n return { text: property };\n },\n);\n\n/**\n * Binding for initializing an observable from the ``value`` attribute of an\n * element -- for example a form ```` element.\n */\nexport const valueInit = add_init_handler(\n (element) => {\n return element.value;\n },\n (property) => {\n return { value: property };\n },\n);\n\n/**\n * JSON binding for writing JSON configuration objects in HTML and initializing\n * the value in a Knockout observable. This is used to transfer configuration\n * from Django and Django template tags, into our front end code.\n *\n * This binding does not set anything, it is only used to initialize an\n * observable on page load.\n *\n * Usage:\n *\n * .. code:: html\n *\n * \n *\n * In turn, there should be a Knockout observable ``config`` in the view:\n *\n * .. code:: javascript\n *\n * self.config = ko.observable()\n * self.url = ko.computed(() => {\n * return self.config().url;\n * })\n */\nexport const jsonInit = add_init_handler((element) => {\n try {\n return JSON.parse(element.innerHTML);\n } catch (err) {\n console.error(err);\n return {};\n }\n});\n\nfunction add_init_handler(getter, setter) {\n return {\n init: function (element, valueAccessor, allBindingsAccessor, data) {\n const property = valueAccessor();\n const value = getter(element);\n\n // Create the observable, if it doesn't exist\n if (!ko.isWriteableObservable(property)) {\n throw new Error(\"Property not found:\", property);\n }\n\n property(value);\n\n if (setter) {\n ko.applyBindingsToNode(element, setter(property));\n }\n },\n };\n}\n\nexport const element = {\n init: function (element, value_accessor) {\n var property = value_accessor();\n property(element);\n },\n};\n\n/**\n * Chart binding used in a couple views to instantiate chartjs on a ````.\n * This plugin loads chartjs, which is rather large, via an async import in\n * Webpack. This will load the chartjs and dependencies separately from the rest\n * of our application code.\n *\n * Usage:\n *\n * .. code:: html\n *\n * \n * \n */\nexport const chart = {\n init: function (element, value_accessor) {\n var property = value_accessor();\n\n // Dynamic webpack import of library. This will trigger a new request.\n import(\n /* webpackChunkName: \"chartjs\" */\n \"chart.js\"\n ).then(({ default: chartjs }) => {\n let config = property();\n\n const datasets = config.data.datasets.map((value) => {\n value.backgroundColor = \"rgb(65, 131, 196, 0.8)\";\n value.borderColor = \"rgb(65, 131, 196, 1)\";\n value.pointBorderColor = \"rgb(65, 131, 196, 1)\";\n value.borderWidth = \"1px\";\n return value;\n });\n\n config.data.datasets = datasets;\n const chart = new chartjs(element, config);\n });\n },\n};\n\n/**\n * Popup plugin for configuring SUI popups. This can be replaced by\n * :func:`semanticui`.\n */\nexport const popup = {\n init: (element, value_accessor, bindings, view, context) => {\n const config = Object.assign(\n {\n hoverable: true,\n delay: {\n show: 300,\n hide: 100,\n },\n exclusive: true,\n onHide: () => {\n context.$rawData.hide();\n },\n },\n value_accessor(),\n );\n const jq_element = jquery(element);\n jq_element.popup(config).hover(() => {\n context.$rawData.show();\n });\n },\n};\n\n/**\n * Web component bridge binding\n *\n * This binding is used to help bridge Knockout views and web components, but\n * allowing observables to set web component attributes when updated.\n *\n * It's important to note that there is likely a bit of extra overhead here as\n * both Knockout and Lit have differing patterns for property/observable\n * lifecycles. That is, Knockout will process the observable change with\n * multiple calls, and then pass the value off to the LitElement, which will do\n * its own round of internal calls to update the property value.\n *\n * Either way, this binding can help with the transition to web components.\n *\n * With an underlying Knockout view, a web component property can be updated\n * with this data binding like so:\n *\n * .. code:: html\n *\n * \n *\n * In the above example here, the web component property ``someProperty`` is\n * updated by the Knockout view observable ``someObservable``. When there is an\n * update to the observable in the Knockout view, this property will then be\n * updated on the web component. This can be a full object, this pattern is not\n * limited to data primitives, like when using web components from HTML.\n */\nexport const webcomponent = {\n update: (element, value_accessor, all_bindings) => {\n const binding_value = ko.unwrap(value_accessor());\n for (const [key, value] of Object.entries(binding_value)) {\n if (value !== undefined) {\n if (typeof value === \"function\") {\n console.error(\"Unsupported function in data binding\");\n } else {\n element[key] = value;\n }\n }\n }\n },\n};\n\n/**\n * SemanticUI Knockout binding for applying SemanticUI jQuery plugins, and\n * plugin configuration to individual elements.\n *\n * .. warning::\n * The modal plugin is not supported in this configuration because of some\n * fun interaction with jQuery.\n *\n * There are two methods of using this Knockout plugin. The first is using\n * literal values from tempaltes:\n *\n * .. code:: html\n *\n * \n *\n * This template code would be similar to executing the following JS:\n *\n * .. code:: js\n *\n * $(\".ui.item\").popup({on: \"click\"});\n *\n * The second way of using this plugin is through an Knockout observable that\n * returns either a literal object or a function from the observable.\n *\n * See :func:`BuildDetailView.progress_config` for an example of both.\n *\n * To pass a literal object via an observable, use an observable such as:\n *\n * .. code:: js\n *\n * this.popup_config = ko.computed(() => {\n * return {\n * label: this.example_observable(),\n * on: \"click\",\n * }\n * });\n *\n * You can also return a function from an observable. This function will be\n * called with a single argument: a callback function representing the jQuery\n * plugin method for the underlying element. This allows for also executing\n * module _behaviors_. Behaviors are listed on some SUI modules, such as:\n * https://fomantic-ui.com/modules/progress.html#behavior\n *\n * For example, the bound element in template code would be:\n *\n * .. code:: html\n *\n * \n *\n * The the matching observable code to trigger a behavior:\n *\n * .. code:: js\n *\n * this.progress_config = ko.computed(() => {\n * if (ko.computedContext.isInitial()) {\n * // First call, initialize the module\n * return {\n * total: 10,\n * }\n * } else {\n * return (progress) => {\n * progress(\"set progress\", self.value());\n * }\n * }\n * });\n *\n */\nexport const semanticui = {\n update: (element, value_accessor, all_bindings) => {\n const binding_value = ko.unwrap(value_accessor());\n const jq_element = jquery(element);\n for (const [key, value] of Object.entries(binding_value)) {\n if (value !== undefined) {\n if (typeof value === \"function\") {\n const callback = (behavior, ...args) => {\n console.debug(\n \"Calling SemanticUI component behavior:\",\n key,\n element,\n behavior,\n ...args,\n );\n jq_element[key](behavior, ...args);\n };\n value(callback);\n } else {\n if (key === \"modal\") {\n // We do something fun here and move the element into ``body``\n // before the SUI initialization. The reason for this is that SUI\n // will move the element automatically already, however when it\n // does the KO bindings are all re-evaluated. This will cause\n // exceptions to be thrown around duplicate binding definitions. To\n // make the ``modal`` module play with KO nicely, we mark the modal\n // as _not detachable_, meaning SUI won't move the element when\n // initializing, and move the element manually so that the\n // positioning is relative to ``body`` instead of being relative to\n // the modal element's parent element. If detachable is manually\n // configured, throw an error.\n if (value.detachable == true) {\n throw new Error(\n \"Setting a modal as detachable is not supported by the semanticui binding.\",\n );\n }\n value.detachable = false;\n document.body.prepend(element);\n }\n // The value is probably an object, and is almost certainly a module\n // configuration for initializing the module\n console.debug(\n \"Setting up SemanticUI component:\",\n key,\n value,\n element,\n );\n jq_element[key](value);\n }\n\n // Set attribute for CSS selector on element. This is used to avoid\n // initializing SUI jQuery plugins twice on elements.\n jq_element.attr(\"data-semanticui-\" + key, true);\n }\n }\n },\n};\n\n/**\n * Plausible tracking module\n *\n * This reuses jQuery to provide explicit tracking of events at Plausible. To\n * use events, add the ``data-analytics-events`` attribute to an element. In most\n * cases, this should be a link element, however in the case of other UI\n * components, it may be a ``
`` or ``\n *\n * In the case of a link with a ``href`` attribute, the link click event will\n * continue after all events have been tracked at Plausible, or after a 1s\n * timeout passes.\n */\nfunction jqueryPlausible(domain, debug = false) {\n let plausibleSettings = { domain: domain };\n if (debug === true) {\n plausibleSettings.trackLocalhost = true;\n }\n const { trackEvent } = Plausible(plausibleSettings);\n const { trackPageview } = Plausible(plausibleSettings);\n\n // Track pageview for all pages\n trackPageview();\n\n return this.each((index, elem) => {\n // ``data-analytics`` is used on the website, but we added some more\n // functionality here so ``data-analytics-events`` is preferred.\n const data = jquery(elem).data();\n const eventNames =\n data.analyticsEvents?.split(/,/) || data.analytics?.split(/,/) || [];\n const eventProperties = {};\n\n // ``data-analytics-property-*`` attributes are used to populate properties.\n Object.keys(data).forEach((key) => {\n const match = key.match(/analyticsProperty(.*)/);\n if (match) {\n const [_, property] = match;\n eventProperties[property.toLowerCase()] = data[key];\n }\n });\n\n function handleAnalyticsEvent(event) {\n const isLink =\n elem.tagName != undefined && elem.tagName.toLowerCase() == \"a\";\n const isMiddleClick = event.type == \"auxclick\" && event.which == 2;\n const isClick = event.type == \"click\";\n const isLinkClick =\n isLink &&\n isClick &&\n !elem.target &&\n !(event.ctrlKey || event.metaKey || event.shiftKey);\n\n if (isMiddleClick || isClick) {\n Promise.all(\n eventNames.map((eventName) => {\n return new Promise((resolve, reject) => {\n const options = { callback: resolve, props: eventProperties };\n trackEvent(eventName, options);\n // Fallback timeout\n setTimeout(() => {\n reject();\n }, 1000);\n });\n }),\n )\n .catch((e) => {\n console.debug(\n \"Plausible didn't receive a response for one or more event\",\n );\n })\n .finally(() => {\n console.debug(\n \"Plausible tracked events:\",\n eventNames,\n eventProperties,\n );\n if (isLinkClick && elem.href && elem.href != \"#\") {\n console.debug(\"Plausible replaying click event\", elem.href);\n window.location = elem.href;\n }\n });\n }\n\n // If this is a normal click of an anchor element, prevent the default\n // event from propagating and instead wait until the callback\n // returns/expires to redirect the current page URL. If the user held\n // control/shift/meta while clicking, we're assuming the browser is doing\n // something special instead and will not block the default event.\n if (isLinkClick) {\n event.preventDefault();\n return false;\n }\n }\n\n // TODO support other methods than click\n elem.addEventListener(\"click\", handleAnalyticsEvent);\n elem.addEventListener(\"auxclick\", handleAnalyticsEvent);\n });\n}\n\n/**\n * Tab group SUI module helper\n *\n * The tab module is instantiated in a unique way that conflicts with the normal\n * patterns used for instantiating FUI modules here. Instead of being called on\n * a singular element, the tab module is called on child elements of a menu.\n * That is, the tab module would normally be set up on multiple modules at a\n * time with ``$(\".ui.menu > .item\").tab({...})``.\n *\n * Calling the module on multiple ``.item`` elements in a query is important,\n * or we end up instantiating a tab menu for each menu item and the tab menu\n * does not work correctly.\n *\n * In short, this consolidates the tab module instantiation onto a query\n * instead of a singular element like the ``semanticui`` data binding normal\n * would.\n */\nfunction jquery_tabmenu(settings) {\n return this.each((index, elem) => {\n $(elem).find(\".item\").tab(settings);\n });\n}\n","import ko from \"knockout\";\n\n/**\n * Registry pattern for views, to accumulate public views for templates\n *\n * To avoid using a routing library, or treating this JS as a single page\n * application on top of a Django backend, we simply will make all views\n * available to all templates. This registry ultimately attaches to the\n * main :class:`ApplicationView` instance, and all views will be available in\n * that bound context.\n *\n * See :class:`ApplicationView` here for examples and more information\n */\nexport class Registry {\n static views = {};\n\n /**\n * Add view to registry. View should have ``view_name`` proprety defined.\n *\n * A ``view_name`` attribute is required as the class name will change when\n * the sources are minified.\n *\n * @param {class} view - Knockout view to expose to the application\n */\n static add_view(view) {\n if (view.name === undefined) {\n console.error(\"View view_name is unspecified\", view);\n return;\n }\n this.views[view.view_name] = (...params) => {\n console.debug(\"Loading view with parameters:\", view.view_name, params);\n // ignoreDependencies is needed here or the context used by the subview\n // is incorrect\n return ko.ignoreDependencies(() => {\n return new view(...params);\n }, this);\n };\n }\n\n /**\n * Attach all of the registered views to a view, almost always, the root\n * application view.\n *\n * @param {ApplicationView} view - View to attach to\n */\n attach(view) {\n for (const [view_name, view_class] of Object.entries(\n this.constructor.views,\n )) {\n view[view_name] = view_class;\n }\n }\n}\n","// Build - detail view\n\nimport jquery from \"jquery\";\nimport ko from \"knockout\";\nimport dayjs from \"dayjs\";\nimport RelativeTime from \"dayjs/plugin/relativeTime\";\nimport Duration from \"dayjs/plugin/duration\";\nimport LocalizedFormat from \"dayjs/plugin/localizedFormat\";\n\nimport { Registry } from \"../application/registry\";\n\ndayjs.extend(RelativeTime);\ndayjs.extend(Duration);\ndayjs.extend(LocalizedFormat);\n\n/** Build command output subview, represented in :class:`BuildCommand` as an\n * array of output lines.\n *\n * @param {Object} build_command_output - BuildCommand APIv2 data\n */\nclass BuildCommandOutput {\n constructor(build_command_output) {\n /** The command that was executed\n * @type {string} */\n this.command = build_command_output.command;\n /** @observable {string} Build command output line */\n this.output = ko.observable(build_command_output.output);\n /** Command output line number provided by :class:`BuildCommand`.\n * @observable {number} Command output line number */\n this.line_number = ko.observable(build_command_output.line_number);\n /** Computed observable for the achor id, the linkable element in the UI.\n * The anchor matches the syntax ``12--123``, which is the command index in\n * the array of commands, and the command output line number index in the\n * array of command output lines.\n * @computed {string} Anchor id in the syntax ``12--123`` */\n this.anchor_id = ko.computed(() => {\n return this.command.id() + \"--\" + this.line_number();\n });\n\n /** @observable {Boolean} Is the line selected/highlighted. Selected lines\n * are lines that are linked to via URL hash */\n this.is_selected = ko.observable(false);\n }\n}\n\n/**\n * Build command subview. :class:`BuildDetailView` retains an array of\n * :class:`BuildCommand` objects for display. This class uses an array of\n * :class:`BuildCommandOutput` objects to display individual lines of output.\n *\n * @param {Object} build_command - APIv2 build command data\n */\nclass BuildCommand {\n constructor(build_command) {\n // Remove the full path from build command display, and hack debug flag\n // TODO rely on debug flag from build model when it's added\n const re_command_trim =\n /(\\/usr\\/src\\/app|\\/home\\/docs)\\/checkouts\\/readthedocs.org\\/user_builds\\/[^\\/]+\\/[^\\/]+\\/[^\\/]+\\//g;\n let command = build_command.command.replace(re_command_trim, \"\");\n let looks_like_debug = false;\n if (build_command.is_debug === undefined) {\n const re_commands = /^(pip freeze|cat .*conf.py)$/;\n looks_like_debug = command.match(re_commands);\n }\n const is_debug = build_command.is_debug || looks_like_debug;\n\n /** @observable {number} Build command id */\n this.id = ko.observable(build_command.id);\n /** @observable {string} Build command executed */\n this.command = ko.observable(command);\n /** @observable {number} Build command posix exit code */\n this.exit_code = ko.observable(build_command.exit_code || 0);\n /** @computed {Boolean} Was :func:`exit_code` successful? */\n this.is_successful = ko.computed(() => {\n return this.exit_code() === 0;\n });\n /** @computed {Boolean} Did command emit exit code 183? */\n this.is_cancelled = ko.computed(() => {\n return this.exit_code() === 183;\n });\n /** @observable {number} Command run time in seconds */\n this.run_time = ko.observable(build_command.run_time);\n /** @observable {number} Command end time in seconds */\n this.end_time = ko.observable(build_command.end_time);\n /** @computed {Boolean} Command is finished running? */\n this.finished = ko.computed(() => {\n return this.end_time() !== null;\n });\n /** @computed {Boolean} This command is a debug class command */\n this.is_debug = ko.observable(is_debug);\n /** @computed {Boolean} Hide debug commands until debug mode is enabled */\n this.is_visible = ko.computed(\n () => {\n if (this.is_debug()) {\n return false;\n } else {\n return true;\n }\n },\n null,\n { deferEvaluation: true },\n );\n /** @computed {string} Command text class */\n this.command_class = ko.computed(() => {\n if (this.is_debug()) {\n return \"grey\";\n } else if (this.is_cancelled()) {\n return \"yellow\";\n } else {\n return this.is_successful() ? \"olive\" : \"red\";\n }\n });\n\n /** @observable {Boolean} Is this command expanded? */\n this.is_expanded = ko.observable(false);\n this.exit_code.subscribe((exit_code) => {\n if (exit_code !== undefined && exit_code > 0) {\n this.is_expanded(true);\n }\n });\n\n /** @observable {string} Raw command output */\n this.output = ko.observable();\n /** @computed {Array.} Split output lines */\n this.output_lines = ko.computed(\n () => {\n const output_lines = this.output().split(/\\n/);\n\n return output_lines.map((line, index) => {\n return new BuildCommandOutput({\n command: this,\n output: line,\n line_number: index + 1,\n });\n });\n },\n null,\n { deferEvaluation: true },\n );\n\n this.output(build_command.output);\n // TODO color output is disabled for now. This needs to be async due to the\n // extra libraries loaded, and should block page load, polling, and updating\n // the selected line. This also requires an application change.\n // this.color_output(build_command.output);\n }\n\n /**\n * Add ANSI coloring and other fun to output string. Modules used here are\n * dynamically loaded separate from the normal vendor bundle. This is to\n * reduce the size of the standard vendor bundle.\n *\n * @param {string} output - The output string to colorize\n * @returns {Promise}\n */\n color_output(output) {\n // Dynamically load expensive chunks. These will be kept out of the normal\n // vendor bundle.\n return import(\n /* webpackChunkName: 'ansi_up' */\n \"ansi_up\"\n ).then(({ default: AnsiUp }) => {\n // Build output lines\n let ansi_up = new AnsiUp();\n ansi_up.use_classes = true;\n output = ansi_up.ansi_to_html(output);\n // TODO use dompurify here\n //output = DOMPurify.sanitize_html(output);\n return output;\n });\n }\n\n /**\n * Toggle :func:`is_expanded`, used to expand command output\n *\n * This is triggered by a click event, so ``false`` is returned to avoid\n * default behavior and event propagation.\n */\n toggle_expanded() {\n this.is_expanded(!this.is_expanded());\n return false;\n }\n}\n\n/**\n * Build detail view shows build metadata, build commands, and build command\n * output. In most cases you are only passing in the build pk, and relying on\n * the API to fill in the rest of the build data.\n *\n * Usage from a Django template:\n *\n * .. code:: html\n *\n *
\n *\n * @param {Object} build - API data for a build.\n */\nexport class BuildDetailView {\n static view_name = \"BuildDetailView\";\n\n constructor(build = {}, url_api_build, url_api_notifications) {\n /** @type {number} The build pk/id to fetch */\n this.id = build.id;\n /** @type {string} APIv2 build detail API URL */\n this.url_api_build = url_api_build;\n /** @type {string} APIv3 build notification API URL */\n this.url_api_notifications = url_api_notifications;\n\n /** @observable {Boolean} Was for successful build or not */\n this.success = ko.observable(build.success);\n /** @observable {string} Build error message */\n this.error = ko.observable(build.error);\n /** @observableArray {Object} List of notifications from API */\n this.notifications = ko.observableArray();\n /** @computed {Boolean} Has notifications? */\n this.has_notifications = ko.computed(() => {\n return this.notifications().length > 0;\n });\n\n /** @obsevable {string} Build state */\n this.state = ko.observable(build.state);\n /** @observable {string} Build state as a display string */\n this.state_display = ko.observable(build.state_display);\n\n // State helpers that are not modeled from the backend API\n /** @observable {Boolean} Is the build in a finished state? */\n this.is_finished = ko.observable(false);\n /** @observable {Boolean} Have we received data from the API yet? */\n this.is_loading = ko.observable(true);\n /** @observable {Boolean} Build can be cancelled */\n this.can_cancel = ko.observable(false);\n /** @observable {Boolean} Build can be retried */\n this.can_retry = ko.observable(false);\n /** @observable {Boolean} There was doc output in the build */\n this.can_view_docs = ko.observable(false);\n\n /** @observable {Boolean} Is the command output wrapped? */\n this.is_wrapped = ko.observable(true);\n\n // Consolidate all of the observable updates that depend on build state\n this.state.subscribe((state) => {\n this.update_state(state);\n });\n\n /** SUI progress module config/behavior\n * @computed {Object or Function} the parameters to pass to the module call\n *\n * See the `semanticui` Knockout plugin for more information */\n this.progress_config = ko\n .computed(() => {\n const state = this.state();\n const states = [\n \"triggered\",\n \"queued\",\n \"cloning\",\n \"installing\",\n \"building\",\n \"uploading\",\n \"finished\",\n ];\n // If this is the first update, configure the module. If this is an\n // update, then send progress updates using module behaviors instead.\n if (ko.computedContext.isInitial()) {\n return {\n autoSuccess: false,\n value: states.indexOf(state),\n total: states.length - 1,\n label: this.state_display(),\n };\n } else {\n if (this.is_finished()) {\n const is_cancelled = state === \"cancelled\";\n const is_failed = this.error() || this.success() === false;\n if (is_cancelled) {\n return (progress) => {\n progress(\"set warning\", \"Build cancelled\");\n };\n } else if (is_failed) {\n return (progress) => {\n // TODO translate this in the application or templates\n progress(\"set error\", \"Build failed\");\n };\n } else {\n return (progress) => {\n // TODO translate this in the application or templates\n progress(\"set success\", \"Build succeeded\");\n };\n }\n } else {\n return (progress) => {\n progress(\"set progress\", states.indexOf(state));\n progress(\"set label\", this.state_display());\n };\n }\n }\n })\n .extend({\n // Debounce API updates, so we aren't triggering this once for each\n // observable update -- from the API response for example.\n deferred: true,\n });\n\n // Date and time manipulation\n /* @observable {number} Build date ... as integer? TBD */\n this.date = ko.observable(build.date);\n /* @observable {number} Build length in seconds */\n this.length = ko.observable(build.length);\n /* @observable {string} Build date display in a localized format */\n this.date_display = ko.observable();\n /* @observable {string} Build date as a relative format */\n this.date_display_since = ko.observable();\n /* @observable {string} Build length in a human readable format */\n this.length_display = ko.observable();\n\n this.date.subscribe((date) => {\n const date_readable = dayjs(date);\n this.date_display(date_readable.format(\"llll\"));\n this.date_display_since(date_readable.fromNow());\n });\n this.length.subscribe((length) => {\n let duration;\n if (length) {\n duration = dayjs.duration(length, \"seconds\");\n } else {\n // Infer length from build start time\n const dateNow = dayjs();\n const dateStart = dayjs(this.date());\n duration = dayjs.duration(dateNow.diff(dateStart));\n }\n let formatParts = [\"s[s]\"];\n if (duration.minutes()) {\n formatParts.unshift(\"m[m]\");\n }\n if (duration.hours()) {\n formatParts.unshift(\"H[h]\");\n }\n this.length_display(duration.format(formatParts.join(\" \")));\n });\n\n /* Output */\n /** @observable {Object} Build configuration used for the build */\n this.config = ko.observable();\n /** @observable {string} The build instance to process the build */\n this.builder = ko.observable(build.builder);\n /** @observable {Array.} Build command objects as an array */\n this.commands = ko.observableArray(build.commands);\n\n /** @observable {string} Repository commit for the build */\n this.commit = ko.observable(build.commit);\n /** @computed {string} A truncated version of the build commit */\n this.commit_short = ko.computed(() => {\n let commit = this.commit();\n if (commit) {\n return commit.substring(0, 8);\n }\n });\n /** @observable {string} URL for build's documentation */\n this.docs_url = ko.observable(build.docs_url);\n /** @observable {string} URL for build commit */\n this.commit_url = ko.observable(build.commit_url);\n\n /* Others */\n /** This is old old build output, before we were separating commands by\n * build command and just lumping evertying by STDOUT/STDERR. Oooof. We\n * don't want to show these, and probably just want to show a \"Sorry, this\n * is too old\" error.\n * @observable {Boolean} Build output doesn't have build commands */\n this.legacy_output = ko.observable(false);\n\n // Selected line handling\n /** The selected command and command line are updated when the window hash\n * (anchor) changes. The hash is meant to be in the format of ``12--123``,\n * which is the command id and the command id output line number.\n * @observable {string} The window hash/anchor */\n this.selected_hash = ko.observable(jquery(location).attr(\"hash\"));\n this.selected_hash.subscribe((selected_hash) => {\n jquery(location).attr(\"hash\", selected_hash);\n });\n /** @observable {BuildCommandOutput} The command line found from the selected hash*/\n this.selected_line = ko.observable();\n // Remove the selected state on the current/old selected line\n this.selected_line.subscribe(\n (selected_line_prev) => {\n if (selected_line_prev) {\n selected_line_prev.is_selected(false);\n }\n },\n this,\n \"beforeChange\",\n );\n // Update the new selected line\n this.selected_line.subscribe((selected_line) => {\n if (selected_line.command.is_debug()) {\n this.show_debug(true);\n }\n selected_line.command.is_expanded(true);\n selected_line.is_selected(true);\n this.selected_hash(selected_line.anchor_id());\n });\n\n /* Debug */\n /** @observable {Boolean} Show debug/info commands */\n this.show_debug = ko.observable(false);\n\n /** @observable {Boolean} Are we still polling the API? */\n this.is_polling = ko.observable(true);\n this.is_polling.subscribe((is_polling) => {\n if (!is_polling) {\n this.set_selected_line_from_hash(this.selected_hash());\n }\n });\n\n if (this.url_api_build) {\n this.poll_api_build();\n }\n if (this.url_api_notifications) {\n this.poll_api_notifications();\n }\n }\n\n /**\n * Continually poll our APIv2 for build object and update Build, BuildCommand,\n * and BuildCommandOutput states. When the API return indicates the build is\n * finished, we stop recursive polling.\n */\n poll_api_build() {\n jquery\n .getJSON(this.url_api_build)\n .then((data) => {\n this.date(data.date);\n this.success(data.success);\n this.error(data.error);\n this.length(data.length);\n this.commit(data.commit);\n this.docs_url(data.docs_url);\n this.commit_url(data.commit_url);\n this.builder(data.builder);\n this.config(data.config);\n this.state(data.state);\n this.state_display(data.state_display);\n\n // Always update date and length, as these should update as the build progresses\n this.date.valueHasMutated();\n this.length.valueHasMutated();\n\n // This is a mock command used to preview the command output.\n // TODO probably do this in the application instead\n this.add_command({\n id: 0,\n command: \"readthedocs-build --show-config\",\n output: JSON.stringify(data.config, null, \" \"),\n exit_code: 0,\n run_time: 0,\n is_debug: true,\n });\n for (const command of data.commands) {\n this.add_command(command);\n }\n\n // We've completed a request to the API. From here, we are not loading\n // from the API, but we'll be polling until the build is finished.\n this.is_loading(false);\n })\n .then(() => {\n // Continually poll API while build is not finished. If it is in a finished\n // state, this method will return without setting another timer. We do not\n // updated :attr:`is_polling` by computed/subscription as we want to ensure\n // this update happens at the very end of API updates instead.\n if (this.is_finished()) {\n this.is_polling(false);\n } else {\n setTimeout(() => {\n this.poll_api_build();\n this.poll_api_notifications();\n }, 2000);\n }\n });\n }\n\n /** Poll APIv3 build notification API directly\n *\n * We have to do this because we rely on the build APIv2 for everything else\n * and the APIv3 build endpoints don't have the data required yet.\n *\n * TODO this should all happen under a single build API v3 poll instead, and\n * this method should go away.\n *\n * @param {str} url - APIv3 build notification endpoint\n */\n poll_api_notifications() {\n const params = {\n state__in: \"read,unread\",\n };\n jquery.getJSON(this.url_api_notifications, params).then((data) => {\n if (data.results) {\n this.notifications(data.results);\n }\n });\n }\n\n /** Add a command to :attr:`commands` if it doesn't already exist\n *\n * @param {Object} command - Build command API data structure\n */\n add_command(command) {\n const command_found = ko.utils.arrayFirst(\n this.commands(),\n (command_search) => {\n return command_search.id() === command.id;\n },\n );\n if (command_found) {\n command_found.output(command.output);\n command_found.exit_code(command.exit_code || 0);\n command_found.run_time(command.run_time);\n command_found.end_time(command.end_time);\n } else {\n this.commands.push(new BuildCommand(command));\n }\n }\n\n /**\n * Set the selected line and focus on the new selected element\n *\n * This is called from :meth:`set_selected_line_from_hash`, but also from the\n * line number link click event. We return ``false`` at the end to avoid the\n * default behavior and event propagation.\n *\n * @param {BuildCommandOutput} selected_line - Command output line to target\n */\n set_selected_line(selected_line) {\n this.selected_line(selected_line);\n // The attribute ``data-selected`` is set in the templates. This isn't\n // ideal, but easier than a custom KO plugin.\n const elem = document.querySelector(\"[data-selected=true]\");\n if (elem) {\n if (elem.scrollIntoView) {\n // Try modern centered focus on element, instead of focus at the top of\n // the viewport.\n elem.scrollIntoView({\n behavior: \"auto\",\n block: \"center\",\n inline: \"center\",\n });\n } else {\n // Back up to the default focus for old browsers\n jquery(elem).focus();\n }\n }\n return false;\n }\n\n /**\n * Set the selected line by looking up the line that corresponds to the\n * selected anchor hash.\n *\n * This loops over the commands and lines to reduce the number of operations.\n * Normally, :attr:`BuildCommandOutput.is_selected` might be a computed\n * observable, but then updates to the selected line are always O(n), for\n * every line of output, across all commands. We can reduce this greatly by\n * iterating over commands, then command lines.\n *\n * @param {string} selected_hash - Hash to lookup\n */\n set_selected_line_from_hash(selected_hash) {\n const re_hash = /^#(\\d+)--(\\d+)$/; // (?:$|(\\d+)$)/; // multiple lines!\n\n if (selected_hash) {\n let found = selected_hash.match(re_hash);\n\n if (!found) {\n return;\n }\n\n const selected_command = ko.utils.arrayFirst(\n this.commands(),\n (command_search) => {\n return command_search.id() == found[1];\n },\n );\n if (selected_command) {\n const selected_line = ko.utils.arrayFirst(\n selected_command.output_lines(),\n (output_line) => {\n return output_line.line_number() == found[2];\n },\n );\n\n if (selected_line) {\n this.set_selected_line(selected_line);\n }\n }\n }\n }\n\n // TODO is this needed? This is likely old view cruft\n show_legacy_output() {\n this.legacy_output(true);\n }\n\n /** Helper for toggling debug mode on the view. This hides some informational\n * commands and the configuration file output step */\n toggle_debug() {\n const show_debug = this.show_debug();\n this.show_debug(!show_debug);\n }\n\n /** Update all attributes and observables that depend on build state */\n update_state(state) {\n // Is build in one of the finished states?\n if ([\"finished\", \"cancelled\"].includes(state)) {\n this.is_finished(true);\n this.can_cancel(false);\n // TODO there is more logic on whether a build can retry in the\n // application, but this is not surfaced in the API response.\n this.can_retry(true);\n\n if (this.success()) {\n this.can_view_docs(true);\n }\n } else {\n // We use any other status here to finally update ``can_cancel`` from\n // it's default of ``false``. The default ensure we don't flash the\n // button if the API response ends up showing that the build finished.\n this.can_cancel(true);\n }\n }\n}\n\nRegistry.add_view(BuildDetailView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n// Constants, pulled from SUI:\n// https://semantic-ui.com/elements/container.html\nconst breakpoints = {\n mobile: 0,\n tablet: 768,\n computer: 992,\n large_screen: 1200,\n};\n\n/**\n * :class:`ResponsiveView` is used to create bindings that alter elements on\n * changes to the viewport width. This can be used to add an SUI class when the\n * viewport width changes.\n *\n * Usage in a binding context:\n *\n * .. code:: html\n *\n *
\n *
\n *
\n *
\n */\nexport class ResponsiveView {\n constructor() {\n this.viewport_width = ko.observable();\n this.device = {\n mobile: ko.observable(true),\n tablet: ko.observable(false),\n computer: ko.observable(false),\n large_screen: ko.observable(false),\n };\n\n // Don't send too many events to listeners\n this.viewport_width.extend({ ratelimit: 500 });\n this.viewport_width.subscribe((width) => {\n for (const device_name of Object.keys(this.device)) {\n const is_device = width >= breakpoints[device_name];\n this.device[device_name](is_device);\n }\n });\n\n // Update window width. This will trigger changes to this.device\n const jq_window = jquery(window);\n const fn_update = () => {\n this.viewport_width(jq_window.width());\n };\n jq_window.on(\"resize\", fn_update);\n fn_update();\n }\n}\n\n/**\n * Base class for API listing views. Provides a foundation for waiting to load\n * data from an API, loading data from an API request, and handling the data.\n *\n * ``data`` parameter needs an ``id`` and ``url`` property.\n *\n */\nexport class APIListItemView {\n constructor(data) {\n this.id = data.id;\n this.url = data.url;\n /** @observable {Boolean} Is the API request started loading? */\n this.loaded = ko.observable(false);\n /** @observable {Boolean} Is the API request done loading? */\n this.loading = ko.observable(false);\n /** The central promise for the request.\n * @type {Promise} */\n this.promise = null;\n /** @observable {Object} The data returned from the API */\n this.data = ko.observable();\n }\n\n /**\n * Using the supplied configuration, perform an API request. Sets up\n * :attr:`promise` so that the child class can manage promise resolve and\n * reject\n */\n fetch() {\n if (this.promise) {\n return this.promise;\n }\n this.promise = new Promise((resolve, reject) => {\n if (this.loaded()) {\n return resolve(this.data());\n }\n this.loading(true);\n jquery.getJSON(this.url).then((data) => {\n this.data(data);\n this.loaded(true);\n this.loading(false);\n return resolve(data);\n });\n });\n }\n}\n\n// And some partial views for base template components\n\n/**\n * HeaderView\n */\nexport class HeaderView {\n static view_name = \"HeaderView\";\n\n constructor() {\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Header configuration, mostly for search */\n this.config = ko.observable();\n /** SUI search configuration object, used from templates\n * @observable {Object} Search configuration */\n this.search_project_config = ko.observable();\n\n // Wait for :func:`config` to change before we init search\n this.config.subscribe((config) => {\n if (config === undefined) {\n return;\n }\n // The URL from the config object is a relative URL, we'll use the\n // window URL origin as the full URL\n const url = new URL(config.api_projects_list_url, window.location.origin);\n url.search = \"?name={query}\";\n this.search_project_config({\n type: \"category\",\n apiSettings: {\n url: url.href,\n onResponse: (resp) => {\n const projects = resp.results.map((elem, index) => {\n // TODO description might be better off in the application model\n let description = elem.slug;\n if (elem.subproject_of) {\n // TODO localize this\n description = \"Subproject of \" + elem.subproject_of.name;\n } else if (elem.translation_of) {\n // TODO localize this\n description =\n elem.language.name +\n \" translation of \" +\n elem.translation_of.name;\n }\n\n // Normalize URL for use in non-standard domain names\n // TODO this is a hack to support alternative domains, like our\n // beta/staging instance. This can be removed when there is only\n // one dashboard subdomain.\n let url_project = new URL(elem.urls.home);\n let url_window = new URL(window.location.href);\n if (url_project.hostname != url_window.hostname) {\n url_project.hostname = url_window.hostname;\n }\n\n return {\n title: elem.name,\n description: description,\n url: url_project.toString(),\n };\n });\n const results = {\n results: {\n \"category-projects\": {\n name: \"Projects\",\n results: projects,\n },\n },\n };\n return results;\n },\n },\n minCharacters: 2,\n });\n });\n }\n}\nRegistry.add_view(HeaderView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\nimport { loadStripe } from \"@stripe/stripe-js/dist/pure.esm.js\";\n\nimport { Registry } from \"../application/registry\";\n\nclass StripeCheckoutView {\n static view_name = \"StripeCheckoutView\";\n\n constructor(config) {\n this.stripeKey = config.stripeKey || \"\";\n this.checkoutSessionUrl = config.checkoutSessionUrl || \"\";\n this.csrfToken = config.csrfToken || \"\";\n\n this.stripe = ko.observable();\n this.stripeLoading = ko.observable(true);\n\n this.priceId = ko.observable();\n\n this.initializeStripe();\n }\n\n /**\n * Load Stripe JS client dynamically\n *\n * The package installed through NPM is just a wrapper for the Stripe hosted\n * JS, which is required for PCI compliance. We treat this similar to a Webpack\n * dynamic import and wait to load the library until doing anything with it.\n * The form element will appear disabled while the library is loading.\n */\n initializeStripe() {\n return loadStripe(this.stripeKey).then((stripe) => {\n this.stripe(stripe);\n this.stripeLoading(false);\n });\n }\n\n /**\n * Click event handler for the Gold subscription form\n *\n * This posts to an internal URL to generate the Stripe checkout session and\n * then redirects the user\n */\n createCheckoutSession() {\n this.stripeLoading(true);\n\n fetch(this.checkoutSessionUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRFToken\": this.csrfToken,\n },\n body: JSON.stringify({\n priceId: this.priceId(),\n }),\n })\n .then((result) => {\n this.stripeLoading(false);\n result.json().then((data) => {\n this.stripe().redirectToCheckout({ sessionId: data.session_id });\n });\n })\n .catch((err) => {\n this.stripeLoading(false);\n });\n }\n}\n\nRegistry.add_view(StripeCheckoutView);\n","import { LitElement } from \"lit\";\n\n/**\n * LightDOMElement\n *\n * This is a helper class for using a light DOM with LitElement\n * instead of a shadow DOM. Light DOM is what allows FUI styles\n * to be used inside the element.\n *\n * Also adds some debugger helpers.\n **/\nexport class LightDOMElement extends LitElement {\n // Use light DOM with inherited styles instead of shadow DOM\n createRenderRoot() {\n return this;\n }\n\n // And some debugging calls\n connectedCallback() {\n super.connectedCallback();\n\n console.debug(\"Setting up web component instance:\", this.constructor.name);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n console.debug(\n \"Disconnecting web component instance:\",\n this.constructor.name,\n );\n }\n}\n","import { LitElement, css, html, nothing, unsafeCSS } from \"lit\";\nimport pureRand from \"pure-rand\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n// This image lives alongside our CSS sources, and bundling outputs this image\n// to the application static path. From here, Django ``static`` template tag is\n// used to reference the file through storage. So, this import is not directly\n// needed here, and this might be a pattern to redo eventually.\nimport avatarImage from \"../../css/images/avatar-1.png\";\n\nexport class AvatarElement extends LitElement {\n static properties = {\n seed: { type: String },\n url: { type: String },\n };\n\n static styles = css`\n :host {\n --avatar-x: 0;\n --avatar-y: 0;\n --avatar-scale: -10px;\n --avatar-background-image: none;\n }\n\n :host > div {\n background-image: var(--avatar-background-image);\n background-repeat: no-repeat;\n background-size: calc(100 * -1 * var(--avatar-scale))\n calc(100 * -1 * var(--avatar-scale));\n background-position-x: calc(var(--avatar-x) * var(--avatar-scale));\n background-position-y: calc(var(--avatar-y) * var(--avatar-scale));\n image-rendering: pixelated;\n width: calc(var(--avatar-scale) * -4);\n height: calc(var(--avatar-scale) * -4);\n }\n `;\n\n render() {\n return html`
`;\n }\n\n updated(changed) {\n // Dynamically update background position through CSS variables. The\n // ``styles`` attribute does not work with dynamic rules, but we can do the\n // same after an updated event on the web component.\n if (changed.has(\"seed\") && this.seed) {\n const rng = pureRand.xoroshiro128plus(this.seed);\n const posX = pureRand.unsafeUniformIntDistribution(0, 99, rng);\n const posY = pureRand.unsafeUniformIntDistribution(0, 99, rng);\n this.style.setProperty(\"--avatar-x\", posX);\n this.style.setProperty(\"--avatar-y\", posY);\n }\n // Similarly, load the image through the avatar URL attribute, as we want\n // the fully resolved storage URL from Django staticfiles.\n if (changed.has(\"url\") && this.url) {\n this.style.setProperty(\"--avatar-background-image\", `url(\"${this.url}\")`);\n }\n }\n}\n\ncustomElements.define(\"readthedocs-avatar\", AvatarElement);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Collapsing header view, for project and organization detail pages\n *\n * @class\n * @constructor\n * @public\n */\nexport class CollapsingHeaderView {\n static view_name = \"CollapsingHeaderView\";\n\n constructor(collapsed = true) {\n /** @observable {Object} Whether the header view is collapsed by default */\n this.is_collapsed = ko.observable(collapsed);\n\n /** Computed observable for the dropdown link class, so it swaps\n *\n * @computed {Object} CSS class for dropdown link\n */\n this.dropdown_class = ko.computed(() => {\n return this.is_collapsed() ? \"fa-caret-down\" : \"fa-caret-up\";\n });\n }\n\n toggle_collapsed() {\n const value = this.is_collapsed();\n this.is_collapsed(!value);\n }\n}\nRegistry.add_view(CollapsingHeaderView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Base view for configuring a view filter.\n *\n * Filters fields are all individually configured with the ``filter_config``\n * property as the configuration for the FUI dropdown element. This\n * configuration converts an ``onchange`` event into a form submission\n * automatically.\n *\n * This configuration is used directly in the ``includes/filter/form.html``\n * include, once per filter field.\n *\n * @class\n * @constructor\n * @public\n */\nexport class FilterView {\n static view_name = \"FilterView\";\n\n constructor() {\n this.filter_config = {\n action: \"activate\",\n onChange: (value, label, $elem) => {\n // Note: limit use of jQuery selector aid. It's confusing to mix Django\n // templates, knockout, and random jQuery selections in the page. Most\n // of the time, you should be able to use a knockout binding, but this\n // was rather trivial and resulted in no additional observables on the\n // view.\n const form = $elem.closest(\"form\");\n form.submit();\n },\n };\n }\n}\nRegistry.add_view(FilterView);\n","import jquery from \"jquery\";\nimport { LitElement, css, html, nothing } from \"lit\";\nimport { ContextProvider, ContextConsumer, createContext } from \"@lit/context\";\nimport { msg } from \"@lit/localize\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { when } from \"lit/directives/when.js\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n/**\n * API event wrapper\n *\n * Generic button/link wrapper to POST to a URL on an event like \"click\".\n * Handles error feedback via toast message and redirection on success.\n *\n * @param {string} csrfToken - CSRF token from Django, attribute ``csrf-token``\n * @param {string} url - API URL for request\n *\n * TODO Deprecate this in favor of APIProviderElement\n **/\nexport class APIEventWrapper extends LightDOMElement {\n static properties = {\n csrfToken: { type: String, attribute: \"csrf-token\" },\n url: { type: String },\n\n // For API response\n data: { state: true },\n };\n\n static method = \"POST\";\n static event = \"click\";\n static errorMessage = \"There was a problem with your request\";\n\n // This is just a wrapper, so we rely on the inner HTML for all of the\n // display and instead just wrap the outer with a clickable element.\n constructor() {\n super();\n this.addEventListener(this.constructor.event, () => {\n this.onEvent();\n });\n }\n\n getHeaders() {\n let headers = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n if (this.csrfToken) {\n headers[\"X-CSRFToken\"] = this.csrfToken;\n }\n return headers;\n }\n\n getUrl() {\n return this.url;\n }\n\n onEvent() {\n if (this.request == undefined) {\n const classes = this.classList;\n classes.add(\"loading\");\n this.sendRequest().finally(() => {\n classes.remove(\"loading\");\n });\n }\n }\n\n sendRequest() {\n const options = {\n method: this.constructor.method,\n headers: this.getHeaders(),\n };\n\n this.request = fetch(this.getUrl(), options)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Request failed\");\n }\n return response.json();\n })\n .then((data) => {\n console.debug(\"Received API reponse:\", data);\n return this.onResponse(data);\n })\n .catch((err) => {\n this.onError(err);\n });\n\n return this.request;\n }\n\n onResponse(data) {\n this.data = data;\n const urlSuccess = this.getSuccessURL();\n if (urlSuccess) {\n window.location.href = urlSuccess;\n }\n }\n\n /** Return URL to redirect to on success\n *\n * Can use ``this.data`` to get API return from ``_link`` and other fields.\n *\n * @returns {string} - URL\n **/\n getSuccessURL() {\n return;\n }\n\n /** Display error toast message on request error\n *\n * @param {Error} err - Exception raised during request\n **/\n onError(err) {\n jquery.toast({\n class: \"error\",\n message: this.constructor.errorMessage,\n });\n }\n}\n\n/** Menu item for rebuilding a version **/\nclass MenuBuildRebuildElement extends APIEventWrapper {\n // TODO translate this here or use a different pattern\n static errorMessage =\n \"There was an error starting a new build for this version\";\n\n getSuccessURL() {\n return this?.data?.build?.urls?.build;\n }\n}\n\ncustomElements.define(\n \"readthedocs-menu-build-rebuild\",\n MenuBuildRebuildElement,\n);\n\n/** Button for resyncing all versions **/\nclass ButtonSyncAllVersionsElement extends APIEventWrapper {\n // TODO translate this here or use a different pattern\n static errorMessage = \"There was an error syncing versions.\";\n\n getSuccessURL() {\n console.log(\"Successfully synced versions\");\n }\n\n // Override the base class to delay the loading state removal\n onEvent() {\n if (this.request == undefined) {\n const classes = this.classList;\n classes.add(\"loading\");\n this.sendRequest().finally(() => {\n setTimeout(() => {\n classes.remove(\"loading\");\n }, 2000);\n });\n }\n }\n}\n\ncustomElements.define(\n \"readthedocs-button-sync-versions\",\n ButtonSyncAllVersionsElement,\n);\n\n/**\n * Lit data contexts for elements with API interactions\n *\n * These data contexts are provided by :js:class:`APIProviderElement` and\n * consumed by :js:class:`APIConsumerElement`. This allows a central element to\n * execute an API request (table row, or a group of buttons) and for sub elements\n * at any point in the nested DOM to use this response (a button nested in the\n * table row, a submenu in the group of buttons).\n **/\nconst contextData = createContext(Symbol(\"data\"));\nconst contextState = createContext(Symbol(\"state\"));\n\n/**\n * API response states enum\n *\n * These are used by API response provider/consumer\n **/\nconst States = Object.freeze({\n WAITING: Symbol(\"waiting\"),\n LOADING: Symbol(\"loading\"),\n DONE: Symbol(\"done\"),\n});\n\n/**\n * Context provider element for API response\n *\n * On an event (mouseover by default), this element starts an API request to the\n * URL specified. It eventually stores the response data in a data context for\n * nested consumer elements.\n *\n * Handles error feedback via toast message and redirection on success.\n *\n * @extends APIEventWrapper\n *\n * TODO This can replace the parent APIEventWrapper element above\n **/\nexport class APIProviderElement extends APIEventWrapper {\n static method = \"GET\";\n static event = \"mouseover\";\n\n /** @type {ContextProvider} Reactive data context for API response data **/\n _providerData = new ContextProvider(this, {\n context: contextData,\n });\n\n set data(value) {\n this._providerData.setValue(value);\n }\n\n /** @type {ContextProvider} Reactive data context for API response state **/\n _providerState = new ContextProvider(this, {\n context: contextState,\n });\n\n set state(value) {\n this._providerState.setValue(value);\n }\n\n constructor() {\n super();\n this.state = States.WAITING;\n }\n\n onEvent() {\n if (this.request == undefined) {\n this.state = States.LOADING;\n this.sendRequest().finally(() => {\n this.state = States.DONE;\n });\n }\n }\n\n onResponse(data) {\n this.data = data;\n }\n}\n\ncustomElements.define(\"readthedocs-api\", APIProviderElement);\n\n/**\n * Context consumer element for API response\n *\n * This element waits for a parent anywhere up the DOM tree to emit a data\n * context element. There are two data contexts: the response state and the\n * response data.\n *\n * @extends LightDOMElement\n *\n * @property {Boolean} disabled - Render the element in a disabled state\n * @property {String} label - Label for the element and ARIA\n **/\nexport class APIConsumerElement extends LightDOMElement {\n static properties = {\n disabled: {\n type: Boolean,\n },\n label: {\n type: String,\n },\n };\n\n /** @type {ContextConsumer} Reactive consumer for API response context data **/\n _consumerData = new ContextConsumer(this, {\n context: contextData,\n subscribe: true,\n });\n\n get data() {\n return this._consumerData.value;\n }\n\n /** @type {ContextConsumer} Reactive consumer for API request state context data **/\n _consumerState = new ContextConsumer(this, {\n context: contextState,\n subscribe: true,\n });\n\n /** @type {State} Reactive context data for API request state **/\n get state() {\n return this._consumerState.value;\n }\n\n constructor() {\n super();\n this.disabled = false;\n }\n\n /**\n * Queue event for late loading links\n *\n * Wait until the request promise resolves and then reemit the event to\n * finally follow the link. This is useful for links that have a late-loaded\n * ``href``.\n *\n * Use it in templates with ``html`
``\n *\n * @param event {Event} - Click or other event\n **/\n queueEvent(event) {\n if (this.state !== States.DONE) {\n console.debug(\"Queueing click event:\", event);\n event.preventDefault();\n event.stopPropagation();\n\n this._consumerState.callback = (value) => {\n if (value === States.DONE) {\n console.debug(\"Replaying click event:\", event);\n // dispatchEvent doesn't seem to work here, so we just create a brand\n // new event here instead.\n event.target.click();\n }\n };\n }\n }\n}\n\n// Menu items\nexport class ItemDocsElement extends APIConsumerElement {\n render() {\n let label = this.label || msg(`View documentation`);\n return html`\n html`0`,\n () => html`-1`,\n )}\"\n >\n \n \n `;\n }\n}\ncustomElements.define(\"readthedocs-item-docs\", ItemDocsElement);\n\nexport class ItemDownloadsElement extends APIConsumerElement {\n render() {\n let label = this.label || msg(`Offline formats`);\n return html`\n html`0`,\n () => html`-1`,\n )}\"\n >\n \n
\n
${msg(`Offline formats`)}
\n \n \n ${msg(`PDF file`)}\n \n \n \n ${msg(`ePUB file`)}\n \n \n \n ${msg(`HTML archive`)}\n \n
\n \n `;\n }\n}\ncustomElements.define(\"readthedocs-item-downloads\", ItemDownloadsElement);\n\nclass MenuProjectAdminElement extends APIConsumerElement {\n static get properties() {\n // TODO `urlSettings` should be part of APIv3 response\n let _properties = APIConsumerElement.properties;\n _properties[\"urlSettings\"] = { type: String, attribute: \"url-settings\" };\n return _properties;\n }\n\n render() {\n const isAdmin = this.data?.permissions?.admin;\n // This preemptively supports a settings URL, which can be passed in as an\n // attribute in the meantime. The `urlSettings` property can go away with this.\n const urlSettings = this.data?.urls?.settings || this.urlSettings;\n return html`\n
${msg(`Admin`)}
\n \n \n ${msg(`Configure project`)}\n \n `;\n }\n}\ncustomElements.define(\n \"readthedocs-menu-project-admin\",\n MenuProjectAdminElement,\n);\n","/*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */\n\nconst {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n} = Object;\nlet {\n freeze,\n seal,\n create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n apply,\n construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n}\nif (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n// SVG\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\${[\\w\\W]*}/gm);\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.2.2';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n remove(node);\n }\n };\n /**\n * _removeAttribute\n *\n * @param name an Attribute name\n * @param element a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, element) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: element.getAttributeNode(name),\n from: element\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: element\n });\n }\n element.removeAttribute(name);\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '' + dirty + '';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * _isClobbered\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n };\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param value object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n const _isNode = function _isNode(value) {\n return typeof Node === 'function' && value instanceof Node;\n };\n function _executeHooks(hooks, currentNode, data) {\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* Detect mXSS attempts abusing namespace confusion */\n if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const {\n attributes\n } = currentNode;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n let value = name === 'value' ? attrValue : stringTrim(attrValue);\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Remove attribute */\n _removeAttribute(name, currentNode);\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n continue;\n }\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {}\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint) {\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","import jquery from \"jquery\";\nimport { LitElement, css, html, nothing } from \"lit\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { when } from \"lit/directives/when.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport DOMPurify from \"dompurify\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n/**\n * Notification\n *\n * Used internally and directly to render a notification API response. This\n * element is not rendered using element attributes, but it is possible to\n * pass in a full notification API response item via the ``notification``\n * object attribute.\n *\n * @param {Object} notification - Single item from notification API response\n * @param {string} csrfToken - CSRF token from Django, attribute ``csrf-token``\n * @param {Boolean} inverted - Whether the message is ``inverted`` variant\n **/\nexport class NotificationElement extends LightDOMElement {\n static properties = {\n csrfToken: { type: String, attribute: \"csrf-token\" },\n notification: { state: true },\n inverted: { type: Boolean },\n };\n\n render() {\n if (this.notification === undefined || this.notification.message === null) {\n return nothing;\n }\n\n // classMap can't be mixed with any other template logic inside ``class=``\n // so we include all conditional logic outside.\n const classes = {\n // Explicitly always invert high level messages to make sure these are\n // more visible than tip/note messages.\n inverted:\n this.inverted ||\n [\"error\", \"warning\", \"info\"].includes(this.notification.message.type),\n };\n classes[this.notification.message.type] = true;\n\n return html`\n
\n ${when(\n this.notification.dismissable,\n () => html`\n \n `,\n )}\n
\n \n ${unsafeHTML(this.notification.message.header)}\n
\n

${unsafeHTML(this.notification.message.body)}

\n
\n `;\n }\n\n dismiss() {\n console.debug(\"Dismissing notification:\", this.notification.id);\n const options = {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRFToken\": this.csrfToken,\n },\n body: JSON.stringify({\n state: \"dismissed\",\n }),\n };\n fetch(this.notification._links._self, options)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Invalid API request\");\n }\n // Use FUI transition module to fade out and remove the notification\n jquery(this).transition({\n animation: \"fade\",\n onComplete: () => {\n this.parentElement.removeChild(this);\n },\n });\n })\n .catch((err) => {\n console.error(\"Error dismissing notification\", err);\n });\n }\n}\n\n/**\n * NotificationListElement\n *\n * This is the wrapper to :js:class:`NotificationElement`, and provides the initial\n * API interaction to populate all of the notification element instances with\n * data.\n *\n * @param {string} url - APIv3 notification URL to use\n * @param {string} csrfToken - Django CSRF token\n * @param {string} state - Notification states to filter for\n * @param {Boolean} inverted - Whether inverted variant should be forced\n **/\nexport class NotificationListElement extends LightDOMElement {\n static properties = {\n url: { type: String },\n csrfToken: { type: String, attribute: \"csrf-token\" },\n state: { type: String },\n inverted: { type: Boolean },\n\n notifications: { state: true },\n request: { state: true },\n };\n\n constructor() {\n super();\n this.state = \"read,unread\";\n }\n\n fetchNotifications() {\n if (!this.url || this.request !== undefined) {\n return;\n }\n const params = new URLSearchParams({\n state__in: this.state,\n });\n this.request = fetch(`${this.url}?${params}`)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Request failed\");\n }\n return response.json();\n })\n .then((data) => {\n if (data?.results === undefined) {\n throw new Error(\"Invalid notification API response\");\n }\n return data.results;\n })\n .then((notifications) => {\n if (notifications) {\n this.notifications = notifications.map((notification) => {\n notification.message.header = DOMPurify.sanitize(\n notification.message.header,\n );\n notification.message.body = DOMPurify.sanitize(\n notification.message.body,\n );\n return notification;\n });\n }\n })\n .catch((err) => {\n console.error(`Error fetching notifications from ${this.url}`, err);\n });\n }\n\n render() {\n // Trigger async notification fetch\n this.fetchNotifications();\n\n if (this.notifications && this.notifications.length > 0) {\n return repeat(\n this.notifications,\n (notification) => notification.id,\n (notification, index) => {\n const elem = document.createElement(\"readthedocs-notification\");\n elem.notification = notification;\n elem.csrfToken = this.csrfToken;\n elem.inverted = this.inverted;\n\n // For FUI .ui.list.item\n elem.className = \"item\";\n return elem;\n },\n );\n } else {\n return nothing;\n }\n }\n}\n\ncustomElements.define(\"readthedocs-notification\", NotificationElement);\ncustomElements.define(\"readthedocs-notification-list\", NotificationListElement);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\nexport class PopupcardView {\n static view_name = \"PopupcardView\";\n\n constructor(url) {\n this.url = url;\n\n /** @observable {Boolean} Is the popup showing currently? */\n this.is_showing = ko.observable(false);\n this.is_showing.subscribe((is_showing) => {\n if (is_showing) {\n this.fetch();\n }\n });\n /** @observable {Boolean} Is the popup loading from the API? */\n this.is_loading = ko.observable(false);\n /** @observable {Boolean} Is the popup loading from the API? */\n this.is_loaded = ko.observable(false);\n\n /** @computed */\n this.popup = ko.observable();\n /** @computed */\n this.popup_config = ko.computed(() => {\n const popup = this.popup();\n if (ko.computedContext.isInitial()) {\n return {\n hoverable: true,\n delay: {\n show: 200,\n hide: 200,\n },\n onShow: () => {\n this.is_showing(true);\n },\n onHide: () => {\n this.is_showing(false);\n },\n };\n } else {\n return popup;\n }\n });\n\n /** @observable {Object} The response object from the API */\n this.data = ko.observable();\n\n this.promise = null;\n }\n\n fetch() {\n if (!this.url) {\n // This popupcard is for a local only request, there might not be an API\n // to request from.\n this.data({});\n this.is_loaded(true);\n this.is_loading(false);\n return;\n }\n if (this.promise) {\n return this.promise;\n }\n this.promise = new Promise((resolve, reject) => {\n if (this.is_loaded()) {\n return resolve(data);\n }\n this.is_loading(true);\n jquery\n .getJSON(this.url)\n .then((data) => {\n this.data(data);\n this.is_loaded(true);\n this.is_loading(false);\n return resolve(data);\n })\n .catch((err) => {\n reject(err);\n });\n }).catch((err) => {\n console.debug(\"Error fetching from API:\", err.responseJSON);\n this.is_loading(false);\n this.is_loaded(false);\n });\n }\n\n show() {\n this.is_showing(true);\n }\n\n hide() {\n this.is_showing(false);\n }\n}\nRegistry.add_view(PopupcardView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Organization authorization settings\n */\nexport class OrganizationSettingsAuthorizationView {\n static view_name = \"OrganizationSettingsAuthorizationView\";\n\n constructor() {\n this.provider_original = undefined;\n this.provider = ko.observable();\n\n this.show_warning = ko.observable(false);\n this.provider.subscribe(\n (value) => {\n if (this.provider_original === undefined) {\n this.provider_original = value;\n }\n },\n this,\n \"beforeChange\",\n );\n this.provider.subscribe((value) => {\n if (\n this.provider_original !== undefined &&\n value !== this.provider_original\n ) {\n this.show_warning(true);\n } else {\n this.show_warning(false);\n }\n });\n this.use_domain = ko.computed(() => {\n return this.provider() === \"email\";\n });\n }\n}\nRegistry.add_view(OrganizationSettingsAuthorizationView);\n\n/**\n * Organization creation\n */\nexport class OrganizationCreateView {\n static view_name = \"OrganizationCreateView\";\n\n constructor() {\n this.name = ko.observable();\n this.slug = ko.observable();\n this.name.subscribe((name) => {\n const slugified = this.slugify(name);\n this.slug(slugified);\n });\n this.example = ko.computed(() => {\n const slug = this.slug() || \"organization\";\n const example = \"https://\" + slug + \"-project.readthedocs-hosted.com\";\n return example;\n });\n }\n\n slugify(val) {\n if (!val) return \"\";\n return (\n val\n .toString()\n .toLowerCase()\n .trim()\n // Replace spaces, non-word chars, underscores and dashes with a single '-'\n // Copied from Django, which is what we are using under the hood\n // https://github.com/django/django/blob/1e9db35/django/utils/text.py#L469-L470\n .replace(/[^\\w\\s-_]+/g, \"-\")\n .replace(/[-\\s]+/g, \"-\")\n // And then also replicate our dns_safe slugging from\n // :py:method:`readthedocs.core.utils.sluggify`\n .replace(/[\\-\\_]+/g, \"-\")\n .replace(/^\\-+/, \"\")\n .replace(/\\-+$/, \"\")\n );\n }\n}\nRegistry.add_view(OrganizationCreateView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Project automation rule form view\n *\n * @param {Object} automation_rule - Initial instance data, optional\n */\nexport class ProjectAutomationRuleView {\n static view_name = \"ProjectAutomationRuleView\";\n\n constructor(automation_rule) {\n this.predefined_match_arg = ko.observable();\n this.is_match_arg_visible = ko.computed(() => {\n let predefined_match_arg = this.predefined_match_arg();\n return predefined_match_arg === \"\";\n });\n this.is_all_versions = ko.computed(() => {\n return this.predefined_match_arg() === \"all-versions\";\n });\n this.is_semver_versions = ko.computed(() => {\n return this.predefined_match_arg() === \"semver-versions\";\n });\n this.is_custom = ko.computed(() => {\n return this.predefined_match_arg() === \"\";\n });\n }\n}\nRegistry.add_view(ProjectAutomationRuleView);\n\n/**\n * Project redirect rule form view\n *\n * @param {Object} redirect - Initial instance data, optional\n */\nexport class ProjectRedirectView {\n static view_name = \"ProjectRedirectView\";\n\n constructor(redirect) {\n this.redirect_type = ko.observable();\n this.from_url = ko.observable(\"\");\n this.to_url = ko.observable(\"\");\n\n this.is_example_disabled = ko.observable(false);\n this.is_from_url_visible = ko.observable();\n this.is_to_url_visible = ko.observable();\n\n // HTML prefix content for from field, don't use user input here\n this.redirect_from_prefix = ko.computed(() => {\n const redirect_type = this.redirect_type();\n const lang_part = `/$lang`;\n const version_part = `/$version`;\n\n if (redirect_type === \"page\") {\n return `${lang_part}${version_part}/`;\n } else if (redirect_type === \"clean_url_to_html\") {\n return `${lang_part}${version_part}/$file/`;\n } else if (redirect_type === \"clean_url_without_trailing_slash_to_html\") {\n return `${lang_part}${version_part}/$file`;\n } else if (redirect_type === \"html_to_clean_url\") {\n return `${lang_part}${version_part}/$file.html`;\n }\n return \"\";\n });\n // User input for from field as text, no HTML allowed\n this.redirect_from = ko.computed(() => {\n const from_url = this.from_url();\n const redirect_type = this.redirect_type();\n if (redirect_type === \"prefix\") {\n return from_url + \"faq.html\";\n } else if (redirect_type === \"page\") {\n return from_url.replace(/^\\/+/, \"\");\n } else if (redirect_type === \"exact\") {\n return from_url;\n }\n return \"\";\n });\n // HTML prefix content for to field, don't use user input here.\n this.redirect_to_prefix = ko.computed(() => {\n const redirect_type = this.redirect_type();\n const lang_part = `/$lang`;\n const version_part = `/$version`;\n\n if (redirect_type === \"prefix\") {\n return `${lang_part}${version_part}/faq.html`;\n } else if (redirect_type === \"page\") {\n return `${lang_part}${version_part}/`;\n } else if (redirect_type === \"clean_url_to_html\") {\n return `${lang_part}${version_part}/$file.html`;\n } else if (redirect_type === \"clean_url_without_trailing_slash_to_html\") {\n return `${lang_part}${version_part}/$file.html`;\n } else if (redirect_type === \"html_to_clean_url\") {\n return `${lang_part}${version_part}/$file/`;\n }\n return \"\";\n });\n // User input for to field as text, no HTML allowed\n this.redirect_to = ko.computed(() => {\n const to_url = this.to_url();\n const redirect_type = this.redirect_type();\n if (redirect_type === \"page\") {\n return to_url.replace(/^\\/+/, \"\");\n } else if (redirect_type === \"exact\") {\n return to_url;\n }\n return \"\";\n });\n\n this.redirect_type.subscribe((redirect_type) => {\n if ([\"prefix\", \"page\", \"exact\"].includes(redirect_type)) {\n this.is_example_disabled(false);\n let is_to_url_visible = true;\n\n // Update visibility\n if (redirect_type == \"prefix\") {\n is_to_url_visible = false;\n }\n this.is_from_url_visible(true);\n this.is_to_url_visible(is_to_url_visible);\n } else if (\n [\n \"clean_url_to_html\",\n \"clean_url_without_trailing_slash_to_html\",\n \"html_to_clean_url\",\n ].includes(redirect_type)\n ) {\n this.is_example_disabled(false);\n this.is_from_url_visible(false);\n this.is_to_url_visible(false);\n } else {\n this.is_example_disabled(true);\n this.is_from_url_visible(false);\n this.is_to_url_visible(false);\n }\n });\n }\n}\nRegistry.add_view(ProjectRedirectView);\n\n/**\n * Project sharing form view\n *\n * @param {Object} share - Initial instance data, optional\n */\nexport class ProjectTemporaryAccessView {\n static view_name = \"ProjectTemporaryAccessView\";\n\n constructor(share) {\n this.access_type = ko.observable();\n this.show_password_field = ko.computed(() => {\n return this.access_type() == \"password\";\n });\n\n this.allow_all = ko.observable(share.allow_all);\n this.show_versions_list = ko.computed(() => {\n return this.allow_all() === false;\n });\n }\n}\nRegistry.add_view(ProjectTemporaryAccessView);\n\n/**\n * Project search analytics view\n *\n * Search analytics chart data and config is loaded from an inline\n * application/json script block, so that data, labels, and localized strings\n * can be handled from the templates.\n *\n * @param {Element} elem - Element that view is attached to\n */\nexport class ProjectSearchAnalyticsView {\n static view_name = \"ProjectSearchAnalyticsView\";\n\n constructor() {\n this.config = ko.observable();\n this.is_loading = ko.observable(true);\n this.config.subscribe((config) => {\n this.is_loading(false);\n });\n }\n}\nRegistry.add_view(ProjectSearchAnalyticsView);\n\n/**\n * Project traffic analytics view\n *\n * This is identical to search analytics currently\n */\nexport class ProjectTrafficAnalyticsView extends ProjectSearchAnalyticsView {\n static view_name = \"ProjectTrafficAnalyticsView\";\n}\nRegistry.add_view(ProjectTrafficAnalyticsView);\n","/* Public task tracking */\n\nimport jquery from \"jquery\";\n\nexport function poll_task(data) {\n var defer = jquery.Deferred();\n var tries = 5;\n\n function poll_task_loop() {\n jquery\n .getJSON(data.url)\n .done(function (task) {\n if (task.finished) {\n if (task.success) {\n defer.resolve();\n } else {\n defer.reject({ message: task.error });\n }\n } else {\n setTimeout(poll_task_loop, 2000);\n }\n })\n .fail(function (error) {\n console.error(\"Error polling task\");\n tries -= 1;\n if (tries > 0) {\n setTimeout(poll_task_loop, 2000);\n } else {\n let error_msg = error.statusText;\n if (error.responseJSON) {\n error_msg = error.responseJSON.detail;\n }\n defer.reject({ message: error_msg });\n }\n });\n }\n\n setTimeout(poll_task_loop, 2000);\n\n return defer;\n}\n\nexport function trigger_task(config) {\n var defer = jquery.Deferred();\n var url = config.url;\n var token = config.token;\n var data = { csrfmiddlewaretoken: token };\n\n jquery.ajax({\n method: \"POST\",\n url: url,\n data: data,\n success: function (data) {\n poll_task(data)\n .then(function () {\n defer.resolve();\n })\n .fail(function (error) {\n // The poll_task function defer will only reject with\n // normalized error objects\n defer.reject(error);\n });\n },\n error: function (error) {\n var error_msg = error.responseJSON.detail || error.statusText;\n defer.reject({ message: error_msg });\n },\n });\n\n return defer;\n}\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\n\nimport * as tasks from \"../tasks\";\nimport * as utils from \"../core/utils\";\nimport { ResponsiveView } from \"../core/views\";\nimport { Registry } from \"../application/registry\";\n\n/**\n * Remote repository instance for remote repository listing.\n *\n * @param {Object} remote_repo - Remote repository API data\n */\nclass RemoteRepository {\n constructor(remote_repo) {\n // Just copy attributes over instead of prototyping. KO observables make a\n // prototype change more awkward. Note, ``projects`` now comes directly from\n // the API response, there is no need to parse this data from the v2\n // ``matches`` response.\n for (const key of Object.keys(remote_repo)) {\n this[key] = remote_repo[key];\n }\n\n /** @observable {Boolean} Is this repository private? */\n this.is_private = ko.observable(this.private);\n /** @observable {Booleean} Is this repository active? */\n this.is_active = ko.observable(this.active);\n /** @observable {Boolean} Does user have admin privilege on the repo? */\n this.has_admin = ko.observable(this.admin);\n /** @computed {Boolean} Can user import this repository? */\n this.is_locked = ko.computed(() => {\n // TODO take platform private repo setting into consideration\n return this.is_private() && !this.has_admin();\n });\n /** @observable {Boolean} Was the repository already imported? */\n this.has_project = ko.computed(() => {\n return this.projects.length > 0;\n });\n }\n}\n\n/**\n * Project creation view, for setting up a new project or linking an existing\n * repository to a new project.\n *\n * @extends {ResposiveView}\n */\nexport class ProjectCreateView extends ResponsiveView {\n static view_name = \"ProjectCreateView\";\n\n constructor() {\n super();\n\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} View configuration */\n this.config = ko.observable();\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Search configuration */\n this.search_config = ko.observable();\n /** @observable {Object} Search popup module configuration */\n this.search_popup_config = ko.observable();\n /** @observable {Object} Search modal module configuration */\n this.search_modal_config = ko.observable(undefined);\n /** @observable {Object} The selected repository */\n this.selected = ko.observable();\n /** @observable {Boolean} Is UI loading from the API currently? */\n this.is_loading = ko.observable(false);\n /** @observable {Boolean} Are remote repositories current resyncing? */\n this.is_syncing = ko.observable(false);\n /** @observable {Boolean} Are remote repositories done resyncing? */\n this.is_synced = ko.observable(false);\n /** @computed {Boolean} Is there a selected repository? */\n this.is_selected = ko.computed(() => {\n return this.selected() !== undefined;\n });\n /** @observable {Boolean} Can private repositories be imported */\n this.allow_private_repos = ko.observable(false);\n /** @observable {string} The error message to show the user */\n this.error = ko.observable();\n\n // Wait for config to be loaded to init search\n this.config.subscribe((config) => {\n if (config !== undefined) {\n this.allow_private_repos(config.allow_private_repos);\n this.init_search();\n }\n });\n }\n\n /**\n * Sync remote repository objects using a call to our API. This sets the UI to\n * a loading state so that user interaction can be limited. Configuration is\n * loaded using :func:`config` and :func:`application.plugins.jsonInit`.\n */\n sync_remote_repos() {\n const config = this.config();\n\n const params = {\n url: config.urls.api_sync_remote_repositories,\n token: config.csrf_token,\n };\n\n this.is_synced(false);\n this.is_syncing(true);\n this.is_loading(true);\n\n let promise = tasks\n .trigger_task(params)\n .fail((error) => {\n console.error(\"Error syncing remote repositories:\", error.message);\n this.error(error.message);\n })\n .always(() => {\n this.is_syncing(false);\n this.is_loading(false);\n this.is_synced(true);\n });\n\n return promise;\n }\n\n /**\n * Set up SUI search once :func:`config` is fully loaded.\n *\n * This uses a Knockout template to make it easier to display the individual\n * elements in the list. The template is loaded from the element\n * ``remote-repo-results``.\n *\n * Ultimately, this sets :func:`search_config`, which is the configuration\n * object that will be eventually be used by SUI search jQuery plugin.\n *\n * .. seealso::\n * https://knockoutjs.com/documentation/template-binding.html\n */\n init_search() {\n const config = this.config();\n const url = config.urls.remoterepository_list + \"?full_name={query}\";\n\n // Configuration for the trigger of the popup element. We manually show the\n // popup in the case that the user has tried searching multiple times\n // unsuccessfully, or has a query with no results.\n let attemptsRemaining = 3;\n this.search_popup_config({\n on: \"manual\",\n position: \"top right\",\n hoverable: true,\n closable: true,\n preserve: true,\n onHidden: () => {\n // If the user did something to hide the popup, like click outside the\n // popup, reset the attempts so that the popup can show again.\n attemptsRemaining = 3;\n },\n // Add a long delay so that hover doesn't accidentally dismiss the popup\n delay: {\n hide: 5000,\n },\n });\n\n // Show repair modal immediately on view load if the URL contains `#repair` hash.\n // Use this for linking users in support directly to this modal.\n const show_modal = jquery(location).attr(\"hash\") == \"#repair\";\n this.search_modal_config({\n autoShow: show_modal,\n centered: false,\n });\n\n this.search_config({\n // We use a Knockout template here, embedded in the template as a script\n // element. This avoids string interpolation in JS and keeps HTML in one\n // place, along with HTML translations.\n type: \"knockout\",\n templates: {\n knockout: (response) => {\n let node_temp = jquery(\"
\");\n\n ko.applyBindingsToNode(node_temp[0], {\n template: {\n name: \"remote-repo-results\",\n data: {\n remote_repos: response.results.map((repo) => {\n return new RemoteRepository(repo);\n }),\n },\n },\n });\n\n const output = node_temp.html();\n node_temp.remove();\n return output;\n },\n },\n error: {\n noResultsHeader: \"No matching repositories found\",\n },\n apiSettings: {\n url: url,\n },\n selector: {\n // Required because the default of ``prompt`` is a rounded input\n prompt: \".ui.text\",\n // Required as we use `.title` to style a complex result title. SUI uses\n // the `text()` of this element to look up the result\n title: \".title .text\",\n },\n fullTextSearch: true,\n onSelect: (result, response) => {\n this.selected(new RemoteRepository(result));\n },\n // Listen for results and decide to show the resync popup based on what\n // the user's interaction with search results.\n onResults: (response, fromCache) => {\n if ((response && response.count == 0) || attemptsRemaining <= 0) {\n // Search results are empty or user tried searching multiple times\n // unsuccessfully so far. Calls with the behavior style call supported by\n // :js:func:`application.plugins.semanticui`.\n this.search_popup_config((popup) => popup(\"show\"));\n }\n attemptsRemaining--;\n },\n });\n }\n\n /** {Boolean} Is repository supported, based on permissions? */\n is_repository_supported(repo) {\n if (repo.is_private()) {\n return this.allow_private_repos();\n }\n return true;\n }\n\n /** Show search modal */\n show_modal() {\n this.search_popup_config((popup) => popup(\"hide\"));\n this.search_modal_config((modal) => modal(\"show\"));\n }\n}\nRegistry.add_view(ProjectCreateView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\nimport { html, render } from \"lit\";\nimport { map } from \"lit/directives/map.js\";\nimport { when } from \"lit/directives/when.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\n\nimport * as admin from \"./admin\";\nimport * as create from \"./create\";\n\nimport { APIListItemView } from \"../core/views\";\nimport { Registry } from \"../application/registry\";\n\nexport { admin, create };\n\n/**\n * Project item view object used for displaying individual projects in the project\n * listing.\n *\n * @param {Object} project - Project API data\n * @extends {APIListItemView}\n */\nexport class ProjectListItemView extends APIListItemView {\n static view_name = \"ProjectListItemView\";\n\n constructor(project) {\n super(project);\n\n // Add expansion to API URL\n this.url = this.url + \"?expand=permissions\";\n\n /** Asynchronously load documentation URL as rendering this URL for each\n * project slows the dashboard down considerably. Instead, this is only\n * fetched when it is needed.\n * @observable {string} Documentation URL for the project */\n this.url_docs = ko.observable();\n /* @observable {Boolean} Does the user have admin permissions on this? */\n this.is_admin = ko.observable(false);\n\n // Subscribe to the data loaded via :class:`APIListItemView`\n this.data.subscribe((data) => {\n this.url_docs(data.urls.documentation);\n this.is_admin(data.permissions.admin);\n });\n }\n}\nRegistry.add_view(ProjectListItemView);\n\n/**\n * View for project version creation and version activation.\n *\n * @class\n * @construtor\n * @public\n */\nexport class ProjectVersionCreateView {\n static view_name = \"ProjectVersionCreateView\";\n\n constructor() {\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Search configuration */\n this.config = ko.observable();\n\n /** @observable {Boolean} Is search data loading? */\n this.is_loading = ko.observable(false);\n\n /** Computed observable for rendering the final search configuration. This\n * is used to initialize search as soon as the :func:`config` observable is\n * finalized.\n * @computed {Object} Search configuration object */\n this.search_config = ko.computed(() => {\n const config = this.config();\n if (config !== undefined) {\n return this.init_search(config);\n }\n });\n }\n\n /**\n * Initialize the SUI search element using the configuration loaded in\n * :func:`search_config`.\n *\n * This sets up various configuration for the search SUI element, but also\n * sets up functions like `onSelect`, for performing actions on events.\n *\n * @param {object} config - configuration for search element\n */\n init_search(config) {\n const maxResults = 100;\n // String interpolation over URLSearchParams here as FUI uses basic string\n // replacement for `{query}`, but this is encoded for URLSearchParams.\n const url = config.api_url + `?limit=${maxResults}&verbose_name={query}`;\n const errors = config.errors || {};\n return {\n apiSettings: {\n url: url,\n },\n error: errors,\n fullTextSearch: true,\n maxResults: maxResults,\n onSelect: (result, response) => {\n window.location.href = result.urls.dashboard.edit;\n },\n selector: {\n // Required because this uses ``.ui.text`` instead of ``.ui.prompt``\n // because prompt uses a rounded input style\n prompt: \".ui.text\",\n // Required as ``.title`` is a complex element in our use, not a simple\n // string like normal. The inner ``.title .text`` sets the field result\n // to just the string value.\n title: \".title .text\",\n },\n // Show results immediately on focus\n minCharacters: 0,\n searchOnFocus: true,\n // Use custom template for rich result display\n type: \"versions\",\n templates: {\n versions: (response) => {\n // Using Lit here as this will likely very soon just be a web component\n // anyways. The project create form references a Knockout observable\n // and a template in HTML. This uses a temporary element to render down\n // to HTML, then removes the element from ``document`` immediately.\n const container = document.createElement(\"div\");\n const results = html`\n \n `;\n\n // Lit renders on an element, but FUI search templates expect HTML return\n render(results, container);\n const htmlResults = container.innerHTML;\n container.remove();\n return htmlResults;\n },\n },\n };\n }\n}\nRegistry.add_view(ProjectVersionCreateView);\n\n/** Version list item subview\n *\n * This mutates project version API return data for use in the Knockout view.\n *\n * URLs for documentation output are lazy loaded when they are requested. We\n * don't do an API call until the user interacts with the version object. This\n * way we don't have to render all of the documentation artifact URLs at once\n * through the resolver. This can cause 10s dashboard load times with a lot of\n * versions.\n *\n * @param {Object} version - Version object data from API\n * @extends {APIListItemView}\n */\nexport class VersionListItemView extends APIListItemView {\n static view_name = \"VersionListItemView\";\n\n constructor(version) {\n super(version);\n\n /** @observable {string} Async loaded URL for version PDF */\n this.url_pdf = ko.observable();\n /** @observable {string} Async loaded URL for version EPUB */\n this.url_epub = ko.observable();\n /** @observable {string} Async loaded URL for version HTMLzip */\n this.url_html = ko.observable();\n /** @observable {string} Async loaded URL for version docs */\n this.url_docs = ko.observable();\n /** @observable {Boolean} is version successfully built? */\n this.is_built = ko.observable(true);\n\n // On resolving the data from the API, fill out these observables.\n this.data.subscribe((data) => {\n this.url_pdf(data.downloads.pdf);\n this.url_epub(data.downloads.epub);\n this.url_html(data.downloads.htmlzip);\n this.url_docs(data.urls.documentation);\n this.is_built(data.built);\n });\n }\n\n /**\n * Trigger a build task for a specific version. This replaces the build\n * dropdown form and instead provides a link on each version admin menu, which\n * is far more intuitive.\n *\n * @param {string} url - URL to post to, this is a project form view, so comes\n * from the Django template\n * @param {string} csrf_token - Also from the Django form, the CSRF token\n * @returns {function} Callback function\n */\n trigger_build(url, csrf_token) {\n return (context, ev) => {\n jquery\n .ajax({\n type: \"POST\",\n url: url,\n data: {\n csrfmiddlewaretoken: csrf_token,\n },\n })\n .then((data) => {\n if (data.build.urls.build) {\n window.location.href = data.build.urls.build;\n } else {\n console.debug(\"Redirect to new build failed\");\n }\n })\n .catch((err) => {\n console.error(err);\n });\n };\n }\n}\nRegistry.add_view(VersionListItemView);\n\nexport class ProjectAnnouncementView {\n static view_name = \"ProjectAnnouncementView\";\n\n constructor(cache_key) {\n this.cache_key = cache_key;\n this.prefix_key = \"announcements\";\n this.storage_key = `${this.prefix_key}.${this.cache_key}`;\n this.closed = ko.observable();\n const cached_value = localStorage.getItem(this.storage_key);\n if (cached_value) {\n this.closed(true);\n } else {\n this.closed(false);\n }\n }\n\n close_announcement() {\n this.closed(true);\n localStorage.setItem(this.storage_key, true);\n }\n}\nRegistry.add_view(ProjectAnnouncementView);\n","import { Registry } from \"../application/registry\";\n\n/*\n * View for tracking opened links, and reloading the page when they are closed.\n *\n * Useful when we depend on changes done outside of the app,\n * but we don't want to have users manually reload the page,\n * or constantly poll the server.\n */\nexport class MigrateGitHubAppView {\n static view_name = \"MigrateGitHubAppView\";\n constructor() {\n this.openedWindows = [];\n this.trackClosedWindows();\n }\n\n trackClosedWindows() {\n setInterval(() => {\n let originalLength = this.openedWindows.length;\n this.openedWindows = this.openedWindows.filter((win) => !win.closed);\n if (this.openedWindows.length < originalLength) {\n // Wait some seconds before reloading the page,\n // so our app has time to update the status.\n setTimeout(() => {\n window.location.reload();\n }, 500);\n }\n }, 250);\n }\n\n /*\n * Click event handler for tracking opened links.\n */\n trackLinkClick(data, event) {\n event.preventDefault();\n const newWindow = window.open(event.target.href, \"_blank\");\n if (newWindow) {\n this.openedWindows.push(newWindow);\n }\n }\n}\n\nRegistry.add_view(MigrateGitHubAppView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\nimport clipboard from \"clipboard\";\nimport * as Sentry from \"@sentry/browser\";\n\nimport { ApplicationView } from \"./views\";\nimport * as plugins from \"./plugins\";\nimport { Registry } from \"./registry\";\n\n// Application views\nimport * as build_views from \"../build\";\nimport * as core_views from \"../core\";\nimport * as gold_views from \"../gold\";\nimport * as module_views from \"../modules\";\nimport * as organization_views from \"../organization\";\nimport * as project_views from \"../project\";\nimport * as profile_views from \"../profile\";\n\n/**\n * This is the main entry point for the front end code and is used to set up and\n * instantiate Webpack, Knockout, and SemanticUI. This class is used to set up\n * and instantiate all of the front end functionality. The main entry point is\n * :meth:`Application.run`.\n */\nexport class Application {\n constructor(config) {\n this.config = config;\n this.registry = new Registry();\n }\n\n /**\n * This is the first method to be executed after instantiation. It handles\n * all of the set up and instantiation.\n *\n * - :meth:`Application.load_config` loads the site configuration\n * - :meth:`Application.configure_plugins` loads plugins\n * - :meth:`Application.attach_view` does view routing and attaches the view\n * - :meth:`Application.start_plugins` sets up jQuery plugins on some elements\n */\n run() {\n this.load_config();\n this.configure_plugins();\n this.attach_view();\n this.add_jquery_plugins();\n }\n\n /**\n * Load site configuration from a special ``application/json`` script element.\n * This configures paths for Webpack async imports, console debugging.\n *\n * .. seealso::\n * Convention on :ref:`js-json-config`\n */\n load_config() {\n if (this.config === undefined) {\n console.debug(\"Loading site front end configuration from script tag\");\n const site_config_src = jquery(\"script#site-config\").text() || \"{}\";\n this.config = JSON.parse(site_config_src);\n }\n if (this.config?.webpack_public_path) {\n __webpack_public_path__ = this.config.webpack_public_path;\n globalThis.__webpack_public_path__ = this.config.webpack_public_path;\n }\n // Null route debug logging, don't do output anything that was debug\n if (!this.config?.debug) {\n console.debug = () => {};\n }\n // Load Sentry\n if (this.config?.sentry?.dsn) {\n Sentry.init({\n dsn: this.config.sentry.dsn,\n environment: this.config.sentry?.environment,\n integrations: [],\n });\n }\n\n return this.config;\n }\n\n /**\n * Add jQuery and Knockout plugins so that HTML and JS can use these plugins.\n * This is mainly just the various import logic and configuration, not where\n * we would run something like ``$('.ui.modal').modal()``.\n */\n configure_plugins() {\n plugins.configure_jquery_plugins();\n plugins.configure_knockout_plugins();\n }\n\n /**\n * Attach the :class:`ApplicationView` view router, which gives templates\n * access to all views that we have available. This is how we are able to\n * reference a view in a Knockout data binding.\n */\n attach_view() {\n const view = new ApplicationView();\n this.registry.attach(view);\n view.attach();\n }\n\n /**\n * Set up jQuery and SUI jQuery plugins that were not explicitly set up in\n * templates. Elements that are configured inside templates use the Knockout\n * plugin :func:`~application.plugins.semanticui`. This allows for explicit\n * set up of an element's plugin, and should be the standard way to attach a\n * jQuery plugin to an element.\n *\n * We don't do generic targeting of elements when setting up jQuery plugins as\n * there are a number of places where an element needs to be initialized with\n * specific plugin configuration. It's easiest to define in HTML what plugin\n * and plugin configuration the element needs.\n *\n * .. warning::\n * Generic targeting use should be avoided and it's use deprecated.\n */\n add_jquery_plugins() {\n // TODO remove instances of these in code and replace with the explicit\n // semanticui KO plugin.\n jquery(\".ui.progress:not([data-semanticui-progress])\").progress();\n jquery(\".ui.accordion:not([data-semanticui-accordion])\").accordion();\n jquery(\".ui.dropdown:not([data-semanticui-dropdown])\").dropdown({\n placeholder: \"\",\n });\n // Automatically convert ```` element.\n */\nexport const valueInit = add_init_handler(\n (element) => {\n return element.value;\n },\n (property) => {\n return { value: property };\n },\n);\n\n/**\n * JSON binding for writing JSON configuration objects in HTML and initializing\n * the value in a Knockout observable. This is used to transfer configuration\n * from Django and Django template tags, into our front end code.\n *\n * This binding does not set anything, it is only used to initialize an\n * observable on page load.\n *\n * Usage:\n *\n * .. code:: html\n *\n * \n *\n * In turn, there should be a Knockout observable ``config`` in the view:\n *\n * .. code:: javascript\n *\n * self.config = ko.observable()\n * self.url = ko.computed(() => {\n * return self.config().url;\n * })\n */\nexport const jsonInit = add_init_handler((element) => {\n try {\n return JSON.parse(element.innerHTML);\n } catch (err) {\n console.error(err);\n return {};\n }\n});\n\nfunction add_init_handler(getter, setter) {\n return {\n init: function (element, valueAccessor, allBindingsAccessor, data) {\n const property = valueAccessor();\n const value = getter(element);\n\n // Create the observable, if it doesn't exist\n if (!ko.isWriteableObservable(property)) {\n throw new Error(\"Property not found:\", property);\n }\n\n property(value);\n\n if (setter) {\n ko.applyBindingsToNode(element, setter(property));\n }\n },\n };\n}\n\nexport const element = {\n init: function (element, value_accessor) {\n var property = value_accessor();\n property(element);\n },\n};\n\n/**\n * Chart binding used in a couple views to instantiate chartjs on a ````.\n * This plugin loads chartjs, which is rather large, via an async import in\n * Webpack. This will load the chartjs and dependencies separately from the rest\n * of our application code.\n *\n * Usage:\n *\n * .. code:: html\n *\n * \n * \n */\nexport const chart = {\n init: function (element, value_accessor) {\n var property = value_accessor();\n\n // Dynamic webpack import of library. This will trigger a new request.\n import(\n /* webpackChunkName: \"chartjs\" */\n \"chart.js\"\n ).then(({ default: chartjs }) => {\n let config = property();\n\n const datasets = config.data.datasets.map((value) => {\n value.backgroundColor = \"rgb(65, 131, 196, 0.8)\";\n value.borderColor = \"rgb(65, 131, 196, 1)\";\n value.pointBorderColor = \"rgb(65, 131, 196, 1)\";\n value.borderWidth = \"1px\";\n return value;\n });\n\n config.data.datasets = datasets;\n const chart = new chartjs(element, config);\n });\n },\n};\n\n/**\n * Popup plugin for configuring SUI popups. This can be replaced by\n * :func:`semanticui`.\n */\nexport const popup = {\n init: (element, value_accessor, bindings, view, context) => {\n const config = Object.assign(\n {\n hoverable: true,\n delay: {\n show: 300,\n hide: 100,\n },\n exclusive: true,\n onHide: () => {\n context.$rawData.hide();\n },\n },\n value_accessor(),\n );\n const jq_element = jquery(element);\n jq_element.popup(config).hover(() => {\n context.$rawData.show();\n });\n },\n};\n\n/**\n * Web component bridge binding\n *\n * This binding is used to help bridge Knockout views and web components, but\n * allowing observables to set web component attributes when updated.\n *\n * It's important to note that there is likely a bit of extra overhead here as\n * both Knockout and Lit have differing patterns for property/observable\n * lifecycles. That is, Knockout will process the observable change with\n * multiple calls, and then pass the value off to the LitElement, which will do\n * its own round of internal calls to update the property value.\n *\n * Either way, this binding can help with the transition to web components.\n *\n * With an underlying Knockout view, a web component property can be updated\n * with this data binding like so:\n *\n * .. code:: html\n *\n * \n *\n * In the above example here, the web component property ``someProperty`` is\n * updated by the Knockout view observable ``someObservable``. When there is an\n * update to the observable in the Knockout view, this property will then be\n * updated on the web component. This can be a full object, this pattern is not\n * limited to data primitives, like when using web components from HTML.\n */\nexport const webcomponent = {\n update: (element, value_accessor, all_bindings) => {\n const binding_value = ko.unwrap(value_accessor());\n for (const [key, value] of Object.entries(binding_value)) {\n if (value !== undefined) {\n if (typeof value === \"function\") {\n console.error(\"Unsupported function in data binding\");\n } else {\n element[key] = value;\n }\n }\n }\n },\n};\n\n/**\n * SemanticUI Knockout binding for applying SemanticUI jQuery plugins, and\n * plugin configuration to individual elements.\n *\n * .. warning::\n * The modal plugin is not supported in this configuration because of some\n * fun interaction with jQuery.\n *\n * There are two methods of using this Knockout plugin. The first is using\n * literal values from tempaltes:\n *\n * .. code:: html\n *\n * \n *\n * This template code would be similar to executing the following JS:\n *\n * .. code:: js\n *\n * $(\".ui.item\").popup({on: \"click\"});\n *\n * The second way of using this plugin is through an Knockout observable that\n * returns either a literal object or a function from the observable.\n *\n * See :func:`BuildDetailView.progress_config` for an example of both.\n *\n * To pass a literal object via an observable, use an observable such as:\n *\n * .. code:: js\n *\n * this.popup_config = ko.computed(() => {\n * return {\n * label: this.example_observable(),\n * on: \"click\",\n * }\n * });\n *\n * You can also return a function from an observable. This function will be\n * called with a single argument: a callback function representing the jQuery\n * plugin method for the underlying element. This allows for also executing\n * module _behaviors_. Behaviors are listed on some SUI modules, such as:\n * https://fomantic-ui.com/modules/progress.html#behavior\n *\n * For example, the bound element in template code would be:\n *\n * .. code:: html\n *\n * \n *\n * The the matching observable code to trigger a behavior:\n *\n * .. code:: js\n *\n * this.progress_config = ko.computed(() => {\n * if (ko.computedContext.isInitial()) {\n * // First call, initialize the module\n * return {\n * total: 10,\n * }\n * } else {\n * return (progress) => {\n * progress(\"set progress\", self.value());\n * }\n * }\n * });\n *\n */\nexport const semanticui = {\n update: (element, value_accessor, all_bindings) => {\n const binding_value = ko.unwrap(value_accessor());\n const jq_element = jquery(element);\n for (const [key, value] of Object.entries(binding_value)) {\n if (value !== undefined) {\n if (typeof value === \"function\") {\n const callback = (behavior, ...args) => {\n console.debug(\n \"Calling SemanticUI component behavior:\",\n key,\n element,\n behavior,\n ...args,\n );\n jq_element[key](behavior, ...args);\n };\n value(callback);\n } else {\n if (key === \"modal\") {\n // We do something fun here and move the element into ``body``\n // before the SUI initialization. The reason for this is that SUI\n // will move the element automatically already, however when it\n // does the KO bindings are all re-evaluated. This will cause\n // exceptions to be thrown around duplicate binding definitions. To\n // make the ``modal`` module play with KO nicely, we mark the modal\n // as _not detachable_, meaning SUI won't move the element when\n // initializing, and move the element manually so that the\n // positioning is relative to ``body`` instead of being relative to\n // the modal element's parent element. If detachable is manually\n // configured, throw an error.\n if (value.detachable == true) {\n throw new Error(\n \"Setting a modal as detachable is not supported by the semanticui binding.\",\n );\n }\n value.detachable = false;\n document.body.prepend(element);\n }\n // The value is probably an object, and is almost certainly a module\n // configuration for initializing the module\n console.debug(\n \"Setting up SemanticUI component:\",\n key,\n value,\n element,\n );\n jq_element[key](value);\n }\n\n // Set attribute for CSS selector on element. This is used to avoid\n // initializing SUI jQuery plugins twice on elements.\n jq_element.attr(\"data-semanticui-\" + key, true);\n }\n }\n },\n};\n\n/**\n * Plausible tracking module\n *\n * This reuses jQuery to provide explicit tracking of events at Plausible. To\n * use events, add the ``data-analytics-events`` attribute to an element. In most\n * cases, this should be a link element, however in the case of other UI\n * components, it may be a ``
`` or ``\n *\n * In the case of a link with a ``href`` attribute, the link click event will\n * continue after all events have been tracked at Plausible, or after a 1s\n * timeout passes.\n */\nfunction jqueryPlausible(domain, debug = false) {\n let plausibleSettings = { domain: domain };\n if (debug === true) {\n plausibleSettings.trackLocalhost = true;\n }\n const { trackEvent } = Plausible(plausibleSettings);\n const { trackPageview } = Plausible(plausibleSettings);\n\n // Track pageview for all pages\n trackPageview();\n\n return this.each((index, elem) => {\n // ``data-analytics`` is used on the website, but we added some more\n // functionality here so ``data-analytics-events`` is preferred.\n const data = jquery(elem).data();\n const eventNames =\n data.analyticsEvents?.split(/,/) || data.analytics?.split(/,/) || [];\n const eventProperties = {};\n\n // ``data-analytics-property-*`` attributes are used to populate properties.\n Object.keys(data).forEach((key) => {\n const match = key.match(/analyticsProperty(.*)/);\n if (match) {\n const [_, property] = match;\n eventProperties[property.toLowerCase()] = data[key];\n }\n });\n\n function handleAnalyticsEvent(event) {\n const isLink =\n elem.tagName != undefined && elem.tagName.toLowerCase() == \"a\";\n const isMiddleClick = event.type == \"auxclick\" && event.which == 2;\n const isClick = event.type == \"click\";\n const isLinkClick =\n isLink &&\n isClick &&\n !elem.target &&\n !(event.ctrlKey || event.metaKey || event.shiftKey);\n\n if (isMiddleClick || isClick) {\n Promise.all(\n eventNames.map((eventName) => {\n return new Promise((resolve, reject) => {\n const options = { callback: resolve, props: eventProperties };\n trackEvent(eventName, options);\n // Fallback timeout\n setTimeout(() => {\n reject();\n }, 1000);\n });\n }),\n )\n .catch((e) => {\n console.debug(\n \"Plausible didn't receive a response for one or more event\",\n );\n })\n .finally(() => {\n console.debug(\n \"Plausible tracked events:\",\n eventNames,\n eventProperties,\n );\n if (isLinkClick && elem.href && elem.href != \"#\") {\n console.debug(\"Plausible replaying click event\", elem.href);\n window.location = elem.href;\n }\n });\n }\n\n // If this is a normal click of an anchor element, prevent the default\n // event from propagating and instead wait until the callback\n // returns/expires to redirect the current page URL. If the user held\n // control/shift/meta while clicking, we're assuming the browser is doing\n // something special instead and will not block the default event.\n if (isLinkClick) {\n event.preventDefault();\n return false;\n }\n }\n\n // TODO support other methods than click\n elem.addEventListener(\"click\", handleAnalyticsEvent);\n elem.addEventListener(\"auxclick\", handleAnalyticsEvent);\n });\n}\n\n/**\n * Tab group SUI module helper\n *\n * The tab module is instantiated in a unique way that conflicts with the normal\n * patterns used for instantiating FUI modules here. Instead of being called on\n * a singular element, the tab module is called on child elements of a menu.\n * That is, the tab module would normally be set up on multiple modules at a\n * time with ``$(\".ui.menu > .item\").tab({...})``.\n *\n * Calling the module on multiple ``.item`` elements in a query is important,\n * or we end up instantiating a tab menu for each menu item and the tab menu\n * does not work correctly.\n *\n * In short, this consolidates the tab module instantiation onto a query\n * instead of a singular element like the ``semanticui`` data binding normal\n * would.\n */\nfunction jquery_tabmenu(settings) {\n return this.each((index, elem) => {\n $(elem).find(\".item\").tab(settings);\n });\n}\n","import ko from \"knockout\";\n\n/**\n * Registry pattern for views, to accumulate public views for templates\n *\n * To avoid using a routing library, or treating this JS as a single page\n * application on top of a Django backend, we simply will make all views\n * available to all templates. This registry ultimately attaches to the\n * main :class:`ApplicationView` instance, and all views will be available in\n * that bound context.\n *\n * See :class:`ApplicationView` here for examples and more information\n */\nexport class Registry {\n static views = {};\n\n /**\n * Add view to registry. View should have ``view_name`` proprety defined.\n *\n * A ``view_name`` attribute is required as the class name will change when\n * the sources are minified.\n *\n * @param {class} view - Knockout view to expose to the application\n */\n static add_view(view) {\n if (view.name === undefined) {\n console.error(\"View view_name is unspecified\", view);\n return;\n }\n this.views[view.view_name] = (...params) => {\n console.debug(\"Loading view with parameters:\", view.view_name, params);\n // ignoreDependencies is needed here or the context used by the subview\n // is incorrect\n return ko.ignoreDependencies(() => {\n return new view(...params);\n }, this);\n };\n }\n\n /**\n * Attach all of the registered views to a view, almost always, the root\n * application view.\n *\n * @param {ApplicationView} view - View to attach to\n */\n attach(view) {\n for (const [view_name, view_class] of Object.entries(\n this.constructor.views,\n )) {\n view[view_name] = view_class;\n }\n }\n}\n","import { Registry } from \"../application/registry\";\n\n/**\n * LoginView manages login-related functionality including saving the\n * last used login method to a cookie for session persistence.\n *\n * Usage in a binding context:\n *\n * .. code:: html\n *\n *
\n *
\n * \n *
\n *
\n */\nexport class LoginView {\n static view_name = \"LoginView\";\n\n constructor() {}\n\n /**\n * Save the provider used for login.\n *\n * This could be used like:\n *\n * .. code:: html\n *\n *
\n * \n *
\n *\n * @param {Object} data - Context data\n * @param {Event} event - Click event\n * @returns {knockout_click}\n */\n save_login_method(data, event) {\n const elem = event.currentTarget;\n if (window.isSecureContext) {\n console.debug(\"Setting last login method: \", elem.dataset.provider);\n cookieStore.set(\"last-login-method\", elem.dataset.provider);\n }\n return true;\n }\n}\n\nRegistry.add_view(LoginView);\n","// Build - detail view\n\nimport jquery from \"jquery\";\nimport ko from \"knockout\";\nimport dayjs from \"dayjs\";\nimport RelativeTime from \"dayjs/plugin/relativeTime\";\nimport Duration from \"dayjs/plugin/duration\";\nimport LocalizedFormat from \"dayjs/plugin/localizedFormat\";\n\nimport { Registry } from \"../application/registry\";\n\ndayjs.extend(RelativeTime);\ndayjs.extend(Duration);\ndayjs.extend(LocalizedFormat);\n\n/** Build command output subview, represented in :class:`BuildCommand` as an\n * array of output lines.\n *\n * @param {Object} build_command_output - BuildCommand APIv2 data\n */\nclass BuildCommandOutput {\n constructor(build_command_output) {\n /** The command that was executed\n * @type {string} */\n this.command = build_command_output.command;\n /** @observable {string} Build command output line */\n this.output = ko.observable(build_command_output.output);\n /** Command output line number provided by :class:`BuildCommand`.\n * @observable {number} Command output line number */\n this.line_number = ko.observable(build_command_output.line_number);\n /** Computed observable for the achor id, the linkable element in the UI.\n * The anchor matches the syntax ``12--123``, which is the command index in\n * the array of commands, and the command output line number index in the\n * array of command output lines.\n * @computed {string} Anchor id in the syntax ``12--123`` */\n this.anchor_id = ko.computed(() => {\n return this.command.id() + \"--\" + this.line_number();\n });\n\n /** @observable {Boolean} Is the line selected/highlighted. Selected lines\n * are lines that are linked to via URL hash */\n this.is_selected = ko.observable(false);\n }\n}\n\n/**\n * Build command subview. :class:`BuildDetailView` retains an array of\n * :class:`BuildCommand` objects for display. This class uses an array of\n * :class:`BuildCommandOutput` objects to display individual lines of output.\n *\n * @param {Object} build_command - APIv2 build command data\n */\nclass BuildCommand {\n constructor(build_command) {\n // Remove the full path from build command display, and hack debug flag\n // TODO rely on debug flag from build model when it's added\n const re_command_trim =\n /(\\/usr\\/src\\/app|\\/home\\/docs)\\/checkouts\\/readthedocs.org\\/user_builds\\/[^\\/]+\\/[^\\/]+\\/[^\\/]+\\//g;\n let command = build_command.command.replace(re_command_trim, \"\");\n let looks_like_debug = false;\n if (build_command.is_debug === undefined) {\n const re_commands = /^(pip freeze|cat .*conf.py)$/;\n looks_like_debug = command.match(re_commands);\n }\n const is_debug = build_command.is_debug || looks_like_debug;\n\n /** @observable {number} Build command id */\n this.id = ko.observable(build_command.id);\n /** @observable {string} Build command executed */\n this.command = ko.observable(command);\n /** @observable {number} Build command posix exit code */\n this.exit_code = ko.observable(build_command.exit_code || 0);\n /** @computed {Boolean} Was :func:`exit_code` successful? */\n this.is_successful = ko.computed(() => {\n return this.exit_code() === 0;\n });\n /** @computed {Boolean} Did command emit exit code 183? */\n this.is_cancelled = ko.computed(() => {\n return this.exit_code() === 183;\n });\n /** @observable {number} Command run time in seconds */\n this.run_time = ko.observable(build_command.run_time);\n /** @observable {number} Command end time in seconds */\n this.end_time = ko.observable(build_command.end_time);\n /** @computed {Boolean} Command is finished running? */\n this.finished = ko.computed(() => {\n return this.end_time() !== null;\n });\n /** @computed {Boolean} This command is a debug class command */\n this.is_debug = ko.observable(is_debug);\n /** @computed {Boolean} Hide debug commands until debug mode is enabled */\n this.is_visible = ko.computed(\n () => {\n if (this.is_debug()) {\n return false;\n } else {\n return true;\n }\n },\n null,\n { deferEvaluation: true },\n );\n /** @computed {string} Command text class */\n this.command_class = ko.computed(() => {\n if (this.is_debug()) {\n return \"grey\";\n } else if (this.is_cancelled()) {\n return \"yellow\";\n } else {\n return this.is_successful() ? \"olive\" : \"red\";\n }\n });\n\n /** @observable {Boolean} Is this command expanded? */\n this.is_expanded = ko.observable(false);\n this.exit_code.subscribe((exit_code) => {\n if (exit_code !== undefined && exit_code > 0) {\n this.is_expanded(true);\n }\n });\n\n /** @observable {string} Raw command output */\n this.output = ko.observable();\n /** @computed {Array.} Split output lines */\n this.output_lines = ko.computed(\n () => {\n const output_lines = this.output().split(/\\n/);\n\n return output_lines.map((line, index) => {\n return new BuildCommandOutput({\n command: this,\n output: line,\n line_number: index + 1,\n });\n });\n },\n null,\n { deferEvaluation: true },\n );\n\n this.output(build_command.output);\n // TODO color output is disabled for now. This needs to be async due to the\n // extra libraries loaded, and should block page load, polling, and updating\n // the selected line. This also requires an application change.\n // this.color_output(build_command.output);\n }\n\n /**\n * Add ANSI coloring and other fun to output string. Modules used here are\n * dynamically loaded separate from the normal vendor bundle. This is to\n * reduce the size of the standard vendor bundle.\n *\n * @param {string} output - The output string to colorize\n * @returns {Promise}\n */\n color_output(output) {\n // Dynamically load expensive chunks. These will be kept out of the normal\n // vendor bundle.\n return import(\n /* webpackChunkName: 'ansi_up' */\n \"ansi_up\"\n ).then(({ default: AnsiUp }) => {\n // Build output lines\n let ansi_up = new AnsiUp();\n ansi_up.use_classes = true;\n output = ansi_up.ansi_to_html(output);\n // TODO use dompurify here\n //output = DOMPurify.sanitize_html(output);\n return output;\n });\n }\n\n /**\n * Toggle :func:`is_expanded`, used to expand command output\n *\n * This is triggered by a click event, so ``false`` is returned to avoid\n * default behavior and event propagation.\n */\n toggle_expanded() {\n this.is_expanded(!this.is_expanded());\n return false;\n }\n}\n\n/**\n * Build detail view shows build metadata, build commands, and build command\n * output. In most cases you are only passing in the build pk, and relying on\n * the API to fill in the rest of the build data.\n *\n * Usage from a Django template:\n *\n * .. code:: html\n *\n *
\n *\n * @param {Object} build - API data for a build.\n */\nexport class BuildDetailView {\n static view_name = \"BuildDetailView\";\n\n constructor(build = {}, url_api_build, url_api_notifications) {\n /** @type {number} The build pk/id to fetch */\n this.id = build.id;\n /** @type {string} APIv2 build detail API URL */\n this.url_api_build = url_api_build;\n /** @type {string} APIv3 build notification API URL */\n this.url_api_notifications = url_api_notifications;\n\n /** @observable {Boolean} Was for successful build or not */\n this.success = ko.observable(build.success);\n /** @observable {string} Build error message */\n this.error = ko.observable(build.error);\n /** @observableArray {Object} List of notifications from API */\n this.notifications = ko.observableArray();\n /** @computed {Boolean} Has notifications? */\n this.has_notifications = ko.computed(() => {\n return this.notifications().length > 0;\n });\n\n /** @obsevable {string} Build state */\n this.state = ko.observable(build.state);\n /** @observable {string} Build state as a display string */\n this.state_display = ko.observable(build.state_display);\n\n // State helpers that are not modeled from the backend API\n /** @observable {Boolean} Is the build in a finished state? */\n this.is_finished = ko.observable(false);\n /** @observable {Boolean} Have we received data from the API yet? */\n this.is_loading = ko.observable(true);\n /** @observable {Boolean} Build can be cancelled */\n this.can_cancel = ko.observable(false);\n /** @observable {Boolean} Build can be retried */\n this.can_retry = ko.observable(false);\n /** @observable {Boolean} There was doc output in the build */\n this.can_view_docs = ko.observable(false);\n\n /** @observable {Boolean} Is the command output wrapped? */\n this.is_wrapped = ko.observable(true);\n\n // Consolidate all of the observable updates that depend on build state\n this.state.subscribe((state) => {\n this.update_state(state);\n });\n\n /** SUI progress module config/behavior\n * @computed {Object or Function} the parameters to pass to the module call\n *\n * See the `semanticui` Knockout plugin for more information */\n this.progress_config = ko\n .computed(() => {\n const state = this.state();\n const states = [\n \"triggered\",\n \"queued\",\n \"cloning\",\n \"installing\",\n \"building\",\n \"uploading\",\n \"finished\",\n ];\n // If this is the first update, configure the module. If this is an\n // update, then send progress updates using module behaviors instead.\n if (ko.computedContext.isInitial()) {\n return {\n autoSuccess: false,\n value: states.indexOf(state),\n total: states.length - 1,\n label: this.state_display(),\n };\n } else {\n if (this.is_finished()) {\n const is_cancelled = state === \"cancelled\";\n const is_failed = this.error() || this.success() === false;\n if (is_cancelled) {\n return (progress) => {\n progress(\"set warning\", \"Build cancelled\");\n };\n } else if (is_failed) {\n return (progress) => {\n // TODO translate this in the application or templates\n progress(\"set error\", \"Build failed\");\n };\n } else {\n return (progress) => {\n // TODO translate this in the application or templates\n progress(\"set success\", \"Build succeeded\");\n };\n }\n } else {\n return (progress) => {\n progress(\"set progress\", states.indexOf(state));\n progress(\"set label\", this.state_display());\n };\n }\n }\n })\n .extend({\n // Debounce API updates, so we aren't triggering this once for each\n // observable update -- from the API response for example.\n deferred: true,\n });\n\n // Date and time manipulation\n /* @observable {number} Build date ... as integer? TBD */\n this.date = ko.observable(build.date);\n /* @observable {number} Build length in seconds */\n this.length = ko.observable(build.length);\n /* @observable {string} Build date display in a localized format */\n this.date_display = ko.observable();\n /* @observable {string} Build date as a relative format */\n this.date_display_since = ko.observable();\n /* @observable {string} Build length in a human readable format */\n this.length_display = ko.observable();\n\n this.date.subscribe((date) => {\n const date_readable = dayjs(date);\n this.date_display(date_readable.format(\"llll\"));\n this.date_display_since(date_readable.fromNow());\n });\n this.length.subscribe((length) => {\n let duration;\n if (length) {\n duration = dayjs.duration(length, \"seconds\");\n } else {\n // Infer length from build start time\n const dateNow = dayjs();\n const dateStart = dayjs(this.date());\n duration = dayjs.duration(dateNow.diff(dateStart));\n }\n let formatParts = [\"s[s]\"];\n if (duration.minutes()) {\n formatParts.unshift(\"m[m]\");\n }\n if (duration.hours()) {\n formatParts.unshift(\"H[h]\");\n }\n this.length_display(duration.format(formatParts.join(\" \")));\n });\n\n /* Output */\n /** @observable {Object} Build configuration used for the build */\n this.config = ko.observable();\n /** @observable {string} The build instance to process the build */\n this.builder = ko.observable(build.builder);\n /** @observable {Array.} Build command objects as an array */\n this.commands = ko.observableArray(build.commands);\n\n /** @observable {string} Repository commit for the build */\n this.commit = ko.observable(build.commit);\n /** @computed {string} A truncated version of the build commit */\n this.commit_short = ko.computed(() => {\n let commit = this.commit();\n if (commit) {\n return commit.substring(0, 8);\n }\n });\n /** @observable {string} URL for build's documentation */\n this.docs_url = ko.observable(build.docs_url);\n /** @observable {string} URL for build commit */\n this.commit_url = ko.observable(build.commit_url);\n\n /* Others */\n /** This is old old build output, before we were separating commands by\n * build command and just lumping evertying by STDOUT/STDERR. Oooof. We\n * don't want to show these, and probably just want to show a \"Sorry, this\n * is too old\" error.\n * @observable {Boolean} Build output doesn't have build commands */\n this.legacy_output = ko.observable(false);\n\n // Selected line handling\n /** The selected command and command line are updated when the window hash\n * (anchor) changes. The hash is meant to be in the format of ``12--123``,\n * which is the command id and the command id output line number.\n * @observable {string} The window hash/anchor */\n this.selected_hash = ko.observable(jquery(location).attr(\"hash\"));\n this.selected_hash.subscribe((selected_hash) => {\n jquery(location).attr(\"hash\", selected_hash);\n });\n /** @observable {BuildCommandOutput} The command line found from the selected hash*/\n this.selected_line = ko.observable();\n // Remove the selected state on the current/old selected line\n this.selected_line.subscribe(\n (selected_line_prev) => {\n if (selected_line_prev) {\n selected_line_prev.is_selected(false);\n }\n },\n this,\n \"beforeChange\",\n );\n // Update the new selected line\n this.selected_line.subscribe((selected_line) => {\n if (selected_line.command.is_debug()) {\n this.show_debug(true);\n }\n selected_line.command.is_expanded(true);\n selected_line.is_selected(true);\n this.selected_hash(selected_line.anchor_id());\n });\n\n /* Debug */\n /** @observable {Boolean} Show debug/info commands */\n this.show_debug = ko.observable(false);\n\n /** @observable {Boolean} Are we still polling the API? */\n this.is_polling = ko.observable(true);\n this.is_polling.subscribe((is_polling) => {\n if (!is_polling) {\n this.set_selected_line_from_hash(this.selected_hash());\n }\n });\n\n if (this.url_api_build) {\n this.poll_api_build();\n }\n if (this.url_api_notifications) {\n this.poll_api_notifications();\n }\n }\n\n /**\n * Continually poll our APIv2 for build object and update Build, BuildCommand,\n * and BuildCommandOutput states. When the API return indicates the build is\n * finished, we stop recursive polling.\n */\n poll_api_build() {\n jquery\n .getJSON(this.url_api_build)\n .then((data) => {\n this.date(data.date);\n this.success(data.success);\n this.error(data.error);\n this.length(data.length);\n this.commit(data.commit);\n this.docs_url(data.docs_url);\n this.commit_url(data.commit_url);\n this.builder(data.builder);\n this.config(data.config);\n this.state(data.state);\n this.state_display(data.state_display);\n\n // Always update date and length, as these should update as the build progresses\n this.date.valueHasMutated();\n this.length.valueHasMutated();\n\n // This is a mock command used to preview the command output.\n // TODO probably do this in the application instead\n this.add_command({\n id: 0,\n command: \"readthedocs-build --show-config\",\n output: JSON.stringify(data.config, null, \" \"),\n exit_code: 0,\n run_time: 0,\n is_debug: true,\n });\n for (const command of data.commands) {\n this.add_command(command);\n }\n\n // We've completed a request to the API. From here, we are not loading\n // from the API, but we'll be polling until the build is finished.\n this.is_loading(false);\n })\n .then(() => {\n // Continually poll API while build is not finished. If it is in a finished\n // state, this method will return without setting another timer. We do not\n // updated :attr:`is_polling` by computed/subscription as we want to ensure\n // this update happens at the very end of API updates instead.\n if (this.is_finished()) {\n this.is_polling(false);\n } else {\n setTimeout(() => {\n this.poll_api_build();\n this.poll_api_notifications();\n }, 2000);\n }\n });\n }\n\n /** Poll APIv3 build notification API directly\n *\n * We have to do this because we rely on the build APIv2 for everything else\n * and the APIv3 build endpoints don't have the data required yet.\n *\n * TODO this should all happen under a single build API v3 poll instead, and\n * this method should go away.\n *\n * @param {str} url - APIv3 build notification endpoint\n */\n poll_api_notifications() {\n const params = {\n state__in: \"read,unread\",\n };\n jquery.getJSON(this.url_api_notifications, params).then((data) => {\n if (data.results) {\n this.notifications(data.results);\n }\n });\n }\n\n /** Add a command to :attr:`commands` if it doesn't already exist\n *\n * @param {Object} command - Build command API data structure\n */\n add_command(command) {\n const command_found = ko.utils.arrayFirst(\n this.commands(),\n (command_search) => {\n return command_search.id() === command.id;\n },\n );\n if (command_found) {\n command_found.output(command.output);\n command_found.exit_code(command.exit_code || 0);\n command_found.run_time(command.run_time);\n command_found.end_time(command.end_time);\n } else {\n this.commands.push(new BuildCommand(command));\n }\n }\n\n /**\n * Set the selected line and focus on the new selected element\n *\n * This is called from :meth:`set_selected_line_from_hash`, but also from the\n * line number link click event. We return ``false`` at the end to avoid the\n * default behavior and event propagation.\n *\n * @param {BuildCommandOutput} selected_line - Command output line to target\n */\n set_selected_line(selected_line) {\n this.selected_line(selected_line);\n // The attribute ``data-selected`` is set in the templates. This isn't\n // ideal, but easier than a custom KO plugin.\n const elem = document.querySelector(\"[data-selected=true]\");\n if (elem) {\n if (elem.scrollIntoView) {\n // Try modern centered focus on element, instead of focus at the top of\n // the viewport.\n elem.scrollIntoView({\n behavior: \"auto\",\n block: \"center\",\n inline: \"center\",\n });\n } else {\n // Back up to the default focus for old browsers\n jquery(elem).focus();\n }\n }\n return false;\n }\n\n /**\n * Set the selected line by looking up the line that corresponds to the\n * selected anchor hash.\n *\n * This loops over the commands and lines to reduce the number of operations.\n * Normally, :attr:`BuildCommandOutput.is_selected` might be a computed\n * observable, but then updates to the selected line are always O(n), for\n * every line of output, across all commands. We can reduce this greatly by\n * iterating over commands, then command lines.\n *\n * @param {string} selected_hash - Hash to lookup\n */\n set_selected_line_from_hash(selected_hash) {\n const re_hash = /^#(\\d+)--(\\d+)$/; // (?:$|(\\d+)$)/; // multiple lines!\n\n if (selected_hash) {\n let found = selected_hash.match(re_hash);\n\n if (!found) {\n return;\n }\n\n const selected_command = ko.utils.arrayFirst(\n this.commands(),\n (command_search) => {\n return command_search.id() == found[1];\n },\n );\n if (selected_command) {\n const selected_line = ko.utils.arrayFirst(\n selected_command.output_lines(),\n (output_line) => {\n return output_line.line_number() == found[2];\n },\n );\n\n if (selected_line) {\n this.set_selected_line(selected_line);\n }\n }\n }\n }\n\n // TODO is this needed? This is likely old view cruft\n show_legacy_output() {\n this.legacy_output(true);\n }\n\n /** Helper for toggling debug mode on the view. This hides some informational\n * commands and the configuration file output step */\n toggle_debug() {\n const show_debug = this.show_debug();\n this.show_debug(!show_debug);\n }\n\n /** Update all attributes and observables that depend on build state */\n update_state(state) {\n // Is build in one of the finished states?\n if ([\"finished\", \"cancelled\"].includes(state)) {\n this.is_finished(true);\n this.can_cancel(false);\n // TODO there is more logic on whether a build can retry in the\n // application, but this is not surfaced in the API response.\n this.can_retry(true);\n\n if (this.success()) {\n this.can_view_docs(true);\n }\n } else {\n // We use any other status here to finally update ``can_cancel`` from\n // it's default of ``false``. The default ensure we don't flash the\n // button if the API response ends up showing that the build finished.\n this.can_cancel(true);\n }\n }\n}\n\nRegistry.add_view(BuildDetailView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n// Constants, pulled from SUI:\n// https://semantic-ui.com/elements/container.html\nconst breakpoints = {\n mobile: 0,\n tablet: 768,\n computer: 992,\n large_screen: 1200,\n};\n\n/**\n * :class:`ResponsiveView` is used to create bindings that alter elements on\n * changes to the viewport width. This can be used to add an SUI class when the\n * viewport width changes.\n *\n * Usage in a binding context:\n *\n * .. code:: html\n *\n *
\n *
\n *
\n *
\n */\nexport class ResponsiveView {\n constructor() {\n this.viewport_width = ko.observable();\n this.device = {\n mobile: ko.observable(true),\n tablet: ko.observable(false),\n computer: ko.observable(false),\n large_screen: ko.observable(false),\n };\n\n // Don't send too many events to listeners\n this.viewport_width.extend({ ratelimit: 500 });\n this.viewport_width.subscribe((width) => {\n for (const device_name of Object.keys(this.device)) {\n const is_device = width >= breakpoints[device_name];\n this.device[device_name](is_device);\n }\n });\n\n // Update window width. This will trigger changes to this.device\n const jq_window = jquery(window);\n const fn_update = () => {\n this.viewport_width(jq_window.width());\n };\n jq_window.on(\"resize\", fn_update);\n fn_update();\n }\n}\n\n/**\n * Base class for API listing views. Provides a foundation for waiting to load\n * data from an API, loading data from an API request, and handling the data.\n *\n * ``data`` parameter needs an ``id`` and ``url`` property.\n *\n */\nexport class APIListItemView {\n constructor(data) {\n this.id = data.id;\n this.url = data.url;\n /** @observable {Boolean} Is the API request started loading? */\n this.loaded = ko.observable(false);\n /** @observable {Boolean} Is the API request done loading? */\n this.loading = ko.observable(false);\n /** The central promise for the request.\n * @type {Promise} */\n this.promise = null;\n /** @observable {Object} The data returned from the API */\n this.data = ko.observable();\n }\n\n /**\n * Using the supplied configuration, perform an API request. Sets up\n * :attr:`promise` so that the child class can manage promise resolve and\n * reject\n */\n fetch() {\n if (this.promise) {\n return this.promise;\n }\n this.promise = new Promise((resolve, reject) => {\n if (this.loaded()) {\n return resolve(this.data());\n }\n this.loading(true);\n jquery.getJSON(this.url).then((data) => {\n this.data(data);\n this.loaded(true);\n this.loading(false);\n return resolve(data);\n });\n });\n }\n}\n\n// And some partial views for base template components\n\n/**\n * HeaderView\n */\nexport class HeaderView {\n static view_name = \"HeaderView\";\n\n constructor() {\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Header configuration, mostly for search */\n this.config = ko.observable();\n /** SUI search configuration object, used from templates\n * @observable {Object} Search configuration */\n this.search_project_config = ko.observable();\n\n // Wait for :func:`config` to change before we init search\n this.config.subscribe((config) => {\n if (config === undefined) {\n return;\n }\n // The URL from the config object is a relative URL, we'll use the\n // window URL origin as the full URL\n const url = new URL(config.api_projects_list_url, window.location.origin);\n url.search = \"?name={query}\";\n this.search_project_config({\n type: \"category\",\n apiSettings: {\n url: url.href,\n onResponse: (resp) => {\n const projects = resp.results.map((elem, index) => {\n // TODO description might be better off in the application model\n let description = elem.slug;\n if (elem.subproject_of) {\n // TODO localize this\n description = \"Subproject of \" + elem.subproject_of.name;\n } else if (elem.translation_of) {\n // TODO localize this\n description =\n elem.language.name +\n \" translation of \" +\n elem.translation_of.name;\n }\n\n // Normalize URL for use in non-standard domain names\n // TODO this is a hack to support alternative domains, like our\n // beta/staging instance. This can be removed when there is only\n // one dashboard subdomain.\n let url_project = new URL(elem.urls.home);\n let url_window = new URL(window.location.href);\n if (url_project.hostname != url_window.hostname) {\n url_project.hostname = url_window.hostname;\n }\n\n return {\n title: elem.name,\n description: description,\n url: url_project.toString(),\n };\n });\n const results = {\n results: {\n \"category-projects\": {\n name: \"Projects\",\n results: projects,\n },\n },\n };\n return results;\n },\n },\n minCharacters: 2,\n });\n });\n }\n}\nRegistry.add_view(HeaderView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\nimport { loadStripe } from \"@stripe/stripe-js/dist/pure.esm.js\";\n\nimport { Registry } from \"../application/registry\";\n\nclass StripeCheckoutView {\n static view_name = \"StripeCheckoutView\";\n\n constructor(config) {\n this.stripeKey = config.stripeKey || \"\";\n this.checkoutSessionUrl = config.checkoutSessionUrl || \"\";\n this.csrfToken = config.csrfToken || \"\";\n\n this.stripe = ko.observable();\n this.stripeLoading = ko.observable(true);\n\n this.priceId = ko.observable();\n\n this.initializeStripe();\n }\n\n /**\n * Load Stripe JS client dynamically\n *\n * The package installed through NPM is just a wrapper for the Stripe hosted\n * JS, which is required for PCI compliance. We treat this similar to a Webpack\n * dynamic import and wait to load the library until doing anything with it.\n * The form element will appear disabled while the library is loading.\n */\n initializeStripe() {\n return loadStripe(this.stripeKey).then((stripe) => {\n this.stripe(stripe);\n this.stripeLoading(false);\n });\n }\n\n /**\n * Click event handler for the Gold subscription form\n *\n * This posts to an internal URL to generate the Stripe checkout session and\n * then redirects the user\n */\n createCheckoutSession() {\n this.stripeLoading(true);\n\n fetch(this.checkoutSessionUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRFToken\": this.csrfToken,\n },\n body: JSON.stringify({\n priceId: this.priceId(),\n }),\n })\n .then((result) => {\n this.stripeLoading(false);\n result.json().then((data) => {\n this.stripe().redirectToCheckout({ sessionId: data.session_id });\n });\n })\n .catch((err) => {\n this.stripeLoading(false);\n });\n }\n}\n\nRegistry.add_view(StripeCheckoutView);\n","import { LitElement } from \"lit\";\n\n/**\n * LightDOMElement\n *\n * This is a helper class for using a light DOM with LitElement\n * instead of a shadow DOM. Light DOM is what allows FUI styles\n * to be used inside the element.\n *\n * Also adds some debugger helpers.\n **/\nexport class LightDOMElement extends LitElement {\n // Use light DOM with inherited styles instead of shadow DOM\n createRenderRoot() {\n return this;\n }\n\n // And some debugging calls\n connectedCallback() {\n super.connectedCallback();\n\n console.debug(\"Setting up web component instance:\", this.constructor.name);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n console.debug(\n \"Disconnecting web component instance:\",\n this.constructor.name,\n );\n }\n}\n","import { LitElement, css, html, nothing, unsafeCSS } from \"lit\";\nimport pureRand from \"pure-rand\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n// This image lives alongside our CSS sources, and bundling outputs this image\n// to the application static path. From here, Django ``static`` template tag is\n// used to reference the file through storage. So, this import is not directly\n// needed here, and this might be a pattern to redo eventually.\nimport avatarImage from \"../../css/images/avatar-1.png\";\n\nexport class AvatarElement extends LitElement {\n static properties = {\n seed: { type: String },\n url: { type: String },\n };\n\n static styles = css`\n :host {\n --avatar-x: 0;\n --avatar-y: 0;\n --avatar-scale: -10px;\n --avatar-background-image: none;\n }\n\n :host > div {\n background-image: var(--avatar-background-image);\n background-repeat: no-repeat;\n background-size: calc(100 * -1 * var(--avatar-scale))\n calc(100 * -1 * var(--avatar-scale));\n background-position-x: calc(var(--avatar-x) * var(--avatar-scale));\n background-position-y: calc(var(--avatar-y) * var(--avatar-scale));\n image-rendering: pixelated;\n width: calc(var(--avatar-scale) * -4);\n height: calc(var(--avatar-scale) * -4);\n }\n `;\n\n render() {\n return html`
`;\n }\n\n updated(changed) {\n // Dynamically update background position through CSS variables. The\n // ``styles`` attribute does not work with dynamic rules, but we can do the\n // same after an updated event on the web component.\n if (changed.has(\"seed\") && this.seed) {\n const rng = pureRand.xoroshiro128plus(this.seed);\n const posX = pureRand.unsafeUniformIntDistribution(0, 99, rng);\n const posY = pureRand.unsafeUniformIntDistribution(0, 99, rng);\n this.style.setProperty(\"--avatar-x\", posX);\n this.style.setProperty(\"--avatar-y\", posY);\n }\n // Similarly, load the image through the avatar URL attribute, as we want\n // the fully resolved storage URL from Django staticfiles.\n if (changed.has(\"url\") && this.url) {\n this.style.setProperty(\"--avatar-background-image\", `url(\"${this.url}\")`);\n }\n }\n}\n\ncustomElements.define(\"readthedocs-avatar\", AvatarElement);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Collapsing header view, for project and organization detail pages\n *\n * @class\n * @constructor\n * @public\n */\nexport class CollapsingHeaderView {\n static view_name = \"CollapsingHeaderView\";\n\n constructor(collapsed = true) {\n /** @observable {Object} Whether the header view is collapsed by default */\n this.is_collapsed = ko.observable(collapsed);\n\n /** Computed observable for the dropdown link class, so it swaps\n *\n * @computed {Object} CSS class for dropdown link\n */\n this.dropdown_class = ko.computed(() => {\n return this.is_collapsed() ? \"fa-caret-down\" : \"fa-caret-up\";\n });\n }\n\n toggle_collapsed() {\n const value = this.is_collapsed();\n this.is_collapsed(!value);\n }\n}\nRegistry.add_view(CollapsingHeaderView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Base view for configuring a view filter.\n *\n * Filters fields are all individually configured with the ``filter_config``\n * property as the configuration for the FUI dropdown element. This\n * configuration converts an ``onchange`` event into a form submission\n * automatically.\n *\n * This configuration is used directly in the ``includes/filter/form.html``\n * include, once per filter field.\n *\n * @class\n * @constructor\n * @public\n */\nexport class FilterView {\n static view_name = \"FilterView\";\n\n constructor() {\n this.filter_config = {\n action: \"activate\",\n onChange: (value, label, $elem) => {\n // Note: limit use of jQuery selector aid. It's confusing to mix Django\n // templates, knockout, and random jQuery selections in the page. Most\n // of the time, you should be able to use a knockout binding, but this\n // was rather trivial and resulted in no additional observables on the\n // view.\n const form = $elem.closest(\"form\");\n form.submit();\n },\n };\n }\n}\nRegistry.add_view(FilterView);\n","import jquery from \"jquery\";\nimport { LitElement, css, html, nothing } from \"lit\";\nimport { ContextProvider, ContextConsumer, createContext } from \"@lit/context\";\nimport { msg } from \"@lit/localize\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { when } from \"lit/directives/when.js\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n/**\n * API event wrapper\n *\n * Generic button/link wrapper to POST to a URL on an event like \"click\".\n * Handles error feedback via toast message and redirection on success.\n *\n * @param {string} csrfToken - CSRF token from Django, attribute ``csrf-token``\n * @param {string} url - API URL for request\n *\n * TODO Deprecate this in favor of APIProviderElement\n **/\nexport class APIEventWrapper extends LightDOMElement {\n static properties = {\n csrfToken: { type: String, attribute: \"csrf-token\" },\n url: { type: String },\n\n // For API response\n data: { state: true },\n };\n\n static method = \"POST\";\n static event = \"click\";\n static errorMessage = \"There was a problem with your request\";\n\n // This is just a wrapper, so we rely on the inner HTML for all of the\n // display and instead just wrap the outer with a clickable element.\n constructor() {\n super();\n this.addEventListener(this.constructor.event, () => {\n this.onEvent();\n });\n }\n\n getHeaders() {\n let headers = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n if (this.csrfToken) {\n headers[\"X-CSRFToken\"] = this.csrfToken;\n }\n return headers;\n }\n\n getUrl() {\n return this.url;\n }\n\n onEvent() {\n if (this.request == undefined) {\n const classes = this.classList;\n classes.add(\"loading\");\n this.sendRequest().finally(() => {\n classes.remove(\"loading\");\n });\n }\n }\n\n sendRequest() {\n const options = {\n method: this.constructor.method,\n headers: this.getHeaders(),\n };\n\n this.request = fetch(this.getUrl(), options)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Request failed\");\n }\n return response.json();\n })\n .then((data) => {\n console.debug(\"Received API reponse:\", data);\n return this.onResponse(data);\n })\n .catch((err) => {\n this.onError(err);\n });\n\n return this.request;\n }\n\n onResponse(data) {\n this.data = data;\n const urlSuccess = this.getSuccessURL();\n if (urlSuccess) {\n window.location.href = urlSuccess;\n }\n }\n\n /** Return URL to redirect to on success\n *\n * Can use ``this.data`` to get API return from ``_link`` and other fields.\n *\n * @returns {string} - URL\n **/\n getSuccessURL() {\n return;\n }\n\n /** Display error toast message on request error\n *\n * @param {Error} err - Exception raised during request\n **/\n onError(err) {\n jquery.toast({\n class: \"error\",\n message: this.constructor.errorMessage,\n });\n }\n}\n\n/** Menu item for rebuilding a version **/\nclass MenuBuildRebuildElement extends APIEventWrapper {\n // TODO translate this here or use a different pattern\n static errorMessage =\n \"There was an error starting a new build for this version\";\n\n getSuccessURL() {\n return this?.data?.build?.urls?.build;\n }\n}\n\ncustomElements.define(\n \"readthedocs-menu-build-rebuild\",\n MenuBuildRebuildElement,\n);\n\n/** Button for resyncing all versions **/\nclass ButtonSyncAllVersionsElement extends APIEventWrapper {\n // TODO translate this here or use a different pattern\n static errorMessage = \"There was an error syncing versions.\";\n\n getSuccessURL() {\n console.log(\"Successfully synced versions\");\n }\n\n // Override the base class to delay the loading state removal\n onEvent() {\n if (this.request == undefined) {\n const classes = this.classList;\n classes.add(\"loading\");\n this.sendRequest().finally(() => {\n setTimeout(() => {\n classes.remove(\"loading\");\n }, 2000);\n });\n }\n }\n}\n\ncustomElements.define(\n \"readthedocs-button-sync-versions\",\n ButtonSyncAllVersionsElement,\n);\n\n/**\n * Lit data contexts for elements with API interactions\n *\n * These data contexts are provided by :js:class:`APIProviderElement` and\n * consumed by :js:class:`APIConsumerElement`. This allows a central element to\n * execute an API request (table row, or a group of buttons) and for sub elements\n * at any point in the nested DOM to use this response (a button nested in the\n * table row, a submenu in the group of buttons).\n **/\nconst contextData = createContext(Symbol(\"data\"));\nconst contextState = createContext(Symbol(\"state\"));\n\n/**\n * API response states enum\n *\n * These are used by API response provider/consumer\n **/\nconst States = Object.freeze({\n WAITING: Symbol(\"waiting\"),\n LOADING: Symbol(\"loading\"),\n DONE: Symbol(\"done\"),\n});\n\n/**\n * Context provider element for API response\n *\n * On an event (mouseover by default), this element starts an API request to the\n * URL specified. It eventually stores the response data in a data context for\n * nested consumer elements.\n *\n * Handles error feedback via toast message and redirection on success.\n *\n * @extends APIEventWrapper\n *\n * TODO This can replace the parent APIEventWrapper element above\n **/\nexport class APIProviderElement extends APIEventWrapper {\n static method = \"GET\";\n static event = \"mouseover\";\n\n /** @type {ContextProvider} Reactive data context for API response data **/\n _providerData = new ContextProvider(this, {\n context: contextData,\n });\n\n set data(value) {\n this._providerData.setValue(value);\n }\n\n /** @type {ContextProvider} Reactive data context for API response state **/\n _providerState = new ContextProvider(this, {\n context: contextState,\n });\n\n set state(value) {\n this._providerState.setValue(value);\n }\n\n constructor() {\n super();\n this.state = States.WAITING;\n }\n\n onEvent() {\n if (this.request == undefined) {\n this.state = States.LOADING;\n this.sendRequest().finally(() => {\n this.state = States.DONE;\n });\n }\n }\n\n onResponse(data) {\n this.data = data;\n }\n}\n\ncustomElements.define(\"readthedocs-api\", APIProviderElement);\n\n/**\n * Context consumer element for API response\n *\n * This element waits for a parent anywhere up the DOM tree to emit a data\n * context element. There are two data contexts: the response state and the\n * response data.\n *\n * @extends LightDOMElement\n *\n * @property {Boolean} disabled - Render the element in a disabled state\n * @property {String} label - Label for the element and ARIA\n **/\nexport class APIConsumerElement extends LightDOMElement {\n static properties = {\n disabled: {\n type: Boolean,\n },\n label: {\n type: String,\n },\n };\n\n /** @type {ContextConsumer} Reactive consumer for API response context data **/\n _consumerData = new ContextConsumer(this, {\n context: contextData,\n subscribe: true,\n });\n\n get data() {\n return this._consumerData.value;\n }\n\n /** @type {ContextConsumer} Reactive consumer for API request state context data **/\n _consumerState = new ContextConsumer(this, {\n context: contextState,\n subscribe: true,\n });\n\n /** @type {State} Reactive context data for API request state **/\n get state() {\n return this._consumerState.value;\n }\n\n constructor() {\n super();\n this.disabled = false;\n }\n\n /**\n * Queue event for late loading links\n *\n * Wait until the request promise resolves and then reemit the event to\n * finally follow the link. This is useful for links that have a late-loaded\n * ``href``.\n *\n * Use it in templates with ``html`
``\n *\n * @param event {Event} - Click or other event\n **/\n queueEvent(event) {\n if (this.state !== States.DONE) {\n console.debug(\"Queueing click event:\", event);\n event.preventDefault();\n event.stopPropagation();\n\n this._consumerState.callback = (value) => {\n if (value === States.DONE) {\n console.debug(\"Replaying click event:\", event);\n // dispatchEvent doesn't seem to work here, so we just create a brand\n // new event here instead.\n event.target.click();\n }\n };\n }\n }\n}\n\n// Menu items\nexport class ItemDocsElement extends APIConsumerElement {\n render() {\n let label = this.label || msg(`View documentation`);\n return html`\n html`0`,\n () => html`-1`,\n )}\"\n >\n \n \n `;\n }\n}\ncustomElements.define(\"readthedocs-item-docs\", ItemDocsElement);\n\nexport class ItemDownloadsElement extends APIConsumerElement {\n render() {\n let label = this.label || msg(`Offline formats`);\n return html`\n html`0`,\n () => html`-1`,\n )}\"\n >\n \n
\n
${msg(`Offline formats`)}
\n \n \n ${msg(`PDF file`)}\n \n \n \n ${msg(`ePUB file`)}\n \n \n \n ${msg(`HTML archive`)}\n \n
\n \n `;\n }\n}\ncustomElements.define(\"readthedocs-item-downloads\", ItemDownloadsElement);\n\nclass MenuProjectAdminElement extends APIConsumerElement {\n static get properties() {\n // TODO `urlSettings` should be part of APIv3 response\n let _properties = APIConsumerElement.properties;\n _properties[\"urlSettings\"] = { type: String, attribute: \"url-settings\" };\n return _properties;\n }\n\n render() {\n const isAdmin = this.data?.permissions?.admin;\n // This preemptively supports a settings URL, which can be passed in as an\n // attribute in the meantime. The `urlSettings` property can go away with this.\n const urlSettings = this.data?.urls?.settings || this.urlSettings;\n return html`\n
${msg(`Admin`)}
\n \n \n ${msg(`Configure project`)}\n \n `;\n }\n}\ncustomElements.define(\n \"readthedocs-menu-project-admin\",\n MenuProjectAdminElement,\n);\n","/*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */\n\nconst {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n} = Object;\nlet {\n freeze,\n seal,\n create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n apply,\n construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n}\nif (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n// SVG\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\${[\\w\\W]*}/gm);\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.2.2';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n remove(node);\n }\n };\n /**\n * _removeAttribute\n *\n * @param name an Attribute name\n * @param element a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, element) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: element.getAttributeNode(name),\n from: element\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: element\n });\n }\n element.removeAttribute(name);\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '' + dirty + '';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * _isClobbered\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n };\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param value object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n const _isNode = function _isNode(value) {\n return typeof Node === 'function' && value instanceof Node;\n };\n function _executeHooks(hooks, currentNode, data) {\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* Detect mXSS attempts abusing namespace confusion */\n if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const {\n attributes\n } = currentNode;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n let value = name === 'value' ? attrValue : stringTrim(attrValue);\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Remove attribute */\n _removeAttribute(name, currentNode);\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n continue;\n }\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {}\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint) {\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","import jquery from \"jquery\";\nimport { LitElement, css, html, nothing } from \"lit\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { when } from \"lit/directives/when.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport DOMPurify from \"dompurify\";\n\nimport { LightDOMElement } from \"../application/elements\";\n\n/**\n * Notification\n *\n * Used internally and directly to render a notification API response. This\n * element is not rendered using element attributes, but it is possible to\n * pass in a full notification API response item via the ``notification``\n * object attribute.\n *\n * @param {Object} notification - Single item from notification API response\n * @param {string} csrfToken - CSRF token from Django, attribute ``csrf-token``\n * @param {Boolean} inverted - Whether the message is ``inverted`` variant\n **/\nexport class NotificationElement extends LightDOMElement {\n static properties = {\n csrfToken: { type: String, attribute: \"csrf-token\" },\n notification: { state: true },\n inverted: { type: Boolean },\n };\n\n render() {\n if (this.notification === undefined || this.notification.message === null) {\n return nothing;\n }\n\n // classMap can't be mixed with any other template logic inside ``class=``\n // so we include all conditional logic outside.\n const classes = {\n // Explicitly always invert high level messages to make sure these are\n // more visible than tip/note messages.\n inverted:\n this.inverted ||\n [\"error\", \"warning\", \"info\"].includes(this.notification.message.type),\n };\n classes[this.notification.message.type] = true;\n\n return html`\n
\n ${when(\n this.notification.dismissable,\n () => html`\n \n `,\n )}\n
\n \n ${unsafeHTML(this.notification.message.header)}\n
\n

${unsafeHTML(this.notification.message.body)}

\n
\n `;\n }\n\n dismiss() {\n console.debug(\"Dismissing notification:\", this.notification.id);\n const options = {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRFToken\": this.csrfToken,\n },\n body: JSON.stringify({\n state: \"dismissed\",\n }),\n };\n fetch(this.notification._links._self, options)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Invalid API request\");\n }\n // Use FUI transition module to fade out and remove the notification\n jquery(this).transition({\n animation: \"fade\",\n onComplete: () => {\n this.parentElement.removeChild(this);\n },\n });\n })\n .catch((err) => {\n console.error(\"Error dismissing notification\", err);\n });\n }\n}\n\n/**\n * NotificationListElement\n *\n * This is the wrapper to :js:class:`NotificationElement`, and provides the initial\n * API interaction to populate all of the notification element instances with\n * data.\n *\n * @param {string} url - APIv3 notification URL to use\n * @param {string} csrfToken - Django CSRF token\n * @param {string} state - Notification states to filter for\n * @param {Boolean} inverted - Whether inverted variant should be forced\n **/\nexport class NotificationListElement extends LightDOMElement {\n static properties = {\n url: { type: String },\n csrfToken: { type: String, attribute: \"csrf-token\" },\n state: { type: String },\n inverted: { type: Boolean },\n\n notifications: { state: true },\n request: { state: true },\n };\n\n constructor() {\n super();\n this.state = \"read,unread\";\n }\n\n fetchNotifications() {\n if (!this.url || this.request !== undefined) {\n return;\n }\n const params = new URLSearchParams({\n state__in: this.state,\n });\n this.request = fetch(`${this.url}?${params}`)\n .then((response) => {\n if (!response.ok) {\n throw new Error(\"Request failed\");\n }\n return response.json();\n })\n .then((data) => {\n if (data?.results === undefined) {\n throw new Error(\"Invalid notification API response\");\n }\n return data.results;\n })\n .then((notifications) => {\n if (notifications) {\n this.notifications = notifications.map((notification) => {\n notification.message.header = DOMPurify.sanitize(\n notification.message.header,\n );\n notification.message.body = DOMPurify.sanitize(\n notification.message.body,\n );\n return notification;\n });\n }\n })\n .catch((err) => {\n console.error(`Error fetching notifications from ${this.url}`, err);\n });\n }\n\n render() {\n // Trigger async notification fetch\n this.fetchNotifications();\n\n if (this.notifications && this.notifications.length > 0) {\n return repeat(\n this.notifications,\n (notification) => notification.id,\n (notification, index) => {\n const elem = document.createElement(\"readthedocs-notification\");\n elem.notification = notification;\n elem.csrfToken = this.csrfToken;\n elem.inverted = this.inverted;\n\n // For FUI .ui.list.item\n elem.className = \"item\";\n return elem;\n },\n );\n } else {\n return nothing;\n }\n }\n}\n\ncustomElements.define(\"readthedocs-notification\", NotificationElement);\ncustomElements.define(\"readthedocs-notification-list\", NotificationListElement);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\nexport class PopupcardView {\n static view_name = \"PopupcardView\";\n\n constructor(url) {\n this.url = url;\n\n /** @observable {Boolean} Is the popup showing currently? */\n this.is_showing = ko.observable(false);\n this.is_showing.subscribe((is_showing) => {\n if (is_showing) {\n this.fetch();\n }\n });\n /** @observable {Boolean} Is the popup loading from the API? */\n this.is_loading = ko.observable(false);\n /** @observable {Boolean} Is the popup loading from the API? */\n this.is_loaded = ko.observable(false);\n\n /** @computed */\n this.popup = ko.observable();\n /** @computed */\n this.popup_config = ko.computed(() => {\n const popup = this.popup();\n if (ko.computedContext.isInitial()) {\n return {\n hoverable: true,\n delay: {\n show: 200,\n hide: 200,\n },\n onShow: () => {\n this.is_showing(true);\n },\n onHide: () => {\n this.is_showing(false);\n },\n };\n } else {\n return popup;\n }\n });\n\n /** @observable {Object} The response object from the API */\n this.data = ko.observable();\n\n this.promise = null;\n }\n\n fetch() {\n if (!this.url) {\n // This popupcard is for a local only request, there might not be an API\n // to request from.\n this.data({});\n this.is_loaded(true);\n this.is_loading(false);\n return;\n }\n if (this.promise) {\n return this.promise;\n }\n this.promise = new Promise((resolve, reject) => {\n if (this.is_loaded()) {\n return resolve(data);\n }\n this.is_loading(true);\n jquery\n .getJSON(this.url)\n .then((data) => {\n this.data(data);\n this.is_loaded(true);\n this.is_loading(false);\n return resolve(data);\n })\n .catch((err) => {\n reject(err);\n });\n }).catch((err) => {\n console.debug(\"Error fetching from API:\", err.responseJSON);\n this.is_loading(false);\n this.is_loaded(false);\n });\n }\n\n show() {\n this.is_showing(true);\n }\n\n hide() {\n this.is_showing(false);\n }\n}\nRegistry.add_view(PopupcardView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Organization authorization settings\n */\nexport class OrganizationSettingsAuthorizationView {\n static view_name = \"OrganizationSettingsAuthorizationView\";\n\n constructor() {\n this.provider_original = undefined;\n this.provider = ko.observable();\n\n this.show_warning = ko.observable(false);\n this.provider.subscribe(\n (value) => {\n if (this.provider_original === undefined) {\n this.provider_original = value;\n }\n },\n this,\n \"beforeChange\",\n );\n this.provider.subscribe((value) => {\n if (\n this.provider_original !== undefined &&\n value !== this.provider_original\n ) {\n this.show_warning(true);\n } else {\n this.show_warning(false);\n }\n });\n this.use_domain = ko.computed(() => {\n return this.provider() === \"email\";\n });\n }\n}\nRegistry.add_view(OrganizationSettingsAuthorizationView);\n\n/**\n * Organization creation\n */\nexport class OrganizationCreateView {\n static view_name = \"OrganizationCreateView\";\n\n constructor() {\n this.name = ko.observable();\n this.slug = ko.observable();\n this.name.subscribe((name) => {\n const slugified = this.slugify(name);\n this.slug(slugified);\n });\n this.example = ko.computed(() => {\n const slug = this.slug() || \"organization\";\n const example = \"https://\" + slug + \"-project.readthedocs-hosted.com\";\n return example;\n });\n }\n\n slugify(val) {\n if (!val) return \"\";\n return (\n val\n .toString()\n .toLowerCase()\n .trim()\n // Replace spaces, non-word chars, underscores and dashes with a single '-'\n // Copied from Django, which is what we are using under the hood\n // https://github.com/django/django/blob/1e9db35/django/utils/text.py#L469-L470\n .replace(/[^\\w\\s-_]+/g, \"-\")\n .replace(/[-\\s]+/g, \"-\")\n // And then also replicate our dns_safe slugging from\n // :py:method:`readthedocs.core.utils.sluggify`\n .replace(/[\\-\\_]+/g, \"-\")\n .replace(/^\\-+/, \"\")\n .replace(/\\-+$/, \"\")\n );\n }\n}\nRegistry.add_view(OrganizationCreateView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Project automation rule form view\n *\n * @param {Object} automation_rule - Initial instance data, optional\n */\nexport class ProjectAutomationRuleView {\n static view_name = \"ProjectAutomationRuleView\";\n\n constructor(automation_rule) {\n this.predefined_match_arg = ko.observable();\n this.is_match_arg_visible = ko.computed(() => {\n let predefined_match_arg = this.predefined_match_arg();\n return predefined_match_arg === \"\";\n });\n this.is_all_versions = ko.computed(() => {\n return this.predefined_match_arg() === \"all-versions\";\n });\n this.is_semver_versions = ko.computed(() => {\n return this.predefined_match_arg() === \"semver-versions\";\n });\n this.is_custom = ko.computed(() => {\n return this.predefined_match_arg() === \"\";\n });\n }\n}\nRegistry.add_view(ProjectAutomationRuleView);\n\n/**\n * Project redirect rule form view\n *\n * @param {Object} redirect - Initial instance data, optional\n */\nexport class ProjectRedirectView {\n static view_name = \"ProjectRedirectView\";\n\n constructor(redirect) {\n this.redirect_type = ko.observable();\n this.from_url = ko.observable(\"\");\n this.to_url = ko.observable(\"\");\n\n this.is_example_disabled = ko.observable(false);\n this.is_from_url_visible = ko.observable();\n this.is_to_url_visible = ko.observable();\n\n // HTML prefix content for from field, don't use user input here\n this.redirect_from_prefix = ko.computed(() => {\n const redirect_type = this.redirect_type();\n const lang_part = `/$lang`;\n const version_part = `/$version`;\n\n if (redirect_type === \"page\") {\n return `${lang_part}${version_part}/`;\n } else if (redirect_type === \"clean_url_to_html\") {\n return `${lang_part}${version_part}/$file/`;\n } else if (redirect_type === \"clean_url_without_trailing_slash_to_html\") {\n return `${lang_part}${version_part}/$file`;\n } else if (redirect_type === \"html_to_clean_url\") {\n return `${lang_part}${version_part}/$file.html`;\n }\n return \"\";\n });\n // User input for from field as text, no HTML allowed\n this.redirect_from = ko.computed(() => {\n const from_url = this.from_url();\n const redirect_type = this.redirect_type();\n if (redirect_type === \"prefix\") {\n return from_url + \"faq.html\";\n } else if (redirect_type === \"page\") {\n return from_url.replace(/^\\/+/, \"\");\n } else if (redirect_type === \"exact\") {\n return from_url;\n }\n return \"\";\n });\n // HTML prefix content for to field, don't use user input here.\n this.redirect_to_prefix = ko.computed(() => {\n const redirect_type = this.redirect_type();\n const lang_part = `/$lang`;\n const version_part = `/$version`;\n\n if (redirect_type === \"prefix\") {\n return `${lang_part}${version_part}/faq.html`;\n } else if (redirect_type === \"page\") {\n return `${lang_part}${version_part}/`;\n } else if (redirect_type === \"clean_url_to_html\") {\n return `${lang_part}${version_part}/$file.html`;\n } else if (redirect_type === \"clean_url_without_trailing_slash_to_html\") {\n return `${lang_part}${version_part}/$file.html`;\n } else if (redirect_type === \"html_to_clean_url\") {\n return `${lang_part}${version_part}/$file/`;\n }\n return \"\";\n });\n // User input for to field as text, no HTML allowed\n this.redirect_to = ko.computed(() => {\n const to_url = this.to_url();\n const redirect_type = this.redirect_type();\n if (redirect_type === \"page\") {\n return to_url.replace(/^\\/+/, \"\");\n } else if (redirect_type === \"exact\") {\n return to_url;\n }\n return \"\";\n });\n\n this.redirect_type.subscribe((redirect_type) => {\n if ([\"prefix\", \"page\", \"exact\"].includes(redirect_type)) {\n this.is_example_disabled(false);\n let is_to_url_visible = true;\n\n // Update visibility\n if (redirect_type == \"prefix\") {\n is_to_url_visible = false;\n }\n this.is_from_url_visible(true);\n this.is_to_url_visible(is_to_url_visible);\n } else if (\n [\n \"clean_url_to_html\",\n \"clean_url_without_trailing_slash_to_html\",\n \"html_to_clean_url\",\n ].includes(redirect_type)\n ) {\n this.is_example_disabled(false);\n this.is_from_url_visible(false);\n this.is_to_url_visible(false);\n } else {\n this.is_example_disabled(true);\n this.is_from_url_visible(false);\n this.is_to_url_visible(false);\n }\n });\n }\n}\nRegistry.add_view(ProjectRedirectView);\n\n/**\n * Project sharing form view\n *\n * @param {Object} share - Initial instance data, optional\n */\nexport class ProjectTemporaryAccessView {\n static view_name = \"ProjectTemporaryAccessView\";\n\n constructor(share) {\n this.access_type = ko.observable();\n this.show_password_field = ko.computed(() => {\n return this.access_type() == \"password\";\n });\n\n this.allow_all = ko.observable(share.allow_all);\n this.show_versions_list = ko.computed(() => {\n return this.allow_all() === false;\n });\n }\n}\nRegistry.add_view(ProjectTemporaryAccessView);\n\n/**\n * Project search analytics view\n *\n * Search analytics chart data and config is loaded from an inline\n * application/json script block, so that data, labels, and localized strings\n * can be handled from the templates.\n *\n * @param {Element} elem - Element that view is attached to\n */\nexport class ProjectSearchAnalyticsView {\n static view_name = \"ProjectSearchAnalyticsView\";\n\n constructor() {\n this.config = ko.observable();\n this.is_loading = ko.observable(true);\n this.config.subscribe((config) => {\n this.is_loading(false);\n });\n }\n}\nRegistry.add_view(ProjectSearchAnalyticsView);\n\n/**\n * Project traffic analytics view\n *\n * This is identical to search analytics currently\n */\nexport class ProjectTrafficAnalyticsView extends ProjectSearchAnalyticsView {\n static view_name = \"ProjectTrafficAnalyticsView\";\n}\nRegistry.add_view(ProjectTrafficAnalyticsView);\n","/* Public task tracking */\n\nimport jquery from \"jquery\";\n\nexport function poll_task(data) {\n var defer = jquery.Deferred();\n var tries = 5;\n\n function poll_task_loop() {\n jquery\n .getJSON(data.url)\n .done(function (task) {\n if (task.finished) {\n if (task.success) {\n defer.resolve();\n } else {\n defer.reject({ message: task.error });\n }\n } else {\n setTimeout(poll_task_loop, 2000);\n }\n })\n .fail(function (error) {\n console.error(\"Error polling task\");\n tries -= 1;\n if (tries > 0) {\n setTimeout(poll_task_loop, 2000);\n } else {\n let error_msg = error.statusText;\n if (error.responseJSON) {\n error_msg = error.responseJSON.detail;\n }\n defer.reject({ message: error_msg });\n }\n });\n }\n\n setTimeout(poll_task_loop, 2000);\n\n return defer;\n}\n\nexport function trigger_task(config) {\n var defer = jquery.Deferred();\n var url = config.url;\n var token = config.token;\n var data = { csrfmiddlewaretoken: token };\n\n jquery.ajax({\n method: \"POST\",\n url: url,\n data: data,\n success: function (data) {\n poll_task(data)\n .then(function () {\n defer.resolve();\n })\n .fail(function (error) {\n // The poll_task function defer will only reject with\n // normalized error objects\n defer.reject(error);\n });\n },\n error: function (error) {\n var error_msg = error.responseJSON.detail || error.statusText;\n defer.reject({ message: error_msg });\n },\n });\n\n return defer;\n}\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\n\nimport * as tasks from \"../tasks\";\nimport * as utils from \"../core/utils\";\nimport { ResponsiveView } from \"../core/views\";\nimport { Registry } from \"../application/registry\";\n\n/**\n * Remote repository instance for remote repository listing.\n *\n * @param {Object} remote_repo - Remote repository API data\n */\nclass RemoteRepository {\n constructor(remote_repo) {\n // Just copy attributes over instead of prototyping. KO observables make a\n // prototype change more awkward. Note, ``projects`` now comes directly from\n // the API response, there is no need to parse this data from the v2\n // ``matches`` response.\n for (const key of Object.keys(remote_repo)) {\n this[key] = remote_repo[key];\n }\n\n /** @observable {Boolean} Is this repository private? */\n this.is_private = ko.observable(this.private);\n /** @observable {Booleean} Is this repository active? */\n this.is_active = ko.observable(this.active);\n /** @observable {Boolean} Does user have admin privilege on the repo? */\n this.has_admin = ko.observable(this.admin);\n /** @computed {Boolean} Can user import this repository? */\n this.is_locked = ko.computed(() => {\n // TODO take platform private repo setting into consideration\n return this.is_private() && !this.has_admin();\n });\n /** @observable {Boolean} Was the repository already imported? */\n this.has_project = ko.computed(() => {\n return this.projects.length > 0;\n });\n }\n}\n\n/**\n * Project creation view, for setting up a new project or linking an existing\n * repository to a new project.\n *\n * @extends {ResposiveView}\n */\nexport class ProjectCreateView extends ResponsiveView {\n static view_name = \"ProjectCreateView\";\n\n constructor() {\n super();\n\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} View configuration */\n this.config = ko.observable();\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Search configuration */\n this.search_config = ko.observable();\n /** @observable {Object} Search popup module configuration */\n this.search_popup_config = ko.observable();\n /** @observable {Object} Search modal module configuration */\n this.search_modal_config = ko.observable(undefined);\n /** @observable {Object} The selected repository */\n this.selected = ko.observable();\n /** @observable {Boolean} Is UI loading from the API currently? */\n this.is_loading = ko.observable(false);\n /** @observable {Boolean} Are remote repositories current resyncing? */\n this.is_syncing = ko.observable(false);\n /** @observable {Boolean} Are remote repositories done resyncing? */\n this.is_synced = ko.observable(false);\n /** @computed {Boolean} Is there a selected repository? */\n this.is_selected = ko.computed(() => {\n return this.selected() !== undefined;\n });\n /** @observable {Boolean} Can private repositories be imported */\n this.allow_private_repos = ko.observable(false);\n /** @observable {string} The error message to show the user */\n this.error = ko.observable();\n\n // Wait for config to be loaded to init search\n this.config.subscribe((config) => {\n if (config !== undefined) {\n this.allow_private_repos(config.allow_private_repos);\n this.init_search();\n }\n });\n }\n\n /**\n * Sync remote repository objects using a call to our API. This sets the UI to\n * a loading state so that user interaction can be limited. Configuration is\n * loaded using :func:`config` and :func:`application.plugins.jsonInit`.\n */\n sync_remote_repos() {\n const config = this.config();\n\n const params = {\n url: config.urls.api_sync_remote_repositories,\n token: config.csrf_token,\n };\n\n this.is_synced(false);\n this.is_syncing(true);\n this.is_loading(true);\n\n let promise = tasks\n .trigger_task(params)\n .fail((error) => {\n console.error(\"Error syncing remote repositories:\", error.message);\n this.error(error.message);\n })\n .always(() => {\n this.is_syncing(false);\n this.is_loading(false);\n this.is_synced(true);\n });\n\n return promise;\n }\n\n /**\n * Set up SUI search once :func:`config` is fully loaded.\n *\n * This uses a Knockout template to make it easier to display the individual\n * elements in the list. The template is loaded from the element\n * ``remote-repo-results``.\n *\n * Ultimately, this sets :func:`search_config`, which is the configuration\n * object that will be eventually be used by SUI search jQuery plugin.\n *\n * .. seealso::\n * https://knockoutjs.com/documentation/template-binding.html\n */\n init_search() {\n const config = this.config();\n const url = config.urls.remoterepository_list + \"?full_name={query}\";\n\n // Configuration for the trigger of the popup element. We manually show the\n // popup in the case that the user has tried searching multiple times\n // unsuccessfully, or has a query with no results.\n let attemptsRemaining = 3;\n this.search_popup_config({\n on: \"manual\",\n position: \"top right\",\n hoverable: true,\n closable: true,\n preserve: true,\n onHidden: () => {\n // If the user did something to hide the popup, like click outside the\n // popup, reset the attempts so that the popup can show again.\n attemptsRemaining = 3;\n },\n // Add a long delay so that hover doesn't accidentally dismiss the popup\n delay: {\n hide: 5000,\n },\n });\n\n // Show repair modal immediately on view load if the URL contains `#repair` hash.\n // Use this for linking users in support directly to this modal.\n const show_modal = jquery(location).attr(\"hash\") == \"#repair\";\n this.search_modal_config({\n autoShow: show_modal,\n centered: false,\n });\n\n this.search_config({\n // We use a Knockout template here, embedded in the template as a script\n // element. This avoids string interpolation in JS and keeps HTML in one\n // place, along with HTML translations.\n type: \"knockout\",\n templates: {\n knockout: (response) => {\n let node_temp = jquery(\"
\");\n\n ko.applyBindingsToNode(node_temp[0], {\n template: {\n name: \"remote-repo-results\",\n data: {\n remote_repos: response.results.map((repo) => {\n return new RemoteRepository(repo);\n }),\n },\n },\n });\n\n const output = node_temp.html();\n node_temp.remove();\n return output;\n },\n },\n error: {\n noResultsHeader: \"No matching repositories found\",\n },\n apiSettings: {\n url: url,\n },\n selector: {\n // Required because the default of ``prompt`` is a rounded input\n prompt: \".ui.text\",\n // Required as we use `.title` to style a complex result title. SUI uses\n // the `text()` of this element to look up the result\n title: \".title .text\",\n },\n fullTextSearch: true,\n onSelect: (result, response) => {\n this.selected(new RemoteRepository(result));\n },\n // Listen for results and decide to show the resync popup based on what\n // the user's interaction with search results.\n onResults: (response, fromCache) => {\n if ((response && response.count == 0) || attemptsRemaining <= 0) {\n // Search results are empty or user tried searching multiple times\n // unsuccessfully so far. Calls with the behavior style call supported by\n // :js:func:`application.plugins.semanticui`.\n this.search_popup_config((popup) => popup(\"show\"));\n }\n attemptsRemaining--;\n },\n });\n }\n\n /** {Boolean} Is repository supported, based on permissions? */\n is_repository_supported(repo) {\n if (repo.is_private()) {\n return this.allow_private_repos();\n }\n return true;\n }\n\n /** Show search modal */\n show_modal() {\n this.search_popup_config((popup) => popup(\"hide\"));\n this.search_modal_config((modal) => modal(\"show\"));\n }\n}\nRegistry.add_view(ProjectCreateView);\n","import ko from \"knockout\";\nimport jquery from \"jquery\";\nimport { html, render } from \"lit\";\nimport { map } from \"lit/directives/map.js\";\nimport { when } from \"lit/directives/when.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\n\nimport * as admin from \"./admin\";\nimport * as create from \"./create\";\n\nimport { APIListItemView } from \"../core/views\";\nimport { Registry } from \"../application/registry\";\n\nexport { admin, create };\n\n/**\n * Project item view object used for displaying individual projects in the project\n * listing.\n *\n * @param {Object} project - Project API data\n * @extends {APIListItemView}\n */\nexport class ProjectListItemView extends APIListItemView {\n static view_name = \"ProjectListItemView\";\n\n constructor(project) {\n super(project);\n\n // Add expansion to API URL\n this.url = this.url + \"?expand=permissions\";\n\n /** Asynchronously load documentation URL as rendering this URL for each\n * project slows the dashboard down considerably. Instead, this is only\n * fetched when it is needed.\n * @observable {string} Documentation URL for the project */\n this.url_docs = ko.observable();\n /* @observable {Boolean} Does the user have admin permissions on this? */\n this.is_admin = ko.observable(false);\n\n // Subscribe to the data loaded via :class:`APIListItemView`\n this.data.subscribe((data) => {\n this.url_docs(data.urls.documentation);\n this.is_admin(data.permissions.admin);\n });\n }\n}\nRegistry.add_view(ProjectListItemView);\n\n/**\n * View for project version creation and version activation.\n *\n * @class\n * @construtor\n * @public\n */\nexport class ProjectVersionCreateView {\n static view_name = \"ProjectVersionCreateView\";\n\n constructor() {\n /** Configuration passed in via :func:`~application.plugins.jsonInit`\n * @observable {Object} Search configuration */\n this.config = ko.observable();\n\n /** @observable {Boolean} Is search data loading? */\n this.is_loading = ko.observable(false);\n\n /** Computed observable for rendering the final search configuration. This\n * is used to initialize search as soon as the :func:`config` observable is\n * finalized.\n * @computed {Object} Search configuration object */\n this.search_config = ko.computed(() => {\n const config = this.config();\n if (config !== undefined) {\n return this.init_search(config);\n }\n });\n }\n\n /**\n * Initialize the SUI search element using the configuration loaded in\n * :func:`search_config`.\n *\n * This sets up various configuration for the search SUI element, but also\n * sets up functions like `onSelect`, for performing actions on events.\n *\n * @param {object} config - configuration for search element\n */\n init_search(config) {\n const maxResults = 100;\n // String interpolation over URLSearchParams here as FUI uses basic string\n // replacement for `{query}`, but this is encoded for URLSearchParams.\n const url = config.api_url + `?limit=${maxResults}&verbose_name={query}`;\n const errors = config.errors || {};\n return {\n apiSettings: {\n url: url,\n },\n error: errors,\n fullTextSearch: true,\n maxResults: maxResults,\n onSelect: (result, response) => {\n window.location.href = result.urls.dashboard.edit;\n },\n selector: {\n // Required because this uses ``.ui.text`` instead of ``.ui.prompt``\n // because prompt uses a rounded input style\n prompt: \".ui.text\",\n // Required as ``.title`` is a complex element in our use, not a simple\n // string like normal. The inner ``.title .text`` sets the field result\n // to just the string value.\n title: \".title .text\",\n },\n // Show results immediately on focus\n minCharacters: 0,\n searchOnFocus: true,\n // Use custom template for rich result display\n type: \"versions\",\n templates: {\n versions: (response) => {\n // Using Lit here as this will likely very soon just be a web component\n // anyways. The project create form references a Knockout observable\n // and a template in HTML. This uses a temporary element to render down\n // to HTML, then removes the element from ``document`` immediately.\n const container = document.createElement(\"div\");\n const results = html`\n \n `;\n\n // Lit renders on an element, but FUI search templates expect HTML return\n render(results, container);\n const htmlResults = container.innerHTML;\n container.remove();\n return htmlResults;\n },\n },\n };\n }\n}\nRegistry.add_view(ProjectVersionCreateView);\n\n/** Version list item subview\n *\n * This mutates project version API return data for use in the Knockout view.\n *\n * URLs for documentation output are lazy loaded when they are requested. We\n * don't do an API call until the user interacts with the version object. This\n * way we don't have to render all of the documentation artifact URLs at once\n * through the resolver. This can cause 10s dashboard load times with a lot of\n * versions.\n *\n * @param {Object} version - Version object data from API\n * @extends {APIListItemView}\n */\nexport class VersionListItemView extends APIListItemView {\n static view_name = \"VersionListItemView\";\n\n constructor(version) {\n super(version);\n\n /** @observable {string} Async loaded URL for version PDF */\n this.url_pdf = ko.observable();\n /** @observable {string} Async loaded URL for version EPUB */\n this.url_epub = ko.observable();\n /** @observable {string} Async loaded URL for version HTMLzip */\n this.url_html = ko.observable();\n /** @observable {string} Async loaded URL for version docs */\n this.url_docs = ko.observable();\n /** @observable {Boolean} is version successfully built? */\n this.is_built = ko.observable(true);\n\n // On resolving the data from the API, fill out these observables.\n this.data.subscribe((data) => {\n this.url_pdf(data.downloads.pdf);\n this.url_epub(data.downloads.epub);\n this.url_html(data.downloads.htmlzip);\n this.url_docs(data.urls.documentation);\n this.is_built(data.built);\n });\n }\n\n /**\n * Trigger a build task for a specific version. This replaces the build\n * dropdown form and instead provides a link on each version admin menu, which\n * is far more intuitive.\n *\n * @param {string} url - URL to post to, this is a project form view, so comes\n * from the Django template\n * @param {string} csrf_token - Also from the Django form, the CSRF token\n * @returns {function} Callback function\n */\n trigger_build(url, csrf_token) {\n return (context, ev) => {\n jquery\n .ajax({\n type: \"POST\",\n url: url,\n data: {\n csrfmiddlewaretoken: csrf_token,\n },\n })\n .then((data) => {\n if (data.build.urls.build) {\n window.location.href = data.build.urls.build;\n } else {\n console.debug(\"Redirect to new build failed\");\n }\n })\n .catch((err) => {\n console.error(err);\n });\n };\n }\n}\nRegistry.add_view(VersionListItemView);\n\nexport class ProjectAnnouncementView {\n static view_name = \"ProjectAnnouncementView\";\n\n constructor(cache_key) {\n this.cache_key = cache_key;\n this.prefix_key = \"announcements\";\n this.storage_key = `${this.prefix_key}.${this.cache_key}`;\n this.closed = ko.observable();\n const cached_value = localStorage.getItem(this.storage_key);\n if (cached_value) {\n this.closed(true);\n } else {\n this.closed(false);\n }\n }\n\n close_announcement() {\n this.closed(true);\n localStorage.setItem(this.storage_key, true);\n }\n}\nRegistry.add_view(ProjectAnnouncementView);\n","import { Registry } from \"../application/registry\";\n\n/*\n * View for tracking opened links, and reloading the page when they are closed.\n *\n * Useful when we depend on changes done outside of the app,\n * but we don't want to have users manually reload the page,\n * or constantly poll the server.\n */\nexport class MigrateGitHubAppView {\n static view_name = \"MigrateGitHubAppView\";\n constructor() {\n this.openedWindows = [];\n this.trackClosedWindows();\n }\n\n trackClosedWindows() {\n setInterval(() => {\n let originalLength = this.openedWindows.length;\n this.openedWindows = this.openedWindows.filter((win) => !win.closed);\n if (this.openedWindows.length < originalLength) {\n // Wait some seconds before reloading the page,\n // so our app has time to update the status.\n setTimeout(() => {\n window.location.reload();\n }, 500);\n }\n }, 250);\n }\n\n /*\n * Click event handler for tracking opened links.\n */\n trackLinkClick(data, event) {\n event.preventDefault();\n const newWindow = window.open(event.target.href, \"_blank\");\n if (newWindow) {\n this.openedWindows.push(newWindow);\n }\n }\n}\n\nRegistry.add_view(MigrateGitHubAppView);\n","import jquery from \"jquery\";\nimport ko from \"knockout\";\nimport clipboard from \"clipboard\";\nimport * as Sentry from \"@sentry/browser\";\n\nimport { ApplicationView } from \"./views\";\nimport * as plugins from \"./plugins\";\nimport { Registry } from \"./registry\";\n\n// Application views\nimport * as account_views from \"../account\";\nimport * as build_views from \"../build\";\nimport * as core_views from \"../core\";\nimport * as gold_views from \"../gold\";\nimport * as module_views from \"../modules\";\nimport * as organization_views from \"../organization\";\nimport * as project_views from \"../project\";\nimport * as profile_views from \"../profile\";\n\n/**\n * This is the main entry point for the front end code and is used to set up and\n * instantiate Webpack, Knockout, and SemanticUI. This class is used to set up\n * and instantiate all of the front end functionality. The main entry point is\n * :meth:`Application.run`.\n */\nexport class Application {\n constructor(config) {\n this.config = config;\n this.registry = new Registry();\n }\n\n /**\n * This is the first method to be executed after instantiation. It handles\n * all of the set up and instantiation.\n *\n * - :meth:`Application.load_config` loads the site configuration\n * - :meth:`Application.configure_plugins` loads plugins\n * - :meth:`Application.attach_view` does view routing and attaches the view\n * - :meth:`Application.start_plugins` sets up jQuery plugins on some elements\n */\n run() {\n this.load_config();\n this.configure_plugins();\n this.attach_view();\n this.add_jquery_plugins();\n }\n\n /**\n * Load site configuration from a special ``application/json`` script element.\n * This configures paths for Webpack async imports, console debugging.\n *\n * .. seealso::\n * Convention on :ref:`js-json-config`\n */\n load_config() {\n if (this.config === undefined) {\n console.debug(\"Loading site front end configuration from script tag\");\n const site_config_src = jquery(\"script#site-config\").text() || \"{}\";\n this.config = JSON.parse(site_config_src);\n }\n if (this.config?.webpack_public_path) {\n __webpack_public_path__ = this.config.webpack_public_path;\n globalThis.__webpack_public_path__ = this.config.webpack_public_path;\n }\n // Null route debug logging, don't do output anything that was debug\n if (!this.config?.debug) {\n console.debug = () => {};\n }\n // Load Sentry\n if (this.config?.sentry?.dsn) {\n Sentry.init({\n dsn: this.config.sentry.dsn,\n environment: this.config.sentry?.environment,\n integrations: [],\n });\n }\n\n return this.config;\n }\n\n /**\n * Add jQuery and Knockout plugins so that HTML and JS can use these plugins.\n * This is mainly just the various import logic and configuration, not where\n * we would run something like ``$('.ui.modal').modal()``.\n */\n configure_plugins() {\n plugins.configure_jquery_plugins();\n plugins.configure_knockout_plugins();\n }\n\n /**\n * Attach the :class:`ApplicationView` view router, which gives templates\n * access to all views that we have available. This is how we are able to\n * reference a view in a Knockout data binding.\n */\n attach_view() {\n const view = new ApplicationView();\n this.registry.attach(view);\n view.attach();\n }\n\n /**\n * Set up jQuery and SUI jQuery plugins that were not explicitly set up in\n * templates. Elements that are configured inside templates use the Knockout\n * plugin :func:`~application.plugins.semanticui`. This allows for explicit\n * set up of an element's plugin, and should be the standard way to attach a\n * jQuery plugin to an element.\n *\n * We don't do generic targeting of elements when setting up jQuery plugins as\n * there are a number of places where an element needs to be initialized with\n * specific plugin configuration. It's easiest to define in HTML what plugin\n * and plugin configuration the element needs.\n *\n * .. warning::\n * Generic targeting use should be avoided and it's use deprecated.\n */\n add_jquery_plugins() {\n // TODO remove instances of these in code and replace with the explicit\n // semanticui KO plugin.\n jquery(\".ui.progress:not([data-semanticui-progress])\").progress();\n jquery(\".ui.accordion:not([data-semanticui-accordion])\").accordion();\n jquery(\".ui.dropdown:not([data-semanticui-dropdown])\").dropdown({\n placeholder: \"\",\n });\n // Automatically convert `` - {% endif %} - - {% block authentication_extra %} diff --git a/readthedocsext/theme/templates/socialaccount/snippets/provider_list.html b/readthedocsext/theme/templates/socialaccount/snippets/provider_list.html index 980df739..0d0ec885 100644 --- a/readthedocsext/theme/templates/socialaccount/snippets/provider_list.html +++ b/readthedocsext/theme/templates/socialaccount/snippets/provider_list.html @@ -20,6 +20,7 @@ {% trans "GitHub" as provider_name %}
  • diff --git a/readthedocsext/theme/templates/socialaccount/snippets/provider_list_item.html b/readthedocsext/theme/templates/socialaccount/snippets/provider_list_item.html index 7994de41..8d777614 100644 --- a/readthedocsext/theme/templates/socialaccount/snippets/provider_list_item.html +++ b/readthedocsext/theme/templates/socialaccount/snippets/provider_list_item.html @@ -7,9 +7,15 @@ action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"> {% csrf_token %} + {# djlint: off D018 #} + * + *
  • + */ +export class LoginView { + static view_name = "LoginView"; + + constructor() {} + + /** + * Save the provider used for login. + * + * This could be used like: + * + * .. code:: html + * + *
    + * + *
    + * + * @param {Object} data - Context data + * @param {Event} event - Click event + * @returns {knockout_click} + */ + save_login_method(data, event) { + const elem = event.currentTarget; + if (window.isSecureContext) { + console.debug("Setting last login method: ", elem.dataset.provider); + cookieStore.set("last-login-method", elem.dataset.provider); + } + return true; + } +} + +Registry.add_view(LoginView); diff --git a/src/js/application/index.js b/src/js/application/index.js index 4d93d6c1..93befaa0 100644 --- a/src/js/application/index.js +++ b/src/js/application/index.js @@ -8,6 +8,7 @@ import * as plugins from "./plugins"; import { Registry } from "./registry"; // Application views +import * as account_views from "../account"; import * as build_views from "../build"; import * as core_views from "../core"; import * as gold_views from "../gold"; diff --git a/src/js/application/views.js b/src/js/application/views.js index 344b0e4f..d83e2cab 100644 --- a/src/js/application/views.js +++ b/src/js/application/views.js @@ -65,6 +65,16 @@ export class ApplicationView { if (found_modal.length === 0) { console.debug("Modal not found:", selector); } + + // Remove "visible" variation property to remove "Last used" tooltip + const buttons = document.querySelectorAll(".button.ui"); + for (const button of buttons) { + if (button.dataset.variation) { + const variation = button.dataset.variation.split(" "); + variation.pop("visible"); + button.dataset.variation = variation.join(" "); + } + } }; }