二、站点转化为 PDF 文档 (将 web 内容输出到一个HTML文件中)

115 阅读3分钟

背景

文档中心需要将现有 web 内容转化为 PDF 文档 供用户下载。 如:

  1. docs.rongcloud.cn/android-iml…
  2. docs.rongcloud.cn/ios-imlib
  3. docs.rongcloud.cn/harmonyOS-i…

一个模块下有很多页面,需要将这些页面合并到一个PDF文件中输出。

技术方案

输出目录树

  1. 收集目录产出 目录树文件。
<?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文件中

  1. 按目录树收集 HTML 文件。
  2. 按目录树处理 文档内的 H1 - H5 的内容。
  3. 处理 HTML 输出到 output.html中, 删除头尾部分。

将 HTML 转化为 PDF

  1. 将合并后的 HTML 转化为 PDF 文档。
  2. 为 PDF 添加封面
  3. 为 PDF 添加目录
  4. 为 PDF 添加页码

将 web 内容输出到一个HTML文件中

内容分析

  1. 页面头尾
    • 在拼接过程中需要删除头尾。
    • 拼接完成后再把头尾加上( A + X...X + B)
  2. 页面层级处理
    • 注:由于wkhtmltopdf 生成目录是以h1,h2,h3的层级生成的
结构分析index是否为目录内容修改
开发指导1文档不做修改
推送管理1目录增加 对应的级别的标题,如 <h1>推送管理</h1>
推送服务概述2文档修改 H1 -> h2 , h2 -> h3 , h3 -> h4 , h4 -> h5
推送集成指南2目录增加 对应的级别的标题,如 <h2>推送集成指南</h2>
开始集成推送 2.03文档修改 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