Hướng dẫn sử dụng PostDecoratorManager để chuyển đổi nội dung sang HTML
Back to ezyarticleTổng quan
PostDecoratorManager là thành phần trung tâm dùng để chuyển đổi hoặc “decorate” nội dung bài viết trước khi hiển thị, preview hoặc trả về qua API.Manager không tự parse từng định dạng nội dung. Thay vào đó, nó tìm các
PostDecorator đã được đăng ký trong container, lọc theo contentType, sắp xếp theo priority, rồi chạy tuần tự các decorator phù hợp. Kết quả đầu ra thường là HTML.Khi nào sử dụng
Dùng
PostDecoratorManager khi cần:- Chuyển EditorJS JSON sang HTML.
- Render nội dung Thymeleaf template sang HTML.
- Thực thi nội dung JavaScript để tạo HTML.
- Áp dụng nhiều bước decorate liên tiếp cho cùng một loại nội dung.
- Preview nội dung trong admin trước khi lưu hoặc xuất bản.
Luồng hoạt động
flowchart TD
A[Client gửi nội dung cần chuyển đổi] --> B[API convert-content]
B --> C[PostDecoratorManager.decorateContent]
C --> D{contentType có rỗng không?}
D -- Có --> E[Dùng HTML làm mặc định]
D -- Không --> F[Dùng contentType từ request]
E --> G[Lấy danh sách PostDecorator theo contentType]
F --> G
G --> H[Sắp xếp decorator theo priority]
H --> I[Chạy từng decorator tuần tự]
I --> J[Decorator gọi converter tương ứng]
J --> K[Trả về HTML đã chuyển đổi]
API chuyển đổi nội dung
Admin cung cấp API:
POST /api/v1/convert-content
API này yêu cầu user đã đăng nhập và thuộc feature quản lý bài viết.
Request body:
{
"contentType": "EDITOR_JS_JSON",
"languageCode": "vi",
"content": "{"blocks":[...]}",
"parameters": {
"name": "EzyArticle"
}
}
Response:
{
"content": "<div class="block-wrapper" type="paragraph"><p>...</p></div>"
}
Nếu
content null, hệ thống xử lý như chuỗi rỗng. Nếu parameters null, hệ thống dùng map rỗng.Cách gọi trong Java
String html = postDecoratorManager.decorateContent(
contentType,
content,
languageCode,
parameters
);
Trong đó:
-
contentType: loại nội dung đầu vào. -
content: nội dung gốc cần chuyển đổi. -
languageCode: mã ngôn ngữ, ví dụvi,en. -
parameters: dữ liệu dùng để thay thế biến trong template hoặc truyền vào converter.
Nếu
contentType rỗng, manager mặc định dùng HTML.
Các contentType mặc định
Các decorator mặc định đang hỗ trợ:
| contentType | Ý nghĩa | Đầu ra |
|---|---|---|
EDITOR_JS_JSON | Chuyển JSON của EditorJS sang HTML | HTML blocks |
THYMELEAF | Render template Thymeleaf với biến truyền vào | HTML |
JAVASCRIPT | Thực thi JavaScript với parameters làm dữ liệu đầu vào | Chuỗi HTML hoặc chuỗi kết quả |
HTML | Mặc định của interface nếu decorator không override | Thường giữ nguyên hoặc decorate thêm |
Cơ chế chọn decorator
PostDecoratorManager lấy toàn bộ bean implement PostDecorator từ singleton factory, sau đó:- Sắp xếp theo
getPriority(), số nhỏ chạy trước. - Gom nhóm decorator theo
getContentTypes(). - Khi convert, chỉ chạy decorator thuộc
contentTypetương ứng. - Kết quả của decorator trước là input của decorator sau.
flowchart LR
A[content ban đầu] --> B[Decorator priority 0]
B --> C[Decorator priority 10]
C --> D[Decorator priority 20]
D --> E[content sau cùng]
EditorJS sang HTML
Với
EDITOR_JS_JSON, converter đọc field blocks trong JSON và chuyển từng block sang HTML. Một số block đang được hỗ trợ gồm:-
paragraph-><p>...</p> -
header-><h1>đến<h6> -
image-><img> -
embed-><iframe> -
list-><ul>hoặc<ol> -
quote-><blockquote> -
code-><pre> -
table-><table> -
raw-> HTML gốc -
linkTool-> thẻ<a> -
media-> audio, video, image hoặc file link
Mỗi block được bọc bởi:
<div class="block-wrapper" type="paragraph">...</div>
Nếu nội dung không giống JSON hoặc parse lỗi, converter trả lại nội dung gốc.
Thymeleaf sang HTML
Với
THYMELEAF, nội dung được xem là template. Converter render template bằng ViewContext, truyền vào:- template là chính chuỗi
content, - locale lấy từ
languageCode, - content type đầu ra là HTML,
- variables lấy từ
parameters.
Ví dụ:
{
"contentType": "THYMELEAF",
"languageCode": "vi",
"content": "<p>Xin chào [[]]</p>",
"parameters": {
"name": "EzyArticle"
}
}
Kết quả:
<p>Xin chào EzyArticle</p>
JavaScript sang HTML
Với
JAVASCRIPT, nội dung được đưa vào JavascriptService.execute(content, parameters). Kết quả thực thi được chuyển thành chuỗi. Nếu kết quả null, hệ thống trả về chuỗi rỗng.Xử lý lỗi
Decorator nền bắt exception khi convert thất bại, ghi log, rồi trả về nội dung gốc. Vì vậy API
/convert-content không tự động fail chỉ vì converter lỗi.Điều này hữu ích cho preview/editor: người dùng vẫn nhận lại nội dung ban đầu thay vì mất toàn bộ kết quả. Tuy nhiên, nếu cần validate hoặc chặn HTML nguy hiểm, nên thực hiện ở bước validate riêng trước khi lưu hoặc trước khi public nội dung.
Mở rộng decorator mới
Để thêm loại chuyển đổi mới:
@EzySingleton public class MarkdownPostDecorator implements PostDecorator { @Override public String decorateContent(String content, Locale locale) { return markdownToHtml(content); } @Override public String getContentType() { return "MARKDOWN"; } @Override public int getPriority() { return 10; } }
Sau khi bean được đăng ký,
PostDecoratorManager sẽ tự phát hiện và đưa decorator vào nhóm MARKDOWN.Lưu ý
-
parametersđược dùng cho Thymeleaf, JavaScript và cả một số field trong EditorJS. - Nếu không có decorator nào khớp
contentType, nội dung trả về không đổi. - Decorator chạy tuần tự, nên thứ tự
priorityảnh hưởng trực tiếp đến HTML cuối cùng. - API admin chỉ convert/decorate content; việc lưu bài viết, publish, sanitize hoặc validate đầy đủ không nằm trong endpoint này.