From f745a722f1f8587184ebc24e04fa70627ca25be4 Mon Sep 17 00:00:00 2001 From: "William J. Bowman" Date: Thu, 9 Jul 2026 22:21:31 +0000 Subject: [PATCH] Fix hyperref label mismatch for tech/def cross-references in LaTeX When rendering `@tech` links with `#:tag-prefixes`, the resolved destination tag (e.g. `(tech "chp1:" "book:" "widget")`) differs from the raw link-element tag (e.g. `(tech ("book:" "chp1:" "widget"))`), causing `\hyperref` to reference a label that does not exist. The section/part rendering path appears to handle this by using `(vector-ref dest 1)` from the resolved destination rather than `(link-element-tag e)`. Adapt the same pattern for tech/def refs. --- scribble-lib/scribble/latex-render.rkt | 4 +- .../tests/scribble/latex-tech-hyperref.rkt | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 scribble-test/tests/scribble/latex-tech-hyperref.rkt diff --git a/scribble-lib/scribble/latex-render.rkt b/scribble-lib/scribble/latex-render.rkt index 61435ddcce..a3392b35a9 100644 --- a/scribble-lib/scribble/latex-render.rkt +++ b/scribble-lib/scribble/latex-render.rkt @@ -402,7 +402,7 @@ (link-element? e) (not (disable-hyperref)) (let-values ([(dest ext?) (resolve-get/ext? part ri (link-element-tag e))]) - (and dest (not ext?))))] + (and (not ext?) dest)))] [check-render (lambda () (when (render-element? e) @@ -544,7 +544,7 @@ (core-render e tt?)])) (when hyperref? (printf "\\hyperref[t:~a]{" - (t-encode (link-element-tag e)))) + (t-encode (vector-ref hyperref? 1)))) (let loop ([l (if style (style-properties style) null)] [tt? #f]) (if (null? l) (if hyperref? diff --git a/scribble-test/tests/scribble/latex-tech-hyperref.rkt b/scribble-test/tests/scribble/latex-tech-hyperref.rkt new file mode 100644 index 0000000000..b514cf6ff2 --- /dev/null +++ b/scribble-test/tests/scribble/latex-tech-hyperref.rkt @@ -0,0 +1,54 @@ +#lang racket/base + +(require racket/file + rackunit + scribble/core + scribble/latex-render + scribble/manual + scribble/render) + +(define (latex-render-string doc) + (dynamic-wind + (λ() (render (list doc) + (list "example-for-latex-tech-hyperref-test") + #:render-mixin render-mixin)) + (λ() (file->string "example-for-latex-tech-hyperref-test.tex")) + (λ() (delete-file "example-for-latex-tech-hyperref-test.tex")))) + +; Regression test: when @tech is used with #:tag-prefixes, the resolved +; destination tag must be used for \hyperref rather than the raw link-element +; tag, so that \hyperref and \label refer to the same anchor. +(test-case "tech hyperref tag matches deftech label tag when using tag-prefixes" + (define str + (latex-render-string + (part "book:" + '((part "top")) + '("Doc") + (style #f null) + null + null + (list + (part "chp1:" + '((part "chp1")) + '("Chapter One") + (style #f null) + null + (list (paragraph (style #f null) (list (deftech "widget")))) + null) + (part #f + '((part "sec2")) + '("Section Two") + (style #f null) + null + (list (paragraph (style #f null) + (list (tech #:tag-prefixes '("book:" "chp1:") "widget")))) + null))))) + + (define label-m + (regexp-match #rx"\\\\label\\{(t:[a-z0-9:_]+)\\}\\\\textit\\{widget\\}" str)) + (define href-m + (regexp-match #rx"\\\\hyperref\\[(t:[a-z0-9:_]+)\\]" str)) + + (check-not-false (and label-m href-m) "both \\label and \\hyperref for tech term must appear") + (check-equal? (cadr label-m) (cadr href-m) + "\\hyperref tag must match \\label tag for tech term"))