-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathcapo.js
More file actions
3 lines (3 loc) · 25.1 KB
/
capo.js
File metadata and controls
3 lines (3 loc) · 25.1 KB
1
2
3
(()=>{let e={META:10,TITLE:9,PRECONNECT:8,ASYNC_SCRIPT:7,IMPORT_STYLES:6,SYNC_SCRIPT:5,SYNC_STYLES:4,PRELOAD:3,DEFER_SCRIPT:2,PREFETCH_PRERENDER:1,OTHER:0},t={META:function(e,t){let n=t.getTagName(e);if("base"===n)return!0;if("meta"!==n)return!1;if(t.hasAttribute(e,"charset"))return!0;let r=t.getAttribute(e,"name");if(r&&"viewport"===r.toLowerCase())return!0;let a=t.getAttribute(e,"http-equiv");if(a){let e=a.toLowerCase();return i.includes(e)}return!1},TITLE:function(e,t){return"title"===t.getTagName(e)},PRECONNECT:function(e,t){if("link"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"rel");return i?.toLowerCase()==="preconnect"},ASYNC_SCRIPT:function(e,t){return"script"===t.getTagName(e)&&t.hasAttribute(e,"src")&&t.hasAttribute(e,"async")},IMPORT_STYLES:function(e,t){return"style"===t.getTagName(e)&&/@import/.test(t.getTextContent(e))},SYNC_SCRIPT:function(e,t){if("script"!==t.getTagName(e)||t.hasAttribute(e,"src")&&t.hasAttribute(e,"defer"))return!1;if(t.hasAttribute(e,"src")){let i=t.getAttribute(e,"type");if(i&&"module"===i.toLowerCase())return!1}if(t.hasAttribute(e,"src")&&t.hasAttribute(e,"async"))return!1;let i=t.getAttribute(e,"type");return!(i&&i.toLowerCase().includes("json"))},SYNC_STYLES:function(e,t){let i=t.getTagName(e);if("style"===i)return!0;if("link"===i){let i=t.getAttribute(e,"rel");return i?.toLowerCase()==="stylesheet"}return!1},PRELOAD:function(e,t){if("link"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"rel");if(!i)return!1;let n=i.toLowerCase();return"preload"===n||"modulepreload"===n},DEFER_SCRIPT:function(e,t){if("script"!==t.getTagName(e)||!t.hasAttribute(e,"src"))return!1;if(t.hasAttribute(e,"defer"))return!0;let i=t.getAttribute(e,"type");return!!i&&"module"===i.toLowerCase()&&!t.hasAttribute(e,"async")},PREFETCH_PRERENDER:function(e,t){if("link"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"rel");if(!i)return!1;let n=i.toLowerCase();return"prefetch"===n||"dns-prefetch"===n||"prerender"===n}},i=["accept-ch","content-security-policy","content-type","default-style","delegate-ch","origin-trial","x-dns-prefetch-control"],n=new Set(["base","link","meta","noscript","script","style","template","title"]);function r(e,t,i,n){let r=n.getChildren(e);for(let e of r){if(e===i)continue;let r=n.getTagName(e);if("link"===r){let i=n.getAttribute(e,"rel");if(i&&/\b(preload|modulepreload)\b/i.test(i))continue;let r=n.getAttribute(e,"href");if(r===t)return e}if("script"===r){let i=n.getAttribute(e,"src");if(i===t)return e}}return null}class a{isElement(e){throw Error("isElement() not implemented")}getTagName(e){throw Error("getTagName() not implemented")}getAttribute(e,t){throw Error("getAttribute() not implemented")}hasAttribute(e,t){throw Error("hasAttribute() not implemented")}getAttributeNames(e){throw Error("getAttributeNames() not implemented")}getTextContent(e){throw Error("getTextContent() not implemented")}getChildren(e){throw Error("getChildren() not implemented")}getParent(e){throw Error("getParent() not implemented")}getSiblings(e){throw Error("getSiblings() not implemented")}getLocation(e){return null}stringify(e){throw Error("stringify() not implemented")}}class s extends a{isElement(e){return!!e&&1===e.nodeType}getTagName(e){return e&&e.tagName?e.tagName.toLowerCase():""}getAttribute(e,t){return e&&"function"==typeof e.getAttribute?e.getAttribute(t):null}hasAttribute(e,t){return!!e&&"function"==typeof e.hasAttribute&&e.hasAttribute(t)}getAttributeNames(e){return e&&"function"==typeof e.getAttributeNames?e.getAttributeNames():[]}getTextContent(e){return e&&e.textContent||""}getChildren(e){return e&&e.children?Array.from(e.children):[]}getParent(e){return e&&e.parentElement||null}getSiblings(e){if(!e)return[];let t=e.parentElement;return t?Array.from(t.children).filter(t=>t!==e):[]}getLocation(e){return null}stringify(e){if(!e||!e.nodeName)return"[invalid node]";let t=this.getTagName(e),i=this.getAttributeNames(e);if(0===i.length)return`<${t}>`;let n=i.map(t=>{let i=this.getAttribute(e,t),n=i?i.replace(/"/g,"""):"";return`${t}="${n}"`}).join(" ");return`<${t} ${n}>`}}function o(e){return[`oklch(5% .1 ${e})`,`oklch(13% .2 ${e})`,`oklch(25% .2 ${e})`,`oklch(35% .25 ${e})`,`oklch(50% .27 ${e})`,`oklch(67% .31 ${e})`,`oklch(72% .25 ${e})`,`oklch(80% .2 ${e})`,`oklch(90% .1 ${e})`,`oklch(99% .05 ${e})`,"#ccc"]}let l=["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2","#cccccc"],u=o(320),c=o(200),d={DEFAULT:l,PINK:u,BLUE:c};class h{constructor(e,t,i=window.console){this.document=e,this.options=t,this.console=i,this.isStaticHead=!1,this.head=null}async init(){if(!this.head){if(this.options.prefersDynamicAssessment()){this.head=this.document.querySelector("head");return}try{let e=await this.getStaticHTML();e=e.replace(/(\<\/?)(head)/gi,"$1static-head");let t=this.document.implementation.createHTMLDocument("New Document");t.documentElement.innerHTML=e,this.head=t.querySelector("static-head"),this.head?this.isStaticHead=!0:this.head=this.document.head}catch(e){this.console.error(`${this.options.loggingPrefix}An exception occurred while getting the static <head>:`,e),this.head=this.document.head}this.isStaticHead||this.console.warn(`${this.options.loggingPrefix}Unable to parse the static (server-rendered) <head>. Falling back to document.head`,this.head)}}async getStaticHTML(){let e=this.document.location.href,t=await fetch(e);return await t.text()}getHead(){return this.head}stringifyElement(e){return e.getAttributeNames().reduce((t,i)=>t+=`[${CSS.escape(i)}=${JSON.stringify(e.getAttribute(i))}]`,e.nodeName)}getLoggableElement(e){if(!this.isStaticHead)return e;let t=this.stringifyElement(e),i=Array.from(this.document.head.querySelectorAll(t));if(0==i.length)return e;if(1==i.length)return i[0];let n=this.document.createElement("div"),r=this.document.createElement("div");r.innerHTML=e.innerHTML;let a=i.find(e=>(n.innerHTML=e.innerHTML,n.innerHTML==r.innerHTML));return a||e}createElementFromSelector(e){let t=e.match(/^[A-Za-z]+/)[0];if(!t)return;let i=document.createElement(t),n=e.match(/\[([A-Za-z-]+)="([^"]+)"\]/g)||[];return n.forEach(e=>{e=e.slice(1,-1);let t=e.indexOf("="),n=e.slice(0,t),r=e.slice(t+1).slice(1,-1);i.setAttribute(n,r)}),i}logAnalysis(e){let t=this.getHead(),i=e.weights.map(t=>{let i=e.customValidations.find(e=>e.element===t.element);return{element:t.element,weight:t.weight,isValid:!i,customValidations:i||{}}});this.logValidationWarnings(e.validationWarnings),e.customValidations.forEach(e=>{e.warnings.length>0&&this.console.warn(`${this.options.loggingPrefix}${e.warnings[0]}`,e.element,e.payload||"")}),this.visualizeHead("Actual",t,i);let n=[...i].sort((e,t)=>t.weight-e.weight),r=t.cloneNode(!1);return n.forEach(({element:e})=>{e&&r.appendChild(e.cloneNode(!0))}),this.visualizeHead("Sorted",r,n),i}logElementFromSelector({weight:e,selector:t,innerHTML:i,isValid:n,customValidations:r={}}){e=+e;let a=this.getElementVisualization(e,n),s=this.createElementFromSelector(t);s.innerHTML=i,s=this.getLoggableElement(s),this.logElement({viz:a,weight:e,element:s,isValid:n,customValidations:r})}logElement({viz:e,weight:t,element:i,isValid:n,customValidations:r={},omitPrefix:a=!1}){a||(e.visual=`${this.options.loggingPrefix}${e.visual}`);let s="log",o=i.cloneNode(!1);o.innerHTML="";let l=[e.visual,e.style,t+1,o];if(!this.options.isValidationEnabled()){this.console[s](...l);return}let{payload:u,warnings:c}=r;u&&("string"==typeof u.expiry&&(u.expiry=new Date(u.expiry)),l.push(u)),c?.length?(s="warn",l.push("\n"+c.map(e=>` ❌ ${e}`).join("\n"))):!n&&(this.options.prefersDynamicAssessment()||this.isStaticHead)&&(s="warn",l.push(`
❌ invalid element (${i.tagName})`)),this.console[s](...l)}logValidationWarnings(e){this.options.isValidationEnabled()&&e.forEach(({warning:e,elements:t=[],element:i})=>{t=t.map(this.getLoggableElement.bind(this)),this.console.warn(`${this.options.loggingPrefix}${e}`,...t,i||"")})}getColor(e){return this.options.palette[10-e]}getHeadVisualization(e){let t="",i=[];return e.forEach(({weight:e,isValid:n})=>{t+="%c ";let r=this.getColor(e),a="padding: 5px; margin: 0 -1px; ";if(n)a+=`background-color: ${r};`;else{let e;a+=`background-image: ${r==(e="#cccccc")&&(e="red"),`repeating-linear-gradient(45deg, ${r}, ${r} 3px, ${e} 3px, ${e} 6px)`}`}i.push(a)}),{visual:t,styles:i}}getElementVisualization(e,t=!0){let i=`%c${Array(e+1).fill("█").join("")}`,n=this.getColor(e);return{visual:i,style:`color: ${n}`}}visualizeHead(e,t,i){let n=this.getHeadVisualization(i);this.console.groupCollapsed(`${this.options.loggingPrefix}${e} %chead%c order
${n.visual}`,"font-family: monospace","font-family: inherit",...n.styles),i.forEach(({weight:e,element:t,isValid:i,customValidations:n})=>{let r=this.getElementVisualization(e,i);this.logElement({viz:r,weight:e,element:t,isValid:i,customValidations:n,omitPrefix:!0})}),this.console.log(`${e} %chead%c element`,"font-family: monospace","font-family: inherit",t),this.console.groupEnd()}}class g{constructor({preferredAssessmentMode:e=g.AssessmentMode.STATIC,validation:t=!0,palette:i=l,loggingPrefix:n="Capo: "}={}){this.setPreferredAssessmentMode(e),this.setValidation(t),this.setPalette(i),this.setLoggingPrefix(n)}static get AssessmentMode(){return{STATIC:"static",DYNAMIC:"dynamic"}}static get Palettes(){return d}prefersStaticAssessment(){return this.preferredAssessmentMode===g.AssessmentMode.STATIC}prefersDynamicAssessment(){return this.preferredAssessmentMode===g.AssessmentMode.DYNAMIC}isValidationEnabled(){return this.validation}setPreferredAssessmentMode(e){if(!this.isValidAssessmentMode(e))throw Error(`Invalid option: preferred assessment mode, expected AssessmentMode.STATIC or AssessmentMode.DYNAMIC, got "${e}".`);this.preferredAssessmentMode=e}setPreferredAssessmentModeToStatic(e){let t=g.AssessmentMode.STATIC;e||(t=g.AssessmentMode.DYNAMIC),this.setPreferredAssessmentMode(t)}setValidation(e){if(!this.isValidValidation(e))throw Error(`Invalid option: validation, expected boolean, got "${e}".`);this.validation=e}setPalette(e){if(!this.isValidPalette(e))throw Error(`Invalid option: palette, expected [${Object.keys(d).join("|")}] or an array of colors, got "${e}".`);if("string"==typeof e){this.palette=d[e];return}this.palette=e}setLoggingPrefix(e){if(!this.isValidLoggingPrefix(e))throw Error(`Invalid option: logging prefix, expected string, got "${e}".`);this.loggingPrefix=e}isValidAssessmentMode(e){return Object.values(g.AssessmentMode).includes(e)}isValidValidation(e){return"boolean"==typeof e}isValidPalette(e){return"string"==typeof e?Object.keys(d).includes(e):!!Array.isArray(e)&&11===e.length&&e.every(e=>"string"==typeof e)}isValidLoggingPrefix(e){return"string"==typeof e}isPreferredPalette(e){return JSON.stringify(this.palette)==JSON.stringify(e)}valueOf(){return{preferredAssessmentMode:this.preferredAssessmentMode,validation:this.validation,palette:this.palette,loggingPrefix:this.loggingPrefix}}}async function m(i){await i.init();let a=i.getHead(),o=new s,l=function(i,a,s={}){let{includeValidation:o=!0,includeCustomValidations:l=!0}=s,u=function(i,n){let r=n.getChildren(i);return r.filter(e=>{let t=n.getTagName(e);return t&&""!==t}).map(i=>({element:i,weight:function(i,n){for(let[r,a]of Object.entries(t))if(a(i,n))return e[r];return e.OTHER}(i,n)}))}(i,a),c=o?function(e,t){let i=[],r=t.getChildren(e),a=r.filter(e=>"title"===t.getTagName(e)),s=a.length;1!=s&&i.push({ruleId:0===s?"require-title":"no-duplicate-title",warning:`Expected exactly 1 <title> element, found ${s}`,elements:a});let o=r.filter(e=>{if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"name");return i&&"viewport"===i.toLowerCase()});1!=o.length&&i.push({ruleId:0===o.length?"require-meta-viewport":"valid-meta-viewport",warning:`Expected exactly 1 <meta name=viewport> element, found ${o.length}`,elements:o});let l=r.filter(e=>"base"===t.getTagName(e)),u=l.length;return u>1&&i.push({ruleId:"no-duplicate-base",warning:`Expected at most 1 <base> element, found ${u}`,elements:l}),r.forEach(e=>{!function(e,t){let i=t.getTagName(e);return!i||""===i||n.has(i.toLowerCase())}(e,t)&&i.push({ruleId:"no-invalid-head-elements",warning:`${t.getTagName(e)} elements are not allowed in the <head>`,element:e})}),i}(i,a):[],d=l?function(e,t){let i=[],n=t.getChildren(e);for(let a of n){let n=function(e,t,i=null){let n=[];if(function(e,t){if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"http-equiv");return i?.toLowerCase()==="origin-trial"}(e,t)&&n.push(function(e,t){var i,n,r,a;let s={ruleId:"no-invalid-origin-trial",payload:null,warnings:[]},o=t.getAttribute(e,"content");try{s.payload=function(e){let t=new Uint8Array([...atob(e)].map(e=>e.charCodeAt(0))),i=new DataView(t.buffer),n=i.getUint32(65,!1),r=JSON.parse(new TextDecoder().decode(t.slice(69,69+n)));return r.expiry=new Date(1e3*r.expiry),r}(o)}catch{return s.warnings.push("Invalid origin trial token: invalid token"),s}if(s.payload.expiry<new Date&&s.warnings.push("Invalid origin trial token: expired"),"undefined"!=typeof document&&document.location&&document.location.href&&(i=s.payload.origin,n=document.location.href,new URL(i).origin!==new URL(n).origin)){let e=(r=s.payload.origin,a=document.location.href,r=new URL(r),(a=new URL(a)).host.endsWith(`.${r.host}`));e&&!s.payload.isSubdomain?s.warnings.push("Invalid origin trial token: invalid subdomain"):e||s.payload.isThirdParty||s.warnings.push("Invalid origin trial token: invalid third-party origin")}return s}(e,t)),function(e,t){if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"http-equiv");if(!i)return!1;let n=i.toLowerCase();return"content-security-policy"===n||"content-security-policy-report-only"===n}(e,t)&&n.push(function(e,t){let i=[],n=null,r=t.getAttribute(e,"http-equiv"),a=r?.toLowerCase();if("content-security-policy-report-only"===a)return i.push("CSP Report-Only is forbidden in meta tags"),{ruleId:"no-meta-csp",warnings:i,payload:n};"content-security-policy"===a&&i.push("meta CSP discouraged. See https://crbug.com/1458493.");let s=t.getAttribute(e,"content");if(!s)return i.push("Invalid CSP. The content attribute must be set."),{warnings:i,payload:n};let o=Object.fromEntries(s.split(/\s*;\s*/).map(e=>{let[t,...i]=e.split(" ");return[t,i.join(" ")]}));return(n=n??{}).directives=o,"report-uri"in o&&i.push("The report-uri directive is not supported. Use the Content-Security-Policy-Report-Only HTTP header instead."),"frame-ancestors"in o&&i.push("The frame-ancestors directive is not supported. Use the Content-Security-Policy HTTP header instead."),"sandbox"in o&&i.push("The sandbox directive is not supported. Use the Content-Security-Policy HTTP header instead."),{ruleId:"no-meta-csp",warnings:i,payload:n}}(e,t)),function(e,t){if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"http-equiv");return i?.toLowerCase()==="default-style"}(e,t)&&n.push(function(e,t){let i=[],n=null,r=t.getAttribute(e,"content");if(e.parentElement&&e.parentElement.querySelector){let t=e.parentElement.querySelector(`link[rel~="alternate" i][rel~="stylesheet" i][title="${r}"]`);r?t||(n={alternateStylesheets:Array.from(e.parentElement.querySelectorAll('link[rel~="alternate" i][rel~="stylesheet" i]'))},i.push(`This has no effect. No alternate stylesheet found having title="${r}".`)):i.push("This has no effect. The content attribute must be set to a valid stylesheet title.")}else r||i.push("This has no effect. The content attribute must be set to a valid stylesheet title.");return i.push("Even when used correctly, the default-style method of setting a preferred stylesheet results in a flash of unstyled content. Use modern CSS features like @media rules instead."),{ruleId:"no-default-style",warnings:i,payload:n}}(e,t)),function(e,t){if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"name");return i?.toLowerCase()==="viewport"}(e,t)&&n.push(function(e,t){let i=[],n=null,r=t.getSiblings(e),a=r.some(e=>{if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"name");return i?.toLowerCase()==="viewport"});if(a){let r=t.getParent(e);if(r){let a=t.getChildren(r).filter(e=>{if("meta"!==t.getTagName(e))return!1;let i=t.getAttribute(e,"name");return i?.toLowerCase()==="viewport"}),s=a.find(t=>t!==e);if(s)return n={firstMetaViewport:s},i.push("Another meta viewport element has already been declared. Having multiple viewport settings can lead to unexpected behavior."),{warnings:i,payload:n}}}let s=t.getAttribute(e,"content")?.toLowerCase();if(!s)return i.push("Invalid viewport. The content attribute must be set."),{warnings:i,payload:n};let o=Object.fromEntries(s.split(",").map(e=>{let[t,i]=e.split("=");return[t?.trim(),i?.trim()]}));if("width"in o){let e=o.width;1>Number(e)||Number(e)>1e4?i.push(`Invalid width "${e}". Numeric values must be between 1 and 10000.`):"device-width"!=e&&i.push(`Invalid width "${e}".`)}if("height"in o){let e=o.height;1>Number(e)||Number(e)>1e4?i.push(`Invalid height "${e}". Numeric values must be between 1 and 10000.`):"device-height"!=e&&i.push(`Invalid height "${e}".`)}if("initial-scale"in o){let e=Number(o["initial-scale"]);isNaN(e)&&i.push(`Invalid initial zoom level "${o["initial-scale"]}". Values must be numeric.`),(e<.1||e>10)&&i.push(`Invalid initial zoom level "${e}". Values must be between 0.1 and 10.`)}if("minimum-scale"in o){let e=Number(o["minimum-scale"]);isNaN(e)&&i.push(`Invalid minimum zoom level "${o["minimum-scale"]}". Values must be numeric.`),(e<.1||e>10)&&i.push(`Invalid minimum zoom level "${e}". Values must be between 0.1 and 10.`)}if("maximum-scale"in o){let e=Number(o["maximum-scale"]);isNaN(e)&&i.push(`Invalid maximum zoom level "${o["maximum-scale"]}". Values must be numeric.`),(e<.1||e>10)&&i.push(`Invalid maximum zoom level "${e}". Values must be between 0.1 and 10.`),e<2&&i.push(`Disabling zoom levels under 2x can cause accessibility issues. Found "${e}".`)}if("user-scalable"in o){let e=o["user-scalable"];("no"==e||"0"==e)&&i.push(`Disabling zooming can cause accessibility issues to users with visual impairments. Found "${e}".`),["0","1","yes","no"].includes(e)||i.push(`Unsupported value "${e}" found.`)}if("interactive-widget"in o){let e=o["interactive-widget"];["resizes-visual","resizes-content","overlays-content"].includes(e)||i.push(`Unsupported value "${e}" found.`)}if("viewport-fit"in o){let e=o["viewport-fit"],t=["auto","contain","cover"];t.includes(e)||i.push(`Unsupported value "${e}" found. Should be one of: ${t.join(", ")}.`)}"shrink-to-fit"in o&&i.push("The shrink-to-fit directive has been obsolete since iOS 9.2.\n See https://www.scottohara.me/blog/2018/12/11/shrink-to-fit.html");let l=new Set(["width","height","initial-scale","minimum-scale","maximum-scale","user-scalable","interactive-widget"]);return Object.keys(o).filter(e=>!l.has(e)&&"shrink-to-fit"!=e).forEach(e=>{i.push(`Invalid viewport directive "${e}".`)}),{ruleId:"valid-meta-viewport",warnings:i,payload:n}}(e,t)),function(e,t){if("meta"!==t.getTagName(e))return!1;if(t.hasAttribute(e,"charset"))return!0;let i=t.getAttribute(e,"http-equiv");return i?.toLowerCase()==="content-type"}(e,t)&&n.push(function(e,t){let i=[],n=null,r=t.hasAttribute(e,"charset"),a=t.getAttribute(e,"http-equiv"),s=a?.toLowerCase()==="content-type";if(r||s){let r=t.getSiblings(e),a=r.some(e=>{if("meta"!==t.getTagName(e))return!1;if(t.hasAttribute(e,"charset"))return!0;let i=t.getAttribute(e,"http-equiv");return i?.toLowerCase()==="content-type"});if(a){let r=t.getParent(e);if(r){let a=t.getChildren(r).filter(e=>{if("meta"!==t.getTagName(e))return!1;if(t.hasAttribute(e,"charset"))return!0;let i=t.getAttribute(e,"http-equiv");return i?.toLowerCase()==="content-type"}),s=a.find(t=>t!==e);s&&((n=n??{}).encodingDeclaration=s,i.push(`There can only be one meta-based character encoding declaration per document. Already found \`${t.stringify(s)}\`.`))}}}if(e.ownerDocument?.documentElement?.outerHTML&&e.outerHTML){let t=e.ownerDocument.documentElement.outerHTML.indexOf(e.outerHTML)+e.outerHTML.length;t>1024&&((n=n??{}).characterPosition=t,i.push(`The element containing the character encoding declaration must be serialized completely within the first 1024 bytes of the document. Found at byte ${t}.`))}let o=null;return o=r?t.getAttribute(e,"charset"):t.getAttribute(e,"content")?.match(/text\/html;\s*charset=(.*)/i)?.[1]?.trim(),o?.toLowerCase()!="utf-8"&&((n=n??{}).charset=o,i.push(`Documents are required to use UTF-8 encoding. Found "${o}".`)),i.length&&(i[i.length-1]+="\nLearn more: https://html.spec.whatwg.org/multipage/semantics.html#character-encoding-declaration"),{ruleId:"valid-charset",warnings:i,payload:n}}(e,t)),"meta"===t.getTagName(e)&&t.hasAttribute(e,"http-equiv")&&n.push(function(e,t){let i=[],n=t.getAttribute(e,"http-equiv").toLowerCase(),r=t.getAttribute(e,"content")?.toLowerCase();switch(n){case"content-security-policy":case"content-security-policy-report-only":case"origin-trial":case"content-type":case"default-style":break;case"refresh":if(!r){i.push("This doesn't do anything. The content attribute must be set. However, using refresh is discouraged.");break}r.includes("url=")?i.push("Meta auto-redirects are discouraged. Use HTTP 3XX responses instead."):i.push("Meta auto-refreshes are discouraged unless users have the ability to disable it.");break;case"x-dns-prefetch-control":"on"==r?i.push(`DNS prefetching is enabled by default. Setting it to "${r}" has no effect.`):"off"!=r?i.push(`This is a non-standard way of disabling DNS prefetching, which is a performance optimization. Found content="${r}". Use content="off" if you have a legitimate security concern, otherwise remove it.`):i.push("This is non-standard, however most browsers support disabling speculative DNS prefetching. It should still be noted that DNS prefetching is a generally accepted performance optimization and you should only disable it if you have specific security concerns.");break;case"cache-control":case"etag":case"pragma":case"expires":case"last-modified":i.push("This doesn't do anything. Use HTTP headers for any cache directives.");break;case"x-frame-options":i.push("This doesn't do anything. Use the CSP HTTP header with the frame-ancestors directive instead.");break;case"x-ua-compatible":case"content-style-type":case"content-script-type":case"imagetoolbar":case"cleartype":case"page-enter":case"page-exit":case"site-enter":case"site-exit":case"msthemecompatible":case"window-target":i.push("This doesn't do anything. It was an Internet Explorer feature and is now deprecated.");break;case"content-language":case"language":i.push("This is non-conforming. Use the html[lang] attribute instead.");break;case"set-cookie":i.push("This is non-conforming. Use the Set-Cookie HTTP header instead.");break;case"application-name":case"author":case"description":case"generator":case"keywords":case"referrer":case"theme-color":case"color-scheme":case"viewport":case"creator":case"googlebot":case"publisher":case"robots":i.push(`This doesn't do anything. Did you mean \`meta[name=${n}]\`?`);break;case"encoding":i.push("This doesn't do anything. Did you mean `meta[charset]`?");break;case"title":i.push("This doesn't do anything. Did you mean to use the `title` tag instead?");break;case"accept-ch":case"delegate-ch":i.push("This is non-standard and may not work across browsers. Use HTTP headers instead.");break;default:i.push("This is non-standard and may not work across browsers. http-equiv is not an alternative to HTTP headers.")}return{ruleId:"no-invalid-http-equiv",warnings:i}}(e,t)),function(e,t,i=null){let n=t.getTagName(e);if("link"!==n)return!1;let a=t.getAttribute(e,"rel"),s=a?.toLowerCase();if("preload"!==s&&"modulepreload"!==s)return!1;let o=t.getAttribute(e,"href");if(!o)return!1;let l=i||t.getParent(e);if(!l)return!1;let u=r(l,o,e,t);return null!=u}(e,t,i)&&n.push(function(e,t,i=null){let n=t.getAttribute(e,"href");if(!n)return{ruleId:"no-unnecessary-preload",warnings:[]};let a=i||t.getParent(e);if(!a)return{ruleId:"no-unnecessary-preload",warnings:[]};let s=r(a,n,e,t);return s?{ruleId:"no-unnecessary-preload",warnings:[`This preload has little to no effect. ${n} is already discoverable by another ${t.getTagName(s)} element.`]}:{ruleId:"no-unnecessary-preload",warnings:[]}}(e,t,i)),function(e,t){let i=t.getTagName(e);if("link"!==i)return!1;let n=t.getAttribute(e,"rel");if(n?.toLowerCase()!=="preload")return!1;let r=t.getAttribute(e,"as");return r?.toLowerCase()==="font"&&!t.hasAttribute(e,"crossorigin")}(e,t)&&n.push({ruleId:"valid-font-preload",warnings:["Font preloads must have the crossorigin attribute set, even for same-origin fonts."],payload:null}),0===n.length)return{};if(1===n.length)return n[0];let a={warnings:[],payload:{},ruleId:n[0].ruleId};return n.forEach(e=>{e.warnings&&a.warnings.push(...e.warnings),e.payload&&Object.assign(a.payload,e.payload)}),a}(a,t,e);n&&n.warnings&&n.warnings.length>0&&i.push({ruleId:n.ruleId,element:a,warnings:n.warnings,payload:n.payload})}return i}(i,a):[];return{weights:u,validationWarnings:c,customValidations:d,headElement:i}}(a,o),u=i.logAnalysis(l);return{actual:u.map(({element:e,weight:t,isValid:n,customValidations:r})=>(r?.payload?.expiry&&(r.payload.expiry=r.payload.expiry.toString()),{weight:t,color:i.getColor(t),selector:i.stringifyElement(e),innerHTML:e.innerHTML,isValid:n,customValidations:r}))}}async function p(){let{options:e}=await chrome.storage.sync.get("options");return new g(e)}!async function(){let e=await p(),t=new h(document,e),{click:i}=await chrome.storage.local.get("click");if(i)t.logElementFromSelector(JSON.parse(i)),await chrome.storage.local.remove("click");else{let e=await m(t);await chrome.storage.local.set({data:e})}}()})();