Skip to content

Instantly share code, notes, and snippets.

@akunzai
Last active May 25, 2025 17:32
Show Gist options
  • Save akunzai/287ad95138c53e06a219690f8bcfb966 to your computer and use it in GitHub Desktop.
Save akunzai/287ad95138c53e06a219690f8bcfb966 to your computer and use it in GitHub Desktop.
readme.com exporter
#!/usr/bin/env bash
set -euo pipefail
VERSION_DEFAULT="main"
README_API_URL="https://dash.readme.com/api/v1"
SCRIPT_DIR=$(dirname "$0")
EXPORT_HIDDEN_DOCS_DEFAULT="false"
error_exit() {
echo "錯誤: $1" >&2
exit 1
}
warning_msg() {
echo "警告: $1" >&2
}
if [[ -f "$SCRIPT_DIR/.env" ]]; then
echo "正在從 $SCRIPT_DIR/.env 讀取設定..."
set -o allexport
# shellcheck source=/dev/null
source "$SCRIPT_DIR/.env"
set +o allexport
echo ".env 檔案已載入。"
fi
README_API_KEY="${README_API_KEY:-}"
while [[ -z "${README_API_KEY}" ]]; do
read -r -p "請輸入您的 ReadMe API 金鑰: " README_API_KEY
done
if [[ -z "${PROJECT_VERSION:-}" ]]; then
read -r -p "請輸入要匯出的專案版本 (預設: $VERSION_DEFAULT): " PROJECT_VERSION_INPUT
PROJECT_VERSION="${PROJECT_VERSION_INPUT:-$VERSION_DEFAULT}"
else
echo "正在從環境變數讀取專案版本: $PROJECT_VERSION"
fi
FINAL_EXPORT_HIDDEN_DOCS="${EXPORT_HIDDEN_DOCS:-$EXPORT_HIDDEN_DOCS_DEFAULT}"
echo "準備匯出專案版本: $PROJECT_VERSION"
[[ "$FINAL_EXPORT_HIDDEN_DOCS" == "true" ]] && echo "將會匯出隱藏文件。"
OUTPUT_DIR_BASE="$SCRIPT_DIR/exported"
OUTPUT_DIR="$OUTPUT_DIR_BASE/$PROJECT_VERSION"
mkdir -p "$OUTPUT_DIR"
echo "所有文件將匯出至: $OUTPUT_DIR"
echo ""
echo "正在擷取分類列表..."
all_categories_json="[]"
current_page=1
per_page=100
total_categories=0
while true; do
echo "正在擷取第 $current_page 頁分類..."
page_categories_json=$(curl -s -H "x-readme-version: $PROJECT_VERSION" -u "$README_API_KEY:" "$README_API_URL/categories?page=$current_page&perPage=$per_page")
if [[ -z "$page_categories_json" ]]; then
[[ "$current_page" -eq 1 ]] && error_exit "無法擷取分類列表,或 API 回應為空。請檢查 API 金鑰、版本和網路連線。"
echo "第 $current_page 頁無回應,停止分頁擷取。"
break
fi
if echo "$page_categories_json" | jq -e 'if type == "object" then .error else null end' | grep -q -v null; then
[[ "$current_page" -eq 1 ]] && error_exit "分類列表的 API 回應包含錯誤: $(echo "$page_categories_json" | jq '.')"
echo "第 $current_page 頁包含錯誤,停止分頁擷取。"
break
fi
page_num_categories=$(echo "$page_categories_json" | jq '. | length')
if [[ "$page_num_categories" -eq 0 ]]; then
echo "第 $current_page 頁沒有更多分類,完成擷取。"
break
fi
all_categories_json=$(echo "$all_categories_json" "$page_categories_json" | jq -s '.[0] + .[1]')
total_categories=$((total_categories + page_num_categories))
echo "第 $current_page 頁找到 $page_num_categories 個分類。"
if [[ "$page_num_categories" -lt "$per_page" ]]; then
echo "已到達最後一頁,完成擷取。"
break
fi
current_page=$((current_page + 1))
done
categories_json="$all_categories_json"
if [[ "$total_categories" -eq 0 ]]; then
warning_msg "在版本 '$PROJECT_VERSION' 中找不到任何分類。"
exit 0
fi
echo "總共找到 $total_categories 個分類。"
echo ""
echo "$categories_json" | jq -c '.[]' | while IFS= read -r category_item; do
category_type=$(echo "$category_item" | jq -r '.type')
category_slug=$(echo "$category_item" | jq -r '.slug')
category_title=$(echo "$category_item" | jq -r '.title')
echo "--------------------------------------------------"
echo "正在處理分類: '$category_title' (類型: ${category_type}, Slug: $category_slug)"
category_docs_dir="$OUTPUT_DIR/$category_type/$category_slug"
mkdir -p "$category_docs_dir"
echo " 正在擷取分類 '$category_slug' 中的文件(包含子文件)..."
docs_in_category_json=$(curl -s -H "x-readme-version: $PROJECT_VERSION" -u "$README_API_KEY:" "$README_API_URL/categories/$category_slug/docs")
if [[ -z "$docs_in_category_json" ]]; then
warning_msg " 無法擷取分類 '$category_slug' 的文件,或者該分類為空。"
continue
fi
if echo "$docs_in_category_json" | jq -e 'if type == "object" then .error else null end' | grep -q -v null; then
warning_msg " 分類 '$category_slug' 中文件列表的 API 回應包含錯誤: $(echo "$docs_in_category_json" | jq '.') "
continue
fi
num_docs_in_category=$(echo "$docs_in_category_json" | jq '. | length')
if [[ "$num_docs_in_category" -eq 0 ]]; then
echo " 注意: 分類 '$category_slug' 中沒有文件。"
continue
fi
total_docs_count=$(echo "$docs_in_category_json" | jq '[.. | objects | select(has("slug")) | select(.slug != null)] | length')
echo " 找到 $num_docs_in_category 份頂層文件,總共 $total_docs_count 份文件(包含子文件)。"
process_document_hierarchy() {
local doc_item="$1"
local indent_level="${2:-0}"
local parent_path="${3:-""}"
local indent_prefix=""
for ((i=0; i<indent_level; i++)); do
indent_prefix=" $indent_prefix"
done
local doc_slug doc_title is_hidden
doc_slug=$(echo "$doc_item" | jq -r '.slug')
doc_title=$(echo "$doc_item" | jq -r '.title')
is_hidden=$(echo "$doc_item" | jq -r '.hidden')
local current_doc_dir
if [[ -z "$parent_path" ]]; then
current_doc_dir="$category_docs_dir"
else
current_doc_dir="$category_docs_dir/$parent_path"
mkdir -p "$current_doc_dir"
fi
local child_parent_path
if [[ -z "$parent_path" ]]; then
child_parent_path="$doc_slug"
else
child_parent_path="$parent_path/$doc_slug"
fi
if [[ "$is_hidden" == "true" && "$FINAL_EXPORT_HIDDEN_DOCS" != "true" ]]; then
echo "${indent_prefix} 略過隱藏文件: '$doc_title'"
local children_json
children_json=$(echo "$doc_item" | jq -r '.children // []')
if [[ "$children_json" != "[]" && "$children_json" != "null" ]]; then
echo "$children_json" | jq -c '.[]' | while IFS= read -r child_doc; do
process_document_hierarchy "$child_doc" $((indent_level + 1)) "$child_parent_path"
done
fi
return
fi
doc_content_json=$(curl -s -H "x-readme-version: $PROJECT_VERSION" -u "$README_API_KEY:" "$README_API_URL/docs/$doc_slug")
if [[ -z "$doc_content_json" ]]; then
warning_msg "${indent_prefix} 無法擷取文件 '$doc_slug' 的內容 (回應為空)。"
return
fi
echo "${indent_prefix} ------------------------------------"
echo "${indent_prefix} 正在處理文件: '$doc_title' (Slug: $doc_slug)"
echo "${indent_prefix} 存放目錄: $current_doc_dir"
local doc_image_storage_dir="$current_doc_dir/images"
mkdir -p "$doc_image_storage_dir"
markdown_body=$(echo "$doc_content_json" | jq -r '.body')
if echo "$doc_content_json" | jq -e 'if type == "object" then .error else null end' | grep -q -v null; then
warning_msg "${indent_prefix} 文件 '$doc_slug' 內容的 API 回應包含 .error 欄位,但仍嘗試處理 .body。錯誤詳細資訊: $(echo "$doc_content_json" | jq -c '.error')"
fi
# Check for API documents with empty body but swagger path
is_api=$(echo "$doc_content_json" | jq -r '.isApi // false')
swagger_path=$(echo "$doc_content_json" | jq -r '.swagger.path // null')
if [[ "$markdown_body" == "null" || -z "$markdown_body" ]]; then
if [[ "$is_api" == "true" && "$swagger_path" != "null" && -n "$swagger_path" ]]; then
echo "${indent_prefix} 發現 API 文件,body 為空但有 swagger 路徑: $swagger_path"
markdown_body="OpenAPI Path: $swagger_path"
else
echo "${indent_prefix} 跳過建立空白文件: '$doc_title' (body 和 swagger 皆為空)"
# Process children even if parent document is skipped
local children_json children_count
children_json=$(echo "$doc_item" | jq -r '.children // []')
if [[ "$children_json" != "[]" && "$children_json" != "null" ]]; then
children_count=$(echo "$children_json" | jq '. | length')
if [[ "$children_count" -gt 0 ]]; then
echo "${indent_prefix} 找到 $children_count 個子文件,正在遞歸處理..."
echo "$children_json" | jq -c '.[]' | while IFS= read -r child_doc; do
process_document_hierarchy "$child_doc" $((indent_level + 1)) "$child_parent_path"
done
fi
fi
return
fi
fi
# Process custom API documents with api property
if [[ "$is_api" == "true" ]]; then
api_data=$(echo "$doc_content_json" | jq -r '.api // null')
if [[ "$api_data" != "null" ]]; then
echo "${indent_prefix} 發現自訂 API 文件,正在處理 API 屬性..."
# Extract API information
api_method=$(echo "$api_data" | jq -r '.method // ""')
api_url=$(echo "$api_data" | jq -r '.url // ""')
api_auth=$(echo "$api_data" | jq -r '.auth // ""')
# Build API info table with proper escaping
api_table=$'\n\n## API 資訊\n\n'
api_table+=$'| 屬性 | 值 |\n'
api_table+=$'|------|----|\n'
[[ -n "$api_method" ]] && api_table+="| Method | \`$api_method\` |"$'\n'
[[ -n "$api_url" ]] && api_table+="| URL | \`$api_url\` |"$'\n'
[[ -n "$api_auth" ]] && api_table+="| Auth | \`$api_auth\` |"$'\n'
# Process parameters
params_data=$(echo "$api_data" | jq -r '.params // []')
if [[ "$params_data" != "[]" && "$params_data" != "null" ]]; then
api_table+=$'\n## 參數\n\n'
api_table+=$'| 名稱 | 類型 | 必填 | 預設值 | 描述 |\n'
api_table+=$'|------|------|------|--------|------|\n'
echo "$params_data" | jq -c '.[]' | while IFS= read -r param; do
param_name=$(echo "$param" | jq -r '.name // ""')
param_type=$(echo "$param" | jq -r '.type // ""')
param_required=$(echo "$param" | jq -r '.required // false')
param_default=$(echo "$param" | jq -r '.default // ""')
param_desc=$(echo "$param" | jq -r '.desc // ""')
# Clean up description (remove markdown links for table)
param_desc_clean=$(echo "$param_desc" | sed 's/\[\([^]]*\)\]([^)]*)/\1/g')
echo "| \`$param_name\` | \`$param_type\` | $param_required | \`$param_default\` | $param_desc_clean |" >> /tmp/api_params_$$
done
if [[ -f "/tmp/api_params_$$" ]]; then
while IFS= read -r line; do
api_table+="$line"$'\n'
done < "/tmp/api_params_$$"
rm "/tmp/api_params_$$"
fi
fi
# Process response codes
results_data=$(echo "$api_data" | jq -r '.results.codes // []')
if [[ "$results_data" != "[]" && "$results_data" != "null" ]]; then
api_table+=$'\n\n## 回應範例\n\n'
api_table+=$'| 狀態碼 | 名稱 | 回應內容 |\n'
api_table+=$'|--------|------|----------|\n'
echo "$results_data" | jq -c '.[]' | while IFS= read -r result; do
result_status=$(echo "$result" | jq -r '.status // ""')
result_name=$(echo "$result" | jq -r '.name // ""')
result_code=$(echo "$result" | jq -r '.code // ""')
# Properly escape and format code for table
result_code_clean=$(echo "$result_code" | sed 's/|/\\|/g' | sed 's/$/\\n/g' | tr -d '\n' | sed 's/\\n$//g')
echo "| $result_status | $result_name | \`$result_code_clean\` |" >> /tmp/api_results_$$
done
if [[ -f "/tmp/api_results_$$" ]]; then
while IFS= read -r line; do
api_table+="$line"$'\n'
done < "/tmp/api_results_$$"
rm "/tmp/api_results_$$"
fi
fi
# Append API table to markdown
markdown_body="$markdown_body$api_table"
fi
fi
processed_markdown="$markdown_body"
# Convert [block:image] to standard Markdown
if [[ "$processed_markdown" == *"[block:image]"* ]]; then
echo "${indent_prefix} 正在將 [block:image] 區塊轉換為標準 Markdown 語法..."
temp_markdown="$processed_markdown"
processed_markdown=""
while true; do
block_start="[block:image]"
block_end="[/block]"
prefix="${temp_markdown%%"$block_start"*}"
if [[ "$prefix" == "$temp_markdown" ]]; then
processed_markdown="$processed_markdown$temp_markdown"
break
fi
processed_markdown="$processed_markdown$prefix"
remainder="${temp_markdown#*"$prefix"}"
after_start="${remainder#"$block_start"}"
content="${after_start%%"$block_end"*}"
if [[ "$content" == "$after_start" ]]; then
warning_msg "${indent_prefix} 格式錯誤的 [block:image]: 缺少 '$block_end'。"
processed_markdown="$processed_markdown$block_start$after_start"
break
fi
suffix="${after_start#*"$content$block_end"}"
img_url=$(printf "%s" "$content" | perl -0777 -ne 'if (/"image":\s*\[\s*"([^"]+)"/) { print $1; exit }')
if [[ -n "$img_url" && "$img_url" != "null" ]]; then
processed_markdown="$processed_markdown![]($img_url)"
echo "${indent_prefix} 已將 [block:image] (URL: $img_url) 轉換為 Markdown 語法"
else
warning_msg "${indent_prefix} 在 [block:image] 中未找到圖片 URL。"
processed_markdown="$processed_markdown$block_start$content$block_end"
fi
temp_markdown="$suffix"
done
echo "${indent_prefix} 完成轉換 [block:image] 區塊。"
fi
# Convert [block:parameters] to Markdown table
if [[ "$processed_markdown" == *"[block:parameters]"* ]]; then
echo "${indent_prefix} 正在將 [block:parameters] 區塊轉換為 Markdown 表格..."
temp_markdown="$processed_markdown"
processed_markdown=""
while true; do
block_start="[block:parameters]"
block_end="[/block]"
prefix="${temp_markdown%%"$block_start"*}"
if [[ "$prefix" == "$temp_markdown" ]]; then
processed_markdown="$processed_markdown$temp_markdown"
break
fi
processed_markdown="$processed_markdown$prefix"
remainder="${temp_markdown#*"$prefix"}"
after_start="${remainder#"$block_start"}"
content="${after_start%%"$block_end"*}"
if [[ "$content" == "$after_start" ]]; then
warning_msg "${indent_prefix} 格式錯誤的 [block:parameters]: 缺少 '$block_end'。"
processed_markdown="$processed_markdown$block_start$after_start"
break
fi
suffix="${after_start#*"$content$block_end"}"
# Parse JSON content from parameters block
param_json=$(printf "%s" "$content" | jq '.' 2>/dev/null)
if [[ -n "$param_json" && "$param_json" != "null" ]]; then
echo "${indent_prefix} 正在解析參數表格資料..."
# Extract table data
cols=$(echo "$param_json" | jq -r '.cols // 0')
rows=$(echo "$param_json" | jq -r '.rows // 0')
if [[ "$cols" -gt 0 && "$rows" -gt 0 ]]; then
# Build Markdown table
table_md=$'\n\n'
# Build header row
header_row="| "
for ((col=0; col<cols; col++)); do
header_cell=$(echo "$param_json" | jq -r ".data.\"h-$col\" // \"\"")
header_row+="$header_cell | "
done
table_md+="$header_row"$'\n'
# Build separator row
separator_row="|"
for ((col=0; col<cols; col++)); do
separator_row+="------|"
done
table_md+="$separator_row"$'\n'
# Build data rows
for ((row=0; row<rows; row++)); do
data_row="| "
for ((col=0; col<cols; col++)); do
cell_data=$(echo "$param_json" | jq -r ".data.\"$row-$col\" // \"\"")
# Handle newlines and pipe characters for Markdown table compatibility
cell_data_clean=$(echo "$cell_data" | sed 's/\\n/<br>/g' | tr '\n' ' ' | sed 's/|/\\|/g' | sed 's/ */ /g' | sed 's/^ *//;s/ *$//')
data_row+="$cell_data_clean | "
done
table_md+="$data_row"$'\n'
done
table_md+=$'\n'
processed_markdown="$processed_markdown$table_md"
echo "${indent_prefix} 已將 [block:parameters] 轉換為 Markdown 表格 (${rows}行 ${cols}列)"
else
warning_msg "${indent_prefix} [block:parameters] 資料格式錯誤:行列數無效"
processed_markdown="$processed_markdown$block_start$content$block_end"
fi
else
warning_msg "${indent_prefix} 在 [block:parameters] 中未找到有效的 JSON 資料。"
processed_markdown="$processed_markdown$block_start$content$block_end"
fi
temp_markdown="$suffix"
done
echo "${indent_prefix} 完成轉換 [block:parameters] 區塊。"
fi
# Extract and download images
echo "${indent_prefix} 正在解析和下載圖片..."
temp_img_list=$(mktemp)
echo "$processed_markdown" | awk '
{
line = $0
while ( (start_alt = index(line, "![")) > 0 ) {
end_alt = index(substr(line, start_alt), "]")
if (end_alt == 0) { break }
if (substr(line, start_alt + end_alt, 1) == "(") {
link_start = start_alt + end_alt + 1
link_end = index(substr(line, link_start), ")")
if (link_end == 0) { break }
full_link = substr(line, link_start, link_end - 1)
space_pos = index(full_link, " ")
if (space_pos > 0) {
img_url = substr(full_link, 1, space_pos - 1)
} else {
img_url = full_link
}
gsub(/^[\x22\x27]+/, "", img_url);
gsub(/[\x22\x27]+$/, "", img_url);
if (img_url ~ /^https?:\/\//) {
print img_url
}
line = substr(line, link_start + link_end)
} else {
line = substr(line, start_alt + 2)
}
}
}' | sort -u > "$temp_img_list"
images_downloaded=0
perl_script=$(mktemp)
cat > "$perl_script" <<'EOF'
my ($markdown_in, $search_url_in, $replace_path_in) = @ARGV;
$markdown_in =~ s#(!\[([^\]]*)\]\()(\Q$search_url_in\E)(\s*(?:\"[^\"]*\"|\'[^\']*\')?\))#$1$replace_path_in$4#g;
print $markdown_in;
EOF
while IFS= read -r img_url; do
[[ -z "$img_url" ]] && continue
img_filename_raw=$(basename "$img_url")
img_filename_base="${img_filename_raw%%\?*}"
img_filename_sane="${img_filename_base//[^a-zA-Z0-9._-]/_}"
if [[ -z "$img_filename_sane" ]]; then
img_hash=$(echo -n "$img_url" | md5sum | cut -d' ' -f1)
img_filename_sane="image_${img_hash}.png"
fi
if [[ ! "$img_filename_sane" == *.* ]]; then
original_ext="${img_url##*.}"
original_ext="${original_ext%%\?*}"
if [[ "$original_ext" =~ ^(jpe?g|png|gif|svg|webp|ico|bmp|tiff?)$ ]]; then
img_filename_sane="${img_filename_sane}.${original_ext}"
else
img_filename_sane="${img_filename_sane}.png"
fi
fi
img_path_relative="images/$img_filename_sane"
img_download_path="$doc_image_storage_dir/$img_filename_sane"
echo "${indent_prefix} 正在下載圖片: $img_url -> $img_download_path"
if curl -s -L "$img_url" -o "$img_download_path"; then
processed_markdown=$(perl "$perl_script" "$processed_markdown" "$img_url" "$img_path_relative")
images_downloaded=$((images_downloaded + 1))
else
warning_msg "${indent_prefix} 下載圖片 $img_url 失敗"
fi
done < "$temp_img_list"
rm "$temp_img_list" "$perl_script"
if [[ "$images_downloaded" -gt 0 ]]; then
echo "${indent_prefix} 已成功下載此文件的 $images_downloaded 張圖片。"
else
echo "${indent_prefix} 未找到或下載此文件的新圖片。"
fi
output_md_file="$current_doc_dir/${doc_slug}.md"
echo "${indent_prefix} 正在儲存 Markdown 到: $output_md_file"
printf "%s" "$processed_markdown" >"$output_md_file"
[[ $? -ne 0 ]] && warning_msg "${indent_prefix} 儲存 Markdown 檔案 $output_md_file 失敗。"
echo "${indent_prefix} 文件 '$doc_title' (Slug: $doc_slug) 處理完成。"
local children_json children_count
children_json=$(echo "$doc_item" | jq -r '.children // []')
if [[ "$children_json" != "[]" && "$children_json" != "null" ]]; then
children_count=$(echo "$children_json" | jq '. | length')
if [[ "$children_count" -gt 0 ]]; then
echo "${indent_prefix} 找到 $children_count 個子文件,正在遞歸處理..."
echo "$children_json" | jq -c '.[]' | while IFS= read -r child_doc; do
process_document_hierarchy "$child_doc" $((indent_level + 1)) "$child_parent_path"
done
fi
fi
}
echo "$docs_in_category_json" | jq -c '.[]' | while IFS= read -r doc_item_summary; do
process_document_hierarchy "$doc_item_summary" 0
done
echo " 分類 '$category_title' (Slug: $category_slug) 中的所有可處理文件均已處理完畢。"
echo ""
done
echo "=================================================="
echo "所有操作已完成!"
echo "文件已儲存在 '$OUTPUT_DIR' 下的子目錄中。"
echo "=================================================="
exit 0

ReadMe.com 文件匯出工具

這是一個 Bash 腳本,用於從 ReadMe.com 匯出指定專案版本的文件內容,並將其轉換為本地儲存的 Markdown 檔案及圖片

  • 依分類匯出所有文件。
  • 下載文件中引用的圖片(包含 ReadMe 特有的 [block:image] 格式及標準 Markdown 圖片語法)。
  • 將圖片儲存在各分類對應的 images 子目錄下。
  • 自動更新 Markdown 文件中的圖片連結為相對路徑。
  • 支援透過 .env 檔案或環境變數設定 API 金鑰和專案版本。
  • 可選擇是否匯出隱藏文件。

Requirements

  • Bash: 腳本執行環境。
  • curl: 用於發送 API 請求。
  • jq: 用於解析 JSON API 回應。
  • Perl: 用於處理文字和正則表達式替換。
    • 腳本使用 -0777 選項,需要 Perl 5.6 或更高版本。
  • awk: 用於文字處理。
  • sed: 用於文字流編輯。
  • Standard Unix Utilities:
    • basename
    • dirname
    • mktemp
    • sort
    • md5sum: 用於產生圖片檔案名稱的雜湊值。
      • macOS 使用者注意: macOS 預設的 md5md5sum 不同。您可以透過 Homebrew 安裝 coreutils (brew install coreutils) 來取得 gmd5sum,然後在腳本中將 md5sum 改為 gmd5sum,或者建立一個 md5sum 的別名或符號連結指向 gmd5sum。或者,您可以修改腳本,使用 md5 -r 並調整其輸出格式。目前腳本使用 md5sum

Getting Started

請在終端機中執行

# 下載腳本
curl -O -Ls https://gist.github.com/akunzai/287ad95138c53e06a219690f8bcfb966/raw/readme-exporter.sh

# 賦予執行權限
chmod +x readme-exporter.sh

# 執行腳本
# > 如果未在 `.env` 檔案中設定 `README_API_KEY`,腳本會提示您輸入。
# > 如果未在 `.env` 檔案中設定 `PROJECT_VERSION`,腳本會提示您輸入,預設為 `main`。
./readme-exporter.sh

Configuration

為了避免每次執行時都手動輸入 API 金鑰和專案版本,您可以在腳本相同的目錄下建立一個名為 .env 的檔案,內容如下:

README_API_KEY="changeME"
PROJECT_VERSION="v2.8"

File structures

匯出的文件將儲存在腳本目錄下的 exported/<PROJECT_VERSION>/ 子目錄中。結構如下:

exported/
└── <PROJECT_VERSION>/              # 您指定的專案版本
    ├── guide/                      # 分類類型 (例如: guide, reference)
    │   └── <category-slug>/        # 分類 slug
    │       ├── document-slug1.md   # Markdown 文件
    │       ├── document-slug2.md
    │       └── images/             # 此分類文件的圖片
    │           ├── image1.png
    │           └── image2.jpg
    └── reference/
        └── <another-category-slug>/
            ├── ...
            └── images/
                └── ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment