feat: major update - Markdown Editor, CodeMirror upgrades, SEO improvements, tool cleanup

- Added new Markdown Editor with live preview, GFM support, PDF/HTML/DOCX export
- Upgraded all paste fields to CodeMirror with syntax highlighting and expand/collapse
- Enhanced Object Editor with advanced URL fetching and preview mode
- Improved export views with syntax highlighting in Table/Object editors
- Implemented SEO improvements (FAQ schema, breadcrumbs, internal linking)
- Added Related Tools recommendations component
- Created custom 404 page with tool suggestions
- Consolidated tools: removed JSON, Serialize, CSV-JSON (merged into main editors)
- Updated documentation and cleaned up redundant files
- Updated release notes with user-centric improvements
This commit is contained in:
dwindown
2025-10-22 15:20:22 +07:00
parent 08d345eaeb
commit fb9c944366
40 changed files with 6927 additions and 1714 deletions

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { Helmet } from 'react-helmet-async';
import TOOL_FAQS from '../data/faqs';
const SEO = ({
title,
@@ -7,7 +8,8 @@ const SEO = ({
keywords,
path = '/',
type = 'website',
image = 'https://dewe.dev/og-image.png'
image = 'https://dewe.dev/og-image.png',
toolId = null
}) => {
const siteUrl = 'https://dewe.dev';
const fullUrl = `${siteUrl}${path}`;
@@ -17,6 +19,47 @@ const SEO = ({
const defaultKeywords = 'developer tools, json editor, csv converter, base64 encoder, url encoder, code beautifier, diff tool, web developer utilities, online tools';
const metaKeywords = keywords || defaultKeywords;
// Get FAQ data for this tool
const faqs = toolId && TOOL_FAQS[toolId] ? TOOL_FAQS[toolId] : null;
// Generate breadcrumb schema
const breadcrumbSchema = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": siteUrl
}
]
};
// Add current page to breadcrumb if not homepage
if (path !== '/') {
breadcrumbSchema.itemListElement.push({
"@type": "ListItem",
"position": 2,
"name": title || "Page",
"item": fullUrl
});
}
// Generate FAQ schema if FAQs exist
const faqSchema = faqs ? {
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": faqs.map(faq => ({
"@type": "Question",
"name": faq.question,
"acceptedAnswer": {
"@type": "Answer",
"text": faq.answer
}
}))
} : null;
return (
<Helmet>
{/* Basic Meta Tags */}
@@ -46,7 +89,7 @@ const SEO = ({
<meta name="author" content="Developer Tools" />
<meta name="language" content="English" />
{/* JSON-LD Structured Data */}
{/* JSON-LD Structured Data - WebApplication */}
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
@@ -68,6 +111,18 @@ const SEO = ({
}
})}
</script>
{/* JSON-LD Structured Data - Breadcrumb */}
<script type="application/ld+json">
{JSON.stringify(breadcrumbSchema)}
</script>
{/* JSON-LD Structured Data - FAQ (if available) */}
{faqSchema && (
<script type="application/ld+json">
{JSON.stringify(faqSchema)}
</script>
)}
</Helmet>
);
};