[dyad] Extended keyword highlighting - wrote 3 file(s)
This commit is contained in:
@@ -2,17 +2,21 @@
|
|||||||
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import type { HeadlineNode } from "@/app/actions";
|
import type { HeadlineNode } from "@/app/actions";
|
||||||
|
import { KeywordHighlighter } from "./keyword-highlighter";
|
||||||
|
|
||||||
interface HeadlineTreeProps {
|
interface HeadlineTreeProps {
|
||||||
headlines: HeadlineNode[];
|
headlines: HeadlineNode[];
|
||||||
|
keyword?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeadlineNodeDisplay = ({
|
const HeadlineNodeDisplay = ({
|
||||||
node,
|
node,
|
||||||
level,
|
level,
|
||||||
|
keyword,
|
||||||
}: {
|
}: {
|
||||||
node: HeadlineNode;
|
node: HeadlineNode;
|
||||||
level: number;
|
level: number;
|
||||||
|
keyword?: string | null;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -26,24 +30,36 @@ const HeadlineNodeDisplay = ({
|
|||||||
>
|
>
|
||||||
{node.tag}
|
{node.tag}
|
||||||
</Badge>
|
</Badge>
|
||||||
<p className="font-medium flex-grow text-foreground">{node.text}</p>
|
<p className="font-medium flex-grow text-foreground">
|
||||||
|
<KeywordHighlighter text={node.text} keyword={keyword} />
|
||||||
|
</p>
|
||||||
<p className="text-sm text-muted-foreground flex-shrink-0 w-10 text-right">
|
<p className="text-sm text-muted-foreground flex-shrink-0 w-10 text-right">
|
||||||
{node.length}
|
{node.length}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{node.children?.map((child, index) => (
|
{node.children?.map((child, index) => (
|
||||||
<HeadlineNodeDisplay key={index} node={child} level={level + 1} />
|
<HeadlineNodeDisplay
|
||||||
|
key={index}
|
||||||
|
node={child}
|
||||||
|
level={level + 1}
|
||||||
|
keyword={keyword}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function HeadlineTree({ headlines }: HeadlineTreeProps) {
|
export function HeadlineTree({ headlines, keyword }: HeadlineTreeProps) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full rounded-lg overflow-hidden">
|
<div className="w-full rounded-lg overflow-hidden">
|
||||||
<div className="-mt-px">
|
<div className="-mt-px">
|
||||||
{headlines.map((headline, index) => (
|
{headlines.map((headline, index) => (
|
||||||
<HeadlineNodeDisplay key={index} node={headline} level={0} />
|
<HeadlineNodeDisplay
|
||||||
|
key={index}
|
||||||
|
node={headline}
|
||||||
|
level={0}
|
||||||
|
keyword={keyword}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
|
import { KeywordHighlighter } from "./keyword-highlighter";
|
||||||
|
|
||||||
interface ImageAltDisplayProps {
|
interface ImageAltDisplayProps {
|
||||||
images: ImageAltData[];
|
images: ImageAltData[];
|
||||||
|
keyword?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ImageAltDisplay({ images }: ImageAltDisplayProps) {
|
export function ImageAltDisplay({ images, keyword }: ImageAltDisplayProps) {
|
||||||
const [showMissingOnly, setShowMissingOnly] = useState(false);
|
const [showMissingOnly, setShowMissingOnly] = useState(false);
|
||||||
const [imageErrors, setImageErrors] = useState<Record<string, boolean>>({});
|
const [imageErrors, setImageErrors] = useState<Record<string, boolean>>({});
|
||||||
const [sortOrder, setSortOrder] = useState<"default" | "asc" | "desc">(
|
const [sortOrder, setSortOrder] = useState<"default" | "asc" | "desc">(
|
||||||
@@ -47,7 +49,7 @@ export function ImageAltDisplay({ images }: ImageAltDisplayProps) {
|
|||||||
if (sortOrder === "asc") {
|
if (sortOrder === "asc") {
|
||||||
return sizeA - sizeB;
|
return sizeA - sizeB;
|
||||||
} else {
|
} else {
|
||||||
return sizeB - sizeA;
|
return sizeB - a.size;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +141,7 @@ export function ImageAltDisplay({ images }: ImageAltDisplayProps) {
|
|||||||
<div className="flex-grow min-w-0">
|
<div className="flex-grow min-w-0">
|
||||||
<div className="flex justify-between items-start gap-2">
|
<div className="flex justify-between items-start gap-2">
|
||||||
<p className="text-sm text-muted-foreground break-all flex-grow">
|
<p className="text-sm text-muted-foreground break-all flex-grow">
|
||||||
{image.src}
|
<KeywordHighlighter text={image.src} keyword={keyword} />
|
||||||
</p>
|
</p>
|
||||||
{image.size !== null && (
|
{image.size !== null && (
|
||||||
<Badge
|
<Badge
|
||||||
@@ -153,7 +155,8 @@ export function ImageAltDisplay({ images }: ImageAltDisplayProps) {
|
|||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
{image.alt ? (
|
{image.alt ? (
|
||||||
<p className="text-sm text-foreground bg-muted/50 p-2 rounded-md">
|
<p className="text-sm text-foreground bg-muted/50 p-2 rounded-md">
|
||||||
<span className="font-semibold">Alt:</span> {image.alt}
|
<span className="font-semibold">Alt:</span>{" "}
|
||||||
|
<KeywordHighlighter text={image.alt} keyword={keyword} />
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<Badge variant="destructive">Missing alt text</Badge>
|
<Badge variant="destructive">Missing alt text</Badge>
|
||||||
|
|||||||
@@ -437,7 +437,10 @@ export function MetaForm() {
|
|||||||
<TabsContent value="headlines">
|
<TabsContent value="headlines">
|
||||||
<Card className="w-full shadow-lg rounded-lg">
|
<Card className="w-full shadow-lg rounded-lg">
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<HeadlineTree headlines={metaData.headlines} />
|
<HeadlineTree
|
||||||
|
headlines={metaData.headlines}
|
||||||
|
keyword={metaData.keyword}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
@@ -447,7 +450,10 @@ export function MetaForm() {
|
|||||||
<TabsContent value="images">
|
<TabsContent value="images">
|
||||||
<Card className="w-full shadow-lg rounded-lg">
|
<Card className="w-full shadow-lg rounded-lg">
|
||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<ImageAltDisplay images={metaData.images} />
|
<ImageAltDisplay
|
||||||
|
images={metaData.images}
|
||||||
|
keyword={metaData.keyword}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user