Skip to content

Latest commit

 

History

History
622 lines (522 loc) · 18.8 KB

File metadata and controls

622 lines (522 loc) · 18.8 KB

📋 پیشرفت پروژه - چک‌لیست تکمیل

🎯 خلاصه وضعیت

# بخش وضعیت پیشرفت
1️⃣ تعریف دقیق «واحد محتوا» (Production-Grade) ✅ COMPLETE 100%
2️⃣ تعریف ساختار URL نهایی (تایید شده) ✅ COMPLETE 100%
3️⃣ تعریف قرارداد Frontmatter (تنظیم‌شده) ✅ COMPLETE 100%
4️⃣ Generator Functions (مشتق‌سازی) ✅ COMPLETE 100%
5️⃣ Content Loader & Integration ✅ COMPLETE 100%

1️⃣ تعریف دقیق «واحد محتوا» (Production-Grade) - COMPLETED

فایل‌های ایجاد‌شده:

  • types/doc-page.ts (1,086 خط) - Core models + DocPage + RenderedDocPage + Validation
  • types/doc-page-generator.ts - Generator functions (generateDerivedSeo, generateArticleSchema, etc.)
  • types/doc-page.examples.ts - Real-world examples (doc، guide، service)
  • types/index.ts - Exports

تست‌های انجام‌شده:

  • tests/doc-page.validation.test.ts (41 تست)
  • tests/doc-page.generator.test.ts (33 تست)
  • tests/doc-page.seo-safety.test.ts (34 تست)
  • نتیجه: 108 تست ✅ PASS | 0 فیلیور ⏱️ 291ms

2️⃣ تعریف ساختار URL نهایی (تایید شده) - COMPLETE (Documented)

تصمیم نهایی: /docs/{slug} و /services/{slug}

3️⃣ تعریف قرارداد Frontmatter (تنظیم‌شده) - COMPLETE (Documented)

Frontmatter Contract: YAML format با layout, type, title, description, category, order, index/robots, author, timestamps

4️⃣ Generator Functions (مشتق‌سازی) - Frontmatter Parser - COMPLETED

فایل‌های ایجاد‌شده:

  • types/frontmatter.ts (280 خط) - FrontmatterRaw, FrontmatterParsed, Validators, Helpers
  • types/frontmatter-parser.ts (520+ خط) - Parser functions, converters, URL/breadcrumb/TOC generators
  • types/frontmatter.examples.ts (400+ خط) - 5 real-world examples (doc, service, draft, farsi, invalid)
  • types/index.ts - Updated with frontmatter exports

تست‌های انجام‌شده:

  • tests/frontmatter.test.ts (48 تست)
    • Layer 1: Input Validation (26 tests)
    • Layer 2: Conversion (7 tests)
    • Layer 3: Helper Functions (9 tests)
    • Layer 3: Error Cases (6 tests)
  • نتیجه: 48 تست ✅ PASS | 0 فیلیور ⏱️ 306ms

فیچرهای پیاده‌شده:

  • ✅ parseFrontmatter() - Validate YAML frontmatter with detailed errors
  • ✅ frontmatterToDocPage() - Convert parsed frontmatter to DocPage
  • ✅ frontmatterToDocPageE2E() - End-to-end pipeline with validation
  • ✅ generateUrlPath() - Auto URL path generation
  • ✅ generateBreadcrumbsFromPath() - Auto breadcrumb generation
  • ✅ extractTableOfContents() - Auto TOC extraction from markdown
  • ✅ Deterministic & pure functions
  • ✅ Multi-language support (lang field preserved)
  • ✅ Flexible input handling (string/object authors, multiple date formats)

TOTAL TEST RESULTS AFTER SECTION 4:

  • ✅ 156 Tests Total
    • Section 1 (DocPage): 108 ✅
    • Section 4 (Frontmatter): 48 ✅
  • ✅ 0 Failures
  • ⏱️ 350ms

5️⃣ Content Loader & Integration - COMPLETED

فایل‌های ایجاد‌شده:

  • types/content-loader.ts (236 خط) - Type system (RawMarkdownFile, LoadedMarkdownFile, ContentLoaderConfig, ContentLoaderOptions, etc.)
  • types/content-loader-utils.ts (450+ خط) - Core functions for extracting, parsing, loading, and filtering
  • types/content-loader.examples.ts (369 خط) - Real-world examples (installation, web-scraping, draft, farsi)
  • types/index.ts - Updated with content-loader exports

تست‌های انجام‌شده:

  • tests/content-loader.test.ts (41 تست) - 4-layer comprehensive test suite
    • Layer 1: Extraction (Frontmatter & Markdown parsing) - 13 tests ✅
    • Layer 2: File Loading (Parse & Validate) - 9 tests ✅
    • Layer 3: DocPage Generation (Conversion & Validation) - 9 tests ✅
    • Layer 4: Filtering & Sorting - 10 tests ✅
  • نتیجه: 41 تست ✅ PASS | 0 فیلیور ⏱️ 317ms

فیچرهای پیاده‌شده:

  • ✅ extractMarkdownParts() - Parse YAML/TOML/JSON frontmatter with nested object support
  • ✅ parseYAMLFrontmatter() - Advanced YAML parser handling nested objects (author, etc.)
  • ✅ extractFileMetadata() - Extract slug, category, ID from file path
  • ✅ loadMarkdownFile() - Load and validate markdown files with frontmatter
  • ✅ loadedFileToDocPage() - Convert loaded files to DocPage objects
  • ✅ filterAndSortDocPages() - Query pages with filtering (category, lang, status, type), sorting, pagination
  • ✅ Deterministic & pure functions
  • ✅ Comprehensive error handling
  • ✅ Multi-language support
  • ✅ Draft status handling

TOTAL TEST RESULTS AFTER SECTION 5:

  • ✅ 197 Tests Total
    • Section 1 (DocPage): 108 ✅
    • Section 4 (Frontmatter): 48 ✅
    • Section 5 (Content Loader): 41 ✅
  • ✅ 0 Failures
  • ⏱️ 345ms

✅ چک‌لیست طراحی ساختار مستندات

1️⃣ تعریف دقیق «واحد محتوا» (Production-Grade)

🔹 Core Model: DocPage (Frozen – لاغر و پایدار)

/**
 * Core Content Model - SEO Indexable, API Independent
 * این مدل هستهٔ محتوا است و هرگز تغییر نمی‌کند
 * 
 * ✅ لاغر: فقط محتوا و metadata اساسی
 * ✅ مستقل: از API و Dashboard بی‌طرف
 * ✅ قابل‌نگهداری: Backward compatible
 */

type DocPageType = 'doc' | 'guide' | 'service'
type DocPageStatus = 'published' | 'draft'
type RobotsDirective = 'index,follow' | 'noindex,follow' | 'index,nofollow' | 'noindex,nofollow'

interface AuthorInfo {
  name: string
  url?: string
}

interface BreadcrumbItem {
  name: string
  item: string  // Absolute URL
}

interface HeadingItem {
  level: number
  title: string
  anchor: string
}

interface DocPage {
  // === Core Identifiers ===
  id: string
  slug: string
  lang: string

  // === Content Type ===
  type: DocPageType

  // === Core Content ===
  title: string                    // Unique, keyword-rich (50-60 chars)
  description: string              // 120-160 chars for meta tag
  body: string                      // Markdown content

  // === Organization ===
  category: string                 // e.g., 'docs', 'services'
  order: number                     // Display order

  // === Authorship ===
  author: AuthorInfo

  // === Timestamps ===
  publishedAt: Date
  updatedAt: Date

  // === URLs ===
  urlPath: string                  // e.g., /docs/installation

  // === Navigation (Generated) ===
  breadcrumbs: BreadcrumbItem[]
  toc: HeadingItem[]

  // === SEO Control (Unified) ===
  robots: RobotsDirective          // 'index,follow' | 'noindex,follow' | etc.
                                   // covers both indexing and following

  // === Publishing Status ===
  status: DocPageStatus           // 'published' | 'draft'
}

🔹 Derived Model: RenderedDocPage (Generated بعد از DocPage)

/**
 * Rendered Model - توسط Generator ایجاد می‌شود
 * این مدل DocPage را غنی‌سازی می‌کند بدون آلودگی هسته
 */

interface RenderedDocPage extends DocPage {
  // === Derived SEO Metadata ===
  derivedSeo: {
    title: string
    description: string
    canonical: string               // ✅ Generated from siteUrl + urlPath
    ogTitle: string
    ogDescription: string
    ogImage?: string
  }

  // === Generated Metadata ===
  schema: {
    techArticle: any  // JSON-LD Object – type depends on DocPageType
    breadcrumbList: any  // JSON-LD Object
  }

  // === Content Metrics (Optional – فقط برای rendering) ===
  readingTime?: number
  difficulty?: 'beginner' | 'intermediate' | 'advanced'

  // === Head Tags (Generated) ===
  head: {
    meta: Array<{
      name?: string
      property?: string
      content: string
    }>
    links: Array<{
      rel: string
      href: string
      type?: string
    }>
  }
}

🔹 Frontmatter Contract (Input)

---
# === Content Identity ===
layout: doc
type: doc
title: Installation & Setup

# === Content Description ===
description: Step-by-step guide to install and set up DevPaper
body: |
  # Installation
  ...

# === Organization ===
category: docs
order: 1

# === SEO Control ===
index: true                        # false برای drafts
robots: index,follow

# === Authorship ===
author:
  name: DevPaper Team
  url: https://DevPaper.dev

# === Timestamps ===
publishedAt: 2025-01-10
updatedAt: 2025-01-15
---

✅ چرا این طراحی بهتر است:

موضوع مشکل قدیم حل جدید
God Object viewCount, featured, pinned, tags ❌ حذف شدند – فقط Core
Schema زوده‌ازحد SchemaMetadata خودش input ✅ Generated توسط Generator
تداخل SEO vs Head دو جا meta تعریف می‌شد ✅ یک سیستم: derivedSeo + head generated
keywords + tags chaos دو فیلد مختلف ✅ حذف – فقط content-based
API Coupling DocPage = API DTO ✅ Decoupled – RenderedDocPage برای rendering
نگهداری ❌ بسیار وابسته ✅ Core frozen + Derived computed
robots duplication index + robots ✅ فقط robots (جامع‌تر)
canonicalUrl safety User input (خطا ممکن) ✅ Generated از siteUrl + urlPath
Schema rigidity Hardcoded TechArticle ✅ Dynamic based on doc.type

2️⃣ تعریف ساختار URL نهایی (تایید شده)

  • ✅ SELECTED: /docs/{slug} و /services/{slug}

  • دلایل:

    • ✅ ساده‌تر و تمیزتر (کمتر نویسی)
    • ✅ بهتر برای SEO (کلمات کلیدی در URL)
    • ✅ سهل‌الاستفاده برای کاربران
    • ✅ بهتر برای breadcrumb navigation
    • ✅ مطابق ساختار فعلی پروژه
  • مثال‌های واقعی:

    • /docs/installation → نصب و راه‌اندازی
    • /docs/configuration → تنظیمات
    • /services/web-scraping → web scraping
    • /services/api-service → سرویس API

3️⃣ تعریف قرارداد Frontmatter (تنظیم‌شده)

🔹 Frontmatter Specification

---
# === Page Identity ===
layout: doc                  # VitePress layout type
type: doc                    # 'doc' | 'guide' | 'service'
title: Installation Guide    # 50-60 chars, keyword-rich
description: >              # 120-160 chars, natural language
  Step-by-step guide to install DevPaper on your system

# === Organization ===
category: docs              # 'docs' | 'services'
order: 1                    # Display order in sidebar

# === SEO Control ===
index: true                 # false برای drafts/internal
robots: index,follow        # Unified directive (covers indexing + following)

# === Authorship ===
author:
  name: DevPaper Team
  url: https://DevPaper.dev

# === Timestamps (شامل در schema) ===
publishedAt: 2025-01-10
updatedAt: 2025-01-15

# === Note: Generated Fields (اینا توسط Generator تولید می‌شوند) ===
# - canonicalUrl
# - urlPath
# - breadcrumbs
# - toc (Table of Contents)
# - derivedSeo
# - schema
---

# Installation Guide

Your markdown content here...

✅ توضیح مهم

📥 INPUT (Frontmatter):
├── title
├── description
├── body
├── category
├── index/robots
└── author, publishedAt, updatedAt

🔄 PROCESSING (Generator):
├── Parse frontmatter → DocPage
├── Generate urlPath: /docs/installation
├── Generate canonicalUrl: https://DevPaper.dev/docs/installation
├── Generate breadcrumbs
├── Generate schemas (TechArticle, Breadcrumb)
└── Generate head meta tags

📤 OUTPUT (RenderedDocPage):
├── All INPUT fields
├── + derivedSeo (title, description, canonical, og*)
├── + schema (techArticle, breadcrumbList)
├── + head (meta, links)
└── Ready for HTML rendering

4️⃣ Generator Functions (مشتق‌سازی)

🔹 Schema Generator (Dynamic Type)

/**
 * Map DocPageType to Schema Type
 */
const schemaTypeMap: Record<DocPageType, string> = {
  doc: 'TechArticle',
  guide: 'Article',
  service: 'WebPage',
}

/**
 * Generate appropriate Schema from DocPage
 * ✅ Type is determined by docType, not hardcoded
 * ✅ Pure function – no side effects
 */
function generateArticleSchema(doc: DocPage, siteUrl: string) {
  const schemaType = schemaTypeMap[doc.type]
  
  return {
    '@context': 'https://schema.org',
    '@type': schemaType,
    headline: doc.title,
    description: doc.description,
    image: `${siteUrl}/images/og-default.png`,
    datePublished: doc.publishedAt.toISOString(),
    dateModified: doc.updatedAt.toISOString(),
    author: {
      '@type': 'Organization',
      name: doc.author.name,
      url: doc.author.url || siteUrl,
    },
    publisher: {
      '@type': 'Organization',
      name: 'DevPaper',
      logo: {
        '@type': 'ImageObject',
        url: `${siteUrl}/logo.svg`,
      },
    },
    url: `${siteUrl}${doc.urlPath}`,  // ✅ Generated from urlPath
    inLanguage: doc.lang,
  }
}

/**
 * Generate Breadcrumb Schema from DocPage
 */
function generateBreadcrumbSchema(doc: DocPage, siteUrl: string) {
  const parts = doc.urlPath.split('/').filter(Boolean)
  const breadcrumbs = [
    {
      '@type': 'ListItem',
      position: 1,
      name: 'Home',
      item: siteUrl,
    },
  ]

  let currentPath = ''
  for (let i = 0; i < parts.length - 1; i++) {
    currentPath += '/' + parts[i]
    breadcrumbs.push({
      '@type': 'ListItem',
      position: breadcrumbs.length + 1,
      name: parts[i].charAt(0).toUpperCase() + parts[i].slice(1),
      item: siteUrl + currentPath,
    })
  }

  breadcrumbs.push({
    '@type': 'ListItem',
    position: breadcrumbs.length + 1,
    name: doc.title,
    item: `${siteUrl}${doc.urlPath}`,  // ✅ Generated from urlPath
  })

  return {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: breadcrumbs,
  }
}

🔹 SEO Metadata Generator

/**
 * Generate derived SEO metadata from DocPage
 * ✅ Deterministic: same input = same output
 * ✅ canonical is computed from siteUrl + urlPath (never user input)
 */
function generateDerivedSeo(doc: DocPage, siteUrl: string) {
  const canonical = `${siteUrl}${doc.urlPath}`  // ✅ Generated, not input
  
  return {
    title: doc.title,
    description: doc.description,
    canonical,
    ogTitle: doc.title,
    ogDescription: doc.description,
    ogImage: `${siteUrl}/images/og-default.png`,
    robots: doc.robots,  // ✅ Unified robots directive
  }
}

/**
 * Generate head meta tags from DocPage
 */
function generateHeadTags(doc: DocPage, siteUrl: string) {
  const derivedSeo = generateDerivedSeo(doc, siteUrl)
  
  return {
    meta: [
      { name: 'description', content: derivedSeo.description },
      { name: 'robots', content: derivedSeo.robots },
      { property: 'og:title', content: derivedSeo.ogTitle },
      { property: 'og:description', content: derivedSeo.ogDescription },
      { property: 'og:image', content: derivedSeo.ogImage },
      { property: 'og:url', content: derivedSeo.canonical },
      { property: 'og:type', content: 'article' },
    ],
    links: [
      { rel: 'canonical', href: derivedSeo.canonical },
    ],
  }
}

🔹 Render Pipeline

/**
 * Transform raw DocPage → RenderedDocPage
 * ✅ Single responsibility: decoration
 * ✅ All outputs are derived, not input
 */
function renderDocPage(
  doc: DocPage,
  siteUrl: string,
): RenderedDocPage {
  const derivedSeo = generateDerivedSeo(doc, siteUrl)
  const head = generateHeadTags(doc, siteUrl)
  const articleSchema = generateArticleSchema(doc, siteUrl)  // ✅ Dynamic type
  const breadcrumbList = generateBreadcrumbSchema(doc, siteUrl)

  return {
    ...doc,
    derivedSeo,
    schema: {
      techArticle: articleSchema,  // ✅ Auto-determined based on doc.type
      breadcrumbList,
    },
    head,
  }
}

✅ مثال عملی

// INPUT: Raw DocPage (فقط محتوا)
const docPage: DocPage = {
  id: 'installation-001',
  slug: 'installation',
  lang: 'en',
  type: 'doc',  // ✅ 'doc' → generates TechArticle
  title: 'Installation Guide',
  description: 'Step-by-step guide to install DevPaper',
  body: '# Installation\n...',
  category: 'docs',
  order: 1,
  author: { name: 'DevPaper Team', url: 'https://DevPaper.dev' },
  publishedAt: new Date('2025-01-10'),
  updatedAt: new Date('2025-01-15'),
  urlPath: '/docs/installation',
  breadcrumbs: [
    { name: 'Home', item: 'https://DevPaper.dev' },
    { name: 'Docs', item: 'https://DevPaper.dev/docs' },
    { name: 'Installation', item: 'https://DevPaper.dev/docs/installation' },
  ],
  toc: [
    { level: 2, title: 'Prerequisites', anchor: 'prerequisites' },
    { level: 2, title: 'Installation Steps', anchor: 'installation-steps' },
  ],
  robots: 'index,follow',  // ✅ Unified (covers both index + follow)
  status: 'published',
}

// OUTPUT: RenderedDocPage (غنی‌شده)
const rendered = renderDocPage(docPage, 'https://DevPaper.dev')

// rendered.derivedSeo
// {
//   title: 'Installation Guide',
//   description: 'Step-by-step guide to install DevPaper',
//   canonical: 'https://DevPaper.dev/docs/installation',  // ✅ Generated
//   ogTitle: 'Installation Guide',
//   ogDescription: 'Step-by-step guide to install DevPaper',
//   robots: 'index,follow'
// }

// rendered.schema.techArticle
// {
//   "@type": "TechArticle",  // ✅ Dynamic based on doc.type
//   "headline": "Installation Guide",
//   "url": "https://DevPaper.dev/docs/installation",  // ✅ Generated from urlPath
//   "datePublished": "2025-01-10T00:00:00.000Z",
//   ...
// }

// rendered.head.meta
// [
//   { name: 'description', content: 'Step-by-step guide to install DevPaper' },
//   { name: 'robots', content: 'index,follow' },
//   { property: 'og:title', content: 'Installation Guide' },
//   { property: 'og:url', content: 'https://DevPaper.dev/docs/installation' },  // ✅ Generated
//   ...
// ]

// rendered.head.links
// [
//   { rel: 'canonical', href: 'https://DevPaper.dev/docs/installation' }  // ✅ Generated
// ]

✅ Schema Type Examples

// Example 1: Technical Documentation
const docType: DocPage = { type: 'doc', ... }
// → generateArticleSchema() returns '@type': 'TechArticle'

// Example 2: Guide / Tutorial
const guideType: DocPage = { type: 'guide', ... }
// → generateArticleSchema() returns '@type': 'Article'

// Example 3: Service Description
const serviceType: DocPage = { type: 'service', ... }
// → generateArticleSchema() returns '@type': 'WebPage'