Перекрестные ссылки Quarto: постоянные перекрестные ссылки при изменении текста

Я создаю длинный отчет в формате PDF, используя Quarto. Я хочу включить два формата перекрестных ссылок:

  1. К номеру раздела/рисунка, например.
Как обсуждалось в разделе 3.1
  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 есть различные варианты перекрестных ссылок . Однако я не вижу способа сделать так, чтобы текст перекрестной ссылки обновлялся, если заголовок раздела обновляется, при условии, что явный идентификатор остается прежним.

Это существует?

Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
Аутсорсинг разработки PHP для индивидуальных веб-решений
Аутсорсинг разработки PHP для индивидуальных веб-решений
Услуги PHP-разработки могут быть экономически эффективным решением для компаний, которые ищут высококачественные услуги веб-разработки по доступным...
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
HTML предоставляет множество тегов для структурирования и организации содержимого веб-страницы. Одним из наиболее часто используемых тегов для...
4
0
106
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После некоторых экспериментов это подход 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.

Использование:

  1. Для заголовка раздела или подраздела его использование очень простое. Нам просто нужно использовать \nameref{sec-id}, где sec-id — идентификатор раздела, используемый в заголовках как #sec-id

  2. Для изображений или таблиц, сгенерированных из фрагментов кода, нам нужно использовать некоторые параметры фрагмента. нам нужно использовать link в качестве класса фрагмента кода, нужно определить идентификатор для перекрестной ссылки на изображение или таблицу позже с помощью link-id и нужно определить заголовок, который будет использоваться в качестве текста перекрестной ссылки с link-title. А затем используйте идентификатор, который мы присвоили link-id, чтобы сослаться на сгенерированную таблицу/изображение с помощью \nameref{id}.

  3. Для изображений, добавленных с помощью синтаксиса уценки или таблиц уценки, использование этого фильтра немного хакерское. Нам нужно использовать вложенные 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}

![mpg](test-filename/mpg.png)
:::
::::

`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

Первая часть сгенерированного вывода

Теперь вопрос, полезно ли быть фильтром Кварто???

shafee 12.01.2023 14:53

Привет, шафи, у меня не будет возможности попробовать это и принять ответ позже, но это выглядит потрясающе - спасибо. В чем преимущество фильтра Quarto, а не сценария Lua? Кажется, легко включить фильтр в yaml.

SamR 12.01.2023 17:41

Фильтр Quarto фактически основан на фильтре Lua. Так что особой разницы и преимущества я думаю нет. Если вы заглянете в документ quarto, вы поймете эту идею :).

shafee 12.01.2023 18:00

ОК, я пробовал его как для html, так и для pdf - это действительно здорово. Я бы проголосовал дважды, если бы мог. Во-первых, он отлично работает для обоих форматов. Во-вторых, это открыло мне глаза на совершенно новый мир фильтров Lua. Возможно, вам следует сделать это фильтром/расширением Quarto (до сих пор не совсем ясна разница), чтобы его можно было разместить на их веб-сайте Quarto все еще развивается как технология, и я уверен, что многие выиграют от такого фильтра. Кроме того, если разработчики увидят это, они могут подумать о том, чтобы сделать это основной функцией.

SamR 12.01.2023 21:04

Другие вопросы по теме