Sam*_*amR 6 r cross-reference pandoc r-markdown quarto
我正在使用四开本创建一份长 PDF 报告。我想包括两种格式的交叉引用:
正如3.1 节中讨论的
正如我的精彩部分中所讨论的。
可以这样实现:
---
format:
pdf:
number-sections: true
---
# Why Stack Overflow is so great {#sec-stack}
I can use style 1, the section number, with the explicit ID, e.g. as seen in @sec-stack.
I can use style 2, the section title, with a link [Why Stack Overflow is so great].
I can also custom text with [Custom text before the link][Why Stack Overflow is so great].
Run Code Online (Sandbox Code Playgroud)
这会产生所需的输出:
问题是该文件正在由几位作者重新起草。如果章节标题从Why Stack Overflow is so Great更改为Why I love Stack Overflow,则会破坏使用第二种样式(章节标题)的交叉引用。
我正在寻找一种使用显式标识符 引用部分的方法@sec-stack,并让它显示标题而不是部分编号。这将类似于[@sec-stack]而不是@sec-stack。
四开交叉引用文档中有多种选项。但是,我看不到一种方法,以便在更新部分标题时交叉引用文本也会更新,前提是显式标识符保持不变。
这存在吗?
我编写了一个Lua 过滤器 name_crossref.lua来获取交叉引用文本而不是节/图/表号。以下方法适用于 HTML 和 pdf 输出格式。
对于章节或小节标题,其使用非常简单。我们只需要使用header 中使用的部分标识符\nameref{sec-id}作为sec-id#sec-id
对于从代码块生成的图像或表格,我们需要使用一些块选项。我们需要使用link代码块类,需要定义一个 id 以便稍后与 交叉引用图像或表格link-id,并且需要定义一个将用作与 交叉引用文本的标题link-title。然后使用我们分配的 id 来link-id引用生成的表/图像\nameref{id}。
对于使用 Markdown 语法或 Markdown 表添加的图像,使用此过滤器有点麻烦。我们需要使用嵌套 div(使用 pandoc div 语法创建,::::用于外部 div 和:::内部 div)。在第一个 div 中,我们必须添加link类 , link-id,link-title在第二个 div 中我们需要添加另一个类cell-output-display。同样,然后使用我们分配给的 idlink-id来引用生成的表/图像\nameref{id}。
---
title: "Cross Referencing the Name"
author: Shafee
format:
html: default
pdf: default
number-sections: true
filters:
- name_crossref.lua
---
# Why Quarto is so great {#sec-stack}
`r stringi::stri_rand_lipsum(1)`
See \nameref{sec-stack}.
## How it is so {#how}
`r stringi::stri_rand_lipsum(1)`
See \nameref{how}.
## Images
```{r}
#| classes: link
#| link-id: fig1
#| link-title: My Awesome plot
plot(1:10)
```
`r stringi::stri_rand_lipsum(1)`
see \nameref{fig1}
## Tables
```{r}
#| classes: link
#| link-id: tab1
#| link-title: Mtcars Data
head(mtcars)
```
`r stringi::stri_rand_lipsum(1)`
see \nameref{tab1}
# Markdown Images
:::: {.link link-id="fig2" link-title="Scatter plot of mpg"}
::: {.cell-output-display}

:::
::::
`r stringi::stri_rand_lipsum(4)`
see \nameref{fig2}
# Markdown Table
:::: {.link link-id="tab2" link-title="Markdown table"}
::: {.cell-output-display}
| Col1 | Col2 | Col3 |
|------|------|------|
| A | B | C |
| E | F | G |
| A | G | G |
: My Caption
:::
::::
`r stringi::stri_rand_lipsum(4)`
see \nameref{tab2}
Run Code Online (Sandbox Code Playgroud)
name_crossref.lua
local str = pandoc.utils.stringify
function get_header_data(data)
local get_headers = {
Header = function(el)
local id = el.identifier
local text = str(el.content):gsub("^[%d.]+ ", "")
table.insert(data, {id = id, text = text})
end,
Div = function(el)
if el.attributes["link-id"] then
local id = el.attributes["link-id"]
local text = el.attributes["link-title"]
table.insert(data, {id = id, text = text})
end
end
}
return get_headers
end
function change_ref(data)
local change_rawinline = {
RawInline = function(el)
for key, value in pairs(data) do
if el.text:match("\\nameref{(.*)}") == value.id then
local target = "#" .. value.id
local link = pandoc.Link(value.text, target)
return link
end
end
end
}
return change_rawinline
end
local function add_div_id(div)
return {
Div = function(elem)
if elem.classes:includes("cell-output-display")
or elem.classes:includes("cell-output-stdout")then
elem.identifier = div.attributes["link-id"]
return elem
end
end
}
end
function Div(el)
if el.classes:includes('link') then
return el:walk(add_div_id(el))
end
end
function Pandoc(doc)
local header_data = {}
doc:walk(get_header_data(header_data))
return doc:walk(change_ref(header_data))
end
Run Code Online (Sandbox Code Playgroud)