背景
文档中心需要将现有 web 内容转化为 PDF 文档 供用户下载。 如:
一个模块下有很多页面,需要将这些页面合并到一个PDF文件中输出。
技术方案
输出目录树
- 收集目录产出 目录树文件。
<?xml version="1.0" encoding="UTF-8"?>
<outline>
<item title='导入 CallKit SDK' file='./android-callkit/import.md' href='http://docs.rongcloud.cn/android-callkit/import.html' index='1' />
<item title='实时音视频开发指导' file='./android-callkit/prepare.md' href='http://docs.rongcloud.cn/android-callkit/prepare.html' index='1' />
<item title='初始化' file='./android-callkit/init.md' href='http://docs.rongcloud.cn/android-callkit/init.html' index='1' />
<item title='实现音视频通话' file='./android-callkit/integration.md' href='http://docs.rongcloud.cn/android-callkit/integration.html' index='1' />
<item title='运行示例项目(Demo)' file='./android-callkit/demo.md' href='http://docs.rongcloud.cn/android-callkit/demo.html' index='1' />
<item title='升级指南' index='1'>
<item title='CallKit 3.X 升级到 5.X' file='./android-callkit/upgrade/upgrade-callkit-from-3x.md' href='http://docs.rongcloud.cn/android-callkit/upgrade/upgrade-callkit-from-3x.html' index='2' />
<item title='CallKit 5.X 升级' file='./android-callkit/upgrade/upgrade-callkit.md' href='http://docs.rongcloud.cn/android-callkit/upgrade/upgrade-callkit.html' index='2' />
</item>
<item title='客户端 API' file='./android-callkit/api-reference.md' href='http://docs.rongcloud.cn/android-callkit/api-reference.html' index='1' />
<item title='版本说明' file='./android-callkit/release-notes.md' href='http://docs.rongcloud.cn/android-callkit/release-notes.html' index='1' />
<item title='状态码' file='./android-callkit/code.md' href='http://docs.rongcloud.cn/android-callkit/code.html' index='1' />
<item title='' file='./android-callkit/test.123' href='http://docs.rongcloud.cn/android-callkit/test.123' index='1' />
</outline>
将 web 内容输出到一个HTML文件中
- 按目录树收集 HTML 文件。
- 按目录树处理 文档内的 H1 - H5 的内容。
- 处理 HTML 输出到 output.html中, 删除头尾部分。
将 HTML 转化为 PDF
- 将合并后的 HTML 转化为 PDF 文档。
- 为 PDF 添加封面
- 为 PDF 添加目录
- 为 PDF 添加页码
将 web 内容输出到一个HTML文件中
内容分析
- 页面头尾
- 在拼接过程中需要删除头尾。
- 拼接完成后再把头尾加上( A + X...X + B)
- 页面层级处理
注:由于wkhtmltopdf 生成目录是以h1,h2,h3的层级生成的
| 结构分析 | index | 是否为目录 | 内容修改 |
|---|---|---|---|
| 开发指导 | 1 | 文档 | 不做修改 |
| 推送管理 | 1 | 目录 | 增加 对应的级别的标题,如 <h1>推送管理</h1> |
| 推送服务概述 | 2 | 文档 | 修改 H1 -> h2 , h2 -> h3 , h3 -> h4 , h4 -> h5 |
| 推送集成指南 | 2 | 目录 | 增加 对应的级别的标题,如 <h2>推送集成指南</h2> |
| 开始集成推送 2.0 | 3 | 文档 | 修改 H1 -> h3 , h2 -> h4 , h3 -> h5 , h4 -> h6 |
| 集成小米推送 | 3 | 文档 | 修改 H1 -> h3 , h2 -> h4 , h3 -> h5 , h4 -> h6 |
1.添加内容界定符号
在生成页面时为页面添加的界定符号
--- 页面头 ---
+ <hr data-tag="main-content-start" />`
<main> 这里是当前页面的主要内容区域 </main>
+ <hr data-tag="main-content-end" />
--- 页面尾 ---
最终输出的结果 内容太多这里只做示例
--- 页面头 ---
<hr data-tag="main-content-start" />`
+ <main> 这里是页面一的主要内容区域 </main>
+ <main> 这里是页面二的主要内容区域 </main>
+ <main> 这里是页面三的主要内容区域 </main>
+ <main> 这里是页面四的主要内容区域 </main>
<hr data-tag="main-content-end" />
--- 页面尾 ---
2. 页面层级处理
在目录输出时已经输出当前的层级 index="level"
只需要根据 index 输出即可。
注意:目录是不存在内容的,所以需要插入一个<h[1234]>的标签
如何判断是否为目录?是否有 href 即可
if [[ $line =~ 'href=' ]]; then
href=$(echo "$line" | grep -o "href='[^']\+'" | sed "s/^href=//;s/'//g;s/^[[:space:]]*//;s/[[:space:]]*$//;");
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" "$href");
if [ "$HTTP_CODE" -eq 404 ]; then
echo "页面不存在 (404) $href" >> "./page-404.txt"
else
case "$index" in
"1")
curl -s $href >> $2;
;;
"2")
curl -s $href | sed 's/<h4/<h5/g;s/<\/h4>/<\/h5>/g' | sed 's/<h3/<h4/g;s/<\/h3>/<\/h4>/g' | sed 's/<h2/<h3/g;s/<\/h2>/<\/h3>/g' | sed 's/<h1/<h2/g;s/<\/h1>/<\/h2>/g' >> $2;
;;
"3")
curl -s $href | sed 's/<h3/<h5/g;s/<\/h3>/<\/h5>/g' | sed 's/<h2/<h4/g;s/<\/h2>/<\/h4>/g' | sed 's/<h1/<h3/g;s/<\/h1>/<\/h3>/g' >> $2;
;;
"4")
curl -s $href | sed 's/<h2/<h5/g;s/<\/h2>/<\/h5>/g' | sed 's/<h1/<h4/g;s/<\/h1>/<\/h4>/g' >> $2;
;;
esac
fi
else
echo "<h$index>$title</h$index>" >> $2;
fi
完整内容
处理脚本
grep '<item title=' "./pdf-menu$1-menu.xml" | while read -r line; do
index=$(echo "$line" | grep -o "index='[^']\+'" | sed "s/index=//;s/'//g;s/^[[:space:]]*//;s/[[:space:]]*$//;");
title=$(echo "$line" | grep -o "title='[^']\+'" | sed "s/title=//;s/'//g;s/^[[:space:]]*//;s/[[:space:]]*$//;");
if [[ $line =~ 'href=' ]]; then
href=$(echo "$line" | grep -o "href='[^']\+'" | sed "s/^href=//;s/'//g;s/^[[:space:]]*//;s/[[:space:]]*$//;");
if grep -q --no-filename -r $(echo "$href" | sed 's/^.*docs.rongcloud.cn//') ./rectify-url.md; then
subhref=$(echo "$href" | sed 's/^.*docs.rongcloud.cn//')
subpath=$( cat ./rectify-url.md | sed 's/[[:space:]]//g' | awk -v url="$subhref" 'BEGIN {FS="|"} { if($2 == url){print $3; exit;} }');
href="http://docs.rongcloud.cn${subpath}"
fi
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" "$href");
if [ "$HTTP_CODE" -eq 404 ]; then
echo "页面不存在 (404) $href" >> "./page-404.txt"
else
case "$index" in
"1")
curl -s $href | sed 's/<hr data-tag="main-content-start">/\n&\n\n/g;s/<hr data-tag="main-content-end">/\n\n&\n/g;' | sed -n '/<hr data-tag="main-content-start">/,/<hr data-tag="main-content-end">/{//!p;}' >> $2;
;;
"2")
curl -s $href | sed 's/<h4/<h5/g;s/<\/h4>/<\/h5>/g' | sed 's/<h3/<h4/g;s/<\/h3>/<\/h4>/g' | sed 's/<h2/<h3/g;s/<\/h2>/<\/h3>/g' | sed 's/<h1/<h2/g;s/<\/h1>/<\/h2>/g' | sed 's/<hr data-tag="main-content-start">/\n&\n\n/g;s/<hr data-tag="main-content-end">/\n\n&\n/g;' | sed -n '/<hr data-tag="main-content-start">/,/<hr data-tag="main-content-end">/{//!p;}' >> $2;
;;
"3")
curl -s $href | sed 's/<h3/<h5/g;s/<\/h3>/<\/h5>/g' | sed 's/<h2/<h4/g;s/<\/h2>/<\/h4>/g' | sed 's/<h1/<h3/g;s/<\/h1>/<\/h3>/g' | sed 's/<hr data-tag="main-content-start">/\n&\n\n/g;s/<hr data-tag="main-content-end">/\n\n&\n/g;' | sed -n '/<hr data-tag="main-content-start">/,/<hr data-tag="main-content-end">/{//!p;}' >> $2;
;;
"4")
curl -s $href | sed 's/<h2/<h5/g;s/<\/h2>/<\/h5>/g' | sed 's/<h1/<h4/g;s/<\/h1>/<\/h4>/g' | sed 's/<hr data-tag="main-content-start">/\n&\n\n/g;s/<hr data-tag="main-content-end">/\n\n&\n/g;' | sed -n '/<hr data-tag="main-content-start">/,/<hr data-tag="main-content-end">/{//!p;}' >> $2;
;;
esac
fi
else
echo "<h$index>$title</h$index>" >> $2;
fi
done