بینش معماری

اصول راهنما

معماری برپای اصل جدا‌سازی نگرانی‌ها است :

  • محتوا : فایل‌های AsciiDoc ساختار یافته با متاداده‌های غنی

  • معرفی : قالب‌های Thymeleaf قابلِ استفاده دوباره

  • داده‌ها : مدل استخراج خودکار توسط JBake از ویژگی‌های AsciiDoc

  • استایل: Bootstrap 5 برای اتساق بصری

انتخاب استراتژیک : AsciiDoc برای پورتفولیو

Table 1. چرا AsciiDoc ?
معیار مزیت

همسویی

مثل قالب مقالات وبلاگ

متاداده

ویژگی‌های ساختاری و قابل توسعه (project-*)

قابلیت نگهداری

ویرایش ساده متن، گیت قابل نسخ

انعطاف‌پذیری

ممکن است شامل محتوای غنی (جداول، کد، تصاویر) باشد.

قالب‌سازی

JBake به‌صورت خودکار ویژگی‌ها را برای Thymeleaf استخراج می‌کند

مدل داده

هر پروژه پورتفولیو یک سند AsciiDoc است که :

  • میتادیتای سربرگ : اطلاعات ساختار‌دار (مشتری، مدت، فناوری‌ها، و غیره)

  • بدن سند : توضیح داستانی، چالش‌ها، راه‌حل‌ها، نتایج

  • ویژگی‌های سفارشی : پیشوند شده`project-*`برای استخراج خودکار

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "پروژه"
  +jbake-status: published|draft
  +jbake-date: Date
  +jbake-tags: List<String>
  --
  +project-category: String
  +project-client: String
  +project-duration: String
  +project-role: String
  +project-thumbnail: String
  +project-gallery: List<String>
  +project-tech-stack: String
  +project-highlights: List<String>
  +project-demo-url: String
  +project-github-url: String
  --
  +body: HTML (converti)
}

class JBakeEngine {
  +parse(asciidoc)
  +extractMetadata()
  +convertToHTML()
}

class ThymeleafTemplate {
  +portfolio.html
  +project.html
  +partials/project-card.html
}

class PortfolioPage {
  +published_projects: List
  +filtres: categories
}

ProjetAsciiDoc --> JBakeEngine : parse
JBakeEngine --> ThymeleafTemplate : fournit données
ThymeleafTemplate --> PortfolioPage : génère
@enduml

موردهای استفاده دقیق

UC1 : افزودن یک آیتم به پورتفو

فلوز نرمال

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "ویرایشگر
متن" as editor
participant "File\nAsciiDoc" as file
participant "JBake
موتور" as jbake
participant "سایت\nثابت" as site

dev -> editor : Créer nouveau fichier
activate editor
editor -> file : portfolio/nouveau-projet.adoc
activate file

dev -> editor : Rédiger en-tête avec métadonnées\n(titre, type=project, status=published,\nattributs project-*)
dev -> editor : Rédiger contenu narratif\n(contexte, défis, solutions)
dev -> editor : Ajouter images dans assets/img/portfolio/

editor -> file : Sauvegarder
deactivate editor

dev -> jbake : Lancer build (jbake -b)
activate jbake
jbake -> file : Lire et parser
jbake -> jbake : Extraire métadonnées
jbake -> jbake : Convertir AsciiDoc → HTML
jbake -> jbake : Appliquer template project.html
jbake -> jbake : Ajouter à la liste portfolio.html
jbake -> site : Générer pages statiques
deactivate jbake

dev -> site : Vérifier résultat
activate site
site --> dev : Afficher projet
deactivate site
@enduml

قالب فایلی که باید ایجاد شود

توسعه‌دهنده می‌سازد`content/portfolio/nom-projet.adoc`با یک ساختار استاندارد :

  • سربرگ با تمام ویژگی‌های مورد نیاز

  • بخش‌های استانداردی (زمینه, چالش‌ها, راه‌حل‌ها, نتایج)

  • نامگذاری همسو تصاویر

نقاط اعتبارسنجی

  • ویژگی‌های الزامی وجود دارند`jbake-type`, jbake-status, project-thumbnail)

  • تصاویر ارجاع‌شده در`assets/img/portfolio/`

  • ساخت JBake با موفقیت و بدون خطا انجام می‌شود

  • پروژه در صفحه پورتفولیو نمایش داده می‌شود

  • صفحه‌ی فردی پروژه به درستی نمایش داده می‌شود

UC2 : حذف یک عنصر از پورتفو

فلکس نمینی

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "سیستم\nفایل‌ها" as fs
participant "JBake
موتور" as jbake
participant "سایت
استاتیک" as site
database "کش\nJBake" as cache

dev -> fs : Supprimer portfolio/projet-ancien.adoc
activate fs
fs --> dev : Fichier supprimé
deactivate fs

dev -> fs : (Optionnel) Supprimer images associées\nassets/img/portfolio/projet-ancien-*
activate fs
fs --> dev : Images supprimées
deactivate fs

dev -> cache : Nettoyer cache JBake
activate cache
cache --> dev : Cache vidé
deactivate cache

dev -> jbake : Rebuild complet (jbake -b)
activate jbake
jbake -> jbake : Scanner content/portfolio/
jbake -> jbake : Projet absent → non généré
jbake -> jbake : Régénérer portfolio.html\n(sans le projet supprimé)
jbake -> site : Déployer nouveau build
deactivate jbake

dev -> site : Vérifier
activate site
site --> dev : Projet absent de la liste
deactivate site
@enduml

استراتژی جایگزین : بایگانی

به جای حذف دائم، امکان ایجاد یک پوشه وجود دارد.content/portfolio/archive/ :

  • به جای حذف آن، فایل را جابجا کنید

  • به‌راحتی امکان بازگردانی را فراهم می‌کند

  • تاریخچه Git را واضح‌تر نگه دار

پاک‌سازی منابع

  • بررسی تصاویر یتیم در`assets/img/portfolio/`

  • تصاویر که توسط پروژه‌های دیگر ارجاع داده نشده‌اند را حذف کنید

  • پاک کردن کش JBake برای جلوگیری از مراجع فانتوم

UC3 : تنظیم به پیش‌نویس (پیش‌نویس)

فلوكس نومینال

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "فایل
AsciiDoc" as file
participant "JBake
موتور" as jbake
participant "سایت
استاتیک" as site

dev -> file : Ouvrir portfolio/projet.adoc
activate file

dev -> file : Modifier attribut\n:jbake-status: published\n↓\n:jbake-status: draft

file --> dev : Sauvegardé
deactivate file

dev -> jbake : Rebuild (jbake -b)
activate jbake
jbake -> file : Parser le fichier
jbake -> jbake : Détecter status=draft
jbake -> jbake : Exclure de published_projects
jbake -> jbake : Ne pas créer page publique
note right
  Le projet existe toujours
  mais n'est pas publié
end note
jbake -> site : Générer site (sans ce projet)
deactivate jbake

dev -> site : Vérifier portfolio
activate site
site --> dev : Projet absent de la liste publique
deactivate site
@enduml

وضعیت‌های ممکن

@startuml
skinparam backgroundColor #FEFEFE

[*] --> Draft : Création initiale
Draft --> Published : Validation et publication
Published --> Draft : Retrait temporaire
Draft --> Archived : Projet abandonné
Published --> Archived : Projet obsolète
Archived --> [*] : Suppression définitive
Published --> Published : Mises à jour

note right of Draft
  :jbake-status: draft
  Non visible publiquement
  Utile pour projets en cours
end note

note right of Published
  :jbake-status: published
  Visible sur le portfolio
  Indexé par JBake
end note

note right of Archived
  Déplacé dans archive/
  ou jbake-status: archived
  Non publié mais conservé
end note
@enduml

موردهای استفادهٔ معمولی

  • پروژه در حال تدوین : ایجاد به‌عنوان پیش‌نویس، منتشر کردن وقتی آماده باشد

  • پروژه موقتاً محرمانه : به پیش‌نویس 전환 تا زمان توافق با مشتری

  • به‌روزرسانی بزرگ : تغییر به پیش‌نویس، ویرایش، انتشار مجدد

  • A/B testing : به‌عنوان پیش‌نویس کپی کردن، تست کردن و انتشار بهترین نسخه

معماری تمپلیت

استراتژی الگوهای قابل استفاده مجدد

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "قالب‌های Thymeleaf" {
  component [index.html] as index
  component [portfolio.html] as portfolio
  component [project.html] as project

  package "قسمت‌های جزئی" {
    component [header.html] as header
    component [footer.html] as footer
    component [project-card.html] as card
    component [tech-badge.html] as badge
    component [gallery.html] as gallery
  }
}

package "داده‌های JBake" {
  database "پروژه‌های منتشر شده" as data
  database "محتوا (پروژه)" as content
}

index --> header
index --> footer

portfolio --> header
portfolio --> footer
portfolio --> card
data --> portfolio : itération

project --> header
project --> footer
project --> badge
project --> gallery
content --> project : projet individuel

note right of card
  Fragment réutilisable
  pour afficher une carte
  de projet avec :
  - thumbnail
  - titre
  - tags
  - highlights
end note
@enduml

الگوی استخراج داده‌ها

JBake به صورت خودکار ویژگی‌های AsciiDoc را به ویژگی‌های قابل دسترسی در Thymeleaf تبدیل می‌کند:

@startuml
skinparam backgroundColor #FEFEFE

rectangle "سند AsciiDoc" {
  (":project-client: Acme Corp") as attr1
  (":project-duration: 6 ماه") as attr2
  (":project-tags: java, react") as attr3
}

rectangle "مدل JBake" {
  (content['project-client']) as prop1
  (content['project-duration']) as prop2
  (content.tags) as prop3
}

rectangle "قالب Thymeleaf" {
  (th:text="${project['project-client']}") as tmpl1
  (th:text="${project['project-duration']}") as tmpl2
  (th:each="برچسب : ${project.tags}") as tmpl3
}

attr1 --> prop1 : parsing
attr2 --> prop2 : parsing
attr3 --> prop3 : parsing

prop1 --> tmpl1 : binding
prop2 --> tmpl2 : binding
prop3 --> tmpl3 : binding
@enduml

قوانین نامگذاری

  • ویژگی‌های پروژه : پیشوند`project-*` (ex: project-client, project-tech-stack)

  • فایل‌ها : kebab-case (مثال:`ecommerce-platform.adoc`)

  • Images : پیشوند نام پروژه (مثال:`ecommerce-platform-thumb.jpg`)

  • Templates : نام کارکردی (مثال:`project-card.html`, tech-badge.html)

فرآیند کار انتشار

خط أنابيب توسعه

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "پروژه"
  +jbake-status: published|draft
  +jbake-date: Date
  +jbake-tags: List<String>
  __
  +project-category: String
  +project-client: String
  +project-duration: String
  +project-role: String
  +project-thumbnail: String
  +project-gallery: List<String>
  +project-tech-stack: String
  +project-highlights: List<String>
  +project-demo-url: String
  +project-github-url: String
  __
  +body: HTML (converti)
}

class JBakeEngine {
  +parse(asciidoc)
  +extractMetadata()
  +convertToHTML()
}

class ThymeleafTemplate {
  +portfolio.html
  +project.html
  +partials/project-card.html
}

class PortfolioPage {
  +published_projects: List
  +filtres: categories
}

ProjetAsciiDoc --> JBakeEngine : parse
JBakeEngine --> ThymeleafTemplate : fournit données
ThymeleafTemplate --> PortfolioPage : génère
@enduml

محیط‌ها

محیط استفاده وضعیت پذیرفته‌شده

محلی

توسعه و پیش‌نمایش

پیش‌نویس، منتشر شده

آماده‌سازی

اعتبار پیش تولید

منتشر شده فقط

تولید

سایت عمومی

فقط منتشر شده

قابلیت گسترش

افزودن ویژگی‌های جدید

برای غنی‌سازی مدل داده، کافی است ویژگی‌های جدیدی با پیشوند اضافه کنید.project-* :

  • project-awards: جوایز و تقدیرات

  • project-testimonial: نقل‌قول مشتری

  • project-team-size: اندازه تیم

  • `project-budget-range`دامنه بودجه

این ویژگی‌ها به طور خودکار در قالب‌ها در دسترس می‌شوند بدون نیاز به تغییر در موتور JBake

دسته‌بندی پیشرفته

@startuml
skinparam backgroundColor #FEFEFE

object Projet {
  project-category = "وب"
  project-subcategory = "تجاره الکترونیک"
  project-industry = "فروش جزئی"
  project-complexity = "بالا"
}

object Taxonomie {
  categories : [web, mobile, data, devops]
  subcategories : Map<category, List>
  industries : [retail, finance, healthcare, ...]
  complexities : [low, medium, high]
}

Projet --> Taxonomie : classifié selon

note right of Taxonomie
  Permet filtrage multi-critères
  dans le template portfolio.html
  via JavaScript ou côté serveur
end note
@enduml

روش‌های خوب

سازماندهی فایل‌ها

  • یک فایل = یک پروژه : از ترکیب چندین پروژه خودداری کنید

  • تصاویر در پوشه مخصصassets/img/portfolio/nom-projet/

  • نامگذاری سازگار : تسهیل جستجو و نگهداری

  • Versioning Git : پیگیری کامل تغییرات

مدیریت محتوا

  • وضعیت پیش‌نویس پیش‌فرض : فقط وقتی آماده باشد منتشر شود

  • بررسی قبل از انتشار : تأیید کیفیت و حریم خصوصی

  • متادیتاهای کامل : تمام فیلدهای مرتبط را پر کنید

  • محتوای روایت غنی : به متاداده‌ها محدود نشوید

عملکرد

  • بهینه‌سازی تصاویر : فشرده‌سازی قبل از commit

  • صفحه‌بندی در صورت نیاز : اگر >20 پروژه‌ها

  • Lazy loading : تصاویر گالری‌ها به‌صورت تحت‌طلب بارگذاری می‌شوند

  • کش مرورگر : هدرهای مناسب برای دارایی‌ها

نتیجه

این معماری امکان می‌دهد:

  • سادگی استفاده : افزودن یک پروژه = ایجاد یک فایل متنی

  • لچ‌پذیری : قابل توسعه با ویژگی‌های جدید

  • قابلیت نگهداری : جدایی محتوا/نمایش

  • پیگیری : نسخهٔ کامل Git

  • اتوماسیون : ساخت و استقرار مستمر ممکن است

انتخاب AsciiDoc همگونی با بقیه سایت را تضمین می‌کند و در عین حال ثروت ماداده‌های لازم برای یک پورتفوی حرفه‌ای را ارائه می‌دهد.

مقالات مرتبط