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

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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, я соглашусь с ним.

Ответ принят как подходящий

Я написал фильтр Luaname_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

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