rdatasculptor
rdatasculptor

Reputation: 8447

Internal links in rmarkdown don't work

I use rmarkdown to render pdf documents. Now I want to add internal links in the texts.

In the helping pages of rmarkdown, it says an internal link is defined as:

See the [Introduction](#introduction).

When I Use e.g. the next code there should be two internal links: link1 and link2. Both don't link. Is there something obvious that I am doing wrong? Many thanks in advance!

   ---
title: "Test"
author: "test test"
output:
  pdf_document:
    latex_engine: xelatex
    number_sections: yes
    toc: yes
    toc_depth: 3
  html_document:
    css: tables.css
    number_sections: yes
    theme: cerulean
    toc: yes
    toc_depth: 3
subtitle: test test test
mainfont: Calibri Light
fontsize: 12pt
header-includes:
- \usepackage[dutch]{babel}
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \fancyfoot[LE,RO]{this is a fancy foot}
- \usepackage{dcolumn}
- \usepackage{here}
- \usepackage{longtable}
- \usepackage{caption}
- \captionsetup{skip=2pt,labelsep=space,justification=justified,singlelinecheck=off}
---

# start

```{r results="asis",tidy=FALSE,eval=TRUE,echo=FALSE,message=FALSE, error=FALSE, warning=FALSE, comment = NA}
cat("click here: [link1](#test 1)")
```

click here: [link2](#test 1)

\pagebreak

#test 3

\pagebreak

#test 2

\pagebreak

#test 1

Upvotes: 38

Views: 21699

Answers (6)

Brian D
Brian D

Reputation: 2719

I've tried to compile a lot of the information across multiple different posts into a single-answer, working .Rmd file example below:

---
title: "internal link testing"
output: html_document
---

Create some headings that we want to link to later: 

# Heading 1

## Heading 2

### Heading  3

Improperly created headings will not work because there must be a space between the hash (#) and the heading text: 

#Heading1a    
##Heading2a    
###Heading3a    


The following links work as expected regardless of capitalization: 
[Heading 1] [heading 1] 
[Heading 2] [heading 2] 
[Heading  3] [heading  3] 

But, do not replace space(s) with dash(es)... these links will not work: 
[heading-1] [Heading-1]
[heading-2] [Heading-2]
[heading--3] [Heading--3]


*HOWEVER... * 

If using an explicit link, you MUST:   
- replace spaces with dash   
- use lower case    
- and there must be no leading space between the hash and the text:    

[explicit heading 1 link](#heading-1) 
 
Leaving in space(s) creates a broken link leading to something that doesn't exist: 
[broken heading 1 link](#heading 1) 
[broken heading 1 link](# heading-1) 

You can create links within a code chunk as well by `cat`ting or pasting the text and setting results='asis': 

```{r testchunk, results='asis', message=FALSE, warning=FALSE}

# These all work: 
cat("[Heading 1] [heading 1] [explicit heading 1 link](#heading-1) ")
paste("[Heading 1] [heading 1] [explicit heading 1 link](#heading-1) ")
cat('<a href="#heading-1">heading 1 href</a>')

library(DT)
library(dplyr)

for(car in unique(rownames(mtcars))) {

  # You can programmatically create section headers within a for loop, but make sure to include some extra newlines: 
  
  cat("\n")
  cat(paste0("## ", car))
  cat("\n")

  # within a kable, make sure to replace spaces, use lowercase, and set escape=FALSE
  # and remember to print the table within the loop 
  mtcars %>%
    tibble::rownames_to_column(var="vname") %>%
    mutate(link = paste0('<a href="#', tolower(gsub(" ", "-", car)), '">', car, '</a>')) %>%
    filter(vname == car) %>%
    knitr::kable(escape=FALSE) %>%
    print()
}


# if using DT::datatable, make sure to specify escape=F to allow html within the table:
mtcars %>%
  tibble::rownames_to_column(var="vname") %>%
  mutate(link = paste0('<a href="#', tolower(gsub(" ", "-", vname)), '">', vname, '</a>')) %>%
  datatable(escape=FALSE)
  

Upvotes: 2

Raf_97
Raf_97

Reputation: 73

Here is a simple way of doing internal links/references in an RMarkdown PDF document:

A) Create a section header:

## Homework Assignments{#hwks}

B) After creating the section header. I can refer to it in my text like this:

If you are having a hard time with your [homework](#hwks), we have some tutors who can help you. 

This creates a link back to the section header entitled "Homework Assignments".

Notice a couple of things in the way I set up the link:

  1. "homework" ==> the word (or phrase) I use to call the header is in brackets

  2. [homework] is immediately followed by the identifier "#hwks" that I created above, but the identifier is now in parentheses, as in: (#hwks)

This always works for me!

(This was my first post here; I hope it makes sense. :) )

Upvotes: 5

dnlbrky
dnlbrky

Reputation: 9805

@rPirate has a good list, but it was missing a case that was befuddling me. I had a section header like ### 1.1.1 My Section Title that needs to be #my-section-title in the link.

After some searching, I found an official list of transformation rules in the Pandoc manual:

The default algorithm used to derive the identifier from the header text is:

  • Remove all formatting, links, etc.
  • Remove all footnotes.
  • Remove all non-alphanumeric characters, except underscores, hyphens, and periods.
  • Replace all spaces and newlines with hyphens.
  • Convert all alphabetic characters to lowercase.
  • Remove everything up to the first letter (identifiers may not begin with a number or punctuation mark).
  • If nothing is left after this, use the identifier section.

Thus, for example,

Header                      | Identifier
--------------------------------------------------------
Header identifiers in HTML  | header-identifiers-in-html
Maître d'hôtel              | maître-dhôtel
*Dogs*?--in *my* house?     | dogs--in-my-house
[HTML], [S5], or [RTF]?     | html-s5-or-rtf
3. Applications             | applications
33                          | section

Upvotes: 6

rPirate
rPirate

Reputation: 291

There are some tricky rules for internal links in Rmarkdown PDF output, not well documented on cheat sheets, etc.

Rules:

  • Only one # for anchor, even if you are using a header with multiple #.

    Example: ###header becomes #header when linking.

  • No spaces between # and anchor text.

    Example: #header, not # header.

  • Multi-word anchors should be separated by dashes.

    Example: #this is a header needs to become #this-is-a-header in the link.

  • Anchor links need to be lowercase, even if the header you are linking to has capitalization.

    Example: #Section becomes #section in the link.

Upvotes: 29

Junchen
Junchen

Reputation: 1799

Josh Paulson has an article on Rstudio website that goes into details. Here is his solution

Slide 1
====================================
id: slide1

Slide 2
====================================
[Go to slide 1](#/slide1)

This works me. A Handcart And Mohair's code does not work on RHTML

Upvotes: 3

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193517

You're not setting the anchors correctly.

Try the following:

# start

```{r results="asis",tidy=FALSE,eval=TRUE}
cat("click here: [link1](#test1)")
```

click here: [link2](#test1)

\pagebreak

# test 3 {#test3}

\pagebreak

#test 2 {#test2}

\pagebreak

#test 1 {#test1}

Upvotes: 39

Related Questions