Tôi sử dụng excalidraw để quản lý sơ đồ cho blog của mình
I use excalidraw to manage my diagrams for my blog
Các lập trình viên Việt Nam có thể tham khảo cách tự động hóa việc xuất biểu đồ từ Excalidraw thành các file SVG cho chế độ sáng và tối, phục vụ cho blog hoặc tài liệu. Phương pháp này bao gồm việc đóng gói các thành phần biểu đồ trong các "frame" và đặt tiền tố `export_` cho chúng. Sau đó, một extension VS Code tùy chỉnh hoặc GitHub Action sử dụng `excalirender` sẽ tự động tạo ra các file SVG tương ứng. Cách làm này giúp tiết kiệm đáng kể thời gian và công sức so với việc chỉnh sửa thủ công, cho phép cập nhật nội dung và hình ảnh nhanh chóng hơn. Đây là một workflow hữu ích để quản lý biểu đồ hiệu quả cho các dự án tài liệu, thuyết trình hoặc blog cá nhân.
Tôi sử dụng Excalidraw, bọc các phần tử quan tâm bằng một khung, đặt tên nó bằng tiền tố import_, tiện ích mở rộng excalidraw được phân nhánh của tôi sẽ tự động tạo SVG cho chế độ sáng và tối.
TL;DR Tôi sử dụng Excalidraw, bọc các phần tử quan tâm bằng một khung, đặt tên nó bằng tiền tố export_, tiện ích mở rộng excalidraw được phân nhánh của tôi sẽ tự động tạo SVG cho chế độ sáng và tối.
Sử dụng Excalidraw
Trước đây tôi đã sử dụng Excalidraw rất nhiều.
- Khi tự mình giải quyết một vấn đề kỹ thuật
- Khi giải thích một khái niệm hoặc một kiến trúc cho đồng nghiệp của tôi.
Gần đây một usecase mới đã phát triển.
- Bày tỏ suy nghĩ của tôi trong Blog của tôi.
Trong khi viết bài viết đầu tiên của tôi, sự phụ thuộc giữa đồ họa và văn bản khiến tôi rất thất vọng. Tinh chỉnh đồ họa dẫn đến văn bản dễ dàng hơn. Những thay đổi trong văn bản khiến tôi nhận ra rằng một số thông tin trong hình ảnh là không cần thiết để nắm bắt được điều gì sẽ xảy ra.
Vấn đề
Mỗi thay đổi về đồ họa trong Excalidraw có nghĩa là phải có 9 lần nhấp chuột trong Excalidraw.
- Chọn khung
- nhấn xuất
- chọn đúng tên + hậu tố darkmode/lightmode
- xuất
- chuyển chế độ sáng/tối
- chọn đúng tên + hậu tố darkmode/lightmode
- xuất lại
- nhận ra rằng một nhãn đã vượt qua ranh giới khung
- bắt đầu lại từ 1.
Tôi mất khoảng 45 giây.
Tự động hóa nó :-) .

Cách tiếp cận đầu tiên - hành động GitHub
...20 phút sau... Một chút khó chịu nhờ nguồn mở (cụ thể là Excalirender của JonRC) - nó đã hoạt động...
Một hành động nhỏ trên GitHub:
- tìm kiếm các tệp excalidraw đã thay đổi trong lần đẩy cuối cùng,
- sử dụng jq để tìm các khung bên trong các khung đó,
- xuất chúng ở chế độ tối và sáng dưới dạng [framename]-[light/dark],
- cam kết lại các tệp svg mới đó vào kho lưu trữ.
Xem mã tại đây:
tên: Xuất khung Excalidraw
trên:
push:
nhánh:
- main
pull_request:
chi nhánh:
-
quyền:
nội dung: viết
công việc:
khung xuất:
chạy trên: các bước ubuntu mới nhất
:
- tên: Kho lưu trữ Checkout
sử dụng: actions/checkout@v4
với:
tìm nạp độ sâu: 2 # Tìm nạp 2 lần cuối cam kết so sánh với HEAD~1
- tên: Thay đổi Tệp Excalidraw
id: tệp đã thay đổi
chạy: |
# Nhận danh sách các tệp .excalidraw đã thay đổi kể từ lần cam kết cuối cùng
if [[ "${{ github.event_name }" == "push" ]; rồi
CHANGED_FILES=$(git diff --HEAD chỉ có tên~1 HEAD | grep '\.excalidraw$' || true)
else
# Đối với PR, hãy so sánh với nhánh mục tiêu
CHANGED_FILES=$(git diff --chỉ tên Origin/${{ github.base_ref ĐẦU | grep '\.excalidraw$' || true)
fi
if [ -z "$CHANGED_FILES " ]; sau đó
echo "Không tìm thấy tệp .excalidraw đã thay đổi"
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "Các tệp đã thay đổi:"
echo "$CHANGED_FILES"
echo "$CHANGED_FILES" > /tmp/changed_files.txt
echo "has_changes=true" >> $GITHUB_OUTPUT
fi
- tên: Cài đặt excalirender
nếu: step.changed-files.outputs.has_changes == 'true'
chạy: |
curl -fsSL https://raw.githubusercontent.com/JonRC/excalirender/main/install.sh | sh
echo "$HOME/.local/bin" >> $GITHUB_PATH
bộ kiểm tra --version || echo "excalirender đã được cài đặt"
- tên: Xuất khung cho tệp đã thay đổi
nếu: step.changed-files.outputs.has_changes == 'true'
chạy: |
# Tạo tập lệnh xuất
cat > /tmp/export_frames.sh << 'EOF'
#!/bin/bash
EXCALIDRAW_FILE="$1"
OUTPUT_DIR=" $(dirname "$EXCALIDRAW_FILE")"
# Đọc tệp Excalidraw và trích xuất tên khung
FRAME_NAMES=$(jq -r '.elements[] | select(.type == "frame") | .name // "frame-" + .id' "$EXCALIDRAW_FILE")
if [ -z "$FRAME_NAMES" ]; sau đó
echo "Không tìm thấy khung nào trong $EXCALIDRAW_FILE"
thoát 0
fi
tiếng vang "Xuất khung hình từ $EXCALIDRAW_FILE"
# Xuất từng khung hình ở chế độ sáng và tối
while IFS= đọc -r frame_name; làm
if [ -n "$frame_name" ]; sau đó
echo " Xuất khung: $frame_name"
# Dọn dẹp tên khung để sử dụng trong tên tệp
safe_name=$(echo "$frame_name" | sed 's/[<>:"/\\|?*]/-/g' | sed 's/\s+/-/g')
# Xuất chế độ ánh sáng
excalirender "$EXCALIDRAW_FILE" --frame "$frame_name" -o "${OUTPUT_DIR/${safe_name-light.svg"
# Xuất chế độ tối
bộ phân tích "$EXCALIDRAW_FILE" --frame " $frame_name" --dark -o "${OUTPUT_DIR/${safe_name-dark.svg"
fi
hoàn thành <<< "$FRAME_NAMES "
echo " ✓ Đã xuất tất cả các khung từ $EXCALIDRAW_FILE"
EOF
chmod +x /tmp/export_frames.sh
# Xử lý từng tệp đã thay đổi
while IFS= đọc -r file; làm
nếu [ -n " $file" ]; sau đó
echo "Đang xử lý: $file"
/tmp/export_frames.sh "$file"
fi
xong < /tmp/changed_files.txt
- tên: Cam kết các SVG đã xuất
nếu: step.changed-files.outputs.has_changes == 'true'
chạy: |
git cấu hình --local user.email "github-actions[bot]@users.noreply.github.com"
git cấu hình --local user.name "github-actions[bot]"
# Thêm tất cả các tệp SVG mới được tạo
git add **/*.svg 2>/dev/null || git thêm *.svg 2>/dev/null || true
# Kiểm tra xem có bất kỳ thay đổi nào đối với cam kết hay không
if git diff --staged --quiet; rồi
tiếng vang "Không có tệp SVG mới nào để cam kết"
else
echo "Đang cam kết các tệp SVG đã xuất"
git cam kết -m "việc vặt: xuất khung Excalidraw dưới dạng SVG
- Xuất khung từ các tệp .excalidraw đã thay đổi
- Tạo các biến thể chế độ sáng và tối
🤖 Được tạo bằng [Claude Code](https://claude.com/claude-code)
Đồng tác giả: Claude "
git đẩy
fi
Tuyệt vời! Đủ để tiếp tục làm việc với bài viết của tôi.
Sự cố với cách tiếp cận 1
Sau khi làm việc với phương pháp này một thời gian, tôi gặp phải nhiều vấn đề khác nhau.
- Thư viện tôi sử dụng có một số lỗi kết xuất (giống như cái này)
- Quá trình này liên quan đến việc quay hình ảnh docker dựa trên x86 mà tôi không thể chạy trên máy Mac dựa trên ARM của mình
Tôi đã phá vỡ 1.) bằng cách thêm các nhãn bổ sung nhưng 2.) đã phá vỡ toàn bộ khái niệm. Không thể chạy quá trình xuất cục bộ có nghĩa là tôi cần phải đẩy tệp Excalidraw sang GitHub, đợi quy trình kết thúc và thực hiện cam kết mới trước khi tôi có thể thấy hình ảnh mới hoặc những thay đổi trong hình ảnh được phản ánh.
Vì vậy, giải pháp này đã có hiệu quả nhưng việc xem xét bài đăng trên blog cục bộ chỉ có thể thực hiện được với những hình ảnh lỗi thời.
Ý tưởng mới: Thêm tính năng tự động xuất vào Excalidraw
Điều gì sẽ xảy ra nếu tiện ích mở rộng VSCode của Excalidraw kiểm tra các thay đổi trong tệp *.excalidraw đang mở và tự động xuất từng khung dưới dạng hai tệp SVG riêng biệt - một ở chế độ tối, một ở chế độ sáng?
Tôi đã dành chút thời gian cùng Claude vào cuối tuần để viết mã YOLO. Kết quả:
Nếu tôi chỉnh sửa Excalidraw của mình trong VSCode, tất cả những gì tôi cần làm là tạo một phần cho bài đăng trên blog của mình:
- bọc các phần tử bằng khung
- đặt tên khung như
export_${image_name
Tiện ích mở rộng sẽ chọn khung, xuất dưới dạng SVG ở chế độ tối và sáng và lưu hai SVG có tên ${image_name}.light.exp.svg và ${image_name}.dark.exp.svg bên cạnh tệp Excalidraw.
Xem trước trực tiếp cục bộ
Giờ đây, những hình ảnh đó đã có sẵn cục bộ và cập nhật bất cứ khi nào tôi thay đổi khung trong Excalidraw của mình, tôi có thể tham chiếu chúng thông qua tính năng tự động hoàn thành và xem trước trong trình chỉnh sửa, xem chúng được hiển thị trong tab Xem trước.
Kết luận
Tôi khá hài lòng với kết quả này. Tôi chỉ dành một vài giờ để viết bài viết này. Sử dụng công cụ này mang lại niềm vui vì nó giải quyết được nỗi đau thực sự.
Tôi rất nóng lòng được sử dụng nó một cách rộng rãi trong các bài viết đang được thực hiện - SQLite trên Git.
Tuy nhiên, có một điều tôi không chắc chắn. Sau khi nói chuyện với những người khác về cách tiếp cận này, tôi có thể thấy cách tiếp cận của mình mang lại giá trị cho chính tiện ích mở rộng Excalidraw ban đầu. Nhưng tôi sẽ không tạo yêu cầu kéo - vì tôi không sở hữu mã - hay nói đúng hơn là tôi không muốn nắm quyền sở hữu. Thay vào đó, tôi đang nghĩ đến việc mở một vấn đề, mô tả vấn đề và giải pháp để lấy cảm hứng.
Nếu những người khác thấy điều này hữu ích và sử dụng nó - tôi đã tạo các tạo phẩm cho phần phát hành trong ng nhánh GitHub của mình cho phép người khác tải xuống và sử dụng tiện ích mở rộng của tôi. Bây giờ thế là đủ rồi!
Tác giả: mlysk