使用Pandoc做markdown输出时奇数span标签怎么办

What to do with odd span tags when using Pandoc to make markdown output

我有一些 Calibre 创建的 epub,我想将它们制作成 markdown 以在 Obsidian 中使用。我找到了 Pandoc,我的简单转换尝试除其他事项外,就是丢失斜体并传递 Calibre span 标签,这在 Obsidian 中不显示为斜体。

如果我关闭 raw_html 扩展,它不会传递所有 span 标签,但我也不会得到任何斜体。我想要做的是转换 html:

<span class="italic">Some Words</span>

在我的最终降价文件中变成斜体文本。如果 Pandoc 能做到这一点,那就太好了。否则,在将 html 传递给 Pandoc 之前,我会轻扫一下转换它,但是 Calibre 生成的很多 span 标签都堆叠了几层深,所以一个非常简单的解决方案会很棒.

Pandoc 直接处理这个问题还是我需要先处理 html?我不仅关心斜体,还有许多其他格式问题使用各种 Calibre span 标签,这些标签可能更简单,例如粗体和一些标题。所以我正在尝试找出一种方法来处理所有这些问题。

更新:

由于我不得不在网络上进行大量探索和反复试验才能使它足够好地满足我的需要,我认为这对 post 我第一次尝试 lua 过滤器。这在从 EPUB 中提取(通过解压缩)的数百 html 页面上效果很好,这些页面似乎是由名为 Calibre 的工具创作的。

我的电子书是冗长的参考资料,图片很少,所以我的图像处理程序很简单,可以满足我的需要。我可以 grep 结果文件并修复任何 link 问题。我的 Calibre EPUB 集根据它们的创建时间改变了它们的内部结构,所以我不断添加新的 class 名称,因为随着时间的推移似乎没有努力维护相同的命名。因此,随着我转换更多文件,我希望随着时间的推移对其进行修改。我也希望 Markdown 成为比 EPUB 更好的格式!

这是我的第一个 lua 代码,所以我希望它有点草率。此外,我在 bash 脚本中使用了 --wrap=none -t commonmark,该脚本对我工作目录中的所有文件进行了 pandoc 转换。

-- Corrections for some Calibre oddities when using Pandoc to convert to markdown for Obsidian.
-- Note that I converting very old ebooks and that I don't know anything about Calibre.
function Span (span)
    -- Make italic for: <span class="italic">(“Hello there!”)</span>
    if span.classes:includes 'italic' then
        return pandoc.Emph(span.content)
    end

    -- Make bold for: <span class="bold">(“Hello there!”)</span>
    if span.classes:includes 'bold' then
        return pandoc.Strong(span.content)
    end

    -- Unclear what purpose these serve...
    if span.classes:includes 'calibre1' or span.classes:includes 'calibre2'
            or span.classes:includes 'calibre3' or span.classes:includes 'calibre4' then
        return pandoc.Strong(span.content)
    end

    -- My markdown reader (Obsidian) works with this when using commonmark output.
    if span.classes:includes 'underline' then
        span.attributes['style'] = 'text-decoration: double underline ;'
        return span
    end
end

function Image (img)
    -- Fix calibre6 images.
    if img.classes:includes 'calibre6' or img.classes:includes 'calibre9' then
        return pandoc.Image(img.caption, img.src, nil, nil)
    end
end

function Div (div)
    -- Put a horizontal line in for the page break, just to see where they are.
    if div.classes:includes 'mbp_pagebreak' then
        return '---'
    end
    -- These seem to be hardcoded page delimiters put in by calibre for ebook readers?
    if div.classes:includes 'calibre_4' or div.classes:includes 'calibre_13' then
        return '---'
    end
end

最后,我应该注意到我写了一个脚本,通过第一行重命名所有新的降价文件。这使它们以连贯的形式添加到 Obsidian 中,Obsidian 使用文件系统来组织事物。经过一些编辑和重命名后,我的 Obsidian 保险库中有一部分旧参考书,可以在我的所有设备上轻松访问。

Pandoc 不解析 CSS,因此无法知道这应该用斜体显示。一个好的解决方案是使用 Lua filter.

修改 pandoc 的内部文档表示
function Span (span)
  if span.classes:includes 'italic' then
    return pandoc.Emph(span.content)
  end
end

此过滤器检查跨度是否有 class italic,如果有,则将其转换为 强调文本,通常会输出到斜体。通过将过滤器保存到文件并通过 --lua-filter 命令行选项传递该文件 pandoc 来使用过滤器。

您可能想要处理更多 classes;您可能想要使用的其他 pandoc 构造函数是 pandoc.Strongpandoc.Underlineetc.。 运行 pandoc 与 --to=native 以查看 pandoc 如何在内部表示文档。

我不了解 Pandoc,但这有点不好 HTML。使用更好的 HTML 可能会帮助您解决问题。

HTML应该表达内容的语义,

<span class="italic">Some Words</span>

没有表达任何语义,这可能是 Pandoc 不知道如何处理它。

对于一个 class 名称应该表达 为什么 某些东西是这样格式化的,而不是 如何 它是格式化的。例如,更好的 class 名称可以是 importantbook-title(因为书名通常采用斜体格式)。

此外element (tag) span also doesn't express any meaning. But there is an element that (basically) means "important": <em>。因此,最好使用 <em>Some Words</em>.

而不是 <span class="important">Some words</span>

回到 Pandoc:如果你使用斜体的原因是因为文本很重要,那么你应该使用 <em> 并且因为(编辑) 通常呈现为斜体,那么 Pandoc 实际上也可能知道使用斜体。(基于其他答案)Pandoc 具有强调的概念(pandoc.Empf),所以我很确定它会呈现为斜体或至少其他合适的东西。

还有更多元素通常呈现为斜体,因此您也可以使用这些元素,前提是它们符合您的用法,例如 <cite> (which can used for book titles, as in my other example) or the more generic <i>.