PageSourceSearch

https://toolbreezy.com/_next/static/chunks/19113-8a47ddc04b210e81.js

js toolbreezy.com collected 2026-09-24 14:57:15 UTC 51,721 bytes, 59 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[19113],{19113:(e,t,r)=>{r.r(t),r.d(t,{default:()=>er});var n=r(95155),i=r(12115),s=r(97003),a=r(90235),o=r(67001),l=r(33534),d=r(25016),c=r(81322);let u="13 August 2026",h="https://developers.google.com/search/docs/appearance/structured-data/",p=[{feature:"Product snippet and merchant listing",types:["Product","ProductGroup"],status:"live",required:["name"],oneOf:{props:["offers","review","aggregateRating"],why:"a product with no price, no review and no rating has nothing to show in a result"},recommended:["image","description","brand","sku","gtin","aggregateRating","offers"],source:h+"product"},{feature:"Review snippet",types:["Review"],status:"live",required:["itemReviewed","reviewRating","author"],recommended:["datePublished","reviewBody","publisher"],source:h+"review-snippet"},{feature:"Article, top stories and headline results",types:["Article","NewsArticle","BlogPosting","TechArticle","Report"],status:"live",required:[],requiredNote:"Google documents no strictly required property for Article. Without a headline, an image, a date and an author there is almost nothing for a result to render, so treat the recommended list as the real bar.",recommended:["headline","image","datePublished","dateModified","author"],source:h+"article"},{feature:"Recipe rich result",types:["Recipe"],status:"live",required:["name","image"],recommended:["author","datePublished","description","prepTime","cookTime","totalTime","recipeYield","recipeIngredient","recipeInstructions","aggregateRating","nutrition"],source:h+"recipe"},{feature:"Video rich result",types:["VideoObject"],status:"live",required:["name","description","thumbnailUrl","uploadDate"],recommended:["contentUrl","embedUrl","duration","expires","interactionStatistic"],source:h+"video"},{feature:"Event rich result",types:["Event","BusinessEvent","MusicEvent","SportsEvent","TheaterEvent","EducationEvent"],status:"live",required:["name","startDate","location"],requiredHints:{location:'An online event still uses location, holding "@type": "VirtualLocation" with a url, alongside eventAttendanceMode. There is no virtualLocation property to use instead.'},recommended:["description","endDate","eventAttendanceMode","eventStatus","image","offers","organizer","performer"],source:h+"event"},{feature:"Local business result",types:["LocalBusiness","Store","Restaurant","Dentist","Physician","HomeAndConstructionBusiness","ProfessionalService"],status:"live",required:["name","address"],recommended:["telephone","openingHoursSpecification","geo","url","image","priceRange","aggregateRating"],source:h+"local-business"},{feature:"Organization and knowledge panel details",types:["Organization","Corporation","OnlineStore","NGO","EducationalOrganization"],status:"live",required:[],requiredNote:"Google documents no strictly required property here. What you supply is what it can use, so a block with only a name is valid and does almost nothing.",recommended:["name","url","logo","sameAs","address","contactPoint"],source:h+"organization"},{feature:"Breadcrumb trail",types:["BreadcrumbList"],status:"live",required:["itemListElement"],recommended:[],source:h+"breadcrumb"},{feature:"Job posting result",types:["JobPosting"],status:"live",required:["title","description","datePosted","hiringOrganization"],oneOf:{props:["jobLocation","jobLocationType"],why:"either the address people work at, or TELECOMMUTE for a fully remote role"},recommended:["baseSalary","employmentType","identifier","validThrough"],source:h+"job-posting"},{feature:"Q and A result",types:["QAPage"],status:"live",required:["mainEntity"],recommended:[],source:h+"qapage"},{feature:"FAQ rich result",types:["FAQPage"],status:"retired",retiredOn:"7 May 2026",retiredNote:"Restricted in August 2023 to well known government and health sites, then withdrawn for everyone. Rich Results Test and the Search Console report dropped it in June 2026. Google still reads FAQPage markup to understand a page, so the block is not wrong, it just no longer earns a result.",required:["mainEntity"],recommended:[],source:h+"faqpage"},{feature:"HowTo rich result",types:["HowTo"],status:"retired",retiredOn:"September 2023",retiredNote:"Removed from mobile in August 2023 and from desktop in September 2023, and the documentation was withdrawn. There is no HowTo rich result on any surface.",required:["name","step"],recommended:[],source:h+"how-to"},{feature:"Sitelinks search box",types:["WebSite"],status:"retired",retiredOn:"November 2024",retiredNote:"Google deprecated the sitelinks search box. A WebSite block with a SearchAction is still valid markup and no longer produces the search f
1ield in results.",required:["url","potentialAction"],recommended:[],source:h+"sitelinks-searchbox"},{feature:"Course info rich result",types:["Course"],status:"retired",retiredOn:"June 2025",retiredNote:"Course info was one of seven features Google retired in June 2025. Course carousels on a course list page are a separate feature, so check the gallery if that is what you are building.",required:["name","description","provider"],recommended:[],source:h+"search-gallery"},{feature:"Fact check result",types:["ClaimReview"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:["claimReviewed","reviewRating","url"],recommended:[],source:h+"search-gallery"},{feature:"Estimated salary result",types:["Occupation","MonetaryAmountDistribution"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:[],recommended:[],source:h+"search-gallery"},{feature:"Learning video result",types:["LearningResource"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:[],recommended:[],source:h+"search-gallery"},{feature:"Special announcement result",types:["SpecialAnnouncement"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:[],recommended:[],source:h+"search-gallery"},{feature:"Vehicle listing result",types:["Vehicle","Car"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:[],recommended:[],source:h+"search-gallery"},{feature:"Book actions",types:["Book"],status:"retired",retiredOn:"June 2025",retiredNote:"Retired with the other six features in June 2025.",required:[],recommended:[],source:h+"search-gallery"}],m=new Map;for(let e of p)for(let t of e.types)m.has(t)||m.set(t,e);function g(e){return m.get(e)??null}let f={Offer:{required:["price","priceCurrency"],recommended:["availability","url","itemCondition"],satisfiedBy:"priceSpecification"},AggregateOffer:{required:["lowPrice","priceCurrency"],recommended:["highPrice","offerCount"]},AggregateRating:{required:["ratingValue"],recommended:["bestRating","worstRating"]},Rating:{required:["ratingValue"],recommended:["bestRating","worstRating"]},ListItem:{required:["position","name"],recommended:[]}
1,Question:{required:["name","acceptedAnswer"],recommended:[]},Answer:{required:["text"],recommended:[]},PostalAddress:{required:["streetAddress","addressLocality","addressCountry"],recommended:["postalCode","addressRegion"]},HowToStep:{required:["text"],recommended:["name","image","url"]},ImageObject:{required:["url"],recommended:["width","height"]},Person:{required:["name"],recommended:["url"]},Place:{required:["address"],recommended:["name"]},NutritionInformation:{required:["calories"],recommended:[]}},b=new Set([...p.flatMap(e=>e.types),...Object.keys(f),"WebPage","ItemList","CollectionPage","ProfilePage","AboutPage","ContactPage","SearchResultsPage","Thing","CreativeWork","MediaObject","AudioObject","Brand","Service","SearchAction","EntryPoint","GeoCoordinates","OpeningHoursSpecification","ContactPoint","MerchantReturnPolicy","OfferShippingDetails","PriceSpecification","UnitPriceSpecification","MonetaryAmount","QuantitativeValue","PropertyValue","SoftwareApplication","MobileApplication","WebApplication","ImageGallery","SiteNavigationElement","InteractionCounter","Language","Country","AdministrativeArea","DefinedTerm","Audience","Menu","MenuItem"]),y=new Set(["datePublished","dateModified","dateCreated","startDate","endDate","uploadDate","datePosted","validThrough","priceValidUntil","expires","validFrom","availabilityStarts","availabilityEnds","previousStartDate","foundingDate","birthDate","releaseDate","productionDate","expirationDate"]),x=new Set(["duration","cookTime","prepTime","totalTime","performTime","timeRequired"]),v=new Set(["url","contentUrl","embedUrl","thumbnailUrl","logo","sameAs","target","menu"]),k=new Set(["price","lowPrice","highPrice","minPrice","maxPrice"]),w=new Set([...p.flatMap(e=>[...e.required,...e.recommended,...e.oneOf?.props??[]]),...Object.values(f).flatMap(e=>[...e.required,...e.recommended]),...y,...x,...v,...k,"name","description","image","author","publisher","headline","text","about","keywords","itemListElement","mainEntity","mainEntityOfPage","acceptedA
1nswer","suggestedAnswer","answerCount","aggregateRating","review","reviewRating","reviewBody","ratingValue","ratingCount","reviewCount","bestRating","worstRating","itemReviewed","offers","availability","itemCondition","priceCurrency","priceSpecification","brand","sku","gtin","gtin13","mpn","model","color","material","size","telephone","email","address","streetAddress","addressLocality","addressRegion","postalCode","addressCountry","geo","latitude","longitude","openingHours","priceRange","servesCuisine","position","item","step","tool","supply","yield","recipeYield","recipeIngredient","recipeInstructions","recipeCategory","recipeCuisine","nutrition","calories","width","height","caption","thumbnail","contentSize","encodingFormat","inLanguage","isFamilyFriendly","hiringOrganization","jobLocation","jobLocationType","employmentType","baseSalary","identifier","applicantLocationRequirements","title","value","currency","unitText","minValue","maxValue","location","organizer","performer","eventStatus","eventAttendanceMode","contactPoint","contactType","areaServed","availableLanguage","founder","foundingLocation","numberOfEmployees","legalName","vatID","taxID","iso6523Code","duns","naics","leiCode","potentialAction","query","urlTemplate","actionPlatform","provider","claimReviewed","interactionStatistic","interactionType","userInteractionCount","uploadDate","regi
1onsAllowed","issn","game","targetUrl","weight","depth","gtin8","gtin12","gtin14","award","category","citation","startTime","endTime","alternateName","articleBody","articleSection","hasPart","isbn","genre","serialNumber","productID","additionalType","subjectOf","disambiguatingDescription","acceptsReservations","currenciesAccepted","paymentAccepted","hasMap","faxNumber","contentLocation","locationCreated","countryOfOrigin","audio","video","transcript","wordCount","articleBody","isAccessibleForFree","copyrightHolder","copyrightYear","license","creator","editor","contributor","translator","sponsor","funder","isPartOf","hasCourse"]);var N=r(42502);let S={n:"\n",t:"	",r:"\r",b:"\b",f:"\f",'"':'"',"\\":"\\","/":"/"},j=(e,t)=>`${e}.${t}`,$=(e,t)=>`${e}[${t}]`,A=e=>e.replace(/^\$\.?/,"")||"(root)";function C(e){let t=[0];for(let r=0;r<e.length;r++)"\n"===e[r]&&t.push(r+1);return e=>{let r=0,n=t.length-1,i=0;for(;r<=n;){let s=r+n>>1;(t[s]??0)<=e?(i=s,r=s+1):n=s-1}return{line:i+1,col:e-(t[i]??0)+1}}}let O={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" ","#34":'"',"#39":"'","#x27":"'","#x22":'"'};function T(e){return e.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g,(e,t)=>{let r=O[t]??O[t.toLowerCase()];if(r)return r;if("#"===t[0]){let e="x"===t[1]||"X"===t[1]?parseInt(t.slice(2),16):parseInt(t.slice(1),10);if(Number.isFinite(e)&&e>0&&e<1114112)return String.fromCodePoint(e)}return e})}function R(e,t,r,n,i){let s=r,a=n,o=[];65279===s.charCodeAt(0)&&(s=s.slice(1),a=a<0?a:a+1);let l=s.match(/^\s*(?:\/\*\s*)?<!\[CDATA\[([\s\S]*?)\]\]>(?:\s*\*\/)?\s*$/);if(l&&l[1]&&(s=l[1],a=-1,o.push("removed the CDATA wrapper around the block")),!s.trim())return null;!/[{[]/.test(s)&&/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/.test(s)&&(s=T(s),a=-1,o.push("decoded the HTML entities, the block had been copied out of a rendered source view"));let d={index:e,origin:t,text:s,offset:a,transforms:o,data:null,parsed:!1,parseError:null,repairPreview:null};try{return d.data=JSON.parse(s),d.parsed=!0,d}catch(e){d.parseError={message:e instanceof Error?e.message:"This is not valid JSON.",offset:function(e,t){if("number"==typeof e?.position&&e.position>=0)return Math.min(e.position,t);let r="string"==typeof e?.message?e.message.match(/position\s+(\d+)/i):null;return r&&r[1]?Math.min(Number(r[1]),t):0}(e,s.length)}}if(!d.parsed&&/&(quot|#34|#x22|amp|#38);/i.test(s)){let e=T(s);try{return d.data=JSON.parse(e),d.parsed=!0,d.text=e,d.offset=-1,d.parseError=null,d.transforms.push("decoded the HTML entities inside the block"),d}catch{}}try{let e=(0,N.m)(d.text);JSON.parse(e),d.repairPreview=e,i&&(d.data=JSON.parse(e),d.parsed=!0,d.text=e,d.offset=-1,d.parseError=null,d.transforms.push("repaired the JSON, so the line and column numbers below count against the repaired text"))}catch{d.repairPreview=null}return d}let q=["retired","blocked","invalid","advisory"],P=/^\d{4}-\d{2}-\d{2}$/,L=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/,F=/(Z|[+-]\d{2}:?\d{2})$/,D=/^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+(\.\d+)?S)?)?$/,M=/^\d+(\.\d+)?$/,E=/\b(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,I=/^\d{1,2}\/\d{1,2}\/\d{4}$/,J=new Set(["Organization","WebSite","BreadcrumbList","LocalBusiness","WebPage"]),z=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),B=e=>Array.isArray(e)?e:[e];function K(e){return(e.trim().split(/[/#]/).pop()??e).replace(/^schema:/i,"").trim()}function U(e){let t=e["@type"];return null==t?[]:B(t).filter(e=>"string"==typeof e&&""!==e.trim()).map(K)}function G(e){return null==e||("string"==typeof e?""===e.trim():Array.isArray(e)?0===e.length:!!z(e)&&0===Object.keys(e).length)}let W=["url","uri","link","src","s","id"];function H(e,t){let r=e;for(let e of t)if(Array.isArray(r)&&"number"==typeof e)r=r[e];else{if(!z(r)||"string"!=typeof e)return null;r=r[e]}return z(r)?r:null}p.length;var V=r(16110);let Y=[{label:"Product, missing a required part",text:`{
2  "@context": "https://schema.org",
3  "@type": "Product",
4  "name": "Cast Iron Skillet 12 inch",
5  "image": "https://example.com/skillet.jpg",
6  "description": "Pre-seasoned, oven safe to 500F.",
7  "brand": { "@type": "Brand", "name": "Fieldstone" },
8  "aggregateRating": {
9    "@type": "AggregateRating",
10    "ratingValue": "4.7",
11    "reviewCount": 0
12  },
13  "releaseDate": "March 4, 2026"
14}`},{label:"FAQ block that still validates everywhere else",text:`{
15  "@context": "https://schema.org",
16  "@type": "FAQPage",
17  "mainEntity": [
18    {
19      "@type": "Question",
20      "name": "Do you ship internationally?",
21      "acceptedAnswer": { "@type": "Answer", "text": "Yes, to 31 countries." }
22    }
23  ]
24}`},{label:"A whole page, two plugins fighting",text:`<!doctype html>
25<html>
26<head>
27  <title>Fieldstone Cookware</title>
28  <script type="application/ld+json">
29  {
30    "@context": "https://schema.org",
31    "@type": "Organization",
32    "name": "Fieldstone Cookware",
33    "url": "https://example.com",
34    "logo": "https://example.com/logo.png"
35  }
36  </script>
37  <script type="application/ld+json">
38  {
39    "@context": "https://schema.org",
40    "@type": "Organization",
41    "name": "Fieldstone",
42    "url": "/",
43    "sameAs": ["https://example.com/about"]
44  }
45  </script>
46  <script type="application/ld+json">
47  {
48    "@context": "https://schema.org",
49    "@type": "BreadcrumbList",
50    "itemListElement": [
51      { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" },
52    ]
53  }
54  </script>
55</head>
56<body itemscope itemtype="https://schema.org/Organization">
57  <span itemprop="name">Fieldstone Cookware</span>
58</body>
59</html>`}],Q={retired:"Retired",blocked:"Blocks the result",invalid:"Invalid",advisory:"Advisory"},_={retired:"border-violet-500/40 bg-violet-500/[0.05]",blocked:"border-red-500/40 bg-red-500/[0.04]",invalid:"border-amber-500/40 bg-amber-500/[0.04]",advisory:"border-sky-500/40 bg-sky-500/[0.04]"},Z={retired:"bg-violet-500/15 text-violet-700 dark:text-violet-300",blocked:"bg-red-500/15 text-red-700 dark:text-red-300",invalid:"bg-amber-500/15 text-amber-700 dark:text-amber-300",advisory:"bg-sky-500/15 text-sky-700 dark:text-sky-300"},X={eligible:"Eligible",blocked:"Blocked",retired:"Feature retired","no-feature":"No rich result","unknown-type":"Type not checked",broken:"No type"},ee={eligible:"bg-emerald-500/15 text-emerald-700 dark:text-emerald-300",blocked:"bg-red-500/15 text-red-700 dark:text-red-300",retired:"bg-violet-500/15 text-violet-700 dark:text-violet-300","no-feature":"bg-muted text-muted-foreground","unknown-type":"bg-muted text-muted-foreground",broken:"bg-red-500/15 text-red-700 dark:text-red-300"};function et({nodes:e,depth:t,selected:r,onSelect:i}){return(0,n.jsx)("ul",{className:(0,d.cn)("space-y-1",t>0&&"ml-4 border-l border-border pl-3"),children:e.map(e=>(0,n.jsxs)("li",{children:[(0,n.jsxs)("button",{type:"button",onClick:()=>i(r===e.key?null:e.key),className:(0,d.cn)("w-full rounded px-2 py-1 text-left text-xs transition-colors hover:bg-muted",r===e.key&&"bg-muted"),children:[(0,n.jsx)("span",{className:"font-mono font-medium",children:e.types.join(" + ")||"no @type"}),e.label&&(0,n.jsx)("span",{className:"ml-2 text-muted-foreground",children:e.label}),e.refOnly&&(0,n.jsx)("span",{className:"ml-2 text-muted-foreground",children:e.dangling?"reference to nothing":"reference"})]}),e.children.length>0&&(0,n.jsx)(et,{nodes:e.children,depth:t+1,selected:r,onSelect:i})]},e.key))})}function er(){let[e,t]=(0,i.useState)(""),[r,h]=(0,i.useState)(""),[p,m]=(0,i.useState)(!1),[N,O]=(0,i.useState)("all"),[T,K]=(0,i.useState)(null),[er,en]=(0,i.useState)(!1),[ei,es]=(0,i.useState)(null),ea=(0,i.useRef)(null),eo=(0,i.useRef)(null);(0,i.useEffect)(()=>{let e=new URLSearchParams(window.location.search),t=e.get("band");t&&q.includes(t)&&O(t),"1"===e.get("repair")&&m(!0)},[]),(0,i.useEffect)(()=>{let t=setTimeout(()=>h(e),e.length>4e4?350:120);return()=>clearTimeout(t)},[e]);let el=(0,i.useMemo)(()=>(function(e,t){let r=function(e,t){let r,n=e.length>15e5?e.length:null,i=n?e.slice(0,15e5):e,s={kind:"empty",blocks:[],microdata:[],rdfaCount:0,scriptTagsSeen:0,truncatedFrom:n};if(!i.trim())return s;if(!/<\s*(!doctype|html|head|body|script|meta|div|main|article)\b/i.test(i.slice(0,8e3))){let e=R(1,"paste",i,0,t);return{...s,kind:"json",blocks:e?[e]:[]}}let a=[],o=0,l=/<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi;for(;null!==(r=l.exec(i));){o++;let e=r[1]??"",n=r[2]??"";if(!function(e){let t=e.match(/\btype\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/i);return"application/ld+json"===(t?.[2]??t?.[3]??t?.[4]??"").trim().toLowerCase().split(";")[0].trim()}(e))continue;let i=r.index+e.length+8,s=R(a.length+1,"script",n,i,t);s&&a.push(s)}let d=[],c=0;if("undefined"!=typeof DOMParser)try{let e=new DOMParser().parseFromString(i,"text/html"),t=new Map;
59for(let[r,n]of(e.querySelectorAll("[itemscope]").forEach(e=>{let r=(e.getAttribute("itemtype")??"").trim(),n=r?r.split(/[/#]/).pop()??r:"(no itemtype)";t.set(n,(t.get(n)??0)+1)}),t))d.push({type:r,count:n});c=e.querySelectorAll("[typeof]").length}catch{}return{kind:"html",blocks:a,microdata:d,rdfaCount:c,scriptTagsSeen:o,truncatedFrom:n}}(e,t),n=C(e),i=[],s={retired:0,blocked:0,invalid:0,advisory:0},a=0,o=e=>{a++,s[e.band]++,i.length<400&&i.push({...e,id:`f${i.length}`})},l=[],d=[],c={n:0},u=new Map;for(let e of r.blocks){if(!e.parsed){let t=C(e.text),r=e.parseError?.offset??0,i=e.offset>=0?e.offset+r:null,s=null!==i?n(i):t(r);o({band:"blocked",blockIndex:e.index,entityKey:null,path:"(root)",line:s.line,col:s.col,span:null!==i?{start:i,end:i+1}:null,message:`Block ${e.index} is not valid JSON, so nothing can read any of it.`,fix:e.repairPreview?"A repair is available below. Look at what it changes before you accept it, because a repair that guesses wrong is worse than the error.":"The usual causes are a trailing comma after the last property, single quotes where JSON needs double, or a curly quote pasted out of a word processor.",source:null});continue}e.offset<0&&d.push(e.index);let t=function(e){let t=new Map,r=e.length,n=0,i=()=>{for(;n<r;){let t=e.charCodeAt(n);if(32===t||9===t||10===t||13===t||65279===t)n++;else break}},s=()=>{let t="";for(n++;n<r;){let r=e[n];if("\\"===r){let r=e[n+1];if("u"===r){let r=e.slice(n+2,n+6);t+=/^[0-9a-fA-F]{4}$/.test(r)?String.fromCharCode(parseInt(r,16)):"",n+=6}else t+=S[r??""]??r??"",n+=2;continue}if('"'===r){n++;break}t+=r,n++}return t},a=()=>{for(;n<r&&!",}] 	\n\r".includes(e[n]);)n++},o=(l,d)=>{i();let c=n,u=e[n];if(d>80)(()=>{i();let t=e[n];if('"'===t)return s();if("{"!==t&&"["!==t)return a();let o=0;for(;n<r;){let t=e[n];if('"'===t){s();continue}if("{"===t||"["===t)o++;else if(("}"===t||"]"===t)&&0==--o)return void n++;n++}})();else if("{"===u)for(n++;;){if(i(),"}"===e[n]){n++;break}if('"'!==e[n])break;let r=n,a=s(),c=n;if(i(),":"!==e[n])break;n++;let u=j(l,a);if(t.set(u,{start:r,end:c}),o(u,d+1),i(),","===e[n]){n++;continue}"}"===e[n]&&n++;break}else if("["===u){n++;let t=0;for(;;){if(i(),"]"===e[n]){n++;break}if(o($(l,t),d+1),t++,i(),","===e[n]){n++;continue}"]"===e[n]&&n++;break}}else'"'===u?s():a();t.has(l)||t.set(l,{start:c,end:n})};return o("$",0),t}(e.text),r=C(e.text),i=i=>{let s=t.get(i);if(!s)return null;if(e.offset>=0){let t={start:s.start+e.offset,end:s.end+e.offset},r=n(t.start);return{line:r.line,col:r.col,span:t}}let a=r(s.start);return{line:a.line,col:a.col,span:null}},s=new Set,a=(e,t)=>{if(t>40)return;if(Array.isArray(e))return void e.forEach(e=>a(e,t+1));if(!z(e))return;let r=e["@id"],n=Object.keys(e).filter(e=>"@id"!==e&&"@context"!==e);"string"==typeof r&&n.length>0&&s.add(r),Object.values(e).forEach(e=>a(e,t+1))};a(e.data,0),(Array.isArray(e.data)?e.data:[e.data]).forEach((t,r)=>{if(!z(t))return;let n=Array.isArray(e.data)?$("$",r):"$",s=t["@context"];if(void 0===s){let t=i(n);o({band:"invalid",blockIndex:e.index,entityKey:null,path:A(n),line:t?.line??null,col:t?.col??null,span:t?.span??null,message:"No @context on this block.",fix:'Add "@context": "https://schema.org" as the first line. Without it the property names have no vocabulary behind them and the block means nothing.',source:"https://schema.org/docs/gs.html"})}else if("string"==typeof s&&s.startsWith("http://schema.org")){let t=i(j(n,"@context"));o({band:"advisory",blockIndex:e.index,entityKey:null,path:A(j(n,"@context")),line:t?.line??null,col:t?.col??null,span:t?.span??null,message:"@context uses http rather than https.",fix:"Both forms are accepted. https://schema.org is the current one and costs nothing to switch to.",source:"https://schema.org/docs/gs.html"})}});let h=[],p=(e,t,r)=>{if(Array.isArray(e))return void e.forEach((e,n)=>p(e,$(t,n),[...r,n]));if(!z(e))return;let n=e["@graph"];if(void 0!==n)return void p(n,j(t,"@graph"),[...r,"@graph"]);h.push({value:e,path:t,segs:r})};p(e.data,"$",[]);let m=[],N={n:0},O=new Set,T={block:e,pos:t,locate:i,push:e=>{"blocked"===e.band&&e.entityKey&&O.add(e.entityKey),o(e)},definedIds:s,fixes:m,entityCount:N,skipped:c,blockedKeys:O},R=new Set,q=e=>O.has(e.key)||e.children.some(q);for(let t of h){if(!z(t.value))continue;N.n++;let r=function e(t,r,n,i,s,a,o){let l=`${i.block.index}:${r}`,d=U(t),c="string"==typeof t["@id"]?t["@id"]:null,u=Object.keys(t).filter(e=>"@id"!==e&&"@type"!==e&&"@context"!==e),h=null!==c&&0===u.length,p={key:l,blockIndex:i.block.index,path:r,types:d,label:function(e){for(let t of["name","headline","title","claimReviewed"]){let r=e[t];if("string"==typeof r&&r.trim())return r.trim().slice(0,70)}return null}(t),id:c,verdict:"no-feature",feature:null,missingRequired:[],missingRecommended:[],children:[],refOnly:h,dangling:!1,corrected:null,corrections:[]},m=e=>{let t=i.locate(e);return{line:t?.line??null,col:t?.col??null,span:t?.span??null}};if(h)return c&&!i.definedIds.has(c)&&(p.dangling=!0,i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(j(r,"@id")),...m(j(r,"@id")),message:`The reference to ${c} points at nothing in this document.`,fix:"Either define an entity carrying that same @id somewhere in the markup, or write the entity out in place instead of referring to it.",source:null})),p;if(o.has(t))return p;
59if(o.add(t),0===d.length)return p.verdict="broken",i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:"This entity has no @type, so nothing can read it as anything.",fix:'Add "@type" with a schema.org type, for example "@type": "Product".',source:"https://schema.org/docs/gs.html"}),p;let N=d.map(g).find(e=>null!==e)??null;p.feature=N;let S=N?.status==="retired",C=N?.status==="live";S&&N?(p.verdict="retired",i.push({band:"retired",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`${N.feature} was retired${N.retiredOn?` in ${N.retiredOn}`:""}. This ${d[0]} block is valid markup that no longer earns anything in Google.`,fix:`${N.retiredNote??""} Leaving it in place does no harm and Google still reads it. If you were counting on the result, that budget is better spent elsewhere.`,source:N.source})):N||d.filter(e=>!b.has(e)).length===d.length&&(p.verdict="unknown-type",i.push({band:"advisory",blockIndex:i.block.index,entityKey:l,path:A(j(r,"@type")),...m(j(r,"@type")),message:`${d.join(", ")} is not in this tool's type list.`,fix:"The list covers every type Google ties a search feature to, plus their building blocks. If this is a real schema.org type it is simply outside what gets checked here, so treat this as a note rather than a fault.",source:"https://schema.org/docs/full.html"}));let O=C?"blocked":"advisory";if(N){for(let e of N.required){let s=t[e];void 0===s?(p.missingRequired.push(e),i.fixes.push({segs:n,prop:e,value:`TODO: add ${e}`,note:`added ${e} as a placeholder`}),i.push({band:O,blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`${N.feature} needs ${e} and this block has no ${e}.`,fix:[`Add "${e}" to the ${d[0]} block.`,N.requiredHints?.[e],C?"Until it is there the rich result cannot be produced.":null].filter(Boolean).join(" "),source:N.source})):G(s)&&(p.missingRequired.push(e),i.push({band:O,blockIndex:i.block.index,entityKey:l,path:A(j(r,e)),...m(j(r,e)),message:`${e} is there but empty, which satisfies nothing.`,fix:`Give ${e} a real value. An empty string or an empty array passes a syntax check and fails the requirement.`,source:N.source}))}N.oneOf&&0===N.oneOf.props.filter(e=>void 0!==t[e]&&!G(t[e])).length&&(p.missingRequired.push(N.oneOf.props[0]),i.fixes.push({segs:n,prop:N.oneOf.props[0],value:`TODO: add ${N.oneOf.props[0]}`,note:`added ${N.oneOf.props[0]} as a placeholder`}),i.push({band:O,blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`This block needs at least one of ${N.oneOf.props.join(", ")} and has none of them.`,fix:`Add whichever fits, because ${N.oneOf.why}.`,source:N.source}));let e=N.recommended.filter(e=>void 0===t[e]||G(t[e]));p.missingRecommended=e,e.length>0&&!S&&i.push({band:"advisory",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`Missing recommended: ${e.join(", ")}.`,fix:"None of these block the result. Each one is something Google can show if you supply it and cannot if you do not.",source:N.source})}let T=d.map(e=>f[e]).find(e=>void 0!==e);if(T&&!(T.satisfiedBy&&void 0!==t[T.satisfiedBy])){for(let e of T.required)(void 0===t[e]||G(t[e]))&&(p.missingRequired.push(e),i.fixes.push({segs:n,prop:e,value:`TODO: add ${e}`,note:`added ${e} to the ${d[0]} block`}),i.push({band:a?"blocked":"invalid",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`${d[0]} is missing ${e}.`,fix:`Add "${e}". ${T.satisfiedBy?`A ${T.satisfiedBy} in its place works too.`:""}`.trim(),source:N?.source??null}));let e=T.recommended.filter(e=>void 0===t[e]||G(t[e]));e.length>0&&(p.missingRecommended=[...new Set([...p.missingRecommended,...e])],i.push({band:"advisory",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:`Missing recommended: ${e.join(", ")}.`,fix:"None of these block the result. Each one is something Google can show if you supply it and cannot if you do not.",source:N?.source??null}))}if(d.some(e=>"AggregateRating"===e||"Rating"===e)){let e=Number(t.ratingValue),n=void 0===t.bestRating?5:Number(t.bestRating),s=void 0===t.worstRating?1:Number(t.worstRating);if(Number.isFinite(e)&&Number.isFinite(n)&&Number.isFinite(s)&&(e>n||e<s)&&i.push({band:"blocked",blockIndex:i.block.index,entityKey:l,path:A(j(r,"ratingValue")),...m(j(r,"ratingValue")),message:`ratingValue ${e} sits outside the ${s} to ${n} scale this block declares.`,fix:"Either correct the value or set bestRating and worstRating to the scale you actually use. Left as is, the stars are dropped.",s
59ource:"https://developers.google.com/search/docs/appearance/structured-data/review-snippet"}),d.includes("AggregateRating")){let e=Number(t.ratingCount??t.reviewCount??0);(!Number.isFinite(e)||e<=0)&&i.push({band:"blocked",blockIndex:i.block.index,entityKey:l,path:A(r),...m(r),message:"An aggregate rating with no ratingCount or reviewCount above zero is thrown out.",fix:"Add ratingCount, or reviewCount, with the real number of ratings behind the average.",source:"https://developers.google.com/search/docs/appearance/structured-data/review-snippet"})}}for(let[d,c]of Object.entries(t)){if(d.startsWith("@"))continue;let t=j(r,d),u=[...n,d];if(!w.has(d)){let e=function(e){let t=e.toLowerCase();for(let e of w)if(e.toLowerCase()===t)return e;for(let e of W){if(!t.endsWith(e)||t.length<=e.length+3)continue;let r=t.slice(0,t.length-e.length);for(let e of w)if(e.toLowerCase()===r)return e}if(e.length<4)return null;for(let r of w)if(!(Math.abs(r.length-e.length)>1)&&function(e,t){if(e===t)return!1;let r=e.length<=t.length?e:t,n=e.length<=t.length?t:e;if(n.length-r.length>1)return!1;let i=0,s=0,a=0;for(;i<r.length&&s<n.length;){if(r[i]===n[s]){i++,s++;continue}if(++a>1)return!1;r.length===n.length&&i++,s++}
59return!0}(r.toLowerCase(),t))return r;return null}(d);e&&i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:`${d} is not a schema.org property. Did you mean ${e}?`,fix:`Rename it to ${e}. Property names are case sensitive, and a name nothing recognizes is simply skipped, with no error anywhere to tell you.`,source:`https://schema.org/${e}`})}for(let e of B(c).filter(e=>"string"==typeof e||"number"==typeof e)){let r=String(e);if(y.has(d))if(P.test(r)||L.test(r))"startDate"===d&&L.test(r)&&!F.test(r)&&i.push({band:"advisory",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:"startDate carries a time but no timezone offset.",fix:"Append the offset, as in 2027-03-14T19:30:00-05:00. Without it the time is read in an unknown zone and events shift by hours.",source:"https://developers.google.com/search/docs/appearance/structured-data/event"});else{let e=function(e){let t=e.trim();if(!/\d{4}/.test(t)||!E.test(t)&&!I.test(t))return null;let r=Date.parse(t);if(!Number.isFinite(r))return null;let n=new Date(r),i=e=>String(e).padStart(2,"0");return`${n.getFullYear()}-${i(n.getMonth()+1)}-${i(n.getDate())}`}(r);e&&!Array.isArray(c)&&i.fixes.push({segs:n,prop:d,value:e,note:`rewrote ${d} as ${e}`}),i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:`${d} is "${r}", which is not an ISO 8601 date.`,fix:e?`Write it as ${e}. Anything else gets read as no date at all, and a missing date is why plenty of Article blocks show nothing.`:"Use the YYYY-MM-DD form, or the full YYYY-MM-DDThh:mm:ss with an offset. A form like 10-05-2023 is ambiguous and is not accepted.",source:"https://schema.org/Date"})}if(x.has(d)&&!D.test(r)&&i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:`${d} is "${r}", which is not an ISO 8601 duration.`,fix:"Durations look like PT30M for thirty minutes, PT1H15M for an hour and a quarter. Plain English is dropped.",source:"https://schema.org/Duration"}),v.has(d)&&"string"==typeof e){let e=!1;try{let t=new URL(r);e="http:"===t.protocol||"https:"===t.protocol}catch{e=!1}e||i.push({band:"invalid",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:`${d} is "${r.slice(0,80)}", which is not an absolute URL.`,fix:"Write the full address including https and the domain. A relative path resolves differently depending on which URL the markup is served from.",source:"https://schema.org/URL"})}k.has(d)&&!M.test(r)&&i.push({band:"blocked",blockIndex:i.block.index,entityKey:l,path:A(t),...m(t),message:`${d} is "${r}". A price has to be a bare number.`,fix:"Strip the currency symbol, the thousands separator and any text, so 1,299.00 USD becomes 1299.00 and the currency goes in priceCurrency.",source:"https://developers.google.com/search/docs/appearance/stru
59ctured-data/product"})}B(c).forEach((r,n)=>{if(!z(r)||0===U(r).length&&"string"!=typeof r["@id"])return;if(i.entityCount.n>=320){i.skipped.n+=function e(t,r={n:2e4}){if(!z(t)||r.n<=0)return 0;r.n--;let n=1;for(let[i,s]of Object.entries(t))if(!i.startsWith("@"))for(let t of B(s))z(t)&&(0!==U(t).length||"string"==typeof t["@id"])&&(n+=e(t,r));return n}(r);return}i.entityCount.n++;let l=Array.isArray(c)?$(t,n):t,d=Array.isArray(c)?[...u,n]:u;p.children.push(e(r,l,d,i,s+1,a||C,o))})}return p}(t.value,t.path,t.segs,T,0,!1,R),n=function(e,t,r){let n,i=r.filter(e=>(function(e,t){if(t.length>e.length)return!1;for(let r=0;r<t.length;r++)if(e[r]!==t[r])return!1;return!0})(e.segs,t));if(0===i.length)return null;try{n=JSON.parse(JSON.stringify(H(e,t)))}catch{return null}if(!z(n))return null;let s=[];for(let e of i){let r=H(n,e.segs.slice(t.length));r&&(r[e.prop]=e.value,s.push(e.note))}return 0===s.length?null:{json:JSON.stringify(n,null,2),notes:s}}(e.data,t.segs,m);for(let e of(n&&(r.corrected=n.json,r.corrections=n.notes),r.verdict="retired"===r.verdict||"broken"===r.verdict||"unknown-type"===r.verdict?r.verdict:r.feature?r.missingRequired.length>0||q(r)?"blocked":"eligible":"no-feature",l.push(r),r.types))J.has(e)&&u.set(e,(u.get(e)??0)+1)}}for(let[e,t]of u)t<2||o({band:"invalid",blockIndex:0,entityKey:null,path:"(page)",line:null,col:null,span:null,message:`${t} separate ${e} entities on one page.`,fix:`Google has to pick one and you do not get to say which. This is usually a theme and an SEO plugin each emitting their own block. Turn one of them off, or merge them into a single ${e} and point at it with @id.`,source:null});let h=new Set(l.flatMap(e=>e.types)),p=r.microdata.filter(e=>h.has(e.type));p.length>0&&o({band:"advisory",blockIndex:0,entityKey:null,path:"(page)",line:null,col:null,span:null,message:`The page carries Microdata for ${p.map(e=>e.type).join(", ")} as well as JSON-LD for the same types.`,fix:"Two descriptions of one thing is a conflict rather than reinforcement. Keep the JSON-LD and strip the Microdata, which is usually left over from an old theme.",source:null});let m=e=>q.indexOf(e.band);return i.sort((e,t)=>m(e)-m(t)||e.blockIndex-t.blockIndex||(e.line??0)-(t.line??0)),{kind:r.kind,blocks:r.blocks,entities:l.slice(0,80),findings:i,counts:s,entitiesFound:l.length,entitiesShown:Math.min(l.length,80),findingsFound:a,findingsShown:i.length,scriptTagsSeen:r.scriptTagsSeen,microdata:r.microdata,rdfaCount:r.rdfaCount,truncatedFrom:r.truncatedFrom,shiftedBlocks:d,nestedSkipped:c.n}})(r,p),[r,p]);(0,i.useEffect)(()=>{K(null)},[r,p]);let ed=(0,i.useMemo)(()=>el.findings.filter(e=>("all"===N||e.band===N)&&(null===T||e.entityKey===T)),[el.findings,N,T]),ec=(0,i.useMemo)(()=>{let e={retired:0,blocked:0,invalid:0,advisory:0};for(let t of el.findings)e[t.band]++;return e},[el.findings]),eu=(0,i.useCallback)(()=>{let e=new URLSearchParams;return"all"!==N&&e.set("band",N),p&&e.set("repair","1"),e},[N,p]),eh=(0,i.useCallback)(e=>{if(!e.span||!ea.current)return;let t=ea.current;t.focus(),t.setSelectionRange(e.span.start,Math.max(e.span.end,e.span.start+1));let r=window.getComputedStyle(t),n=parseFloat(r.lineHeight)||1.5*parseFloat(r.fontSize)||18,i=t.value.slice(0,e.span.start).split("\n").length;t.scrollTop=Math.max(0,(i-5)*n)},[]),ep=(0,i.useCallback)(async e=>{let r,n=e?.[0];if(!n)return;try{r=await (0,c.G)(n)}catch(e){es(e instanceof Error?e.message:`${n.name} could not be read.`);return}let i=r.text,s=""===r.note?"":r.note+" ";i.length>15e5?(t(i.slice(0,15e5)),es(`${s}${n.name} is ${i.length.toLocaleString()} characters. The first ${15e5.toLocaleString()} were loaded and ${(i.length-15e5).toLocaleString()} were not.`)):(t(i),es(""!==r.note?r.note:null))},[]),em=el.blocks.filter(e=>!e.parsed),eg=em.filter(e=>e.repairPreview),ef=""===r.trim(),eb=(()=>{if(ef)return null;if(0===el.blocks.length)return"html"===el.kind?`No JSON-LD found. ${el.scriptTagsSeen} script ${1===el.scriptTagsSeen?"tag":"tags"} were read and none carried type="application/ld+json".`:"Nothing here parses as markup.";let e=[],t=el.counts;return t.blocked>0&&e.push(`${t.blocked} blocking the result`),t.retired>0&&e.push(`${t.retired} retired`),t.invalid>0&&e.push(`${t.invalid} invalid`),t.advisory>0&&e.push(`${t.advisory} advisory`),0===e.length?"Nothing to fix in what was checked.":e.join(", ")})(),ey=q.find(e=>el.counts[e]>
590)??null,ex=0===el.blocks.length;return(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsxs)("div",{className:"space-y-1.5",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)(a.J,{htmlFor:"schema-input",children:"Your markup, or the whole page"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-1",children:[Y.map(e=>(0,n.jsx)(s.$,{variant:"ghost",size:"sm",onClick:()=>{t(e.text),es(null),K(null)},children:e.label},e.label)),(0,n.jsx)(s.$,{variant:"ghost",size:"sm",onClick:()=>{t(""),K(null),es(null)},children:"Clear"})]})]}),(0,n.jsx)("div",{onDragOver:e=>{e.preventDefault(),en(!0)},onDragLeave:()=>en(!1),onDrop:e=>{e.preventDefault(),en(!1),ep(e.dataTransfer.files)},className:(0,d.cn)("rounded-md transition-colors",er&&"ring-2 ring-primary ring-offset-2"),children:(0,n.jsx)(o.T,{id:"schema-input",ref:ea,spellCheck:!1,rows:14,value:e,onChange:e=>t(e.target.value),placeholder:'Paste a JSON-LD block, or the whole HTML of the page, or drop a saved .html file here.\n\n{\n  "@context": "https://schema.org",\n  "@type": "Product",\n  "name": "Cast Iron Skillet"\n}',className:"font-mono text-xs"})}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("input",{ref:eo,type:"file",accept:".html,.htm,.json,.jsonld,.txt,text/html,application/json,text/plain",className:"hidden",onChange:e=>{ep(e.target.files),eo.current&&(eo.current.value="")}}),(0,n.jsx)(s.$,{variant:"outline",size:"sm",onClick:()=>eo.current?.click(),children:"Open a file"}),(0,n.jsx)("span",{className:"text-xs text-muted-foreground",children:"Click to choose a saved page or .json file, drag one into the box, or paste the text straight in."})]}),ei&&(0,n.jsx)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:ei}),null!==el.truncatedFrom&&(0,n.jsxs)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:["The paste is ",el.truncatedFrom.toLocaleString()," characters. The first"," ",15e5.toLocaleString()," were checked and"," ",(el.truncatedFrom-15e5).toLocaleString()," were not."]})]}),ef?(0,n.jsx)("div",{className:"rounded-lg border border-input bg-muted/40 p-4 text-sm text-muted-foreground",children:"Paste your markup above, or load one of the samples. Each sample is broken in a way real pages are broken, so you can see what the report calls out before you trust it with yours."}):(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:(0,d.cn)("rounded-lg border p-4",ey?_[ey]:ex?"border-amber-500/40 bg-amber-500/[0.05]":"border-emerald-500/40 bg-emerald-500/[0.04]"),children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)("div",{className:"text-sm font-medium",children:eb}),el.findings.length>0&&(0,n.jsx)(V.i,{value:function(e,t){let r=["# Schema markup check",""];r.push(`Checked against Google's documented requirements as of ${t}.`),r.push(`${e.entitiesFound} ${1===e.entitiesFound?"entity":"entities"} found in ${e.blocks.length} ${1===e.blocks.length?"block":"blocks"}.`);let n=function(e){let t=[];return null!==e.truncatedFrom&&t.push(`The paste is ${e.truncatedFrom.toLocaleString()} characters. The first ${15e5.toLocaleString()} were checked and ${(e.truncatedFrom-15e5).toLocaleString()} were not.`),e.findingsFound>e.findingsShown&&t.push(`${e.findingsShown} of ${e.findingsFound} findings are listed and ${e.findingsFound-e.findingsShown} are not. The list stops at 400 so a huge page cannot lock up the tab.`),e.entitiesFound>e.entities.length&&t.push(`${e.entitiesFound-e.entities.length} entities past the first ${e.entities.length} are not listed below. They were still checked and their findings are in this report.`),e.nestedSkipped>0&&t.push(`${e.nestedSkipped} nested ${1===e.nestedSkipped?"entity was":"entities were"} not checked at all. The document nests deeper than this tool follows, so treat the result as partial.`),t}(e);if(n.length>0)for(let e of(r.push(""),r.push("## What this report does NOT cover",""),n))r.push(`- ${e}`);for(let t of(r.push(""),e.entities)){let e=t.label?` "${t.label}"`:"";r.push(`- ${t.types.join(", ")||"no type"}${e}: ${t.verdict.toUpperCase()}${t.feature?` (${t.feature.feature})`:""}`)}if(r.push(""),0===e.findings.length)r.push("No findings.");else for(let t of q){let n=e.findings.filter(e=>e.band===t);if(0===n.length)continue;let i=e.counts[t],s=n.length===i?`${n.length}`:`${n.length} of ${i} listed`;for(let e of(r.push(`## ${t.toUpperCase()} (${s})`,""),n)){let t=e.line?`line ${e.line}, col ${e.col}`:"page level";r.push(`- [${e.path}] ${e.message} (${t})`),r.push(`  Fix: ${e.fix}`),e.source&&r.push(`  Source: ${e.source}`)}r.push("")}return r.push("Eligibility is necessary, not sufficient. Google decides per query whether to show a result."),r.join("\n")}(el,u),label:"Copy report",copiedLabel:"Copied!",variant:"outline",size:"sm"})]}),(0,n.jsxs)("p",{className:"mt-2 text-xs text-muted-foreground",children:[el.blocks.length," ",1===el.blocks.length?"block":"blocks"," read","html"===el.kind&&` out of ${el.scriptTagsSeen} script ${1===el.scriptTagsSeen?"tag":"tags"}`,", ",el.entitiesFound," ",1===el.entitiesFound?"entity":"entities"," found",el.entitiesFound>el.entitiesShown&&`, ${el.entitiesShown} shown and ${el.entitiesFound-el.entitiesShown} not shown`,". Checked against Google's documented requirements as of ",u,"."]}),el.microdata.length>0&&(0,n.jsxs)("p",{className:"mt-1 text-xs text-muted-foreground",children:["Microdata also present: ",el.microdata.map(e=>`${e.type} x${e.count}`).join(", "),el.rdfaCount>0&&`. RDFa attributes: ${el.rdfaCount}`,"."]}),el.shiftedBlocks.length>0&&(0,n.jsxs)("p",{className:"mt-1 text-xs text-muted-foreground",children:["Line numbers for block ",el.shiftedBlocks.join(", ")," count against the corrected text, not your paste, because the block had to be changed before it would parse."]})]}),eg.length>0&&(0,n.jsxs)("div",{className:"rounded-lg border border-red-500/40 bg-red-500/[0.04] p-4",children:[(0,n.jsxs)("p",{className:"text-sm font-medium",children:[eg.length," ",1===eg.length?"block does":"blocks do"," not parse as JSON. A repair is available."]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-muted-foreground",children:"Look at what changes first. A repair that guesses wrong is worse than the error you came in 
59with."}),eg.map(e=>(0,n.jsx)("pre",{className:"mt-2 max-h-48 overflow-auto rounded bg-muted/60 p-2 font-mono text-[11px]",children:e.repairPreview},e.index)),(0,n.jsx)(s.$,{variant:"outline",size:"sm",className:"mt-2",onClick:()=>m(e=>!e),children:p?"Undo the repair":"Use the repaired version"})]}),em.length>eg.length&&(0,n.jsxs)("p",{className:"text-xs text-muted-foreground",children:[em.length-eg.length," broken"," ",em.length-eg.length==1?"block was":"blocks were"," too far gone for any repair to be offered."]}),(0,n.jsxs)("div",{className:"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[(0,n.jsxs)("div",{className:"space-y-3",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold",children:"What Google can do with each entity"}),0===el.entities.length?(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:"No entities were found to judge."}):el.entities.map(e=>(0,n.jsxs)("div",{className:"rounded-lg border p-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:(0,d.cn)("rounded-full px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide",ee[e.verdict]),children:X[e.verdict]}),(0,n.jsx)("span",{className:"font-mono text-sm font-medium",children:e.types.join(" + ")||"no @type"}),e.label&&(0,n.jsx)("span",{className:"text-xs text-muted-foreground",children:e.label})]}),e.feature&&(0,n.jsxs)("p",{className:"mt-1.5 text-xs text-muted-foreground",children:["retired"===e.feature.status?`${e.feature.feature}, retired ${e.feature.retiredOn}.`:`Feeds ${e.feature.feature}.`," ",(0,n.jsx)("a",{href:e.feature.source,target:"_blank",rel:"noopener noreferrer",className:"underline underline-offset-2",children:"Google's page for it"})]}),e.feature?.requiredNote&&(0,n.jsx)("p",{className:"mt-1 text-xs text-muted-foreground",children:e.feature.requiredNote}),e.missingRequired.length>0?(0,n.jsxs)("p",{className:"mt-1.5 text-xs",children:[(0,n.jsx)("span",{className:"font-medium",children:"Missing:"})," ",e.missingRequired.join(", ")]}):"blocked"===e.verdict&&(0,n.jsx)("p",{className:"mt-1.5 text-xs",children:"Nothing is missing. A value inside this entity is malformed enough to stop the result, listed on the right."}),!e.feature&&"no-feature"===e.verdict&&(0,n.jsx)("p",{className:"mt-1.5 text-xs text-muted-foreground",children:"A real schema.org type with no Google search feature tied to it. Useful for describing the page, it will not produce a result on its own."}),e.corrected&&(0,n.jsxs)("details",{className:"mt-2",children:[(0,n.jsxs)("summary",{className:"cursor-pointer text-xs font-medium",children:["Corrected block (",e.corrections.length," ",1===e.corrections.length?"change":"changes",")"]}),(0,n.jsx)("ul",{className:"mt-1 list-disc pl-4 text-xs text-muted-foreground",children:e.corrections.map((e,t)=>(0,n.jsx)("li",{children:e},t))}),(0,n.jsx)("pre",{className:"mt-1 max-h-56 overflow-auto rounded bg-muted/60 p-2 font-mono text-[11px]",children:e.corrected}),(0,n.jsx)(V.i,{value:e.corrected??"",label:"Copy corrected block",copiedLabel:"Copied!",variant:"outline",size:"sm",className:"mt-1"}),(0,n.jsx)("p",{className:"mt-1 text-xs text-muted-foreground",children:"The placeholders read TODO on purpose. Replace them with your real values before this goes anywhere near a live page."})]}),e.children.length>0&&(0,n.jsxs)("details",{className:"mt-2",children:[(0,n.jsxs)("summary",{className:"cursor-pointer text-xs font-medium",children:["Nested entities (",e.children.length,")"]}),(0,n.jsx)("div",{className:"mt-1",children:(0,n.jsx)(et,{nodes:e.children,depth:1,selected:T,onSelect:K})})]}),(0,n.jsx)(s.$,{variant:"ghost",size:"sm",className:"mt-1",onClick:()=>K(T===e.key?null:e.key),children:T===e.key?"Show all findings":"Only this entity"})]},e.key))]}),(0,n.jsxs)("div",{className:"space-y-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold",children:"Findings"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-1",children:[(0,n.jsxs)(s.$,{variant:"all"===N?"outline":"ghost",size:"sm",onClick:()=>O("all"),children:["All ",el.findingsShown]}),q.filter(e=>el.counts[e]>
590).map(e=>(0,n.jsxs)(s.$,{variant:N===e?"outline":"ghost",size:"sm",onClick:()=>O(e),children:[Q[e]," ",ec[e]===el.counts[e]?el.counts[e]:`${ec[e]} of ${el.counts[e]}`]},e))]})]}),el.findingsFound>el.findingsShown&&(0,n.jsxs)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:[el.findingsShown," of ",el.findingsFound," findings are listed and"," ",el.findingsFound-el.findingsShown," are not. The list stops at"," ",400," so a huge page cannot lock up the tab."]}),el.entitiesFound>80&&(0,n.jsxs)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:[el.entitiesFound-80," entities past the first ",80," have no card. They were still checked and their findings are in this list."]}),el.nestedSkipped>0&&(0,n.jsxs)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:[el.nestedSkipped," nested ",1===el.nestedSkipped?"entity was":"entities were"," ","not checked at all. The document nests deeper than this tool follows, so treat the result as partial."]}),0===ed.length?(0,n.jsx)("div",{className:(0,d.cn)("rounded-lg border p-3 text-sm",ex&&0===el.findingsFound?"border-amber-500/40 bg-amber-500/[0.05]":"border-emerald-500/30 bg-emerald-500/[0.04]"),children:ex&&0===el.findingsFound?"html"===el.kind?'No JSON-LD was found, so nothing has been checked. This is not a pass. Structured data has to sit in a <script type="application/ld+json"> tag: check that the tag carries that exact type, and that the markup is in the HTML the server sends rather than added later by JavaScript.':"Nothing here parses as markup, so nothing has been checked. This is not a pass. Paste the JSON-LD itself, or the whole page it sits in.":0===el.findingsFound?"Nothing flagged. Syntax, structure, the documented requirements and the value formats all check out for what was found.":(0,n.jsxs)(n.Fragment,{children:["Nothing under this filter."," ",(0,n.jsx)(s.$,{variant:"ghost",size:"sm",onClick:()=>{O("all"),K(null)},children:"Show everything"})]})}):(0,n.jsx)("ul",{className:"space-y-2",children:ed.map(e=>(0,n.jsxs)("li",{className:(0,d.cn)("rounded-lg border p-3",_[e.band]),children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:(0,d.cn)("rounded-full px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide",Z[e.band]),children:Q[e.band]}),null!=e.line&&(0,n.jsxs)("button",{type:"button",onClick:()=>eh(e),disabled:!e.span,className:(0,d.cn)("rounded bg-muted px-1.5 py-0.5 font-mono text-xs",e.span&&"hover:bg-muted-foreground/20"),title:e.span?"Jump to it in the box above":"Position is relative to the corrected text",children:["line ",e.line,":",e.col]}),(0,n.jsx)("span",{className:"rounded bg-muted px-1.5 py-0.5 font-mono text-xs",children:e.path})]}),(0,n.jsx)("p",{className:"mt-1.5 text-sm font-medium",children:e.message}),(0,n.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:e.fix}),e.source&&(0,n.jsx)("a",{href:e.source,target:"_blank",rel:"noopener noreferrer",className:"mt-1 inline-block text-xs underline underline-offset-2",children:"Where this rule comes from"})]},e.id))})]})]})]}),(0,n.jsx)(l.ToolActions,{getParams:eu,title:"Schema Markup Validator"}),(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:"Everything runs in your browser. Nothing you paste is uploaded, logged or stored, so you can check a staging page or a block that has not shipped yet. The tool reads what you give it and cannot fetch a URL, so if your markup is injected by a tag manager or rendered by JavaScript, copy it from the rendered source rather than the served HTML. Eligibility is necessary and not sufficient: Google decides per query whether to show a result, and any tool promising you one is guessing."})]})}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.