Я создаю длинный отчет в формате PDF, используя Quarto. Я хочу включить два формата перекрестных ссылок:
Как обсуждалось в разделе 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].
Это дает желаемый результат:
Проблема в том, что документ перерабатывается несколькими авторами. Если заголовок раздела изменить с «Почему переполнение стека так здорово» на «Почему я люблю переполнение стека», перекрестные ссылки будут разорваны с использованием второго стиля (заголовок раздела).
Я ищу способ сослаться на раздел, используя явный идентификатор @sec-stack, и отображать заголовок вместо номера раздела. Это будет что-то вроде [@sec-stack], а не @sec-stack.
В документах Quarto есть различные варианты перекрестных ссылок . Однако я не вижу способа сделать так, чтобы текст перекрестной ссылки обновлялся, если заголовок раздела обновляется, при условии, что явный идентификатор остается прежним.
Это существует?
После некоторых экспериментов это подход LaTeX, основанный на этом ответе TeX SE.
Загружаем пакет nameref в шапку, а затем заменяем меняем ссылки Quarto с @sec-stack на \nameref{sec-stack}. Ссылка сохраняется после изменения названия раздела, например. к Почему я люблю переполнение стека:
---
format:
pdf:
number-sections: true
header-includes:
\usepackage{nameref}
---
# Why I love Stack Overflow {#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 \nameref{sec-stack}.
Недостатком является то, что это не родное решение Quarto, и оно не будет отображаться в других форматах, например. HTML. Тем не менее, это работает, и это простая одноразовая замена регулярного выражения для изменения всех ссылок. Я не принял этот ответ, и если есть собственный ответ Quarto, я соглашусь с ним.
Я написал фильтр Lua name_crossref.lua, чтобы получить текст перекрестной ссылки вместо номера раздела/рисунка/таблицы. И следующий подход работает как для выходного формата HTML, так и для pdf.
Для заголовка раздела или подраздела его использование очень простое. Нам просто нужно использовать \nameref{sec-id}, где sec-id — идентификатор раздела, используемый в заголовках как #sec-id
Для изображений или таблиц, сгенерированных из фрагментов кода, нам нужно использовать некоторые параметры фрагмента. нам нужно использовать link в качестве класса фрагмента кода, нужно определить идентификатор для перекрестной ссылки на изображение или таблицу позже с помощью link-id и нужно определить заголовок, который будет использоваться в качестве текста перекрестной ссылки с link-title. А затем используйте идентификатор, который мы присвоили link-id, чтобы сослаться на сгенерированную таблицу/изображение с помощью \nameref{id}.
Для изображений, добавленных с помощью синтаксиса уценки или таблиц уценки, использование этого фильтра немного хакерское. Нам нужно использовать вложенные div (созданные с синтаксисом pandoc div, :::: для внешнего div и ::: для внутреннего div). В первый div мы должны добавить класс link, link-id, link-title, а во второй div нам нужно добавить еще один класс cell-output-display. И аналогичным образом, затем используйте идентификатор, который мы присвоили link-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}
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
Привет, шафи, у меня не будет возможности попробовать это и принять ответ позже, но это выглядит потрясающе - спасибо. В чем преимущество фильтра Quarto, а не сценария Lua? Кажется, легко включить фильтр в yaml.
Фильтр Quarto фактически основан на фильтре Lua. Так что особой разницы и преимущества я думаю нет. Если вы заглянете в документ quarto, вы поймете эту идею :).
ОК, я пробовал его как для html, так и для pdf - это действительно здорово. Я бы проголосовал дважды, если бы мог. Во-первых, он отлично работает для обоих форматов. Во-вторых, это открыло мне глаза на совершенно новый мир фильтров Lua. Возможно, вам следует сделать это фильтром/расширением Quarto (до сих пор не совсем ясна разница), чтобы его можно было разместить на их веб-сайте Quarto все еще развивается как технология, и я уверен, что многие выиграют от такого фильтра. Кроме того, если разработчики увидят это, они могут подумать о том, чтобы сделать это основной функцией.
Теперь вопрос, полезно ли быть фильтром Кварто???