diff --git a/readthedocsext/theme/static/readthedocsext/theme/js/site.js b/readthedocsext/theme/static/readthedocsext/theme/js/site.js index dd5987ae..e4fedc41 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},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&&R(o,n.prototype),o},x.apply(null,arguments)}function R(e,t){return R=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},R(e,t)}function N(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);n1&&void 0!==arguments[1]?arguments[1]:"top center";return this.popups[e]=o.observable((function(r){r({content:(0,H.WI)("Last used"),position:n,variation:"mini teal",closable:!0,preserve:!0,on:"manual"}),Array.isArray(e)||t.last_method()!=e?Array.isArray(e)&&e.includes(t.last_method())&&r("show"):r("show")})),this.popups[e]()}},{key:"save_login_method",value:function(e){console.debug("Saving last login method:",e);var t="last-login-method=".concat(e);return window.isSecureContext&&(t+="; Secure"),document.cookie=t,!0}},{key:"show_github_modal",value:function(){F(V(n.prototype),"show_github_modal",this).call(this);var e=this.last_method();["github","githubapp"].includes(e)&&this.popups[e]((function(e){return e("show")}))}}]),n}(K);J(Z,"view_name","LoginView"),z.add_view(K),z.add_view(Z);var Q=n(7484),ee=n(4110),te=n(1646),ne=n(6176);function re(e){return re="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},re(e)}function oe(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 ie(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 ie(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 ie(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 le({command:n,output:e,line_number:t+1})}))}),null,{deferEvaluation:!0}),this.output(t.output)}return ce(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}(),de=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;se(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 ce(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=oe(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 fe(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 pe(e){return pe="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},pe(e)}function be(e,t){for(var n=0;n=ye[o];t.device[o](i)}}));var n=r(window),i=function(){t.viewport_width(n.width())};n.on("resize",i),i()})),_e=function(){function e(t){ve(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 me(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}(),we=me((function e(){var t=this;ve(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=he(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}(we,"view_name","HeaderView"),z.add_view(we);var Se=n(6566);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 Te(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,'")'))}}])&&Be(t.prototype,n),r&&Be(t,r),Object.defineProperty(t,"prototype",{writable:!1}),i}(je.oi);function Ye(e){return Ye="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},Ye(e)}function Je(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",$e);var Ke=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&&Je(t.prototype,n),r&&Je(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();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 Qe(e,t){for(var n=0;n\n \n \n '])),(0,pt.$)({disabled:this.disabled,loading:!this.disabled&&this.state===Nt.LOADING}),(null===(e=this.data)||void 0===e||null===(e=e.urls)||void 0===e?void 0:e.documentation)||"#",this.queueEvent,t,t,(0,bt.g)(!this.disabled,(function(){return(0,je.dy)(ot||(ot=ht(["0"])))}),(function(){return(0,je.dy)(it||(it=ht(["-1"])))})))}}]),n}(It);customElements.define("readthedocs-item-docs",Lt);var Dt=function(e){_t(n,e);var t=St(n);function n(){return vt(this,n),t.apply(this,arguments)}return gt(n,[{key:"render",value:function(){var e,t,n,r,o,i,a=this.label||(0,H.WI)("Offline formats");return(0,je.dy)(at||(at=ht(['\n \n \n \n \n "])),(0,pt.$)({disabled:this.disabled}),a,a,(0,bt.g)(this.disabled,(function(){return(0,je.dy)(ct||(ct=ht(["0"])))}),(function(){return(0,je.dy)(ut||(ut=ht(["-1"])))})),(0,H.WI)("Offline formats"),null===(e=this.data)||void 0===e||null===(e=e.downloads)||void 0===e?void 0:e.pdf,(0,pt.$)({disabled:!(null!==(t=this.data)&&void 0!==t&&null!==(t=t.downloads)&&void 0!==t&&t.pdf)}),(0,H.WI)("PDF file"),null===(n=this.data)||void 0===n||null===(n=n.downloads)||void 0===n?void 0:n.epub,(0,pt.$)({disabled:!(null!==(r=this.data)&&void 0!==r&&null!==(r=r.downloads)&&void 0!==r&&r.epub)}),(0,H.WI)("ePUB file"),null===(o=this.data)||void 0===o||null===(o=o.downloads)||void 0===o?void 0:o.htmlzip,(0,pt.$)({disabled:!(null!==(i=this.data)&&void 0!==i&&null!==(i=i.downloads)&&void 0!==i&&i.htmlzip)}),(0,H.WI)("HTML archive"))}}]),n}(It);customElements.define("readthedocs-item-downloads",Dt);var Mt=function(e){_t(n,e);var t=St(n);function n(){return vt(this,n),t.apply(this,arguments)}return gt(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,je.dy)(st||(st=ht(['\n
','
\n \n \n ',"\n \n "])),(0,H.WI)("Admin"),(0,pt.$)({disabled:!n}),r,(0,H.WI)("Configure project"))}}],[{key:"properties",get:function(){var e=It.properties;return e.urlSettings={type:String,attribute:"url-settings"},e}}]),n}(It);customElements.define("readthedocs-menu-project-admin",Mt);var Ut=n(2386),zt=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:Ht,setPrototypeOf:Bt,isFrozen:Ft,getPrototypeOf:Wt,getOwnPropertyDescriptor:qt}=Object;let{freeze:Vt,seal:Gt,create:$t}=Object,{apply:Yt,construct:Jt}="undefined"!=typeof Reflect&&Reflect;Vt||(Vt=function(e){return e}),Gt||(Gt=function(e){return e}),Yt||(Yt=function(e,t,n){return e.apply(t,n)}),Jt||(Jt=function(e,t){return new e(...t)});const Xt=ln(Array.prototype.forEach),Kt=ln(Array.prototype.pop),Zt=ln(Array.prototype.push),Qt=ln(String.prototype.toLowerCase),en=ln(String.prototype.toString),tn=ln(String.prototype.match),nn=ln(String.prototype.replace),rn=ln(String.prototype.indexOf),on=ln(String.prototype.trim),an=ln(Object.prototype.hasOwnProperty),cn=ln(RegExp.prototype.test),un=(sn=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]:Qt;Bt&&Bt(e,null);let r=t.length;for(;r--;){let o=t[r];if("string"==typeof o){const e=n(o);e!==o&&(Ft(t)||(t[r]=e),o=e)}e[o]=!0}return e}function dn(e){for(let t=0;t/gm),Pn=Gt(/\${[\w\W]*}/gm),An=Gt(/^data-[\-\w.\u00B7-\uFFFF]/),xn=Gt(/^aria-[\-\w]+$/),Rn=Gt(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Nn=Gt(/^(?:\w+script|data):/i),Cn=Gt(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),In=Gt(/^html$/i),Ln=Gt(/^[a-z][.\w]*(-[.\w]+)+$/i);var Dn=Object.freeze({__proto__:null,ARIA_ATTR:xn,ATTR_WHITESPACE:Cn,CUSTOM_ELEMENT:Ln,DATA_ATTR:An,DOCTYPE_NAME:In,ERB_EXPR:jn,IS_ALLOWED_URI:Rn,IS_SCRIPT_OR_DATA:Nn,MUSTACHE_EXPR:En,TMPLIT_EXPR:Pn});const Mn=1,Un=3,zn=7,Hn=8,Bn=9,Fn=function(){return"undefined"==typeof window?null:window};var Wn,qn,Vn=function e(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Fn();const n=t=>e(t);if(n.version="3.2.2",n.removed=[],!t||!t.document||t.document.nodeType!==Bn)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=bn(m,"cloneNode"),v=bn(m,"remove"),y=bn(m,"nextSibling"),g=bn(m,"childNodes"),_=bn(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 Ht&&"function"==typeof _&&O&&void 0!==O.createHTMLDocument;const{MUSTACHE_EXPR:A,ERB_EXPR:x,TMPLIT_EXPR:R,DATA_ATTR:N,ARIA_ATTR:C,IS_SCRIPT_OR_DATA:I,ATTR_WHITESPACE:L,CUSTOM_ELEMENT:D}=Dn;let{IS_ALLOWED_URI:M}=Dn,U=null;const z=fn({},[...mn,...hn,...vn,...gn,...wn]);let H=null;const B=fn({},[...Sn,...On,...Tn,...kn]);let F=Object.seal($t(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,V=!0,G=!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=fn({},["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=fn({},["audio","video","img","source","image","track"]);let de=null;const pe=fn({},["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=fn({},[be,me,he],en);let we=fn({},["mi","mo","mn","ms","mtext"]),Se=fn({},["annotation-xml"]);const Oe=fn({},["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=pn(e),Te=-1===ke.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,Ee="application/xhtml+xml"===Te?en:Qt,U=an(e,"ALLOWED_TAGS")?fn({},e.ALLOWED_TAGS,Ee):z,H=an(e,"ALLOWED_ATTR")?fn({},e.ALLOWED_ATTR,Ee):B,ge=an(e,"ALLOWED_NAMESPACES")?fn({},e.ALLOWED_NAMESPACES,en):_e,de=an(e,"ADD_URI_SAFE_ATTR")?fn(pn(pe),e.ADD_URI_SAFE_ATTR,Ee):pe,le=an(e,"ADD_DATA_URI_TAGS")?fn(pn(fe),e.ADD_DATA_URI_TAGS,Ee):fe,ue=an(e,"FORBID_CONTENTS")?fn({},e.FORBID_CONTENTS,Ee):se,W=an(e,"FORBID_TAGS")?fn({},e.FORBID_TAGS,Ee):{},q=an(e,"FORBID_ATTR")?fn({},e.FORBID_ATTR,Ee):{},ce=!!an(e,"USE_PROFILES")&&e.USE_PROFILES,V=!1!==e.ALLOW_ARIA_ATTR,G=!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||Rn,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&&(G=!1),te&&(ee=!0),ce&&(U=fn({},wn),H=[],!0===ce.html&&(fn(U,mn),fn(H,Sn)),!0===ce.svg&&(fn(U,hn),fn(H,On),fn(H,kn)),!0===ce.svgFilters&&(fn(U,vn),fn(H,On),fn(H,kn)),!0===ce.mathMl&&(fn(U,gn),fn(H,Tn),fn(H,kn))),e.ADD_TAGS&&(U===z&&(U=pn(U)),fn(U,e.ADD_TAGS,Ee)),e.ADD_ATTR&&(H===B&&(H=pn(H)),fn(H,e.ADD_ATTR,Ee)),e.ADD_URI_SAFE_ATTR&&fn(de,e.ADD_URI_SAFE_ATTR,Ee),e.FORBID_CONTENTS&&(ue===se&&(ue=pn(ue)),fn(ue,e.FORBID_CONTENTS,Ee)),ie&&(U["#text"]=!0),K&&fn(U,["html","head","body"]),U.table&&(fn(U,["tbody"]),delete W.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw un('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw un('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(""));Vt&&Vt(e),je=e}},Re=fn({},[...hn,...vn,...yn]),Ne=fn({},[...gn,..._n]),Ce=function(e){Zt(n.removed,{element:e});try{_(e).removeChild(e)}catch(t){v(e)}},Ie=function(e,t){try{Zt(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){Zt(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=tn(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){Xt(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)&&cn(/<[/\w]/g,e.innerHTML)&&cn(/<[/\w]/g,e.textContent))return Ce(e),!0;if(e.nodeType===zn)return Ce(e),!0;if(X&&e.nodeType===Hn&&cn(/<[/\w]/g,e.data))return Ce(e),!0;if(!U[r]||W[r]){if(!W[r]&&Fe(r)){if(F.tagNameCheck instanceof RegExp&&cn(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=Qt(e.tagName),r=Qt(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(Re[n]):e.namespaceURI===be?t.namespaceURI===he?"math"===n:t.namespaceURI===me?"math"===n&&Se[r]:Boolean(Ne[n]):e.namespaceURI===he?!(t.namespaceURI===me&&!Se[r])&&!(t.namespaceURI===be&&!we[r])&&!Ne[n]&&(Oe[n]||!Re[n]):!("application/xhtml+xml"!==Te||!ge[e.namespaceURI]))}(e)?(Ce(e),!0):"noscript"!==r&&"noembed"!==r&&"noframes"!==r||!cn(/<\/no(script|embed|frames)/i,e.innerHTML)?(J&&e.nodeType===Un&&(t=e.textContent,Xt([A,x,R],(e=>{t=nn(t,e," ")})),e.textContent!==t&&(Zt(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(G&&!q[t]&&cn(N,t));else if(V&&cn(C,t));else if(!H[t]||q[t]){if(!(Fe(e)&&(F.tagNameCheck instanceof RegExp&&cn(F.tagNameCheck,e)||F.tagNameCheck instanceof Function&&F.tagNameCheck(e))&&(F.attributeNameCheck instanceof RegExp&&cn(F.attributeNameCheck,t)||F.attributeNameCheck instanceof Function&&F.attributeNameCheck(t))||"is"===t&&F.allowCustomizedBuiltInElements&&(F.tagNameCheck instanceof RegExp&&cn(F.tagNameCheck,n)||F.tagNameCheck instanceof Function&&F.tagNameCheck(n))))return!1}else if(de[t]);else if(cn(M,nn(n,L,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==rn(n,"data:")||!le[e]){if($&&!cn(I,nn(n,L,"")));else if(n)return!1}else;return!0},Fe=function(e){return"annotation-xml"!==e&&tn(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:on(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&&cn(/((--!?|])>)|<\/(style|title)/i,l)){Ie(a,e);continue}if(r.forceKeepAttr)continue;if(Ie(a,e),!r.keepAttr)continue;if(!Y&&cn(/\/>/i,l)){Ie(a,e);continue}J&&Xt([A,x,R],(e=>{l=nn(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):Kt(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 un("toString is not a function");if("string"!=typeof(e=e.toString()))throw un("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 un("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===Mn&&"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&&cn(In,r.ownerDocument.doctype.name)&&(f="\n"+f),J&&Xt([A,x,R],(e=>{f=nn(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&&Zt(P[e],t)},n.removeHook=function(e){return Kt(P[e])},n.removeHooks=function(e){P[e]=[]},n.removeAllHooks=function(){P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},n}();function Gn(e){return Gn="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},Gn(e)}function $n(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Yn(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Jn(e,t){for(var n=0;n\n ','\n
\n \n ',"\n
\n

","

\n \n "])),(0,pt.$)(t),(0,bt.g)(this.notification.dismissable,(function(){return(0,je.dy)(qn||(qn=$n(['\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))}))}));kr(Pr,"view_name","ProjectRedirectView"),z.add_view(Pr);var Ar=Or((function e(t){var n=this;Tr(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()}))}));kr(Ar,"view_name","ProjectTemporaryAccessView"),z.add_view(Ar);var xr=Or((function e(){var t=this;Tr(this,e),this.config=o.observable(),this.is_loading=o.observable(!0),this.config.subscribe((function(e){t.is_loading(!1)}))}));kr(xr,"view_name","ProjectSearchAnalyticsView"),z.add_view(xr);var Rr=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&&gr(e,t)}(n,e);var t=_r(n);function n(){return Tr(this,n),t.apply(this,arguments)}return Or(n)}(xr);function Nr(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 Cr(e){return Cr="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},Cr(e)}function Ir(e,t){return Ir=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},Ir(e,t)}function Lr(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=Dr(e);if(t){var o=Dr(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===Cr(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 Dr(e){return Dr=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},Dr(e)}function Mr(e,t){for(var n=0;n0}))})),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=Lr(n);function n(){var e;return Hr(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 Ur(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),Nr(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 qr(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 qr(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}(ge);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 t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Yr(e,t){for(var n=0;n\n ',"\n
\n "])),(0,vr.U)(e.results,(function(e){return(0,je.dy)(Fr||(Fr=$r(['\n \n
\n
\n
\n ','\n \n ','\n
\n
\n ',"\n
\n
\n
\n "])),e.verbose_name,(0,pt.$)({"fa-code-branch":"branch"===e.type,"fa-tag":"tag"===e.type}),(0,bt.g)(e.active,(function(){return(0,je.dy)(Wr||(Wr=$r(['\n \n \n Active\n \n '])))})),e.identifier)})));(0,je.sY)(n,t);var r=t.innerHTML;return t.remove(),r}}}}}]),e}();to(oo,"view_name","ProjectVersionCreateView"),z.add_view(oo);var io=function(e){Kr(n,e);var t=Qr(n);function n(e){var r;return Xr(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 Jr(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}(_e);to(io,"view_name","VersionListItemView"),z.add_view(io);var ao=function(){function e(t){Xr(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 Jr(e,[{key:"close_announcement",value:function(){this.closed(!0),localStorage.setItem(this.storage_key,!0)}}]),e}();function co(e){return co="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},co(e)}function uo(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)}}])&&po(t.prototype,c),u&&po(t,u),Object.defineProperty(t,"prototype",{writable:!1}),e}();r(document).ready((function(){(new mo).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?1c0827dac6ef25865bdc \ No newline at end of file +const{entries:Ht,setPrototypeOf:Bt,isFrozen:Ft,getPrototypeOf:Wt,getOwnPropertyDescriptor:qt}=Object;let{freeze:Vt,seal:Gt,create:$t}=Object,{apply:Yt,construct:Jt}="undefined"!=typeof Reflect&&Reflect;Vt||(Vt=function(e){return e}),Gt||(Gt=function(e){return e}),Yt||(Yt=function(e,t,n){return e.apply(t,n)}),Jt||(Jt=function(e,t){return new e(...t)});const Xt=ln(Array.prototype.forEach),Kt=ln(Array.prototype.pop),Zt=ln(Array.prototype.push),Qt=ln(String.prototype.toLowerCase),en=ln(String.prototype.toString),tn=ln(String.prototype.match),nn=ln(String.prototype.replace),rn=ln(String.prototype.indexOf),on=ln(String.prototype.trim),an=ln(Object.prototype.hasOwnProperty),cn=ln(RegExp.prototype.test),un=(sn=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]:Qt;Bt&&Bt(e,null);let r=t.length;for(;r--;){let o=t[r];if("string"==typeof o){const e=n(o);e!==o&&(Ft(t)||(t[r]=e),o=e)}e[o]=!0}return e}function dn(e){for(let t=0;t/gm),Pn=Gt(/\${[\w\W]*}/gm),An=Gt(/^data-[\-\w.\u00B7-\uFFFF]/),xn=Gt(/^aria-[\-\w]+$/),Rn=Gt(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Nn=Gt(/^(?:\w+script|data):/i),Cn=Gt(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),In=Gt(/^html$/i),Ln=Gt(/^[a-z][.\w]*(-[.\w]+)+$/i);var Dn=Object.freeze({__proto__:null,ARIA_ATTR:xn,ATTR_WHITESPACE:Cn,CUSTOM_ELEMENT:Ln,DATA_ATTR:An,DOCTYPE_NAME:In,ERB_EXPR:jn,IS_ALLOWED_URI:Rn,IS_SCRIPT_OR_DATA:Nn,MUSTACHE_EXPR:En,TMPLIT_EXPR:Pn});const Mn=1,Un=3,zn=7,Hn=8,Bn=9,Fn=function(){return"undefined"==typeof window?null:window};var Wn,qn,Vn=function e(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Fn();const n=t=>e(t);if(n.version="3.2.2",n.removed=[],!t||!t.document||t.document.nodeType!==Bn)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=bn(m,"cloneNode"),v=bn(m,"remove"),y=bn(m,"nextSibling"),g=bn(m,"childNodes"),_=bn(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 Ht&&"function"==typeof _&&O&&void 0!==O.createHTMLDocument;const{MUSTACHE_EXPR:A,ERB_EXPR:x,TMPLIT_EXPR:R,DATA_ATTR:N,ARIA_ATTR:C,IS_SCRIPT_OR_DATA:I,ATTR_WHITESPACE:L,CUSTOM_ELEMENT:D}=Dn;let{IS_ALLOWED_URI:M}=Dn,U=null;const z=fn({},[...mn,...hn,...vn,...gn,...wn]);let H=null;const B=fn({},[...Sn,...On,...Tn,...kn]);let F=Object.seal($t(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,V=!0,G=!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=fn({},["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=fn({},["audio","video","img","source","image","track"]);let de=null;const pe=fn({},["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=fn({},[be,me,he],en);let we=fn({},["mi","mo","mn","ms","mtext"]),Se=fn({},["annotation-xml"]);const Oe=fn({},["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=pn(e),Te=-1===ke.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,Ee="application/xhtml+xml"===Te?en:Qt,U=an(e,"ALLOWED_TAGS")?fn({},e.ALLOWED_TAGS,Ee):z,H=an(e,"ALLOWED_ATTR")?fn({},e.ALLOWED_ATTR,Ee):B,ge=an(e,"ALLOWED_NAMESPACES")?fn({},e.ALLOWED_NAMESPACES,en):_e,de=an(e,"ADD_URI_SAFE_ATTR")?fn(pn(pe),e.ADD_URI_SAFE_ATTR,Ee):pe,le=an(e,"ADD_DATA_URI_TAGS")?fn(pn(fe),e.ADD_DATA_URI_TAGS,Ee):fe,ue=an(e,"FORBID_CONTENTS")?fn({},e.FORBID_CONTENTS,Ee):se,W=an(e,"FORBID_TAGS")?fn({},e.FORBID_TAGS,Ee):{},q=an(e,"FORBID_ATTR")?fn({},e.FORBID_ATTR,Ee):{},ce=!!an(e,"USE_PROFILES")&&e.USE_PROFILES,V=!1!==e.ALLOW_ARIA_ATTR,G=!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||Rn,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&&(G=!1),te&&(ee=!0),ce&&(U=fn({},wn),H=[],!0===ce.html&&(fn(U,mn),fn(H,Sn)),!0===ce.svg&&(fn(U,hn),fn(H,On),fn(H,kn)),!0===ce.svgFilters&&(fn(U,vn),fn(H,On),fn(H,kn)),!0===ce.mathMl&&(fn(U,gn),fn(H,Tn),fn(H,kn))),e.ADD_TAGS&&(U===z&&(U=pn(U)),fn(U,e.ADD_TAGS,Ee)),e.ADD_ATTR&&(H===B&&(H=pn(H)),fn(H,e.ADD_ATTR,Ee)),e.ADD_URI_SAFE_ATTR&&fn(de,e.ADD_URI_SAFE_ATTR,Ee),e.FORBID_CONTENTS&&(ue===se&&(ue=pn(ue)),fn(ue,e.FORBID_CONTENTS,Ee)),ie&&(U["#text"]=!0),K&&fn(U,["html","head","body"]),U.table&&(fn(U,["tbody"]),delete W.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw un('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw un('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(""));Vt&&Vt(e),je=e}},Re=fn({},[...hn,...vn,...yn]),Ne=fn({},[...gn,..._n]),Ce=function(e){Zt(n.removed,{element:e});try{_(e).removeChild(e)}catch(t){v(e)}},Ie=function(e,t){try{Zt(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){Zt(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=tn(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){Xt(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)&&cn(/<[/\w]/g,e.innerHTML)&&cn(/<[/\w]/g,e.textContent))return Ce(e),!0;if(e.nodeType===zn)return Ce(e),!0;if(X&&e.nodeType===Hn&&cn(/<[/\w]/g,e.data))return Ce(e),!0;if(!U[r]||W[r]){if(!W[r]&&Fe(r)){if(F.tagNameCheck instanceof RegExp&&cn(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=Qt(e.tagName),r=Qt(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(Re[n]):e.namespaceURI===be?t.namespaceURI===he?"math"===n:t.namespaceURI===me?"math"===n&&Se[r]:Boolean(Ne[n]):e.namespaceURI===he?!(t.namespaceURI===me&&!Se[r])&&!(t.namespaceURI===be&&!we[r])&&!Ne[n]&&(Oe[n]||!Re[n]):!("application/xhtml+xml"!==Te||!ge[e.namespaceURI]))}(e)?(Ce(e),!0):"noscript"!==r&&"noembed"!==r&&"noframes"!==r||!cn(/<\/no(script|embed|frames)/i,e.innerHTML)?(J&&e.nodeType===Un&&(t=e.textContent,Xt([A,x,R],(e=>{t=nn(t,e," ")})),e.textContent!==t&&(Zt(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(G&&!q[t]&&cn(N,t));else if(V&&cn(C,t));else if(!H[t]||q[t]){if(!(Fe(e)&&(F.tagNameCheck instanceof RegExp&&cn(F.tagNameCheck,e)||F.tagNameCheck instanceof Function&&F.tagNameCheck(e))&&(F.attributeNameCheck instanceof RegExp&&cn(F.attributeNameCheck,t)||F.attributeNameCheck instanceof Function&&F.attributeNameCheck(t))||"is"===t&&F.allowCustomizedBuiltInElements&&(F.tagNameCheck instanceof RegExp&&cn(F.tagNameCheck,n)||F.tagNameCheck instanceof Function&&F.tagNameCheck(n))))return!1}else if(de[t]);else if(cn(M,nn(n,L,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==rn(n,"data:")||!le[e]){if($&&!cn(I,nn(n,L,"")));else if(n)return!1}else;return!0},Fe=function(e){return"annotation-xml"!==e&&tn(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:on(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&&cn(/((--!?|])>)|<\/(style|title)/i,l)){Ie(a,e);continue}if(r.forceKeepAttr)continue;if(Ie(a,e),!r.keepAttr)continue;if(!Y&&cn(/\/>/i,l)){Ie(a,e);continue}J&&Xt([A,x,R],(e=>{l=nn(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):Kt(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 un("toString is not a function");if("string"!=typeof(e=e.toString()))throw un("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 un("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===Mn&&"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&&cn(In,r.ownerDocument.doctype.name)&&(f="\n"+f),J&&Xt([A,x,R],(e=>{f=nn(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&&Zt(P[e],t)},n.removeHook=function(e){return Kt(P[e])},n.removeHooks=function(e){P[e]=[]},n.removeAllHooks=function(){P={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},n}();function Gn(e){return Gn="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},Gn(e)}function $n(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Yn(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Jn(e,t){for(var n=0;n\n ','\n
\n \n ',"\n
\n

","

\n \n "])),(0,pt.$)(t),(0,bt.g)(this.notification.dismissable,(function(){return(0,je.dy)(qn||(qn=$n(['\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))}))}));kr(Ar,"view_name","ProjectRedirectView"),z.add_view(Ar);var xr=Or((function e(t){var n=this;Tr(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()}))}));kr(xr,"view_name","ProjectTemporaryAccessView"),z.add_view(xr);var Rr=Or((function e(){var t=this;Tr(this,e),this.config=o.observable(),this.is_loading=o.observable(!0),this.config.subscribe((function(e){t.is_loading(!1)}))}));kr(Rr,"view_name","ProjectSearchAnalyticsView"),z.add_view(Rr);var 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&&gr(e,t)}(n,e);var t=_r(n);function n(){return Tr(this,n),t.apply(this,arguments)}return Or(n)}(Rr);function Cr(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 Ir(e){return Ir="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},Ir(e)}function Lr(e,t){return Lr=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},Lr(e,t)}function Dr(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=Mr(e);if(t){var o=Mr(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===Ir(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 Mr(e){return Mr=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},Mr(e)}function Ur(e,t){for(var n=0;n0}))})),Gr=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&&Lr(e,t)}(n,e);var t=Dr(n);function n(){var e;return Br(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 zr(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),Cr(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 Vr(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 Vr(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}(ge);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){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Jr(e,t){for(var n=0;n\n ',"\n
\n "])),(0,vr.U)(e.results,(function(e){return(0,je.dy)(Wr||(Wr=Yr(['\n \n
\n
\n
\n ','\n \n ','\n
\n
\n ',"\n
\n
\n
\n "])),e.verbose_name,(0,pt.$)({"fa-code-branch":"branch"===e.type,"fa-tag":"tag"===e.type}),(0,bt.g)(e.active,(function(){return(0,je.dy)(qr||(qr=Yr(['\n \n \n Active\n \n '])))})),e.identifier)})));(0,je.sY)(n,t);var r=t.innerHTML;return t.remove(),r}}}}}]),e}();no(io,"view_name","ProjectVersionCreateView"),z.add_view(io);var ao=function(e){Zr(n,e);var t=eo(n);function n(e){var r;return Kr(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 Xr(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}(_e);no(ao,"view_name","VersionListItemView"),z.add_view(ao);var co=function(){function e(t){Kr(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 Xr(e,[{key:"close_announcement",value:function(){this.closed(!0),localStorage.setItem(this.storage_key,!0)}}]),e}();function uo(e){return uo="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},uo(e)}function so(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)}}])&&bo(t.prototype,c),u&&bo(t,u),Object.defineProperty(t,"prototype",{writable:!1}),e}();r(document).ready((function(){(new ho).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?e06907c3b7b480c5c5d3 \ 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 6f286d29..68605142 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?1c0827dac6ef25865bdc","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/account/index.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 // Remove \"visible\" variation property to remove \"Last used\" tooltip\n const buttons = document.querySelectorAll(\".button.ui\");\n for (const button of buttons) {\n if (button.dataset.variation) {\n const variation = button.dataset.variation.split(\" \");\n variation.pop(\"visible\");\n button.dataset.variation = variation.join(\" \");\n }\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 * Knockout binding for calling SemanticUI jQuery plugins on individual elements\n *\n * This binding provides direct access to all of the SemanticUI jQuery plugins\n * provided by each of the SemanticUI module units.\n *\n * Each key passed into the ``semanticui`` binding represents a module plugin\n * that will be called by the data binding. For example, a data binding that\n * initializes ``popup()`` and ``modal()`` module plugins is:\n *\n * .. code:: html\n *\n *
\n *\n * Which would be the following if using the standard jQuery initialization\n * pattern described by SUI guides:\n *\n * .. code:: js\n *\n * $(element).popup({\"on\": \"click\"});\n * $(element).modal({\"closable\": false});\n *\n * Passing arguments\n * -----------------\n *\n * There are three available patterns you can use for passing arguments into the\n * plugin methods:\n *\n * A literal value inside the data binding attribute in template code\n * The simplest option, useful if arguments are fairly basic.\n *\n * An observable in the data binding attribute\n * This is useful when the arguments passed into the plugin method are\n * complex or conditional.\n *\n * An anonymous function through an observable\n * This is for advanced cases and the best pattern for using SUI module\n * behaviors.\n *\n * Literal value\n * ~~~~~~~~~~~~~\n *\n * If you only need to pass basic arguments into the plugin, you can do so in\n * template code without any further JS:\n *\n * .. code:: html\n *\n * \n *\n * To compare this to the standard initialization pattern described by the SUI\n * documentation, which relies on jQuery for targeting:\n *\n * .. code:: js\n *\n * $(element).popup({on: \"click\"});\n *\n * Observable value\n * ~~~~~~~~~~~~~~~~\n *\n * For complex and conditional arguments, it's usually better to pass an\n * observable to the binding for the module plugin. Because we will be creating\n * observables, this requires a view class. Inside the view class, an\n * observable can be declared:\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 * Our template code would reference the observable instead of a literal:\n *\n * .. code:: html\n *\n * \n *\n * .. seealso::\n * :func:`BuildDetailView.progress_config`\n * An example of an observable passing arguments to the ``progress()``\n * module jQuery plugin.\n *\n * Anonymous function\n * ~~~~~~~~~~~~~~~~~~\n *\n * For deep usage of the SUI module jQuery plugins, you can also set an\n * observable to an anonymous function value to use the plugin method directly\n * on an individual element. This binding will call into that function with the\n * jQuery plugin method exposed as a function as the only argument.\n *\n * With the template code still using an observable in the data binding on the\n * view layer, an observable using an anonymous function instead would be:\n *\n * .. code:: js\n *\n * this.popup_config = ko.observable((popup) => {\n * popup({\n * label: \"Test\",\n * on: \"click\",\n * });\n * });\n *\n * This is most helpful for utilizing SUI module *behaviors*. Behaviors are\n * listed on most SUI modules, such as:\n * https://fomantic-ui.com/modules/popup.html#behavior\n *\n * To now call module behaviors from this observable:\n *\n * .. code:: js\n *\n * this.popup_config((popup) => popup(\"show\"));\n *\n * It's also possible to mix these patterns and call behaviors more than once.\n * For example a progress bar that progressively updates can mix both plugin\n * initialization and subsequent behavior calls after initialization:\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 ko from \"knockout\";\nimport { msg } from \"@lit/localize\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Listing view for social account connections.\n *\n * This view is subclassed by the :js:cls:`LoginView`, as the templates that\n * use this code are shared between the social account connection listing view\n * and the login view. On the social account listing we don't want the same\n * features for last login method etc so this view overloads the functions\n * used.\n */\nexport class SocialAccountView {\n static view_name = \"SocialAccountView\";\n\n constructor(options) {\n this.github_modal_config = ko.observable();\n }\n\n show_github_modal() {\n this.github_modal_config((modal) => modal(\"show\"));\n }\n\n // No-op to skip popup setup\n popup_login_method() {}\n\n save_login_method() {\n return true;\n }\n}\n\n/**\n * LoginView saves a cookie for the last login method.\n *\n * Usage:\n *\n * .. code:: html\n *\n *
\n *
\n * \n *
\n *
\n */\nexport class LoginView extends SocialAccountView {\n static view_name = \"LoginView\";\n\n constructor(options) {\n super(options);\n\n /** @observable {string} Last tab to be selected. Comes from view */\n this.last_tab = ko.observable(options?.last_tab || \"vcs\");\n /** @observable {string} Last method to be used. Comes from view */\n this.last_method = ko.observable(options?.last_method);\n\n // This is an named lookup for observables, one for each method. It is\n // populated by the template code as each popup is configured.\n this.popups = {};\n }\n\n /**\n * Add popup for login method\n *\n * This adds an observable using by the semanticui binding to add and\n * manipulate a popup module on the element.\n *\n * Accepts multiple method ids just because we have a GitHub sub-modal right\n * now. This can be removed eventually.\n *\n * @param {string|Array.} method - Method id or list of method ids\n * @param {string} position - Position to pass to SUI popup position attribute\n * @param {string} method - Method id\n */\n popup_login_method(method, position = \"top center\") {\n this.popups[method] = ko.observable((popup) => {\n // First set up the element as a manual popup, then manually show it.\n // This is using the anonymous function pattern for passing arguments to\n // the ``popup()`` jQuery plugin binding, via :func:`application.plugins.semanticui`\n popup({\n content: msg(`Last used`),\n position: position,\n variation: \"mini teal\",\n closable: true,\n preserve: true,\n on: \"manual\",\n });\n if (!Array.isArray(method) && this.last_method() == method) {\n popup(\"show\");\n } else if (Array.isArray(method) && method.includes(this.last_method())) {\n popup(\"show\");\n }\n });\n return this.popups[method]();\n }\n\n /**\n * Save a cookie to track last login method.\n *\n * This could be used like:\n *\n * .. code:: html\n *\n *
\n * \n *
\n *\n * @param {string} method - Method id\n * @returns {knockout_click}\n */\n save_login_method(method) {\n console.debug(\"Saving last login method:\", method);\n let cookie = `last-login-method=${method}`;\n if (window.isSecureContext) {\n cookie = cookie + `; Secure`;\n }\n document.cookie = cookie;\n return true;\n }\n\n // On top of showing the GitHub modal, show any popups for GitHub providers as\n // well. This avoids requiring the popups to always be visible and avoids\n // manual removal of the popups.\n show_github_modal() {\n super.show_github_modal();\n const last_method = this.last_method();\n if ([\"github\", \"githubapp\"].includes(last_method)) {\n this.popups[last_method]((popup) => popup(\"show\"));\n }\n }\n}\n\nRegistry.add_view(SocialAccountView);\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 ```` 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 * Knockout binding for calling SemanticUI jQuery plugins on individual elements\n *\n * This binding provides direct access to all of the SemanticUI jQuery plugins\n * provided by each of the SemanticUI module units.\n *\n * Each key passed into the ``semanticui`` binding represents a module plugin\n * that will be called by the data binding. For example, a data binding that\n * initializes ``popup()`` and ``modal()`` module plugins is:\n *\n * .. code:: html\n *\n *
\n *\n * Which would be the following if using the standard jQuery initialization\n * pattern described by SUI guides:\n *\n * .. code:: js\n *\n * $(element).popup({\"on\": \"click\"});\n * $(element).modal({\"closable\": false});\n *\n * Passing arguments\n * -----------------\n *\n * There are three available patterns you can use for passing arguments into the\n * plugin methods:\n *\n * A literal value inside the data binding attribute in template code\n * The simplest option, useful if arguments are fairly basic.\n *\n * An observable in the data binding attribute\n * This is useful when the arguments passed into the plugin method are\n * complex or conditional.\n *\n * An anonymous function through an observable\n * This is for advanced cases and the best pattern for using SUI module\n * behaviors.\n *\n * Literal value\n * ~~~~~~~~~~~~~\n *\n * If you only need to pass basic arguments into the plugin, you can do so in\n * template code without any further JS:\n *\n * .. code:: html\n *\n * \n *\n * To compare this to the standard initialization pattern described by the SUI\n * documentation, which relies on jQuery for targeting:\n *\n * .. code:: js\n *\n * $(element).popup({on: \"click\"});\n *\n * Observable value\n * ~~~~~~~~~~~~~~~~\n *\n * For complex and conditional arguments, it's usually better to pass an\n * observable to the binding for the module plugin. Because we will be creating\n * observables, this requires a view class. Inside the view class, an\n * observable can be declared:\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 * Our template code would reference the observable instead of a literal:\n *\n * .. code:: html\n *\n * \n *\n * .. seealso::\n * :func:`BuildDetailView.progress_config`\n * An example of an observable passing arguments to the ``progress()``\n * module jQuery plugin.\n *\n * Anonymous function\n * ~~~~~~~~~~~~~~~~~~\n *\n * For deep usage of the SUI module jQuery plugins, you can also set an\n * observable to an anonymous function value to use the plugin method directly\n * on an individual element. This binding will call into that function with the\n * jQuery plugin method exposed as a function as the only argument.\n *\n * With the template code still using an observable in the data binding on the\n * view layer, an observable using an anonymous function instead would be:\n *\n * .. code:: js\n *\n * this.popup_config = ko.observable((popup) => {\n * popup({\n * label: \"Test\",\n * on: \"click\",\n * });\n * });\n *\n * This is most helpful for utilizing SUI module *behaviors*. Behaviors are\n * listed on most SUI modules, such as:\n * https://fomantic-ui.com/modules/popup.html#behavior\n *\n * To now call module behaviors from this observable:\n *\n * .. code:: js\n *\n * this.popup_config((popup) => popup(\"show\"));\n *\n * It's also possible to mix these patterns and call behaviors more than once.\n * For example a progress bar that progressively updates can mix both plugin\n * initialization and subsequent behavior calls after initialization:\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 ko from \"knockout\";\nimport { msg } from \"@lit/localize\";\n\nimport { Registry } from \"../application/registry\";\n\n/**\n * Listing view for social account connections.\n *\n * This view is subclassed by the :js:cls:`LoginView`, as the templates that\n * use this code are shared between the social account connection listing view\n * and the login view. On the social account listing we don't want the same\n * features for last login method etc so this view overloads the functions\n * used.\n */\nexport class SocialAccountView {\n static view_name = \"SocialAccountView\";\n\n constructor(options) {\n this.github_modal_config = ko.observable();\n }\n\n show_github_modal() {\n this.github_modal_config((modal) => modal(\"show\"));\n }\n\n // No-op to skip popup setup\n popup_login_method() {}\n\n save_login_method() {\n return true;\n }\n}\n\n/**\n * LoginView saves a cookie for the last login method.\n *\n * Usage:\n *\n * .. code:: html\n *\n *
\n *
\n * \n *
\n *
\n */\nexport class LoginView extends SocialAccountView {\n static view_name = \"LoginView\";\n\n constructor(options) {\n super(options);\n\n /** @observable {string} Last tab to be selected. Comes from view */\n this.last_tab = ko.observable(options?.last_tab || \"vcs\");\n /** @observable {string} Last method to be used. Comes from view */\n this.last_method = ko.observable(options?.last_method);\n\n // This is an named lookup for observables, one for each method. It is\n // populated by the template code as each popup is configured.\n this.popups = {};\n }\n\n /**\n * Add popup for login method\n *\n * This adds an observable using by the semanticui binding to add and\n * manipulate a popup module on the element.\n *\n * Accepts multiple method ids just because we have a GitHub sub-modal right\n * now. This can be removed eventually.\n *\n * @param {string|Array.} method - Method id or list of method ids\n * @param {string} position - Position to pass to SUI popup position attribute\n * @param {string} method - Method id\n */\n popup_login_method(method, position = \"top center\") {\n this.popups[method] = ko.observable((popup) => {\n // First set up the element as a manual popup, then manually show it.\n // This is using the anonymous function pattern for passing arguments to\n // the ``popup()`` jQuery plugin binding, via :func:`application.plugins.semanticui`\n popup({\n content: msg(`Last used`),\n position: position,\n variation: \"mini teal\",\n closable: true,\n preserve: true,\n on: \"manual\",\n });\n if (!Array.isArray(method) && this.last_method() == method) {\n popup(\"show\");\n } else if (Array.isArray(method) && method.includes(this.last_method())) {\n popup(\"show\");\n }\n });\n return this.popups[method]();\n }\n\n /**\n * Save a cookie to track last login method.\n *\n * This could be used like:\n *\n * .. code:: html\n *\n *
\n * \n *
\n *\n * @param {string} method - Method id\n * @returns {knockout_click}\n */\n save_login_method(method) {\n console.debug(\"Saving last login method:\", method);\n let cookie = `last-login-method=${method}`;\n if (window.isSecureContext) {\n cookie = cookie + `; Secure`;\n }\n document.cookie = cookie;\n return true;\n }\n\n // On top of showing the GitHub modal, show any popups for GitHub providers as\n // well. This avoids requiring the popups to always be visible and avoids\n // manual removal of the popups.\n show_github_modal() {\n super.show_github_modal();\n const last_method = this.last_method();\n if ([\"github\", \"githubapp\"].includes(last_method)) {\n this.popups[last_method]((popup) => popup(\"show\"));\n }\n }\n}\n\nRegistry.add_view(SocialAccountView);\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 basic settings view\n */\nexport class ProjectSettingsView {\n static view_name = \"ProjectSettingsView\";\n\n constructor() {\n this.config = ko.observable({});\n this.config.subscribe((config) => {\n this.repo_has_errors(config.repo_has_errors);\n if (!config.can_connect_repository) {\n this.use_manual_configuration(true);\n }\n });\n\n this.dimmer_config = ko.observable((dimmer) => {\n dimmer(\"show\");\n });\n\n this.use_manual_configuration = ko.observable(false);\n this.use_manual_configuration.subscribe((use_manual_configuration) => {\n if (use_manual_configuration) {\n this.remote_repository((dropdown) => {\n dropdown(\"set selected\", \"\", true);\n });\n } else {\n this.remote_repository((dropdown) => {\n // Restore value that was there on page load, ``preventChangeTrigger=true``\n // to avoid refiring off the field value change event\n dropdown(\"restore defaults\", true);\n });\n }\n });\n\n this.repo = ko.observable();\n this.repo_has_errors = ko.observable(false);\n this.repo_has_errors.subscribe((repo_has_errors) => {\n this.use_manual_configuration(true);\n });\n this.remote_repository = ko.observable({\n onChange: (value, text) => {\n if (value == \"\") {\n this.use_manual_configuration(true);\n } else {\n this.use_manual_configuration(false);\n }\n },\n });\n }\n}\nRegistry.add_view(ProjectSettingsView);\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 `` + +
+
+ +
+ + + +
+
+{% endwith %} diff --git a/readthedocsext/theme/templates/projects/settings_basics_form.html b/readthedocsext/theme/templates/projects/settings_basics_form.html index 9d6a1e50..c9066362 100644 --- a/readthedocsext/theme/templates/projects/settings_basics_form.html +++ b/readthedocsext/theme/templates/projects/settings_basics_form.html @@ -14,9 +14,12 @@ {% endblock project_edit_active %} {% block project_edit_content %} -
+ {% csrf_token %} - {{ form|crispy }} + {% crispy form %}
diff --git a/readthedocsext/theme/templates/semantic-ui/fields/base.html b/readthedocsext/theme/templates/semantic-ui/fields/base.html index 809975bf..18eddd07 100644 --- a/readthedocsext/theme/templates/semantic-ui/fields/base.html +++ b/readthedocsext/theme/templates/semantic-ui/fields/base.html @@ -7,6 +7,7 @@ {% whitespaceless as all_field_classes %} {% if not field|is_checkbox %} {% if field.field.required %}required{% endif %} + {% if field.field.disabled %}disabled{% endif %} {% if field.errors %}error{% endif %} {% if 'form-horizontal' in form_class %}inline{% endif %} field @@ -36,6 +37,7 @@ {% endblock field-label %} {% block field-input %} + {# TODO move this to a property on the form instead? #} {% if field|is_rich_select %} {% include "semantic-ui/layout/rich_select.html" %} {% include "semantic-ui/layout/field_errors_block.html" %} diff --git a/readthedocsext/theme/templates/semantic-ui/layout/rich_select.html b/readthedocsext/theme/templates/semantic-ui/layout/rich_select.html index e50be708..38ccbf99 100644 --- a/readthedocsext/theme/templates/semantic-ui/layout/rich_select.html +++ b/readthedocsext/theme/templates/semantic-ui/layout/rich_select.html @@ -1,5 +1,6 @@ {% load crispy_field from crispy_forms_field %} {% load blocktrans trans from i18n %} +{% load whitespaceless from ext_theme_tags %} {% comment rst %} Rich select field template @@ -26,8 +27,18 @@ {% endcomment %} +{% whitespaceless as form_data_bind %} + {% if "data-bind" not in field.field.widget.attrs.keys %} + semanticui: { dropdown: {}} + {% else %} + {% for key, value in field.field.widget.attrs.items %} + {% if key == "data-bind" %}{{ value }}{% endif %} + {% endfor %} + {% endif %} +{% endwhitespaceless %} +