Skip to content

Commit 03257d7

Browse files
Fix internal links (#19)
* Add failing test for internal links As reported in #18, I ran into this with links to footnotes when using ox-html-stable-ids. This patch adds a failing test which hopefully outlines a way to resolve this issue. Currently, the id and hrefs remain empty, so they're removed, resulting in broken links. Instead, it'd be great if we could use the reference we use in the link as the anchor. However, other options would also be acceptible, as long as it fixes the link issue and produces stable IDs. * Fall back to :value when no :raw-value exists The test case for internal links passes if org-html-stable-ids--extract-id falls back to using the element's :value property when it has no :raw-value property. This breaks a different test, though, which relies on the return value being nil if :raw-value doesn't return anything. It might make sense to only fall back to :value when the :raw-value key doesn't exist at all. * Only use :value when it's not deferred Falling back to the :value property works for inline elements where the :value is string based, like links. For block-level elements like example blocks, which have nested elements, those elements get automatically serialized to a string by org-element-property. The :value fallback should only work for inline elements, so this patch switches to using org-element-property-raw, which doesn't serialize the "deferred" elements. To make sure that doesn't happen, the new org-html-stable-ids--extract-value function only returns non-deferred :value properties. * Manually detangle changes to Org document * Update description of ID creation, explain extracting values
1 parent 8983da1 commit 03257d7

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

ox-html-stable-ids.el

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
:package-version '(Org . "8.0")
3434
:type 'boolean)
3535

36+
(defun org-html-stable-ids--extract-value (datum)
37+
(let ((value (or (org-element-property :raw-value datum)
38+
(org-element-property-raw :value datum))))
39+
(unless (org-element-deferred-p value)
40+
value)))
41+
3642
(defun org-html-stable-ids--extract-id (datum)
3743
"Extract a reference from a DATUM.
3844
@@ -41,7 +47,7 @@ Return DATUM's `:CUSTOM_ID` if set, or generate a reference from its
4147
nil."
4248
(or
4349
(org-element-property :CUSTOM_ID datum)
44-
(let ((value (org-element-property :raw-value datum)))
50+
(let ((value (org-html-stable-ids--extract-value datum)))
4551
(when value
4652
(org-html-stable-ids--to-kebab-case value)))))
4753

ox-html-stable-ids.org

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,16 @@ It only replaces IDs in exported HTML documents when ~org-html-stable-ids~ is no
7272
The function that generates headlines in Org's HTML exporer (~org-html-headline~) calls a function called ~org-export-get-reference~ to generate a unique reference for the headline.
7373
Ox-html-stable-ids adds an advice to overrides that function to return stable IDs, based on the headline's contents, instead.[fn:adam-porter]
7474

75-
First, the ~org-html-stable-ids--extract-id~ helper function takes a headline and returns a stable ID:
75+
First, the ~org-html-stable-ids--extract-id~ helper function takes an element and returns a stable ID:
7676

7777
#+name: extract-id
7878
#+begin_src emacs-lisp
79+
(defun org-html-stable-ids--extract-value (datum)
80+
(let ((value (or (org-element-property :raw-value datum)
81+
(org-element-property-raw :value datum))))
82+
(unless (org-element-deferred-p value)
83+
value)))
84+
7985
(defun org-html-stable-ids--extract-id (datum)
8086
"Extract a reference from a DATUM.
8187

@@ -84,13 +90,14 @@ First, the ~org-html-stable-ids--extract-id~ helper function takes a headline an
8490
nil."
8591
(or
8692
(org-element-property :CUSTOM_ID datum)
87-
(let ((value (org-element-property :raw-value datum)))
93+
(let ((value (org-html-stable-ids--extract-value datum)))
8894
(when value
8995
(org-html-stable-ids--to-kebab-case value)))))
9096
#+end_src
9197

92-
If the headline has a ~:CUSTOM_ID~ property, that's immediately returned.
93-
If not, the ID is created by taking the headline's contents and converting them to "kebab case".
98+
If the element has a ~:CUSTOM_ID~ property, that's immediately returned.
99+
If not, element's contents are used through the ~org-html-stable-ids--extract-value~ function.
100+
To create te ID, the value is then converted to "kebab case".
94101

95102
#+begin_aside
96103

test.el

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,13 @@
6464
(let ((org-html-stable-ids t))
6565
(org-html-export-as-html)))
6666
(org-html-stable-ids-remove))
67+
68+
(ert-deftest internal-link-test ()
69+
(org-html-stable-ids-add)
70+
(find-file "test/fixtures/internal-link.org")
71+
(let ((org-html-stable-ids t))
72+
(org-html-export-as-html))
73+
(let ((buffer (with-current-buffer "*Org HTML Export*" (buffer-string))))
74+
(should (string-match-p "<a id=\"first\"></a>Something" buffer))
75+
(should (string-match-p "See item <a href=\"#first\">1</a>" buffer)))
76+
(org-html-stable-ids-remove))

test/fixtures/internal-link.org

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1. <<first>>Something
2+
2. See item [[first]]

0 commit comments

Comments
 (0)