Архитектурное видение

руководящий принцип

Архитектура основана на принципе разделения ответственности :

  • Содержание : структурированные файлы AsciiDoc с богатыми метаданными

  • Презентация : повторно используемые шаблоны Thymeleaf

  • Данные: модель автоматически извлечённая JBake из атрибутов AsciiDoc

  • Style : Bootstrap 5 для визуальной согласованности

Стратегический выбор: AsciiDoc для портфолио

Table 1. Почему AsciiDoc ?
Критерий Преимущество

Согласованность

Тот же формат, что и у статей в блоге

Метаданные

Структурированные и расширяемые атрибуты (project-*)

поддерживаемость

Простой текстовый редактор, совместимый с Git

Гибкость

Может содержать богатый контент (таблицы, код, изображения)

Шаблонизация

JBake автоматически извлекает атрибуты для Thymeleaf

Модель данных

Каждый проект-портфолио — это документ AsciiDoc с :

  • Метаданные заголовка : структурированная информация (клиент, продолжительность, технологии и т.д.)

  • Тело документа : описание повествования, проблемы, решения, результаты

  • Пользовательские атрибуты : с префиксом`project-*`для автоматического извлечения

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "project"
  +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 "Éditeur\nTexte" as editor
participant "Fichier\nAsciiDoc" as file
participant "JBake\nEngine" as jbake
participant "Site\nStatique" 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 "Système\nFichiers" as fs
participant "JBake\nEngine" as jbake
participant "Site\nStatique" as site
database "Cache\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 "Fichier\nAsciiDoc" as file
participant "JBake\nEngine" as jbake
participant "Site\nStatique" 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 "Templates Thymeleaf" {
  component [index.html] as index
  component [portfolio.html] as portfolio
  component [project.html] as project

  package "Partials" {
    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 "Données JBake" {
  database "published_projects" as data
  database "content (projet)" 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`)

  • Шаблоны : функциональное имя (пример:`project-card.html`, tech-badge.html)

Рабочий процесс публикации

Конвейер разработки

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "project"
  +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-*`(Empty output)

  • project-awards: Награды и признания

  • project-testimonial: Цитата клиента

  • `project-team-size`Размер команды

  • project-budget-range: Бюджетный диапазон

Эти атрибуты автоматически становятся доступными в шаблонах без изменения движка JBake.

Расширенная категоризация

@startuml
skinparam backgroundColor #FEFEFE

object Projet {
  project-category = "web"
  project-subcategory = "ecommerce"
  project-industry = "retail"
  project-complexity = "high"
}

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 : полное отслеживание изменений

Управление контентом

  • Статус draft по умолчанию : публиковать только когда готов

  • Обзор перед публикацией : проверка качества и конфиденциальности

  • Полные метаданные : заполнить все соответствующие поля

  • Богатый нарративный контент : не ограничивайтесь метаданными

Производительность

  • Оптимизировать изображения : сжатие перед коммитом

  • Пагинация при необходимости : если >20 проектов

  • Lazy loading : изображения галерей, загружаемые по требованию

  • Кеш браузера : подходящие заголовки для assets

Заключение

Эта архитектура позволяет :

  • Простота использования : добавить проект = создать текстовый файл

  • Гибкость : расширяется за счёт новых атрибутов

  • Поддерживаемость : разделение содержимого и представления

  • Трассируемость : полное версионирование Git

  • Автоматизация : возможна непрерывная сборка и развертывание

Выбор AsciiDoc обеспечивает согласованность с остальной частью сайта, одновременно предоставляя богатство метаданных, необходимое для профессионального портфолио.

Похожие статьи