[dyad] Added schema display tab - wrote 3 file(s)
This commit is contained in:
@@ -57,12 +57,15 @@ export async function extractMetaData(url: string, keyword?: string) {
|
|||||||
const image = $('meta[property="og:image"]').attr("content") || null;
|
const image = $('meta[property="og:image"]').attr("content") || null;
|
||||||
|
|
||||||
const faqData: FaqItem[] = [];
|
const faqData: FaqItem[] = [];
|
||||||
|
const schemaData: any[] = [];
|
||||||
$('script[type="application/ld+json"]').each((i, el) => {
|
$('script[type="application/ld+json"]').each((i, el) => {
|
||||||
const jsonContent = $(el).html();
|
const jsonContent = $(el).html();
|
||||||
if (!jsonContent) return;
|
if (!jsonContent) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(jsonContent);
|
const data = JSON.parse(jsonContent);
|
||||||
|
schemaData.push(data);
|
||||||
|
|
||||||
const graph = data["@graph"] || [data];
|
const graph = data["@graph"] || [data];
|
||||||
|
|
||||||
for (const item of graph) {
|
for (const item of graph) {
|
||||||
@@ -171,6 +174,7 @@ export async function extractMetaData(url: string, keyword?: string) {
|
|||||||
description,
|
description,
|
||||||
image,
|
image,
|
||||||
faq: faqData.length > 0 ? faqData : null,
|
faq: faqData.length > 0 ? faqData : null,
|
||||||
|
schema: schemaData.length > 0 ? schemaData : null,
|
||||||
headlines: headlines.length > 0 ? headlines : null,
|
headlines: headlines.length > 0 ? headlines : null,
|
||||||
keyword: trimmedKeyword || null,
|
keyword: trimmedKeyword || null,
|
||||||
keywordCount,
|
keywordCount,
|
||||||
|
|||||||
@@ -30,12 +30,14 @@ import { ImageAltDisplay } from "./image-alt-display";
|
|||||||
import { TabIndicator } from "./tab-indicator";
|
import { TabIndicator } from "./tab-indicator";
|
||||||
import { getLengthIndicatorColor, type IndicatorColor } from "@/lib/analysis";
|
import { getLengthIndicatorColor, type IndicatorColor } from "@/lib/analysis";
|
||||||
import { KeywordHighlighter } from "./keyword-highlighter";
|
import { KeywordHighlighter } from "./keyword-highlighter";
|
||||||
|
import { SchemaDisplay } from "./schema-display";
|
||||||
|
|
||||||
interface MetaData {
|
interface MetaData {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
image?: string | null;
|
image?: string | null;
|
||||||
faq?: { question: string; answer: string }[] | null;
|
faq?: { question: string; answer: string }[] | null;
|
||||||
|
schema?: any[] | null;
|
||||||
headlines?: HeadlineNode[] | null;
|
headlines?: HeadlineNode[] | null;
|
||||||
keyword?: string | null;
|
keyword?: string | null;
|
||||||
keywordCount?: number | null;
|
keywordCount?: number | null;
|
||||||
@@ -123,11 +125,18 @@ export function MetaForm() {
|
|||||||
faqColor = "green";
|
faqColor = "green";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Schema Tab
|
||||||
|
let schemaColor: IndicatorColor = "gray";
|
||||||
|
if (metaData.schema && metaData.schema.length > 0) {
|
||||||
|
schemaColor = "green";
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
analysis: analysisColor,
|
analysis: analysisColor,
|
||||||
headlines: headlinesColor,
|
headlines: headlinesColor,
|
||||||
images: imagesColor,
|
images: imagesColor,
|
||||||
faq: faqColor,
|
faq: faqColor,
|
||||||
|
schema: schemaColor,
|
||||||
};
|
};
|
||||||
}, [metaData, editableTitle, editableDescription]);
|
}, [metaData, editableTitle, editableDescription]);
|
||||||
|
|
||||||
@@ -245,6 +254,12 @@ export function MetaForm() {
|
|||||||
FAQ
|
FAQ
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
|
{metaData.schema && metaData.schema.length > 0 && (
|
||||||
|
<TabsTrigger value="schema">
|
||||||
|
{tabColors && <TabIndicator color={tabColors.schema} />}
|
||||||
|
Schema
|
||||||
|
</TabsTrigger>
|
||||||
|
)}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="analysis">
|
<TabsContent value="analysis">
|
||||||
@@ -468,6 +483,16 @@ export function MetaForm() {
|
|||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{metaData.schema && metaData.schema.length > 0 && (
|
||||||
|
<TabsContent value="schema">
|
||||||
|
<Card className="w-full shadow-lg rounded-lg">
|
||||||
|
<CardContent className="p-6">
|
||||||
|
<SchemaDisplay schemas={metaData.schema} />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</TabsContent>
|
||||||
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
40
src/components/schema-display.tsx
Normal file
40
src/components/schema-display.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { CopyButton } from "./copy-button";
|
||||||
|
|
||||||
|
interface SchemaDisplayProps {
|
||||||
|
schemas: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SchemaDisplay({ schemas }: SchemaDisplayProps) {
|
||||||
|
return (
|
||||||
|
<Accordion type="single" collapsible className="w-full">
|
||||||
|
{schemas.map((schema, index) => {
|
||||||
|
const schemaType = schema["@type"] || `Schema Block ${index + 1}`;
|
||||||
|
const schemaJson = JSON.stringify(schema, null, 2);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AccordionItem value={`item-${index}`} key={index}>
|
||||||
|
<AccordionTrigger>{schemaType}</AccordionTrigger>
|
||||||
|
<AccordionContent>
|
||||||
|
<div className="relative bg-muted/50 p-4 rounded-md">
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<CopyButton textToCopy={schemaJson} />
|
||||||
|
</div>
|
||||||
|
<pre className="text-sm overflow-x-auto">
|
||||||
|
<code>{schemaJson}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user