great-cto 3.75.10 → 3.76.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/board/.claude-plugin/plugin.json +1 -1
- package/board/agents/architect.md +4 -0
- package/board/agents/ci-resolver.md +1 -0
- package/board/agents/design-advisor.md +28 -0
- package/board/agents/devops.md +1 -0
- package/board/agents/product-owner.md +13 -1
- package/board/agents/senior-dev.md +25 -9
- package/board/packages/board/lib/alerts.mjs +46 -1
- package/board/packages/board/lib/gate-run.sh +30 -0
- package/board/packages/board/lib/instant-alerts.mjs +159 -0
- package/board/packages/board/lib/merge-readiness.mjs +315 -0
- package/board/packages/board/lib/routes.mjs +29 -3
- package/board/packages/board/openapi.json +2996 -0
- package/board/packages/board/public/assets/icon-192.png +0 -0
- package/board/packages/board/public/assets/icon-512.png +0 -0
- package/board/packages/board/public/assets/icon-maskable-512.png +0 -0
- package/board/packages/board/public/assets/vendor/PROVENANCE.md +5 -3
- package/board/packages/board/public/assets/vendor/purify.min.js +7 -3
- package/board/packages/board/public/assets/work-view.js +83 -3
- package/board/packages/board/public/index.html +112 -1
- package/board/packages/board/public/manifest.webmanifest +16 -0
- package/board/packages/board/public/sw.js +1 -1
- package/board/packages/board/route-coverage-baseline.json +25 -0
- package/board/packages/board/server.mjs +8 -1
- package/board/scripts/lib/gate-run-record.mjs +75 -0
- package/board/scripts/lib/handoff-state.mjs +478 -0
- package/board/scripts/lib/workspace.mjs +277 -0
- package/board/scripts/lib/worktree-state.mjs +128 -0
- package/board/shared/pipeline.toml +29 -0
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -10,10 +10,12 @@ They're now vendored as static assets and served locally instead.
|
|
|
10
10
|
| File | Package | Version | Source | SHA-384 (matches original SRI hash) |
|
|
11
11
|
|------|---------|---------|--------|--------------------------------------|
|
|
12
12
|
| `marked.min.js` | [marked](https://www.npmjs.com/package/marked) | 14.1.3 | https://cdn.jsdelivr.net/npm/marked@14.1.3/marked.min.js | `k8o8HikHweyzW55Wd3wl18ovJj6vHVYNQeQbeSM0fxx+0WiH4TcccOG9uz8Xd2JR` |
|
|
13
|
-
| `purify.min.js` | [dompurify](https://www.npmjs.com/package/dompurify) | 3.
|
|
13
|
+
| `purify.min.js` | [dompurify](https://www.npmjs.com/package/dompurify) | 3.4.17 | `dist/purify.min.js` from the npm tarball dompurify-3.4.17.tgz (registry integrity verified) | `P0JNneQf81HOl9VwNXK76cQ9VMD6Nfsnepxb0cCOg8+UzEdzgPHAPV4wVQrvYQSx` |
|
|
14
14
|
|
|
15
|
-
Downloaded verbatim;
|
|
16
|
-
the board previously used on the CDN `<script>` tags.
|
|
15
|
+
Downloaded verbatim; the marked hash was verified to match the SRI `integrity` attributes
|
|
16
|
+
the board previously used on the CDN `<script>` tags. DOMPurify was moved
|
|
17
|
+
from 3.1.7 to 3.4.17 on 2026-11-09 for GHSA-cg2g-xh64-v4q7 and earlier advisories;
|
|
18
|
+
`no-cdn.test.mjs` checks every hash in this table against the file. These are static
|
|
17
19
|
vendored assets, not npm runtime dependencies — no package.json entry.
|
|
18
20
|
|
|
19
21
|
## Fonts
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),p=b(Array.prototype.push),f=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(Object.prototype.hasOwnProperty),_=b(RegExp.prototype.test),A=(N=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return s(N,t)});var N;function b(e){return function(t){for(var n=arguments.length,o=new Array(n>1?n-1:0),r=1;r<n;r++)o[r-1]=arguments[r];return c(e,t,o)}}function S(e,o){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:f;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function R(e){for(let t=0;t<e.length;t++){E(e,t)||(e[t]=null)}return e}function w(t){const n=l(null);for(const[o,r]of e(t)){E(t,o)&&(Array.isArray(r)?n[o]=R(r):r&&"object"==typeof r&&r.constructor===Object?n[o]=w(r):n[o]=r)}return n}function C(e,t){for(;null!==e;){const n=r(e,t);if(n){if(n.get)return b(n.get);if("function"==typeof n.value)return b(n.value)}e=o(e)}return function(){return null}}const L=i(["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"]),v=i(["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"]),D=i(["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"]),O=i(["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"]),x=i(["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"]),k=i(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),M=i(["#text"]),I=i(["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"]),U=i(["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"]),P=i(["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"]),F=i(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),H=a(/\{\{[\w\W]*|[\w\W]*\}\}/gm),z=a(/<%[\w\W]*|[\w\W]*%>/gm),B=a(/\${[\w\W]*}/gm),W=a(/^data-[\-\w.\u00B7-\uFFFF]/),G=a(/^aria-[\-\w]+$/),Y=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),j=a(/^(?:\w+script|data):/i),X=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i),$=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var K=Object.freeze({__proto__:null,MUSTACHE_EXPR:H,ERB_EXPR:z,TMPLIT_EXPR:B,DATA_ATTR:W,ARIA_ATTR:G,IS_ALLOWED_URI:Y,IS_SCRIPT_OR_DATA:j,ATTR_WHITESPACE:X,DOCTYPE_NAME:q,CUSTOM_ELEMENT:$});const V=1,Z=3,J=7,Q=8,ee=9,te=function(){return"undefined"==typeof window?null:window};var ne=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:te();const o=e=>t(e);if(o.version="3.1.7",o.removed=[],!n||!n.document||n.document.nodeType!==ee)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:N,Node:b,Element:R,NodeFilter:H,NamedNodeMap:z=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:B,DOMParser:W,trustedTypes:G}=n,j=R.prototype,X=C(j,"cloneNode"),$=C(j,"remove"),ne=C(j,"nextSibling"),oe=C(j,"childNodes"),re=C(j,"parentNode");if("function"==typeof N){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let ie,ae="";const{implementation:le,createNodeIterator:ce,createDocumentFragment:se,getElementsByTagName:ue}=r,{importNode:me}=a;let pe={};o.isSupported="function"==typeof e&&"function"==typeof re&&le&&void 0!==le.createHTMLDocument;const{MUSTACHE_EXPR:fe,ERB_EXPR:de,TMPLIT_EXPR:he,DATA_ATTR:ge,ARIA_ATTR:Te,IS_SCRIPT_OR_DATA:ye,ATTR_WHITESPACE:Ee,CUSTOM_ELEMENT:_e}=K;let{IS_ALLOWED_URI:Ae}=K,Ne=null;const be=S({},[...L,...v,...D,...x,...M]);let Se=null;const Re=S({},[...I,...U,...P,...F]);let we=Object.seal(l(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}})),Ce=null,Le=null,ve=!0,De=!0,Oe=!1,xe=!0,ke=!1,Me=!0,Ie=!1,Ue=!1,Pe=!1,Fe=!1,He=!1,ze=!1,Be=!0,We=!1,Ge=!0,Ye=!1,je={},Xe=null;const qe=S({},["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 $e=null;const Ke=S({},["audio","video","img","source","image","track"]);let Ve=null;const Ze=S({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Je="http://www.w3.org/1998/Math/MathML",Qe="http://www.w3.org/2000/svg",et="http://www.w3.org/1999/xhtml";let tt=et,nt=!1,ot=null;const rt=S({},[Je,Qe,et],d);let it=null;const at=["application/xhtml+xml","text/html"];let lt=null,ct=null;const st=r.createElement("form"),ut=function(e){return e instanceof RegExp||e instanceof Function},mt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!ct||ct!==e){if(e&&"object"==typeof e||(e={}),e=w(e),it=-1===at.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,lt="application/xhtml+xml"===it?d:f,Ne=E(e,"ALLOWED_TAGS")?S({},e.ALLOWED_TAGS,lt):be,Se=E(e,"ALLOWED_ATTR")?S({},e.ALLOWED_ATTR,lt):Re,ot=E(e,"ALLOWED_NAMESPACES")?S({},e.ALLOWED_NAMESPACES,d):rt,Ve=E(e,"ADD_URI_SAFE_ATTR")?S(w(Ze),e.ADD_URI_SAFE_ATTR,lt):Ze,$e=E(e,"ADD_DATA_URI_TAGS")?S(w(Ke),e.ADD_DATA_URI_TAGS,lt):Ke,Xe=E(e,"FORBID_CONTENTS")?S({},e.FORBID_CONTENTS,lt):qe,Ce=E(e,"FORBID_TAGS")?S({},e.FORBID_TAGS,lt):{},Le=E(e,"FORBID_ATTR")?S({},e.FORBID_ATTR,lt):{},je=!!E(e,"USE_PROFILES")&&e.USE_PROFILES,ve=!1!==e.ALLOW_ARIA_ATTR,De=!1!==e.ALLOW_DATA_ATTR,Oe=e.ALLOW_UNKNOWN_PROTOCOLS||!1,xe=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,ke=e.SAFE_FOR_TEMPLATES||!1,Me=!1!==e.SAFE_FOR_XML,Ie=e.WHOLE_DOCUMENT||!1,Fe=e.RETURN_DOM||!1,He=e.RETURN_DOM_FRAGMENT||!1,ze=e.RETURN_TRUSTED_TYPE||!1,Pe=e.FORCE_BODY||!1,Be=!1!==e.SANITIZE_DOM,We=e.SANITIZE_NAMED_PROPS||!1,Ge=!1!==e.KEEP_CONTENT,Ye=e.IN_PLACE||!1,Ae=e.ALLOWED_URI_REGEXP||Y,tt=e.NAMESPACE||et,we=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(we.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(we.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(we.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ke&&(De=!1),He&&(Fe=!0),je&&(Ne=S({},M),Se=[],!0===je.html&&(S(Ne,L),S(Se,I)),!0===je.svg&&(S(Ne,v),S(Se,U),S(Se,F)),!0===je.svgFilters&&(S(Ne,D),S(Se,U),S(Se,F)),!0===je.mathMl&&(S(Ne,x),S(Se,P),S(Se,F))),e.ADD_TAGS&&(Ne===be&&(Ne=w(Ne)),S(Ne,e.ADD_TAGS,lt)),e.ADD_ATTR&&(Se===Re&&(Se=w(Se)),S(Se,e.ADD_ATTR,lt)),e.ADD_URI_SAFE_ATTR&&S(Ve,e.ADD_URI_SAFE_ATTR,lt),e.FORBID_CONTENTS&&(Xe===qe&&(Xe=w(Xe)),S(Xe,e.FORBID_CONTENTS,lt)),Ge&&(Ne["#text"]=!0),Ie&&S(Ne,["html","head","body"]),Ne.table&&(S(Ne,["tbody"]),delete Ce.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');ie=e.TRUSTED_TYPES_POLICY,ae=ie.createHTML("")}else void 0===ie&&(ie=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(G,c)),null!==ie&&"string"==typeof ae&&(ae=ie.createHTML(""));i&&i(e),ct=e}},pt=S({},["mi","mo","mn","ms","mtext"]),ft=S({},["annotation-xml"]),dt=S({},["title","style","font","a","script"]),ht=S({},[...v,...D,...O]),gt=S({},[...x,...k]),Tt=function(e){p(o.removed,{element:e});try{re(e).removeChild(e)}catch(t){$(e)}},yt=function(e,t){try{p(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Se[e])if(Fe||He)try{Tt(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Et=function(e){let t=null,n=null;if(Pe)e="<remove></remove>"+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===it&&tt===et&&(e='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+e+"</body></html>");const o=ie?ie.createHTML(e):e;if(tt===et)try{t=(new W).parseFromString(o,it)}catch(e){}if(!t||!t.documentElement){t=le.createDocument(tt,"template",null);try{t.documentElement.innerHTML=nt?ae:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),tt===et?ue.call(t,Ie?"html":"body")[0]:Ie?t.documentElement:i},_t=function(e){return ce.call(e.ownerDocument||e,e,H.SHOW_ELEMENT|H.SHOW_COMMENT|H.SHOW_TEXT|H.SHOW_PROCESSING_INSTRUCTION|H.SHOW_CDATA_SECTION,null)},At=function(e){return e instanceof B&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof z)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Nt=function(e){return"function"==typeof b&&e instanceof b},bt=function(e,t,n){pe[e]&&u(pe[e],(e=>{e.call(o,t,n,ct)}))},St=function(e){let t=null;if(bt("beforeSanitizeElements",e,null),At(e))return Tt(e),!0;const n=lt(e.nodeName);if(bt("uponSanitizeElement",e,{tagName:n,allowedTags:Ne}),e.hasChildNodes()&&!Nt(e.firstElementChild)&&_(/<[/\w]/g,e.innerHTML)&&_(/<[/\w]/g,e.textContent))return Tt(e),!0;if(e.nodeType===J)return Tt(e),!0;if(Me&&e.nodeType===Q&&_(/<[/\w]/g,e.data))return Tt(e),!0;if(!Ne[n]||Ce[n]){if(!Ce[n]&&wt(n)){if(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n))return!1;if(we.tagNameCheck instanceof Function&&we.tagNameCheck(n))return!1}if(Ge&&!Xe[n]){const t=re(e)||e.parentNode,n=oe(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=X(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,ne(e))}}}return Tt(e),!0}return e instanceof R&&!function(e){let t=re(e);t&&t.tagName||(t={namespaceURI:tt,tagName:"template"});const n=f(e.tagName),o=f(t.tagName);return!!ot[e.namespaceURI]&&(e.namespaceURI===Qe?t.namespaceURI===et?"svg"===n:t.namespaceURI===Je?"svg"===n&&("annotation-xml"===o||pt[o]):Boolean(ht[n]):e.namespaceURI===Je?t.namespaceURI===et?"math"===n:t.namespaceURI===Qe?"math"===n&&ft[o]:Boolean(gt[n]):e.namespaceURI===et?!(t.namespaceURI===Qe&&!ft[o])&&!(t.namespaceURI===Je&&!pt[o])&&!gt[n]&&(dt[n]||!ht[n]):!("application/xhtml+xml"!==it||!ot[e.namespaceURI]))}(e)?(Tt(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!_(/<\/no(script|embed|frames)/i,e.innerHTML)?(ke&&e.nodeType===Z&&(t=e.textContent,u([fe,de,he],(e=>{t=g(t,e," ")})),e.textContent!==t&&(p(o.removed,{element:e.cloneNode()}),e.textContent=t)),bt("afterSanitizeElements",e,null),!1):(Tt(e),!0)},Rt=function(e,t,n){if(Be&&("id"===t||"name"===t)&&(n in r||n in st))return!1;if(De&&!Le[t]&&_(ge,t));else if(ve&&_(Te,t));else if(!Se[t]||Le[t]){if(!(wt(e)&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,e)||we.tagNameCheck instanceof Function&&we.tagNameCheck(e))&&(we.attributeNameCheck instanceof RegExp&&_(we.attributeNameCheck,t)||we.attributeNameCheck instanceof Function&&we.attributeNameCheck(t))||"is"===t&&we.allowCustomizedBuiltInElements&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n)||we.tagNameCheck instanceof Function&&we.tagNameCheck(n))))return!1}else if(Ve[t]);else if(_(Ae,g(n,Ee,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!$e[e]){if(Oe&&!_(ye,g(n,Ee,"")));else if(n)return!1}else;return!0},wt=function(e){return"annotation-xml"!==e&&h(e,_e)},Ct=function(e){bt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Se};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=lt(a);let p="value"===a?c:y(c);if(n.attrName=s,n.attrValue=p,n.keepAttr=!0,n.forceKeepAttr=void 0,bt("uponSanitizeAttribute",e,n),p=n.attrValue,n.forceKeepAttr)continue;if(yt(a,e),!n.keepAttr)continue;if(!xe&&_(/\/>/i,p)){yt(a,e);continue}ke&&u([fe,de,he],(e=>{p=g(p,e," ")}));const f=lt(e.nodeName);if(Rt(f,s,p))if(!We||"id"!==s&&"name"!==s||(yt(a,e),p="user-content-"+p),Me&&_(/((--!?|])>)|<\/(style|title)/i,p))yt(a,e);else{if(ie&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(f,s)){case"TrustedHTML":p=ie.createHTML(p);break;case"TrustedScriptURL":p=ie.createScriptURL(p)}try{l?e.setAttributeNS(l,a,p):e.setAttribute(a,p),At(e)?Tt(e):m(o.removed)}catch(e){}}}bt("afterSanitizeAttributes",e,null)},Lt=function e(t){let n=null;const o=_t(t);for(bt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)bt("uponSanitizeShadowNode",n,null),St(n)||(n.content instanceof s&&e(n.content),Ct(n));bt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(nt=!e,nt&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Nt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Ue||mt(t),o.removed=[],"string"==typeof e&&(Ye=!1),Ye){if(e.nodeName){const t=lt(e.nodeName);if(!Ne[t]||Ce[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=Et("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===V&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Fe&&!ke&&!Ie&&-1===e.indexOf("<"))return ie&&ze?ie.createHTML(e):e;if(n=Et(e),!n)return Fe?null:ze?ae:""}n&&Pe&&Tt(n.firstChild);const c=_t(Ye?e:n);for(;i=c.nextNode();)St(i)||(i.content instanceof s&&Lt(i.content),Ct(i));if(Ye)return e;if(Fe){if(He)for(l=se.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Se.shadowroot||Se.shadowrootmode)&&(l=me.call(a,l,!0)),l}let m=Ie?n.outerHTML:n.innerHTML;return Ie&&Ne["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&_(q,n.ownerDocument.doctype.name)&&(m="<!DOCTYPE "+n.ownerDocument.doctype.name+">\n"+m),ke&&u([fe,de,he],(e=>{m=g(m,e," ")})),ie&&ze?ie.createHTML(m):m},o.setConfig=function(){mt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Ue=!0},o.clearConfig=function(){ct=null,Ue=!1},o.isValidAttribute=function(e,t,n){ct||mt({});const o=lt(e),r=lt(t);return Rt(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(pe[e]=pe[e]||[],p(pe[e],t))},o.removeHook=function(e){if(pe[e])return m(pe[e])},o.removeHooks=function(e){pe[e]&&(pe[e]=[])},o.removeAllHooks=function(){pe={}},o}();return ne}));
|
|
3
|
-
|
|
1
|
+
/*! @license DOMPurify 3.4.17 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.17/LICENSE */
|
|
2
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.DOMPurify=t())})(this,function(){"use strict";function e(e,t){this.v=e,this.k=t}function t(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function n(e){if(Array.isArray(e))return e}function r(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function i(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
3
|
+
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}
|
|
4
|
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
|
5
|
+
function a(e,t){return n(e)||r(e,t)||o(e,t)||i()}function o(e,n){if(e){if(typeof e==`string`)return t(e,n);var r={}.toString.call(e).slice(8,-1);return r===`Object`&&e.constructor&&(r=e.constructor.name),r===`Map`||r===`Set`?Array.from(e):r===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?t(e,n):void 0}}function s(t){var n,r;function i(n,r){try{var o=t[n](r),s=o.value,c=s instanceof e;Promise.resolve(c?s.v:s).then(function(e){if(c){var r=n===`return`&&s.k?n:`next`;if(!s.k||e.done)return i(r,e);e=t[r](e).value}a(!!o.done,e)},function(e){i(`throw`,e)})}catch(e){a(2,e)}}function a(e,t){e===2?n.reject(t):n.resolve({value:t,done:e}),(n=n.next)?i(n.key,n.arg):r=null}this._invoke=function(e,t){return new Promise(function(a,o){var s={key:e,arg:t,resolve:a,reject:o,next:null};r?r=r.next=s:(n=r=s,i(e,t))})},typeof t.return!=`function`&&(this.return=void 0)}s.prototype[typeof Symbol==`function`&&Symbol.asyncIterator||`@@asyncIterator`]=function(){return this},s.prototype.next=function(e){return this._invoke(`next`,e)},s.prototype.throw=function(e){return this._invoke(`throw`,e)},s.prototype.return=function(e){return this._invoke(`return`,e)};let c=Object.entries,l=Object.setPrototypeOf,u=Object.isFrozen,d=Object.getPrototypeOf,f=Object.getOwnPropertyDescriptor,p=Object.freeze,m=Object.seal,h=Object.create,ee=typeof Reflect<`u`&&Reflect,g=ee.apply,te=ee.construct;p||(p=function(e){return e}),m||(m=function(e){return e}),g||(g=function(e,t){var n=[...arguments].slice(2);return e.apply(t,n)}),te||(te=function(e){return new e(...[...arguments].slice(1))});let _=E(Array.prototype.forEach);Array.prototype.indexOf;let ne=E(Array.prototype.lastIndexOf),re=E(Array.prototype.pop),ie=E(Array.prototype.push),ae=E(Array.prototype.slice),oe=E(Array.prototype.splice),v=Array.isArray,se=D(Set),ce=E(Set.prototype.add),le=E(Set.prototype.has),y=E(String.prototype.toLowerCase),ue=E(String.prototype.toString),de=E(String.prototype.match),fe=E(String.prototype.replace),pe=E(String.prototype.indexOf),me=E(String.prototype.trim),he=E(Number.prototype.toString),b=E(Boolean.prototype.toString),x=typeof BigInt>`u`?null:E(BigInt.prototype.toString),ge=typeof Symbol>`u`?null:E(Symbol.prototype.toString),S=E(Object.prototype.hasOwnProperty),C=E(Object.prototype.toString),w=E(RegExp.prototype.test),T=D(TypeError);function E(e){return function(t){t instanceof RegExp&&(t.lastIndex=0);var n=[...arguments].slice(1);return g(e,t,n)}}function D(e){return function(){return te(e,[...arguments])}}function O(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:y;if(l&&l(e,null),!v(t))return e;let r=t.length;for(;r--;){let i=t[r];if(typeof i==`string`){let e=n(i);e!==i&&(u(t)||(t[r]=e),i=e)}e[i]=!0}return e}function _e(e){for(let t=0;t<e.length;t++)S(e,t)||(e[t]=null);return e}function k(e){let t=h(null);for(let r of c(e)){var n=a(r,2);let i=n[0],o=n[1];S(e,i)&&(t[i]=v(o)?_e(o):o&&typeof o==`object`&&o.constructor===Object?k(o):o)}return t}function ve(e){switch(typeof e){case`string`:return e;case`number`:return he(e);case`boolean`:return b(e);case`bigint`:return x?x(e):`0`;case`symbol`:return ge?ge(e):`Symbol()`;case`undefined`:return C(e);case`function`:case`object`:{if(e===null)return C(e);let t=e,n=A(t,`toString`);if(typeof n==`function`){let e=n(t);return typeof e==`string`?e:C(e)}return C(e)}default:return C(e)}}function A(e,t){for(;e!==null;){let n=f(e,t);if(n){if(n.get)return E(n.get);if(typeof n.value==`function`)return E(n.value)}e=d(e)}function n(){return null}return n}function ye(e,t){for(;e!==null;){let n=f(e,t);if(n)return n.get?E(n.get):null;e=d(e)}return null}function be(e){try{return w(e,``),!0}catch(e){return!1}}let xe=p(/* @__PURE__ */ `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.search.section.select.shadow.slot.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`.split(`.`)),Se=p(/* @__PURE__ */ `svg.a.altglyph.altglyphdef.altglyphitem.animatecolor.animatemotion.animatetransform.circle.clippath.defs.desc.ellipse.enterkeyhint.exportparts.filter.font.g.glyph.glyphref.hkern.image.inputmode.line.lineargradient.marker.mask.metadata.mpath.part.path.pattern.polygon.polyline.radialgradient.rect.stop.style.switch.symbol.text.textpath.title.tref.tspan.view.vkern`.split(`.`)),Ce=p([`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`]),we=p([`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`]),Te=p(/* @__PURE__ */ `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`.split(`.`)),Ee=p([`maction`,`maligngroup`,`malignmark`,`mlongdiv`,`mscarries`,`mscarry`,`msgroup`,`mstack`,`msline`,`msrow`,`semantics`,`annotation`,`annotation-xml`,`mprescripts`,`none`]),De=p([`#text`]),Oe=p(/* @__PURE__ */ `accept.action.align.alt.autocapitalize.autocomplete.autopictureinpicture.autoplay.background.bgcolor.border.capture.cellpadding.cellspacing.checked.cite.class.clear.color.cols.colspan.command.commandfor.controls.controlslist.coords.crossorigin.datetime.decoding.default.dir.disabled.disablepictureinpicture.disableremoteplayback.download.draggable.enctype.enterkeyhint.exportparts.face.for.headers.height.hidden.high.href.hreflang.id.inert.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.part.pattern.placeholder.playsinline.popover.popovertarget.popovertargetaction.poster.preload.pubdate.radiogroup.readonly.rel.required.rev.reversed.role.rows.rowspan.spellcheck.scope.selected.shape.size.sizes.slot.span.srclang.start.src.srcset.step.style.summary.tabindex.title.translate.type.usemap.valign.value.width.wrap.xmlns`.split(`.`)),ke=p(/* @__PURE__ */ `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.dominant-baseline.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.mask-type.media.method.mode.min.name.numoctaves.offset.operator.opacity.order.orient.orientation.origin.overflow.paint-order.path.pathlength.patterncontentunits.patterntransform.patternunits.pointer-events.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-orientation.text-rendering.textlength.type.u1.u2.unicode.values.vector-effect.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`.split(`.`)),Ae=p(/* @__PURE__ */ `accent.accentunder.align.bevelled.close.columnalign.columnlines.columnspacing.columnspan.denomalign.depth.dir.display.displaystyle.encoding.fence.frame.height.href.id.largeop.length.linethickness.lquote.lspace.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`.split(`.`)),je=p([`xlink:href`,`xml:id`,`xlink:title`,`xml:space`,`xmlns:xlink`]),Me=m(/{{[\w\W]*|^[\w\W]*}}/g),Ne=m(/<%[\w\W]*|^[\w\W]*%>/g),Pe=m(/\${[\w\W]*/g),Fe=m(/^data-[\-\w.\u00B7-\uFFFF]+$/),Ie=m(/^aria-[\-\w]+$/),Le=m(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Re=m(/^(?:\w+script|data):/i),ze=m(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Be=m(/^html$/i),Ve=m(/^[a-z][.\w]*(-[.\w]+)+$/i),He=m(/<[/\w!]/g),Ue=m(/<[/\w]/g),We=m(/<\/no(script|embed|frames)/i),Ge=m(/\/>/i),j={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,processingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12},Ke=p(O({},[`style`,`script`,`xmp`,`iframe`,`noembed`,`noframes`,`plaintext`,`noscript`])),qe=function(){return typeof window>`u`?null:window},Je=function(e,t){if(typeof e!=`object`||typeof e.createPolicy!=`function`)return null;let n=null,r=`data-tt-policy-suffix`;t&&t.hasAttribute(r)&&(n=t.getAttribute(r));let i=`dompurify`+(n?`#`+n:``);try{return e.createPolicy(i,{createHTML(e){return e},createScriptURL(e){return e}})}catch(e){return console.warn(`TrustedTypes policy `+i+` could not be created.`),null}},Ye=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},M=function(e,t,n,r){return S(e,t)&&v(e[t])?O(r.base?k(r.base):{},e[t],r.transform):n},Xe=function(e,t,n){let r=S(e,t)?e[t]:void 0;return r&&typeof r==`object`?k(r):n()};function Ze(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:qe(),t=e=>Ze(e);if(t.version=`3.4.17`,t.removed=[],!e||!e.document||e.document.nodeType!==j.document||!e.Element)return t.isSupported=!1,t;let n=e.document,r=n,i=r.currentScript;e.DocumentFragment;let a=e.HTMLTemplateElement,o=e.Node,s=e.Element,l=e.NodeFilter;e.NamedNodeMap===void 0&&(e.NamedNodeMap||e.MozNamedAttrMap),e.HTMLFormElement;let u=e.DOMParser,d=e.trustedTypes,f=s.prototype,ee=A(f,`cloneNode`),g=A(f,`remove`),te=A(f,`removeAttributeNode`),he=A(f,`nextSibling`),b=A(f,`childNodes`),x=A(f,`parentNode`),ge=A(f,`shadowRoot`),C=A(f,`attributes`),E=o&&o.prototype?A(o.prototype,`nodeType`):null,D=o&&o.prototype?A(o.prototype,`nodeName`):null,_e=o&&o.prototype?A(o.prototype,`ownerDocument`):null,N=function(e){return E?E(e):e.nodeType},Qe=function(e){return D?D(e):e.nodeName},$e=ye(f,`namespaceURI`),et=function(e){return $e?$e(e):e.namespaceURI};if(typeof a==`function`){let e=n.createElement(`template`);e.content&&e.content.ownerDocument&&(n=e.content.ownerDocument)}let P,F=``,tt,nt=!1,rt=0,it=function(){if(rt>0)throw T(`A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.`)},at=function(e){it(),rt++;try{return P.createHTML(e)}finally{rt--}},ot=function(e){it(),rt++;try{return P.createScriptURL(e)}finally{rt--}},st=function(){return nt||(tt=Je(d,i),nt=!0),tt},ct=n,lt=ct.implementation,ut=ct.createNodeIterator,dt=ct.createDocumentFragment,ft=ct.getElementsByTagName,pt=r.importNode,I=Ye();t.isSupported=typeof c==`function`&&typeof x==`function`&<&<.createHTMLDocument!==void 0;let mt=Me,ht=Ne,gt=Pe,_t=Fe,vt=Ie,yt=Re,bt=ze,xt=Ve,St=Le,L=null,Ct=O({},[...xe,...Se,...Ce,...Te,...De]),R=null,wt=O({},[...Oe,...ke,...Ae,...je]),z=Object.seal(h(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}})),Tt=null,Et=null,B=Object.seal(h(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}})),Dt=!0,Ot=!0,kt=!1,At=!0,V=!1,H=!0,U=!1,jt=!1,Mt=null,Nt=null,Pt=!1,W=!1,Ft=!1,It=!1,Lt=!0,Rt=!1,zt=`user-content-`,Bt=!0,Vt=!1,G=null,K={},q=null,Ht=O({},/* @__PURE__ */ `annotation-xml.audio.colgroup.desc.foreignobject.head.iframe.math.mi.mn.mo.ms.mtext.noembed.noframes.noscript.plaintext.script.selectedcontent.style.svg.template.thead.title.video.xmp`.split(`.`)),Ut=null,Wt=O({},[`audio`,`video`,`img`,`source`,`image`,`track`]),Gt=null,Kt=O({},[`alt`,`class`,`for`,`id`,`label`,`name`,`pattern`,`placeholder`,`role`,`summary`,`title`,`value`,`style`,`xmlns`]),qt=`http://www.w3.org/1998/Math/MathML`,Jt=`http://www.w3.org/2000/svg`,J=`http://www.w3.org/1999/xhtml`,Yt=J,Xt=!1,Zt=null,Qt=O({},[qt,Jt,J],ue),$t=p([`mi`,`mo`,`mn`,`ms`,`mtext`]),en=O({},$t),tn=p([`annotation-xml`]),nn=O({},tn),rn=O({},[`title`,`style`,`font`,`a`,`script`]),an=null,on=[`application/xhtml+xml`,`text/html`],Y=null,sn=null,cn=n.createElement(`form`),ln=function(e){return e instanceof RegExp||e instanceof Function},un=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(sn&&sn===e)return;(!e||typeof e!=`object`)&&(e={}),e=k(e),an=on.indexOf(e.PARSER_MEDIA_TYPE)===-1?`text/html`:e.PARSER_MEDIA_TYPE,Y=an===`application/xhtml+xml`?ue:y,L=M(e,`ALLOWED_TAGS`,Ct,{transform:Y}),R=M(e,`ALLOWED_ATTR`,wt,{transform:Y}),Zt=M(e,`ALLOWED_NAMESPACES`,Qt,{transform:ue}),Gt=M(e,`ADD_URI_SAFE_ATTR`,Kt,{transform:Y,base:Kt}),Ut=M(e,`ADD_DATA_URI_TAGS`,Wt,{transform:Y,base:Wt}),q=M(e,`FORBID_CONTENTS`,Ht,{transform:Y}),Tt=M(e,`FORBID_TAGS`,k({}),{transform:Y}),Et=M(e,`FORBID_ATTR`,k({}),{transform:Y}),K=S(e,`USE_PROFILES`)?e.USE_PROFILES&&typeof e.USE_PROFILES==`object`?k(e.USE_PROFILES):e.USE_PROFILES:!1,Dt=e.ALLOW_ARIA_ATTR!==!1,Ot=e.ALLOW_DATA_ATTR!==!1,kt=e.ALLOW_UNKNOWN_PROTOCOLS||!1,At=e.ALLOW_SELF_CLOSE_IN_ATTR!==!1,V=e.SAFE_FOR_TEMPLATES||!1,H=e.SAFE_FOR_XML!==!1,U=e.WHOLE_DOCUMENT||!1,W=e.RETURN_DOM||!1,Ft=e.RETURN_DOM_FRAGMENT||!1,It=e.RETURN_TRUSTED_TYPE||!1,Pt=e.FORCE_BODY||!1,Lt=e.SANITIZE_DOM!==!1,Rt=e.SANITIZE_NAMED_PROPS||!1,Bt=e.KEEP_CONTENT!==!1,Vt=e.IN_PLACE||!1,St=be(e.ALLOWED_URI_REGEXP)?e.ALLOWED_URI_REGEXP:Le,Yt=typeof e.NAMESPACE==`string`?e.NAMESPACE:J,en=Xe(e,`MATHML_TEXT_INTEGRATION_POINTS`,()=>O({},$t)),nn=Xe(e,`HTML_INTEGRATION_POINTS`,()=>O({},tn));let t=Xe(e,`CUSTOM_ELEMENT_HANDLING`,()=>h(null));if(z=h(null),S(t,`tagNameCheck`)&&ln(t.tagNameCheck)&&(z.tagNameCheck=t.tagNameCheck),S(t,`attributeNameCheck`)&&ln(t.attributeNameCheck)&&(z.attributeNameCheck=t.attributeNameCheck),S(t,`allowCustomizedBuiltInElements`)&&typeof t.allowCustomizedBuiltInElements==`boolean`&&(z.allowCustomizedBuiltInElements=t.allowCustomizedBuiltInElements),m(z),V&&(Ot=!1),Ft&&(W=!0),K&&(L=O({},De),R=h(null),K.html===!0&&(O(L,xe),O(R,Oe)),K.svg===!0&&(O(L,Se),O(R,ke),O(R,je)),K.svgFilters===!0&&(O(L,Ce),O(R,ke),O(R,je)),K.mathMl===!0&&(O(L,Te),O(R,Ae),O(R,je))),B.tagCheck=null,B.attributeCheck=null,S(e,`ADD_TAGS`)&&(typeof e.ADD_TAGS==`function`?B.tagCheck=e.ADD_TAGS:v(e.ADD_TAGS)&&(L===Ct&&(L=k(L)),O(L,e.ADD_TAGS,Y))),S(e,`ADD_ATTR`)&&(typeof e.ADD_ATTR==`function`?B.attributeCheck=e.ADD_ATTR:v(e.ADD_ATTR)&&(R===wt&&(R=k(R)),O(R,e.ADD_ATTR,Y))),S(e,`ADD_FORBID_CONTENTS`)&&v(e.ADD_FORBID_CONTENTS)&&(q===Ht&&(q=k(q)),O(q,e.ADD_FORBID_CONTENTS,Y)),Bt&&(L[`#text`]=!0),U&&O(L,[`html`,`head`,`body`]),L.table&&(O(L,[`tbody`]),delete Tt.tbody),e.TRUSTED_TYPES_POLICY){if(typeof e.TRUSTED_TYPES_POLICY.createHTML!=`function`)throw T(`TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.`);if(typeof e.TRUSTED_TYPES_POLICY.createScriptURL!=`function`)throw T(`TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.`);let t=P;P=e.TRUSTED_TYPES_POLICY;try{F=at(``)}catch(e){throw P=t,e}}else e.TRUSTED_TYPES_POLICY===null?(P=void 0,F=``):(P===void 0&&(P=st()),P&&typeof F==`string`&&(F=at(``)));p&&p(e),sn=e},dn=O({},[...Se,...Ce,...we]),fn=O({},[...Te,...Ee]),pn=function(e,t,n){return t.namespaceURI===J?e===`svg`:t.namespaceURI===qt?e===`svg`&&(n===`annotation-xml`||en[n]):!!dn[e]},mn=function(e,t,n){return t.namespaceURI===J?e===`math`:t.namespaceURI===Jt?e===`math`&&nn[n]:!!fn[e]},hn=function(e,t,n){return t.namespaceURI===Jt&&!nn[n]||t.namespaceURI===qt&&!en[n]?!1:!fn[e]&&(rn[e]||!dn[e])},gn=function(e){let t=et(e),n=y(Qe(e)),r=x(e),i,a;return r&&N(r)===j.element?(i={namespaceURI:et(r)},a=y(Qe(r))):(i={namespaceURI:Yt},a=`template`),Zt[t]?t===Jt?pn(n,i,a):t===qt?mn(n,i,a):t===J?hn(n,i,a):!!(an===`application/xhtml+xml`&&Zt[t]):!1},X=function(e){ie(t.removed,{element:e});try{x(e).removeChild(e)}catch(t){if(g(e),!x(e))throw T(`a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place`)}},_n=function(e,t,n){try{te(e,t)}catch(t){try{e.removeAttribute(n)}catch(e){}}},vn=function(e){Sn(e);let t=b(e);t&&_(ae(t),e=>{try{g(e)}catch(e){}});let n=N(e)===j.element?C(e):null;if(n)for(let t=n.length-1;t>=0;--t){let r=n[t],i=r&&r.name;typeof i==`string`&&_n(e,r,i)}},yn=function(e,n,r){if(!r)try{r=n.getAttributeNode(e)}catch(e){r=null}ie(t.removed,{attribute:r||null,from:n});try{r?te(n,r):n.removeAttribute(e)}catch(t){try{n.removeAttribute(e)}catch(e){}}if(e===`is`){if(W||Ft)try{X(n)}catch(e){}else try{n.setAttribute(e,``)}catch(e){}}},bn=function(e){let t=C(e);if(t)for(let n=t.length-1;n>=0;--n){let r=t[n],i=r&&r.name;typeof i!=`string`||R[Y(i)]||_n(e,r,i)}},xn=function(e,t){let n=arguments.length>2&&arguments[2]!==void 0&&arguments[2],r=[e];for(;r.length>0;){let e=r.pop();if(t(e)===!1)continue;if(n&&N(e)===j.element){let t=ge(e);Z(t)&&r.push(t)}let i=b(e);if(i)for(let e=i.length-1;e>=0;--e)r.push(i[e])}},Sn=function(e){xn(e,e=>{N(e)===j.element&&bn(e)})},Cn=function(e){let t=[];return xn(e,e=>{t.push(e)},!0),t},wn=function(e,t){let n=se();_(Cn(e),e=>{N(e)===j.element&&ce(n,e)}),_(t,e=>{N(e)===j.element&&!le(n,e)&&bn(e)})},Tn=function(e,n){let r=!1;return _(t.removed,t=>{t.element&&(r=r||t.element===e,Sn(t.element))}),wn(e,n),r},En=function(e,t){let n=G,r=null,i=()=>(r||(r=se(),_(t,e=>{ce(r,e)})),r);for(let t=0;;t++){let r=Cn(e),a=[e],o=!1;if(_(r,e=>{N(e)===j.documentFragment?ie(a,e):!o&&!le(n,e)&&(o=le(i(),e))}),!o)return;if(t>=8)throw T(`the tree kept changing during in-place sanitization; refusing to return it`);_(a,(t,n)=>{Dn(t,n>0,e,i())})}},Dn=function(e,t,n,r){let i=Mn(e),a;for(;a=i.nextNode();)le(r,a)&&!le(G,a)&&(t&&Q(I.uponSanitizeShadowNode,a,null),Hn(a,n),Yn(a,n),Z(a.content)&&Xn(a.content))},On=function(e){G&&ce(G,e)},kn=function(e,t){return H?e===`patchsrc`||e===`for`&&t!==`label`&&t!==`output`:!1},An=function(e){H&&xn(e,e=>{let t=N(e);if(t===j.processingInstruction||t===j.comment&&w(Ue,e.data)){try{g(e)}catch(e){}return!1}if(t===j.element){let t=e,n=Y(Qe(e));try{t.hasAttribute&&t.hasAttribute(`patchsrc`)&&t.removeAttribute(`patchsrc`),t.hasAttribute&&t.hasAttribute(`for`)&&kn(`for`,n)&&t.removeAttribute(`for`)}catch(e){}}return!0})},jn=function(e){let t=null,r=null;if(Pt)e=`<remove></remove>`+e;else{let t=de(e,/^[\r\n\t ]+/);r=t&&t[0]}an===`application/xhtml+xml`&&Yt===J&&(e=`<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>`+e+`</body></html>`);let i=P?at(e):e;if(Yt===J)try{t=new u().parseFromString(i,an)}catch(e){}if(!t||!t.documentElement){t=lt.createDocument(Yt,`template`,null);try{t.documentElement.innerHTML=Xt?F:i}catch(e){}}let a=t.body||t.documentElement;return e&&r&&a.insertBefore(n.createTextNode(r),a.childNodes[0]||null),Yt===J?ft.call(t,U?`html`:`body`)[0]:U?t.documentElement:a},Mn=function(e){let t=_e?_e(e):e.ownerDocument;return ut.call(t||e,e,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT|l.SHOW_PROCESSING_INSTRUCTION|l.SHOW_CDATA_SECTION,null)},Nn=function(e){return e=fe(e,mt,` `),e=fe(e,ht,` `),e=fe(e,gt,` `),e},Pn=function(e){var t;Fn(e);let n=(t=e.querySelectorAll)==null?void 0:t.call(e,`template`);n&&_(n,e=>{Z(e.content)&&Pn(e.content)})},Fn=function(e){e.normalize();let t=_e?_e(e):e.ownerDocument,n=ut.call(t||e,e,l.SHOW_TEXT|l.SHOW_COMMENT|l.SHOW_CDATA_SECTION|l.SHOW_PROCESSING_INSTRUCTION,null),r=n.nextNode();for(;r;)r.data=Nn(r.data),r=n.nextNode()},In=function(e){let t=D?D(e):null;return typeof t!=`string`||Y(t)!==`form`?!1:typeof e.nodeName!=`string`||typeof e.textContent!=`string`||typeof e.removeChild!=`function`||e.attributes!==C(e)||typeof e.removeAttribute!=`function`||typeof e.removeAttributeNode!=`function`||typeof e.getAttributeNode!=`function`||typeof e.setAttribute!=`function`||typeof e.namespaceURI!=`string`||typeof e.insertBefore!=`function`||typeof e.hasChildNodes!=`function`||e.nodeType!==E(e)||e.childNodes!==b(e)},Z=function(e){if(!E||typeof e!=`object`||!e)return!1;try{return E(e)===j.documentFragment}catch(e){return!1}},Ln=function(e){if(!E||typeof e!=`object`||!e)return!1;try{return typeof E(e)==`number`}catch(e){return!1}};function Q(e,n,r){e.length!==0&&_(e,e=>{e.call(t,n,r,sn)})}let Rn=function(e,t){return!!(H&&e.hasChildNodes()&&!Ln(e.firstElementChild)&&w(He,e.textContent)&&w(He,e.innerHTML)||H&&Ke[t]&&N(e)===j.element&&et(e)===J&&(Ln(e.firstElementChild)||typeof e.textContent==`string`&&w(He,e.textContent))||e.nodeType===j.processingInstruction||H&&e.nodeType===j.comment&&w(Ue,e.data))},zn=function(e,t){return e instanceof RegExp?w(e,t):e instanceof Function&&!!e(t,...[...arguments].slice(2))},Bn=function(e,t,n){if(!Tt[t]&&Gn(t)&&zn(z.tagNameCheck,t))return!1;if(Bt&&!q[t]&&!q[y(t)]){let t=x(e),r=b(e);if(r&&t){let i=r.length;for(let a=i-1;a>=0;--a){let i=e===n?ee(r[a],!0):r[a];t.insertBefore(i,he(e))}}}return X(e),!0},Vn=function(e,t,n,r){return e.length===0?t:t===n||t===r?k(t):t},$=function(e,t){return e===t||x(e)!==null?!1:(Vt&&Sn(e),!0)},Hn=function(e,n){if(On(e),Q(I.beforeSanitizeElements,e,null),$(e,n))return!0;if(In(e))return X(e),!0;let r=Y(Qe(e));if(L=Vn(I.uponSanitizeElement,L,Ct,Mt),Q(I.uponSanitizeElement,e,{tagName:r,allowedTags:L}),$(e,n))return!0;if(Rn(e,r))return X(e),!0;if(Tt[r]||!(B.tagCheck instanceof Function&&B.tagCheck(r))&&!L[r]){let t=Bn(e,r,n);return t===!1&&(Q(I.afterSanitizeElements,e,null),$(e,n))?!0:t}if(N(e)===j.element&&!gn(e)||(r===`noscript`||r===`noembed`||r===`noframes`)&&w(We,e.innerHTML))return X(e),!0;if(V&&e.nodeType===j.text){let n=Nn(e.textContent);e.textContent!==n&&(ie(t.removed,{element:e.cloneNode()}),e.textContent=n)}return Q(I.afterSanitizeElements,e,null),$(e,n)},Un=function(e,t,r){if(Et[t]||kn(t,e)||Lt&&(t===`id`||t===`name`)&&(r in n||r in cn))return!1;let i=R[t]||B.attributeCheck instanceof Function&&B.attributeCheck(t,e);return Ot&&w(_t,t)||Dt&&w(vt,t)?!0:i?Gt[t]||w(St,fe(r,bt,``))||(t===`src`||t===`xlink:href`||t===`href`)&&e!==`script`&&pe(r,`data:`)===0&&Ut[e]||kt&&!w(yt,fe(r,bt,``))?!0:!r:Gn(e)&&zn(z.tagNameCheck,e)&&zn(z.attributeNameCheck,t,e)||t===`is`&&z.allowCustomizedBuiltInElements&&zn(z.tagNameCheck,r)},Wn=O({},[`annotation-xml`,`color-profile`,`font-face`,`font-face-format`,`font-face-name`,`font-face-src`,`font-face-uri`,`missing-glyph`]),Gn=function(e){return!Wn[y(e)]&&w(xt,e)},Kn=function(e,t,n,r){if(P&&typeof d==`object`&&typeof d.getAttributeType==`function`&&!n)switch(d.getAttributeType(e,t)){case`TrustedHTML`:return at(r);case`TrustedScriptURL`:return ot(r)}return r},qn=function(e,t,n,r){try{return n?e.setAttributeNS(n,t,r):e.setAttribute(t,r),!In(e)||(X(e),!1)}catch(n){return yn(t,e),!1}},Jn=function(e,t){return H&&w(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,t)?!0:y(e)===`attributename`&&de(t,`href`)!==null},Yn=function(e,n){if(Q(I.beforeSanitizeAttributes,e,null),$(e,n))return;let r=e.attributes;if(!r||In(e))return;R=Vn(I.uponSanitizeAttribute,R,wt,Nt);let i={attrName:``,attrValue:``,keepAttr:!0,allowedAttributes:R,forceKeepAttr:void 0},a=r.length,o=Y(e.nodeName);for(;a--;){let n=r[a],s=n.name,c=n.namespaceURI,l=n.value,u=Y(s),d=l,f=s===`value`?d:me(d),p=!1;i.attrName=u,i.attrValue=f,i.keepAttr=!0,i.forceKeepAttr=void 0,Q(I.uponSanitizeAttribute,e,i),f=i.attrValue,Rt&&(u===`id`||u===`name`)&&pe(f,zt)!==0&&(yn(s,e,n),f=zt+f,p=!0),Jn(s,f)?yn(s,e,n):i.forceKeepAttr||(i.keepAttr?!At&&w(Ge,f)?yn(s,e,n):(V&&(f=Nn(f)),Un(o,u,f)?(f=Kn(o,u,c,f),f!==d&&qn(e,s,c,f)&&p&&re(t.removed)):yn(s,e,n)):yn(s,e,n))}Q(I.afterSanitizeAttributes,e,null),$(e,n)},Xn=function(e){let t=null,n=Mn(e);for(Q(I.beforeSanitizeShadowDOM,e,null);t=n.nextNode();)if(Q(I.uponSanitizeShadowNode,t,null),Hn(t,e),Yn(t,e),Z(t.content)&&Xn(t.content),N(t)===j.element){let e=ge(t);Z(e)&&(Zn(e),Xn(e))}V&&Fn(e),Q(I.afterSanitizeShadowDOM,e,null)},Zn=function(e){let t=[{node:e,shadow:null}];for(;t.length>0;){let e=t.pop();if(e.shadow){Xn(e.shadow);continue}let n=e.node,r=N(n)===j.element,i=b(n);if(i)for(let e=i.length-1;e>=0;--e)t.push({node:i[e],shadow:null});if(r){let e=D?D(n):null;if(typeof e==`string`&&Y(e)===`template`){let e=n.content;Z(e)&&t.push({node:e,shadow:null})}}if(r){let e=ge(n);Z(e)&&t.push({node:null,shadow:e},{node:e,shadow:null})}}};return t.sanitize=function(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=null,a=null,o=null,s=null;if(Xt=!e,Xt&&(e=`<!-->`),typeof e!=`string`&&!Ln(e)&&(e=ve(e),typeof e!=`string`))throw T(`dirty is not a string, aborting`);if(!t.isSupported)return e;jt?(L=Mt,R=Nt):un(n),(I.uponSanitizeElement.length>0||I.uponSanitizeAttribute.length>0)&&(L=k(L)),I.uponSanitizeAttribute.length>0&&(R=k(R)),t.removed=[];let c=Vt&&typeof e!=`string`&&Ln(e),l=[],u=G;if(c){An(e);let t=Qe(e);if(typeof t==`string`){let n=Y(t);if(!L[n]||Tt[n])throw vn(e),T(`root node is forbidden and cannot be sanitized in-place`)}if(In(e))throw vn(e),T(`root node is clobbered and cannot be sanitized in-place`);l=Cn(e),G=se()}else if(Ln(e))i=jn(`<!---->`),a=i.ownerDocument.importNode(e,!0),a.nodeType===j.element&&a.nodeName===`BODY`||a.nodeName===`HTML`?i=a:i.appendChild(a),Zn(i);else{if(!W&&!V&&!U&&e.indexOf(`<`)===-1)return P&&It?at(e):e;if(i=jn(e),!i)return W?null:It?F:``}i&&Pt&&X(i.firstChild);let d=c?e:i;try{c&&Zn(e);let t=Mn(d);for(;o=t.nextNode();)Hn(o,d),Yn(o,d),Z(o.content)&&Xn(o.content);c&&En(e,l)}catch(t){throw c&&(vn(e),Tn(e,l)),t}finally{G=u}if(c){if(Tn(e,l))throw T(`a node selected for removal could not be safely returned; refusing to sanitize in place`);return V&&Pn(e),e}if(W){if(V&&Pn(i),Ft)for(s=dt.call(i.ownerDocument);i.firstChild;)s.appendChild(i.firstChild);else s=i;return(R.shadowroot||R.shadowrootmode)&&(s=pt.call(r,s,!0)),s}let f=U?i.outerHTML:i.innerHTML;return U&&L[`!doctype`]&&i.ownerDocument&&i.ownerDocument.doctype&&i.ownerDocument.doctype.name&&w(Be,i.ownerDocument.doctype.name)&&(f=`<!DOCTYPE `+i.ownerDocument.doctype.name+`>
|
|
6
|
+
`+f),V&&(f=Nn(f)),P&&It?at(f):f},t.setConfig=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};un(e),jt=!0,Mt=L,Nt=R},t.clearConfig=function(){sn=null,jt=!1,Mt=null,Nt=null,P=tt,F=``},t.isValidAttribute=function(e,t,n){sn||un({});let r=Y(e),i=Y(t);return typeof n==`string`&&(Jn(t,n)||!At&&w(Ge,n))?!1:Un(r,i,n)},t.addHook=function(e,t){typeof t==`function`&&S(I,e)&&ie(I[e],t)},t.removeHook=function(e,t){if(S(I,e)){if(t!==void 0){let n=ne(I[e],t);return n===-1?void 0:oe(I[e],n,1)[0]}return re(I[e])}},t.removeHooks=function(e){S(I,e)&&(I[e]=[])},t.removeAllHooks=function(){I=Ye()},t}return Ze()});
|
|
7
|
+
//# sourceMappingURL=purify.min.js.map
|
|
@@ -251,6 +251,84 @@
|
|
|
251
251
|
svg.dataset.zoom = String(next); svg.setAttribute('width', String(bounds.width * next)); svg.setAttribute('height', String(bounds.height * next));
|
|
252
252
|
return true;
|
|
253
253
|
}
|
|
254
|
+
// ── Merge readiness (design v12): on top of Overview, filled after the paint because gh is slow. ──
|
|
255
|
+
const READINESS_MS = 30000;
|
|
256
|
+
const readiness = new Map();
|
|
257
|
+
const MARKS = { pass: ['✓', 'passed'], fail: ['✗', 'failed'], 'not-read': ['✗', 'not read'], na: ['–', 'not required'] };
|
|
258
|
+
const ago = iso => { const min = Math.max(0, Math.round((Date.now() - Date.parse(iso)) / 60000)); return min ? `${min} min ago` : 'just now'; };
|
|
259
|
+
const safeHref = href => /^https:\/\/(github\.com|claude\.ai)\//.test(href || '') ? href : null;
|
|
260
|
+
function readinessAction(action) {
|
|
261
|
+
if (!action) return '';
|
|
262
|
+
if (action.kind === 'link') return safeHref(action.href) ? `<a class="rdy-link" href="${esc(action.href)}" target="_blank" rel="noopener">${esc(action.label)}</a>` : '';
|
|
263
|
+
if (action.kind === 'tab') return `<button type="button" class="rdy-link" data-work-tab="${esc(action.tab)}">${esc(action.label)}</button>`;
|
|
264
|
+
if (action.kind === 'issue') return `<button type="button" class="rdy-link" data-readiness-issue="${esc(action.issue)}"><span class="rdy-wide">${esc(action.label)}</span><span class="rdy-narrow">${esc(action.narrowLabel || action.label)}</span></button>`;
|
|
265
|
+
if (action.kind === 'copy') return `<button type="button" class="rdy-btn" data-readiness-copy="${esc(action.text)}">${esc(action.label)}</button>`;
|
|
266
|
+
if (action.kind === 'run-gate') return `<button type="button" class="rdy-btn" data-readiness-run>${esc(action.label)}</button>`;
|
|
267
|
+
return `<button type="button" class="rdy-btn" disabled>${esc(action.label)}</button>`;
|
|
268
|
+
}
|
|
269
|
+
function readinessRow(r) {
|
|
270
|
+
const [mark, label] = MARKS[r.state] || MARKS['not-read'];
|
|
271
|
+
const queue = r.queue ? ` New run: <b class="rdy-queue">${esc(r.queue)}</b>` : '';
|
|
272
|
+
const queueBrief = r.queue ? ` New run <b class="rdy-queue">${esc(r.queueBrief || r.queue)}</b>` : '';
|
|
273
|
+
const text = `<span class="rdy-detail"><span class="rdy-wide">${esc(r.detail)}${queue}</span><span class="rdy-narrow">${esc(r.brief || r.detail)}${queueBrief}</span></span>`;
|
|
274
|
+
return `<li class="rdy-row" data-state="${esc(r.state)}"><span class="rdy-mark" aria-label="${label}">${mark}</span><span class="rdy-label">${esc(r.label)}</span>${text}${readinessAction(r.action)}</li>`;
|
|
275
|
+
}
|
|
276
|
+
function renderReadiness(card) {
|
|
277
|
+
const noun = `${card.blockers} blocker${card.blockers === 1 ? '' : 's'}`;
|
|
278
|
+
const wide = card.ready ? 'Ready to merge' : `Ready to merge? Not yet — ${noun}`;
|
|
279
|
+
const narrow = card.ready ? 'Ready to merge' : `Not ready — ${noun}`;
|
|
280
|
+
const when = ago(card.checkedAt);
|
|
281
|
+
return `<section class="rdy" aria-labelledby="rdy-h" data-ready="${card.ready}"><div class="rdy-head"><div class="rdy-count">${card.ready ? '✓' : card.blockers}</div>`
|
|
282
|
+
+ `<div class="rdy-title"><h2 id="rdy-h"><span class="rdy-wide">${esc(wide)}</span><span class="rdy-narrow">${esc(narrow)}</span></h2>`
|
|
283
|
+
+ `<div class="rdy-sub"><span class="rdy-wide">Checked against head ${esc(card.shortHead)} · ${esc(when)}</span><span class="rdy-narrow">Head ${esc(card.shortHead)} · checked ${esc(when)}</span></div></div>`
|
|
284
|
+
+ `<div class="rdy-note"><span class="rdy-wide">The board does not merge. When every row is green it shows the merge command to copy, or you ask an agent to merge.</span><span class="rdy-narrow">The board does not merge; when all rows pass it shows the command to copy.</span></div></div>`
|
|
285
|
+
+ `<ul class="rdy-rows"><li class="rdy-group" data-group="blockers">BLOCKERS FIRST</li><li class="rdy-group" data-group="passed">PASSED</li>${card.rows.map(readinessRow).join('')}</ul>`
|
|
286
|
+
+ `<div class="rdy-foot">A row that could not be read shows “Not read” and counts as a blocker, never as passed.</div></section>`
|
|
287
|
+
+ (card.mergeCommand ? `<section class="rdy-ok" aria-label="Ready to merge"><span class="rdy-ok-mark" aria-hidden="true">✓</span><b>Ready to merge</b><code>${esc(card.mergeCommand)}</code><button type="button" class="rdy-btn" data-readiness-copy="${esc(card.mergeCommand)}">Copy command</button></section>` : '');
|
|
288
|
+
}
|
|
289
|
+
function readinessHtml(state) {
|
|
290
|
+
if (!state?.card && !state?.failed) return '';
|
|
291
|
+
if (state.failed) return '<p class="work-warning">Merge readiness could not be read. No row is assumed to pass.</p>';
|
|
292
|
+
return state.card.branch ? renderReadiness(state.card) : '';
|
|
293
|
+
}
|
|
294
|
+
const readinessSlot = entry => `<div data-readiness-slot="${esc(entry.key)}">${readinessHtml(readiness.get(entry.key))}</div>`;
|
|
295
|
+
async function hydrateReadiness(force = false) {
|
|
296
|
+
const slot = document.querySelector?.('[data-readiness-slot]');
|
|
297
|
+
if (!slot) return;
|
|
298
|
+
const key = slot.dataset.readinessSlot, project = config.project(), held = readiness.get(key);
|
|
299
|
+
if (!force && held && Date.now() - held.at < READINESS_MS) return;
|
|
300
|
+
readiness.set(key, { ...held, at: Date.now() });
|
|
301
|
+
let next;
|
|
302
|
+
try {
|
|
303
|
+
const card = await config.read(`/api/work/readiness?task=${encodeURIComponent(key)}${project ? '&project=' + encodeURIComponent(project) : ''}`);
|
|
304
|
+
next = !card || card.error ? { failed: true, at: Date.now() } : { card, at: Date.now() };
|
|
305
|
+
} catch { next = { failed: true, at: Date.now() }; }
|
|
306
|
+
if (project !== config.project()) return;
|
|
307
|
+
readiness.set(key, next);
|
|
308
|
+
const live = document.querySelector?.('[data-readiness-slot]');
|
|
309
|
+
if (live?.dataset.readinessSlot === key) live.innerHTML = readinessHtml(next);
|
|
310
|
+
}
|
|
311
|
+
async function readinessClick(event) {
|
|
312
|
+
const copy = event.target.closest?.('[data-readiness-copy]');
|
|
313
|
+
if (copy) {
|
|
314
|
+
try {
|
|
315
|
+
if (!navigator.clipboard) throw Error('no clipboard');
|
|
316
|
+
await navigator.clipboard.writeText(copy.dataset.readinessCopy);
|
|
317
|
+
} catch { status('Could not copy. Select the text and copy it by hand.'); return; }
|
|
318
|
+
const label = copy.textContent; copy.textContent = 'Copied'; setTimeout(() => { copy.textContent = label; }, 1500);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const issue = event.target.closest?.('[data-readiness-issue]');
|
|
322
|
+
if (issue) { config.openIssue?.(issue.dataset.readinessIssue); return; }
|
|
323
|
+
const start = event.target.closest?.('[data-readiness-run]');
|
|
324
|
+
if (!start) return;
|
|
325
|
+
start.disabled = true;
|
|
326
|
+
const slot = start.closest('[data-readiness-slot]'), project = config.project();
|
|
327
|
+
const result = await config.publish(`/api/work/readiness/run-gate?task=${encodeURIComponent(slot.dataset.readinessSlot)}${project ? '&project=' + encodeURIComponent(project) : ''}`, {}).catch(() => null);
|
|
328
|
+
if (!result || result.error) status(result?.error || 'The gate could not be started.');
|
|
329
|
+
await hydrateReadiness(true);
|
|
330
|
+
}
|
|
331
|
+
|
|
254
332
|
function renderCockpit(data, options = {}) {
|
|
255
333
|
if (options.canvas) return renderWorkspace(data, options);
|
|
256
334
|
const category = categories.some(([key]) => key === options.category) ? options.category : 'active';
|
|
@@ -267,7 +345,7 @@
|
|
|
267
345
|
// Only the selected Overview owns mutation controls; observation tabs cannot duplicate them.
|
|
268
346
|
const detail = tab === 'execution' ? renderExecution(selected) : tab === 'evidence'
|
|
269
347
|
? (Array.isArray(selected.evidenceSections) && selected.evidenceSections.length ? renderEvidence(selected.evidenceSections).replace('<details ', '<details open ') : '<p>Evidence unavailable. No verification or acceptance is inferred.</p>')
|
|
270
|
-
: render({ ...data, sources: [], sessions: [], entries: [{ ...selected, inspector: null, evidenceSections: null }] }, selected.terminal);
|
|
348
|
+
: readinessSlot(selected) + render({ ...data, sources: [], sessions: [], entries: [{ ...selected, inspector: null, evidenceSections: null }] }, selected.terminal);
|
|
271
349
|
return toolbar + (tab === 'overview' ? '' : observed) + feedback + '<p class="work-meta">Running means host activity was recorded; current liveness is not measured. Closed records do not by themselves prove acceptance.</p>'
|
|
272
350
|
+ `<div class="work-cockpit">${list}<section class="work-detail" aria-label="Selected task details">${tabs}<div id="work-detail-panel" role="tabpanel" aria-labelledby="work-tab-${tab}" tabindex="0">${detail}</div></section></div>`
|
|
273
351
|
+ (data.sessions.length ? `<details><summary>Claude sessions (${data.sessions.length}) · task linkage not recorded</summary>${data.sessions.map(s => `<p>${esc(s.session)} · ${esc(s.state)} · ${esc(s.reason || '')}</p>`).join('')}</details>` : '');
|
|
@@ -316,7 +394,7 @@
|
|
|
316
394
|
const tabs = '<div class="work-tabs" role="tablist" aria-label="Selected task">' + taskTabs.map(name => `<button type="button" class="work-tab" id="work-tab-${name}" data-work-tab="${name}" role="tab" aria-selected="${tab === name}" aria-controls="work-detail-panel" tabindex="${tab === name ? 0 : -1}">${name[0].toUpperCase() + name.slice(1)}</button>`).join('') + '</div>';
|
|
317
395
|
const detail = tab === 'execution' ? renderExecution(selected, { canvas: true, direction: options.direction }) : tab === 'evidence'
|
|
318
396
|
? (Array.isArray(selected.evidenceSections) && selected.evidenceSections.length ? renderEvidence(selected.evidenceSections).replace('<details ', '<details open ') : '<p>Evidence unavailable. No verification or acceptance is inferred.</p>')
|
|
319
|
-
: render({ ...data, sources: [], sessions: [], entries: [{ ...selected, inspector: null, evidenceSections: null }] }, selected.terminal);
|
|
397
|
+
: readinessSlot(selected) + render({ ...data, sources: [], sessions: [], entries: [{ ...selected, inspector: null, evidenceSections: null }] }, selected.terminal);
|
|
320
398
|
const runLabel = selected.title.match(/^Controlled run ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i);
|
|
321
399
|
const title = runLabel ? `Controlled run <small class="work-meta work-run-identifier">${esc(runLabel[1].slice(0, 8))}</small>` : esc(selected.title);
|
|
322
400
|
return `<section class="work-workspace work-detail-only" data-selected-work="${esc(selected.key)}" data-observation-scope="${esc(JSON.stringify([options.observationProject || data.projectId || null, selected.key]))}"><header class="work-task-header"><div class="work-task-navigation">${back}<span class="work-meta">${esc(selected.kind)} · ${esc(selected.host || 'Host not linked')}</span><button type="button" data-work-switch>Switch task</button><button type="button" data-work-previous${rows.findIndex(e => e.key === selected.key) > 0 ? '' : ' disabled'} aria-label="Previous task in current filter">Previous</button><button type="button" data-work-next${rows.findIndex(e => e.key === selected.key) >= 0 && rows.findIndex(e => e.key === selected.key) < rows.length - 1 ? '' : ' disabled'} aria-label="Next task in current filter">Next</button></div><h2>${title}</h2><p>${esc(phaseLabel(selected))}</p></header>${tabs}${feedback}${tab === 'overview' ? '' : observation}<div id="work-detail-panel" role="tabpanel" aria-labelledby="work-tab-${tab}" tabindex="0">${detail}</div></section>`;
|
|
@@ -495,6 +573,7 @@
|
|
|
495
573
|
const graphScroll = oldCanvas?.closest('[data-selected-work]')?.dataset.selectedWork === selectedKey && oldSvg?.dataset.graphLayout === graphDirection ? { left: oldCanvas.scrollLeft, top: oldCanvas.scrollTop } : null;
|
|
496
574
|
document.getElementById('work-list').innerHTML = renderCockpit(snapshot, { search: filter, selectedKey, category, tab, canvas: !!config.canvas, direction: graphDirection, observationProject: snapshotProject });
|
|
497
575
|
document.getElementById('history-list').innerHTML = render(snapshot, true, filter);
|
|
576
|
+
hydrateReadiness();
|
|
498
577
|
if (graphScroll) {
|
|
499
578
|
const canvas = document.querySelector?.('.execution-graph-canvas'), svg = canvas?.querySelector('svg');
|
|
500
579
|
if (svg && Number.isFinite(oldZoom) && oldZoom > 0) { const bounds = svg.viewBox.baseVal; svg.dataset.zoom = String(oldZoom); svg.setAttribute('width', String(bounds.width * oldZoom)); svg.setAttribute('height', String(bounds.height * oldZoom)); canvas.scrollLeft = graphScroll.left; canvas.scrollTop = graphScroll.top; }
|
|
@@ -531,6 +610,7 @@
|
|
|
531
610
|
document.getElementById('work-allow-row').hidden = event.target.value !== 'codex';
|
|
532
611
|
document.getElementById('work-command').textContent = ''; status('');
|
|
533
612
|
});
|
|
613
|
+
document.getElementById('work-list').addEventListener('click', readinessClick);
|
|
534
614
|
for (const id of ['work-list', 'history-list']) document.getElementById(id).addEventListener('click', event => {
|
|
535
615
|
if (config.canvas && snapshotProject !== config.project()) return;
|
|
536
616
|
const pageButton = event.target.closest('[data-host-graph-next]');
|
|
@@ -578,5 +658,5 @@
|
|
|
578
658
|
});
|
|
579
659
|
setInterval(() => { if (!document.hidden && options.visible()) refresh(); }, 10000);
|
|
580
660
|
}
|
|
581
|
-
window.GctoWork = { bind, refresh, reset, leaveView, parseRoute, navigateRoute, render, renderCockpit, renderExecutionGraph, commandFor, publicationCommand, getSnapshot() { return snapshot; }, showCompleted() { category = 'completed'; selectedKey = null; tab = 'overview'; notifyView(); paint(); }, search(value) { filter = value; if (config?.canvas) { if (!selectedKey) changeWorkspace(); } else paint(); } };
|
|
661
|
+
window.GctoWork = { bind, refresh, reset, leaveView, parseRoute, navigateRoute, render, renderCockpit, renderReadiness, renderExecutionGraph, commandFor, publicationCommand, getSnapshot() { return snapshot; }, showCompleted() { category = 'completed'; selectedKey = null; tab = 'overview'; notifyView(); paint(); }, search(value) { filter = value; if (config?.canvas) { if (!selectedKey) changeWorkspace(); } else paint(); } };
|
|
582
662
|
})();
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32.png" />
|
|
24
24
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16.png" />
|
|
25
25
|
<link rel="shortcut icon" href="/assets/favicon.ico" />
|
|
26
|
+
<link rel="manifest" href="/manifest.webmanifest" />
|
|
27
|
+
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png" />
|
|
26
28
|
<link href="/assets/fonts/fonts.css" rel="stylesheet" />
|
|
27
29
|
<link href="/assets/admin-shell.css" rel="stylesheet" />
|
|
28
30
|
<script src="/assets/vendor/marked.min.js"></script>
|
|
@@ -95,6 +97,7 @@
|
|
|
95
97
|
--focus-ring: #00d97e;
|
|
96
98
|
--rail-ok-bg: rgba(0, 217, 126, 0.12);
|
|
97
99
|
--rail-fail-bg: rgba(255, 84, 102, 0.12);
|
|
100
|
+
--rdy-fail-bg: rgba(255, 84, 102, 0.06);
|
|
98
101
|
--surface-drawer: #0f1411;
|
|
99
102
|
|
|
100
103
|
--accent: #00d97e;
|
|
@@ -217,6 +220,7 @@
|
|
|
217
220
|
--surface-translucent: rgba(255, 255, 255, 0.72);
|
|
218
221
|
--rail-ok-bg: rgba(10, 125, 77, 0.12);
|
|
219
222
|
--rail-fail-bg: rgba(196, 48, 48, 0.12);
|
|
223
|
+
--rdy-fail-bg: rgba(196, 48, 48, 0.05);
|
|
220
224
|
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
221
225
|
--shadow-card-hover: 0 1px 3px rgba(0, 0, 0, 0.12), 0 8px 24px rgba(0, 168, 98, 0.08);
|
|
222
226
|
--drawer-shadow: 0 16px 32px rgba(0, 0, 0, 0.18);
|
|
@@ -668,6 +672,16 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
668
672
|
display: flex; align-items: center; transition: border-color .15s, color .15s;
|
|
669
673
|
}
|
|
670
674
|
.btn-bell:hover { border-color: var(--border-strong); color: var(--text); }
|
|
675
|
+
/* Install app: shown only after the browser fires beforeinstallprompt, hidden in the
|
|
676
|
+
installed window (display-mode: standalone). */
|
|
677
|
+
.btn-install {
|
|
678
|
+
display: none; align-items: center; gap: 6px; padding: 6px 10px; cursor: pointer;
|
|
679
|
+
border: 1px solid var(--accent); border-radius: 0; background: var(--accent-soft);
|
|
680
|
+
color: var(--text); font: inherit; font-size: var(--fs-small); font-weight: 500; white-space: nowrap;
|
|
681
|
+
}
|
|
682
|
+
.btn-install.on { display: flex; }
|
|
683
|
+
.btn-install:hover { background: var(--accent-strong); }
|
|
684
|
+
@media (display-mode: standalone) { .btn-install.on { display: none; } }
|
|
671
685
|
.btn-bell-badge {
|
|
672
686
|
position: absolute; top: -5px; right: -5px;
|
|
673
687
|
background: var(--accent); color: var(--on-accent);
|
|
@@ -2963,6 +2977,7 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
2963
2977
|
.notif-row .emoji { font-size: 16px; flex-shrink: 0; }
|
|
2964
2978
|
.notif-row strong { color: var(--text); margin-right: 4px; }
|
|
2965
2979
|
.notif-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
|
|
2980
|
+
.notif-new { font-family: var(--mono); font-size: var(--fs-eyebrow); color: var(--accent-text); border: 1px solid var(--accent-text); padding: 1px 6px; margin-left: 4px; }
|
|
2966
2981
|
|
|
2967
2982
|
.toggle {
|
|
2968
2983
|
width: 38px; height: 22px;
|
|
@@ -3390,6 +3405,57 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
3390
3405
|
.work-meta { color: var(--text2); font-size: var(--fs-caption); }
|
|
3391
3406
|
.work-card [data-work-detail="evidence"] dt { margin-top: 12px; font-weight: 600; }
|
|
3392
3407
|
.work-card [data-work-detail="evidence"] dd { margin: 4px 0 12px; color: var(--text2); font-size: var(--fs-body); overflow-wrap: anywhere; }
|
|
3408
|
+
.rdy { margin: 18px 0 16px; border: 1px solid var(--border-strong); border-radius: 12px; overflow: hidden; }
|
|
3409
|
+
.rdy-head { display: flex; align-items: center; gap: 14px; padding: 16px 20px; background: var(--bg-muted); flex-wrap: wrap; }
|
|
3410
|
+
.rdy-count { width: 36px; height: 36px; border-radius: 50%; background: var(--p0-fg); color: var(--bg-card); display: flex; align-items: center; justify-content: center; font-weight: 600; flex-shrink: 0; }
|
|
3411
|
+
.rdy[data-ready="true"] .rdy-count { background: var(--accent-text); }
|
|
3412
|
+
.rdy-title { flex: 1; min-width: 220px; }
|
|
3413
|
+
.work-page .rdy-title h2, .rdy-title h2 { margin: 0; font-size: var(--fs-title-s); font-weight: 600; }
|
|
3414
|
+
.rdy-sub { font-size: var(--fs-small); color: var(--text2); margin-top: 2px; }
|
|
3415
|
+
.rdy-note { font-size: var(--fs-small); color: var(--text2); max-width: 300px; }
|
|
3416
|
+
.rdy-narrow { display: none; }
|
|
3417
|
+
.rdy-rows { list-style: none; margin: 0; padding: 0; font-size: var(--fs-body); display: flex; flex-direction: column; }
|
|
3418
|
+
.rdy-group { display: none; }
|
|
3419
|
+
.rdy-row { display: flex; gap: 12px; align-items: center; padding: 12px 20px; border-top: 1px solid var(--border); flex-wrap: wrap; }
|
|
3420
|
+
.rdy-row[data-state="fail"], .rdy-row[data-state="not-read"] { background: var(--rdy-fail-bg); }
|
|
3421
|
+
.rdy-mark { width: 22px; font-weight: 600; color: var(--text2); }
|
|
3422
|
+
.rdy-row[data-state="pass"] .rdy-mark { color: var(--accent-text); }
|
|
3423
|
+
.rdy-row[data-state="fail"] .rdy-mark, .rdy-row[data-state="not-read"] .rdy-mark { color: var(--status-blocked-ink); }
|
|
3424
|
+
.rdy-label { width: 170px; font-weight: 500; }
|
|
3425
|
+
.rdy-detail { flex: 1; color: var(--text2); min-width: 200px; }
|
|
3426
|
+
.rdy-queue { color: var(--absent-warn-fg); font-weight: 500; }
|
|
3427
|
+
.rdy-link { font-size: var(--fs-small); color: var(--text); text-decoration: underline; background: none; border: 0; padding: 0; font-family: inherit; cursor: pointer; }
|
|
3428
|
+
.rdy-btn { height: 34px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--bg-card); color: var(--text); font: inherit; font-size: var(--fs-small); cursor: pointer; }
|
|
3429
|
+
.rdy-btn:disabled { color: var(--text2); cursor: default; }
|
|
3430
|
+
.rdy-foot { padding: 10px 20px; border-top: 1px solid var(--border); font-size: var(--fs-caption); color: var(--text2); }
|
|
3431
|
+
.rdy-ok { margin: 16px 0; border: 1px solid var(--accent-text); border-radius: 12px; padding: 14px 20px; display: flex; gap: 14px; align-items: center; flex-wrap: wrap; font-size: var(--fs-body); }
|
|
3432
|
+
.rdy-ok-mark { width: 32px; height: 32px; border-radius: 50%; background: var(--accent-text); color: var(--bg-card); display: flex; align-items: center; justify-content: center; font-weight: 600; }
|
|
3433
|
+
.rdy-ok b { font-weight: 600; flex: 1; min-width: 200px; }
|
|
3434
|
+
.rdy-ok code { font-family: var(--mono); font-size: var(--fs-caption); background: var(--bg-muted); padding: 8px 10px; border-radius: 6px; overflow-wrap: anywhere; }
|
|
3435
|
+
@media (max-width: 600px) {
|
|
3436
|
+
.rdy { margin: 12px 0; }
|
|
3437
|
+
.rdy-wide { display: none; }
|
|
3438
|
+
.rdy-narrow { display: inline; }
|
|
3439
|
+
.rdy-head { flex-direction: column; align-items: stretch; gap: 10px; padding: 14px; }
|
|
3440
|
+
.rdy-title { min-width: 0; }
|
|
3441
|
+
.rdy-count { width: 32px; height: 32px; }
|
|
3442
|
+
.rdy-title h2 { font-size: var(--fs-title-s); }
|
|
3443
|
+
.rdy-note, .rdy-sub { font-size: var(--fs-caption); max-width: none; }
|
|
3444
|
+
.rdy-group { display: block; order: 0; padding: 10px 14px; font-size: var(--fs-caption); font-weight: 600; color: var(--p0-fg); border-top: 1px solid var(--border); }
|
|
3445
|
+
.rdy-group[data-group="passed"] { order: 2; color: var(--accent-text); }
|
|
3446
|
+
.rdy-row { order: 3; padding: 10px 14px; font-size: var(--fs-small); color: var(--text2); gap: 4px; flex-wrap: nowrap; }
|
|
3447
|
+
.rdy-row .rdy-mark { width: auto; margin-right: 2px; }
|
|
3448
|
+
.rdy-row .rdy-label { width: auto; font-weight: 400; }
|
|
3449
|
+
.rdy-row:not([data-state="fail"]):not([data-state="not-read"]) .rdy-label::after { content: " ·"; }
|
|
3450
|
+
.rdy-row:not([data-state="fail"]):not([data-state="not-read"]) .rdy-detail { min-width: 0; }
|
|
3451
|
+
.rdy-row:not([data-state="fail"]):not([data-state="not-read"]) .rdy-link, .rdy-row:not([data-state="fail"]):not([data-state="not-read"]) .rdy-btn { display: none; }
|
|
3452
|
+
.rdy-row[data-state="fail"], .rdy-row[data-state="not-read"] { order: 1; flex-wrap: wrap; padding: 12px 14px; gap: 8px; font-size: var(--fs-body); color: var(--text); }
|
|
3453
|
+
.rdy-row[data-state="fail"] .rdy-label, .rdy-row[data-state="not-read"] .rdy-label { font-weight: 500; flex: 1; }
|
|
3454
|
+
.rdy-row[data-state="fail"] .rdy-detail, .rdy-row[data-state="not-read"] .rdy-detail { flex: 0 0 100%; min-width: 0; font-size: var(--fs-small); }
|
|
3455
|
+
.rdy-row[data-state="fail"] .rdy-btn, .rdy-row[data-state="not-read"] .rdy-btn { flex: 0 0 100%; height: 44px; }
|
|
3456
|
+
.rdy-row[data-state="fail"] .rdy-link, .rdy-row[data-state="not-read"] .rdy-link { min-height: 44px; display: flex; align-items: center; }
|
|
3457
|
+
.rdy-foot { display: none; }
|
|
3458
|
+
}
|
|
3393
3459
|
.work-warning { color: var(--absent-warn-fg); background: var(--bg-card); border: 1px solid var(--absent-warn-fg); padding: 12px; }
|
|
3394
3460
|
.work-page pre { font-weight: 400; white-space: pre-wrap; overflow-wrap: anywhere; margin: 12px 0; }
|
|
3395
3461
|
#work-compose textarea, #work-compose input, #work-compose select { display: block; width: 100%; margin: 8px 0 12px; padding: 8px; background: var(--bg-muted); color: var(--text); border: 1px solid var(--border-strong); border-radius: 4px; }
|
|
@@ -3534,6 +3600,10 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
3534
3600
|
(#topbar-bell, opened the drawer) are deleted as top-level surfaces
|
|
3535
3601
|
here — great_cto-ki1x.5. Their panels/functions are untouched for
|
|
3536
3602
|
.11 to re-wire as Settings rows; nothing here calls them anymore. -->
|
|
3603
|
+
<button class="btn-install" id="install-app-btn" type="button" onclick="installBoardApp()" title="Install the board as an app: own window and Dock icon">
|
|
3604
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 3v12"/><path d="M7 10l5 5 5-5"/><path d="M5 21h14"/></svg>
|
|
3605
|
+
<span class="btn-label">Install app</span>
|
|
3606
|
+
</button>
|
|
3537
3607
|
<button class="btn-bell" id="board-theme-btn" onclick="toggleBoardTheme()" title="Toggle light / dark theme" aria-label="Toggle theme"><svg class="ico-moon" viewBox="0 0 16 16" aria-hidden="true"><path d="M13.5 9.5A6 6 0 0 1 6.5 2.5a6 6 0 1 0 7 7z"></path></svg><svg class="ico-sun" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3"></circle><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1 1M11.6 11.6l1 1M3.4 12.6l1-1M11.6 4.4l1-1"></path></svg></button>
|
|
3538
3608
|
<button class="btn-bell" id="topbar-settings-btn" data-tab="settings" onclick="switchTab('settings', this)" title="Settings" aria-label="Settings" style="gap:6px;padding:6px 10px;">
|
|
3539
3609
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
|
@@ -4051,6 +4121,9 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
4051
4121
|
<label class="notif-row"><input type="checkbox" data-trigger="gate.blocked"> <span class="emoji">🛡️</span><strong>Security BLOCKED</strong> — security-officer rejected a merge</label>
|
|
4052
4122
|
<label class="notif-row"><input type="checkbox" data-trigger="cost.threshold"> <span class="emoji">💸</span><strong>Budget alert</strong> — LLM spend > 80% / 100% of monthly cap</label>
|
|
4053
4123
|
<label class="notif-row"><input type="checkbox" data-trigger="digest.weekly"> <span class="emoji">📊</span><strong>Weekly digest</strong> — Friday 09:00 DORA recap</label>
|
|
4124
|
+
<label class="notif-row"><input type="checkbox" data-trigger="agent.blocked"> <span class="emoji">✋</span><strong>Agent blocked</strong> — a session is waiting for your input <span class="notif-new">NEW</span></label>
|
|
4125
|
+
<label class="notif-row"><input type="checkbox" data-trigger="gate.local_red"> <span class="emoji">🔴</span><strong>Local gate red</strong> — a ci-local run finished with failures <span class="notif-new">NEW</span></label>
|
|
4126
|
+
<label class="notif-row"><input type="checkbox" data-trigger="gate.waiting"> <span class="emoji">⏳</span><strong>Gate waiting now</strong> — at once, not after 2h <span class="notif-new">NEW</span></label>
|
|
4054
4127
|
</div>
|
|
4055
4128
|
|
|
4056
4129
|
<div class="cta-row" style="margin-top:24px;display:flex;gap:10px;flex-wrap:wrap">
|
|
@@ -4080,7 +4153,7 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
4080
4153
|
</div>
|
|
4081
4154
|
<div id="push-status" style="margin-top:10px;font-size: var(--fs-small);font-family:var(--mono);color:var(--text3)"></div>
|
|
4082
4155
|
<div class="share-note" style="margin-top:16px">
|
|
4083
|
-
Push subscriptions are stored locally in <code>~/.great_cto/push-subscriptions.json</code>. Notifications fire for the same
|
|
4156
|
+
Push subscriptions are stored locally in <code>~/.great_cto/push-subscriptions.json</code>. Notifications fire for the same 8 triggers as email alerts; the three marked NEW only when ticked there.
|
|
4084
4157
|
</div>
|
|
4085
4158
|
</div>
|
|
4086
4159
|
|
|
@@ -10591,8 +10664,46 @@ async function _disablePush() {
|
|
|
10591
10664
|
}
|
|
10592
10665
|
}
|
|
10593
10666
|
|
|
10667
|
+
// ── Install app (PWA) ──────────────────────────────────────────────────────────
|
|
10668
|
+
// The button appears only when the browser offers installation (Chrome/Edge fire
|
|
10669
|
+
// beforeinstallprompt once the manifest is valid). Safari has no such event, so
|
|
10670
|
+
// the button stays hidden there. Once installed, the board runs in its own
|
|
10671
|
+
// window (display-mode: standalone) and the button never shows.
|
|
10672
|
+
let _installPrompt = null;
|
|
10673
|
+
function _installBtn() { return document.getElementById('install-app-btn'); }
|
|
10674
|
+
function _isStandalone() {
|
|
10675
|
+
try { return window.matchMedia('(display-mode: standalone)').matches || navigator.standalone === true; }
|
|
10676
|
+
catch { return false; }
|
|
10677
|
+
}
|
|
10678
|
+
function initInstallApp() {
|
|
10679
|
+
window.addEventListener('beforeinstallprompt', (e) => {
|
|
10680
|
+
e.preventDefault();
|
|
10681
|
+
_installPrompt = e;
|
|
10682
|
+
const btn = _installBtn();
|
|
10683
|
+
if (btn && !_isStandalone()) btn.classList.add('on');
|
|
10684
|
+
});
|
|
10685
|
+
window.addEventListener('appinstalled', () => {
|
|
10686
|
+
_installPrompt = null;
|
|
10687
|
+
const btn = _installBtn();
|
|
10688
|
+
if (btn) btn.classList.remove('on');
|
|
10689
|
+
showToast('Board installed as an app', 'success', 3000);
|
|
10690
|
+
});
|
|
10691
|
+
}
|
|
10692
|
+
async function installBoardApp() {
|
|
10693
|
+
if (!_installPrompt) return;
|
|
10694
|
+
const evt = _installPrompt;
|
|
10695
|
+
_installPrompt = null;
|
|
10696
|
+
// A prompt event can be used once: hide the button whatever the answer. If the
|
|
10697
|
+
// user dismissed it, the browser fires beforeinstallprompt again later and the
|
|
10698
|
+
// button comes back with a fresh event.
|
|
10699
|
+
_installBtn()?.classList.remove('on');
|
|
10700
|
+
evt.prompt();
|
|
10701
|
+
try { await evt.userChoice; } catch { /* nothing to undo */ }
|
|
10702
|
+
}
|
|
10703
|
+
|
|
10594
10704
|
init();
|
|
10595
10705
|
initPush();
|
|
10706
|
+
initInstallApp();
|
|
10596
10707
|
loadNotifHistory();
|
|
10597
10708
|
initPeriodChips(); // attaches click handlers + highlights active chip
|
|
10598
10709
|
// Apply persisted period to labels on first paint
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "great_cto board",
|
|
3
|
+
"short_name": "great_cto",
|
|
4
|
+
"description": "Local board for great_cto: work, gates, decisions and agent activity.",
|
|
5
|
+
"id": "/",
|
|
6
|
+
"start_url": "/",
|
|
7
|
+
"scope": "/",
|
|
8
|
+
"display": "standalone",
|
|
9
|
+
"background_color": "#0a0e0c",
|
|
10
|
+
"theme_color": "#0a0e0c",
|
|
11
|
+
"icons": [
|
|
12
|
+
{ "src": "/assets/icon-192.png", "sizes": "192x192", "type": "image/png" },
|
|
13
|
+
{ "src": "/assets/icon-512.png", "sizes": "512x512", "type": "image/png" },
|
|
14
|
+
{ "src": "/assets/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -37,7 +37,7 @@ async function handlePush() {
|
|
|
37
37
|
body,
|
|
38
38
|
tag,
|
|
39
39
|
// icon may not exist — browsers handle missing icon gracefully
|
|
40
|
-
icon: `${BOARD_ORIGIN}/assets/
|
|
40
|
+
icon: `${BOARD_ORIGIN}/assets/icon-192.png`,
|
|
41
41
|
badge: `${BOARD_ORIGIN}/assets/favicon-32.png`,
|
|
42
42
|
data: {
|
|
43
43
|
url: `${BOARD_ORIGIN}/`,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"note": "API routes with no test referencing them. Shrink only: add a test, then remove the line. See docs/testing/BOARD-TEST-STRATEGY.md.",
|
|
3
|
+
"measured": "19 of 57 routes",
|
|
4
|
+
"untested": [
|
|
5
|
+
"/api/agent-budgets",
|
|
6
|
+
"/api/agents/",
|
|
7
|
+
"/api/change-tier",
|
|
8
|
+
"/api/gate-tiers",
|
|
9
|
+
"/api/memory",
|
|
10
|
+
"/api/memory-pattern",
|
|
11
|
+
"/api/notif-history",
|
|
12
|
+
"/api/notif-history/read",
|
|
13
|
+
"/api/notifications",
|
|
14
|
+
"/api/portfolio",
|
|
15
|
+
"/api/push/subscribe",
|
|
16
|
+
"/api/push/vapid-key",
|
|
17
|
+
"/api/receipt",
|
|
18
|
+
"/api/scores",
|
|
19
|
+
"/api/session-search",
|
|
20
|
+
"/api/sessions",
|
|
21
|
+
"/api/sessions/",
|
|
22
|
+
"/api/stand-downs",
|
|
23
|
+
"/api/views"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -105,7 +105,8 @@ const server = http.createServer(async (req, res) => {
|
|
|
105
105
|
// signal to a prober about what exists outside PUBLIC.
|
|
106
106
|
if (isInsideDir(PUBLIC, fullPath) && fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
107
107
|
const ext = path.extname(fullPath);
|
|
108
|
-
const mime = { '.html': 'text/html', '.css': 'text/css', '.js': 'text/javascript', '.svg': 'image/svg+xml'
|
|
108
|
+
const mime = { '.html': 'text/html', '.css': 'text/css', '.js': 'text/javascript', '.svg': 'image/svg+xml',
|
|
109
|
+
'.png': 'image/png', '.ico': 'image/x-icon', '.webmanifest': 'application/manifest+json' };
|
|
109
110
|
// HTML must never cache — board UI is iterated daily and stale layouts
|
|
110
111
|
// hide new features (period selector, push toggle, etc.) until hard refresh
|
|
111
112
|
const headers = { 'Content-Type': mime[ext] || 'text/plain' };
|
|
@@ -186,6 +187,12 @@ server.listen(PORT, HOST, () => {
|
|
|
186
187
|
|
|
187
188
|
server.on('error', e => {
|
|
188
189
|
if (e.code === 'EADDRINUSE') {
|
|
190
|
+
// A workspace must not defer: the board already on this port belongs to another
|
|
191
|
+
// workspace, and its verdicts are not the ones this operator is looking at.
|
|
192
|
+
if (process.env.GREAT_CTO_WORKSPACE_PORT === String(PORT)) {
|
|
193
|
+
log.error(`Port ${PORT} is taken and this workspace was given it. Not attaching to another board.`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
189
196
|
log.info(`Port ${PORT} in use — board already running at http://localhost:${PORT}`);
|
|
190
197
|
} else {
|
|
191
198
|
log.error(e);
|