[dyad] Added keyword counting feature - wrote 2 file(s)
This commit is contained in:
@@ -15,7 +15,7 @@ export interface HeadlineNode {
|
|||||||
children: HeadlineNode[];
|
children: HeadlineNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function extractMetaData(url: string) {
|
export async function extractMetaData(url: string, keyword?: string) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return { error: "URL is required." };
|
return { error: "URL is required." };
|
||||||
}
|
}
|
||||||
@@ -112,6 +112,15 @@ export async function extractMetaData(url: string) {
|
|||||||
path.push(node);
|
path.push(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let keywordCount: number | null = null;
|
||||||
|
const trimmedKeyword = keyword?.trim();
|
||||||
|
if (trimmedKeyword) {
|
||||||
|
const bodyText = $("body").text();
|
||||||
|
const regex = new RegExp(trimmedKeyword, "gi");
|
||||||
|
const matches = bodyText.match(regex);
|
||||||
|
keywordCount = matches ? matches.length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
@@ -119,6 +128,8 @@ export async function extractMetaData(url: string) {
|
|||||||
image,
|
image,
|
||||||
faq: faqData.length > 0 ? faqData : null,
|
faq: faqData.length > 0 ? faqData : null,
|
||||||
headlines: headlines.length > 0 ? headlines : null,
|
headlines: headlines.length > 0 ? headlines : null,
|
||||||
|
keyword: trimmedKeyword || null,
|
||||||
|
keywordCount,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -5,7 +5,15 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Globe, Edit, Check, Loader2, X, ImageOff } from "lucide-react";
|
import {
|
||||||
|
Globe,
|
||||||
|
Edit,
|
||||||
|
Check,
|
||||||
|
Loader2,
|
||||||
|
X,
|
||||||
|
ImageOff,
|
||||||
|
Search,
|
||||||
|
} from "lucide-react";
|
||||||
import { extractMetaData, type HeadlineNode } from "@/app/actions";
|
import { extractMetaData, type HeadlineNode } from "@/app/actions";
|
||||||
import { LengthIndicator } from "./length-indicator";
|
import { LengthIndicator } from "./length-indicator";
|
||||||
import { CopyButton } from "./copy-button";
|
import { CopyButton } from "./copy-button";
|
||||||
@@ -21,10 +29,13 @@ interface MetaData {
|
|||||||
image?: string | null;
|
image?: string | null;
|
||||||
faq?: { question: string; answer: string }[] | null;
|
faq?: { question: string; answer: string }[] | null;
|
||||||
headlines?: HeadlineNode[] | null;
|
headlines?: HeadlineNode[] | null;
|
||||||
|
keyword?: string | null;
|
||||||
|
keywordCount?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MetaForm() {
|
export function MetaForm() {
|
||||||
const [url, setUrl] = useState("");
|
const [url, setUrl] = useState("");
|
||||||
|
const [keyword, setKeyword] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [metaData, setMetaData] = useState<MetaData | null>(null);
|
const [metaData, setMetaData] = useState<MetaData | null>(null);
|
||||||
@@ -53,7 +64,7 @@ export function MetaForm() {
|
|||||||
setIsEditingDescription(false);
|
setIsEditingDescription(false);
|
||||||
setImageError(false);
|
setImageError(false);
|
||||||
|
|
||||||
const result = await extractMetaData(url);
|
const result = await extractMetaData(url, keyword);
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
setError(result.error);
|
setError(result.error);
|
||||||
@@ -66,6 +77,7 @@ export function MetaForm() {
|
|||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setUrl("");
|
setUrl("");
|
||||||
|
setKeyword("");
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setError(null);
|
setError(null);
|
||||||
setMetaData(null);
|
setMetaData(null);
|
||||||
@@ -89,6 +101,17 @@ export function MetaForm() {
|
|||||||
onChange={(e) => setUrl(e.target.value)}
|
onChange={(e) => setUrl(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="relative w-full sm:w-auto">
|
||||||
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-muted-foreground" />
|
||||||
|
<Input
|
||||||
|
name="keyword"
|
||||||
|
type="text"
|
||||||
|
placeholder="Keyword (optional)"
|
||||||
|
className="pl-10 h-12 text-base rounded-lg shadow-sm sm:w-64"
|
||||||
|
value={keyword}
|
||||||
|
onChange={(e) => setKeyword(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
@@ -276,6 +299,26 @@ export function MetaForm() {
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{metaData.keyword &&
|
||||||
|
typeof metaData.keywordCount === "number" && (
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-card-foreground">
|
||||||
|
Keyword: "{metaData.keyword}"
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mt-1 mb-2">
|
||||||
|
The number of times this keyword appears on the
|
||||||
|
page.
|
||||||
|
</p>
|
||||||
|
<div className="text-foreground bg-muted p-3 rounded-md min-h-[40px] flex items-center">
|
||||||
|
<span className="font-mono text-2xl font-bold">
|
||||||
|
{metaData.keywordCount}
|
||||||
|
</span>
|
||||||
|
<span className="ml-2 text-muted-foreground">
|
||||||
|
occurrences
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user