FiveThirtyEight 风格的书本脚注

FiveThirtyEight style in-text footnotes for bookdown

我正在使用 {bookdown}, and I would like to format my footnotes to appear directly in the text when the superscript is selected, as happens in FiveThirtyEight articles (see here 创建一个项目作为示例)。这个想法是,当用户点击脚注时,段落会展开以显示脚注文本,然后在脚注关闭时压缩回正常状态。

我找到了一些实现此功能的资源:

但是,这些解决方案似乎都假定实际的脚注文本位于具有关联 class 的 <span> 标记内。但是,从 {bookdown} 和 Pandoc 生成的 HTML 脚注似乎并非如此。 HTML 看起来像这样:

<p>
  "Figures and tables with captions will be placed in "
  <code>
    "figure
  </code>
  " and "
  <code>
    "table"
  </code>
  " environments, respectively."
  <a href="#fn1" class="footnote-ref" id = "fnref1"><sup>1</sup></a>
</p>

<div class="footnotes">
  <hr>
  <ol start="1">
    <li id="fn1">
      <p>
        "Here is a fancy footnote."
        <a href="intro.html#fnref1" class="footnote-back">"<-"</a>
      </p>
    </li>
  </ol>
</div>

因此,不仅脚注放在未classed <p> 标签中,而不是 classed <span> 标签中,脚注本身也在一个完全独立的 <div>,而不是出现在与文本其余部分相同的标签中,就像链接示例中的情况一样。

我已经创建了一个 bookdown reprex 来尝试根据上面的链接示例使用 CSS 和 javascript 的组合来完成这项工作。 GitHub 回购是 here, and the rendered output here。我已成功隐藏页面底部的脚注,但无法在选择脚注上标时让脚注在文本中显示。

有没有办法使用 {bookdown} 以这种方式设置脚注样式?或者这是 Pandoc 的限制?

Pandoc 让您可以通过过滤器完全控制输出。以下是 Lua filter which uses the HTML/CSS method to hide/show footnotes. See this R Studio article 关于如何使用 Lua 过滤器与 bookdown。

-- how many notes we've seen yet.
local note_number = 0

local fn_opening_template = [[<span id="fn-%d"><!--
--><label for="fn-%d-toggle"><sup>%d</sup></label><!--
--><input type="checkbox" hidden id="fn-%d-toggle"/>
]]
local fn_close = '</span>'

local style_css = [[<style>
input[type=checkbox][id|=fn] + span {display:none;}
input[type=checkbox][id|=fn]:checked + span {display:block;}
</style>
]]

-- Use custom HTML for footnotes.
function Note (note)
  note_number = note_number + 1
  local fn_open = fn_opening_template:format(
    note_number, note_number, note_number, note_number)
  return {
    pandoc.RawInline('html', fn_open),
    pandoc.Span(
      pandoc.utils.blocks_to_inlines(note.content),
      pandoc.Attr(string.format('fn-%d-content', note_number))
    ),
    pandoc.RawInline('html', fn_close)
  }
end

function Meta (meta)
  local header_includes = meta['header-includes']
  -- ensure that header_includes is a MetaList
  if not header_includes then
    header_includes = pandoc.MetaList{}
  elseif header_includes.t ~= 'MetaList' then
    header_includes = pandoc.MetaList {header_includes}
  end
  table.insert(
    header_includes,
    pandoc.MetaBlocks{pandoc.RawBlock('html', style_css)}
  )
  meta['header-includes'] = header_includes
  return meta
end