2

Section Markup for Rich Contents/Literal Examples in org documentation contains the following text:

In literal examples, Org interprets strings like ‘(ref:name)’ as labels, and use them as targets for special hyperlinks like ‘[[(name)]]’—i.e., the reference name enclosed in single parenthesis. In HTML, hovering the mouse over such a link remote-highlights the corresponding code line, which is kind of cool.

It then uses the following example:

 #+BEGIN_SRC emacs-lisp -n -r
   (save-excursion                 (ref:sc)
      (goto-char (point-min))      (ref:jump)
 #+END_SRC
 In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]] jumps to point-min.

I remember to have had it work, but it doesn't work any more. I mean, when I put the mouse on the link in the generated html, nothing is highlighted.

Looking at the generated html I can see referenced lines are put in a span

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span id="coderef-sc" class="coderef-off"><span class="linenr">1: </span>       (<span style="color: #531ab6;">save-excursion</span></span>
<span id="coderef-jump" class="coderef-off"><span class="linenr">2: </span>          (goto-char (point-min))</span>
</pre>
</div>
<p>

And the reference is given an onmouseover event calling a CodeHighlightOn javascript function:

In line <a href="#coderef-sc" class="coderef" onmouseover="CodeHighlightOn(this, 'coderef-sc');" onmouseout="CodeHighlightOff(this, 'coderef-sc');">1</a> we remember the current position. <a href="#coderef-jump" class="coderef" onmouseover="CodeHighlightOn(this, 'coderef-jump');" onmouseout="CodeHighlightOff(this, 'coderef-jump');">Line 2</a>
jumps to point-min.

So I guess the problem is I lack the javascript code defining these CodeHighlightOn and CodeHighlightOff functions.

So the question is: where are these functions defined? (and why don't I have them, the documentation suggests it should work out of the box).

This is org mode 9.6.11 on emacs 30.0.50.

5
  • Check the value of org-html-head-include-scripts: it's t by default but maybe you have turned it off?
    – NickD
    Mar 20 at 23:37
  • To expand a bit on the previous comment, the functions are defined in the string org-html-scripts at the top of ox-html.el, which is inlined into the HTML file by org-html--build-head if org-html-head-include-scripts is non-nil.
    – NickD
    Mar 21 at 1:52
  • Actually, it seems the default value is nil in the sense that emacs -Q starts with that value. But I'm tired and confused and need sleep, so maybe this is all wrong.
    – NickD
    Mar 21 at 2:01
  • You're right: setting org-html-head-include-scripts to t does solve the issue. Thanks!
    – JeanPierre
    Mar 21 at 14:20
  • So I was right, even though I was tired and confused: see my answer.
    – NickD
    Mar 21 at 15:09

1 Answer 1

1

The solution is to customize org-html-head-include-scripts and set it to t. With that setting, org-html--build-head includes the string org-html-scripts in the head section of the HTML document: that string includes the definitions of the JS functions, CodeHighlightOn and CodeHighlightOff.


EDIT: The following analysis was done in an old branch of the Org mode source. The current code (since release 9.5 in 2021) has changed the default value of the variable to nil for unrelated reasons (basically, LibreJS was complaining that "public domain" is no license and not always recognized around the world - see the discussion here).

So the following analysis is obsolete (but the solution above is actually the correct solution to the question, with no need of quotation marks any more.)

The theoretical problem still exists of course, but since this was the only known instance of it, the point is moot.


[Warning: the following analysis is obsolete - see EDIT above.]

But why is org-html-head-include-scripts nil to begin with? The defcustom that defines it says:

(defcustom org-html-head-include-scripts t ...

so why isn't it t?

Reading the description of defcustom in the Emacs Lisp manual provides a clue:

The argument standard is an expression that specifies the standard value for option. Evaluating the defcustom form evaluates standard, but does not necessarily bind the option to that value. If option already has a default value, it is left unchanged. If the user has already saved a customization for option, the user’s customized value is installed as the default value. Otherwise, the result of evaluating standard is installed as the default value.

Note, btw, that this detail is not included in the doc string of defcustom, so C-h f defcustom was not enlightening - perhaps it should be included in the doc string.

So somebody must be binding org-html-head-include-scripts to nil before the defcustom is evaluated. The only other use of the variable is when the HTML backend is created by org-export-define-backend in ox-html.el and that call textually precedes the defcustom in the file, so when the file is loaded, org-export-define-backend is called first, and presumably binds org-html-head-include-scripts to nil, so when the defcustom is evaluated, the standard value is set to t but the actual value remains at nil. I verified that if I move the defcustom in the file to before the call to org-export-define-backend everything works as expected (or at least as I expect it).

This looks like a bug to me, so I'll submit a bug report to Org mode to get the code fixed. I might also submit a doc bug to Emacs to get the missing detail into the doc string of defcustom. I'll update this answer with that information when done.

3
  • Thanks for the nice in depth analysis of the issue, and for the bug report.
    – JeanPierre
    Mar 21 at 17:15
  • About the edit: oh my! Thanks for clarifying that. This is still a bug in org-mode documentation (should mention the need to set org-html-head-include-scripts to t to get the advertised behavior) isn't it?
    – JeanPierre
    Mar 22 at 10:06
  • Yes, you are right. I'll change the bug report to a doc bug and submit a patch.
    – NickD
    Mar 22 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.