解决Sphinx下reStructuredText中英文混合换行导致生成的HTML多出空格

问题起因

比如reStructuredText源文件里的这段文字:

除某些病毒的基因由RNA(核糖核酸)构成以外,多数生物的基因由DNA(脱氧核糖核酸)
构成,并在染色体上作线状排列。基因一词通常指染色体基因。在真核生物中,由于
染色体都在细胞核内,所以又称为核基因。位于线粒体和叶绿体等细胞器中的基因则称为
染色体外基因、核外基因或细胞质基因,也可以分别称为线粒体基因、基因质粒和
叶绿体基因。在核基因或细胞质基因中都储存着遗传信息。

Sphinx生成的HTML页面效果是这样的:

Sphinx生成效果

仔细看会发现一个问题,段落在原始文字换行的地方产生了一个空白(红色圈起来的地方):

多出的空白

为了解决这个问题,我在CSDN上找到了这篇文章:reStructuredText/Sphinx中文段落内换行导致生成的HTML多出空格的问题

按照文章给出的代码我弄了个Sphinx扩展,虽然空白是去了,但是一旦遇到像这样的内容:

下面用C语言实现一个自定义的函数——计算给定两个整数的和:

.. code-block:: c

    int add(int a, int b) {
        return a + b;
    }

输出的页面就会变成这样子了:

去除换行空白后效果

这种显示效果显然是有问题的——这里的 code-block 插入的代码是不能去掉换行的。

此外还有一个问题。如果遇到纯英文的段落一般会在英文单词和单词之间进行换行,这时换行去掉之后两个单词就直接连在一起了。

解决思路

原文是通过在Sphinx的生成过程中移除全部的 \r\n ,从而在生成的HTML里去掉换行符号,最后令显示的时候不出现空白。

为了防止中英文混合场景下全部换行符被去除导致代码和英文排版出现问题,理想的去除换行逻辑应该是:中文字符和中文字符之间的换行符去除,其它情况下的换行符保留。

因此需要一个适应混合中英文字符组成的字符串的替换方法。考虑到英文字符宽度是一个字节,那么找到字符串里的换行符后判断左右两个字符的宽度是几个字节,如果都是大于一个字节的,去掉中间的换行符。这样做基本够用了。

代码实现

# coding=utf-8

# 文件 docs/source/replace_util.py 源码:

import os

def mix_replace(text):
    new_text = text
    pos = 0
    while True:
        pos = new_text.find(os.linesep, pos)
        if pos < 0:
            break
        if pos - 1 < 0:
            pos = pos + 1
            continue
        if pos + 1 > len(new_text) - 1:
            break
        before = new_text[pos - 1]
        after = new_text[pos + 1]
        if len(before.encode()) > 1 and len(after.encode()) > 1:
            new_text = new_text[:pos] + new_text[(pos + 1):]
        else:
            pos = pos + 1
    return new_text

原文的Sphinx扩展改动后:


# 文件 docs/source/remove_newline.py 源码:

import os
from docutils.nodes import NodeVisitor, TextElement, Text
from replace_util import mix_replace

def setup(app):
    app.connect('doctree-resolved', process_chinese_paragraph)

class ParagraphVisitor(NodeVisitor):
    def dispatch_visit(self, node):
        if isinstance(node, TextElement):
            for i in range(len(node.children)):
                if type(node[i]) == Text:
                    # 下面注释掉的是原文实现方式
                    #node[i] = Text(node[i].astext().replace('\r', '').replace('\n', ''))
                    node[i] = Text(mix_replace(node[i].astext()))

def process_chinese_paragraph(app, doctree, fromdocname):
    pv = ParagraphVisitor(doctree)
    doctree.walk(pv)

在本地的Sphinx工程的docs目录添加上面的两个文件后:

目录结构

配置文件 docs/source/conf.py 调整,当前路径添加到模块搜索路径:


# 添加处理加载的模块路径:

import os
import sys

sys.path.insert(0, os.path.abspath('.'))

添加 remove_newline 模块到 extensions


extensions = [
    'remove_newline'
]

完成后重新生成页面,效果:

最终修正后的效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值