HTML attributes are ignored in org
When I write this code:
#+ATTR_HTML: :class img-responsive
[[#/img/quickstart/minimal-template.webp][Random number]]
I expect this HTML
<img class="img-responsive" src="/img/quickstart/minimal-template.webp" alt="Random number">
However, it is ignored.
Return:
<img src="/img/quickstart/minimal-template.webp" alt="Random number">
If it is possible, I can't find it in the documentation.
PS: I love this Static Site Generator.
Hey @tanrax, thank you for giving a try to one.el. I'm glad to hear that you love it.
What you want to do is possible but doesn't come out of the box with one.el.
The keyword #+ATTR_HTML is interpreted by the builtin org html backend (defined in ox-html.el file if you want to look at it). When an org buffer is exported to HTML with that backend, the transcode function org-html-link is used to transcode the org link element into an html link.
In the case of one.el, if you use the default render functions provided, it uses one-ox org backend and the transcode function used for org link elements is one-ox-link.
So, to get the behavior you expect, one way to do this is to redefine a little bit the function one-ox-link such that it takes #+ATTR_HTML keyword into account.
Here is the redefinition that you can add to your onerc.el file at the root of your project:
(defun one-ox-link (link desc info)
"Transcode a LINK object from Org to HTML.
DESC is the description part of the link, or the empty string.
INFO is a plist holding contextual information."
(let* ((type (org-element-property :type link))
(path (org-element-property :path link))
(raw-link (org-element-property :raw-link link))
(custom-type-link
(let ((export-func (org-link-get-parameter type :export)))
(and (functionp export-func)
(funcall export-func path desc 'one-ox info))))
(href (cond
((string= type "custom-id") path)
((string= type "fuzzy")
(let ((beg (org-element-property :begin link)))
(signal 'one-link-broken
`(,raw-link
"fuzzy links not supported"
,(format "goto-char: %s" beg)))))
((string= type "file")
(or
;; ./assets/images/image-1.png --> /images/image-1.png
;; ./public/blog/page-1.md --> /blog/page-1.md
(and (string-match "\\`\\./\\(assets\\|public\\)" path)
(replace-match "" nil nil path))
(let ((beg (org-element-property :begin link)))
(signal 'one-link-broken
`(,raw-link ,(format "goto-char: %s" beg))))))
(t raw-link)))
(class (if-let ((parent (org-export-get-parent-element link))
(class (plist-get (org-export-read-attribute :attr_html parent)
:class)))
(concat " class=\"" class "\" ")
" ")))
(or custom-type-link
(and
(string-match one-ox-link-image-extensions path)
(format "<p><img%ssrc=\"%s\" alt=\"%s\" /></p>"
class href (or (org-string-nw-p desc) href)) )
(format "<a%shref=\"%s\">%s</a>"
class href (or (org-string-nw-p desc) href)))))
Note the let binding class variable that does the trick.
Please tell me if it works for you!
You don't need it to use it but if you don't mind, I leave the test case here for that modified function so that we now it does what we want it to do:
(defmacro org-test-with-temp-text (text &rest body)
"Run body in a temporary buffer with Org mode as the active
mode holding TEXT. If the string \"<point>\" appears in TEXT
then remove it and place the point there before running BODY,
otherwise place the point at the beginning of the inserted text."
(declare (indent 1))
`(let ((inside-text (if (stringp ,text) ,text (eval ,text)))
(org-mode-hook nil))
(with-temp-buffer
(org-mode)
(let ((point (string-match "<point>" inside-text)))
(if point
(progn
(insert (replace-match "" nil nil inside-text))
(goto-char (1+ (match-beginning 0))))
(insert inside-text)
(goto-char (point-min))))
(font-lock-ensure (point-min) (point-max))
,@body)))
(ert-deftest one-ox-link--attr_html ()
"Test keyword #+ATTR_HTML"
(let ((backend
(org-export-create-backend
:transcoders
'((section . (lambda (_e c _i) c))
(paragraph . (lambda (_e c _i) c))
(link . one-ox-link)))))
(should
(string= (org-test-with-temp-text
"#+ATTR_HTML: :class img-responsive
[[#foo][bar]]"
(org-export-as backend))
"<a class=\"img-responsive\" href=\"foo\">bar</a>\n"))
(should
(string=
(org-test-with-temp-text
"[[#foo][bar]]"
(org-export-as backend))
"<a href=\"foo\">bar</a>\n"))))
Yes, it is working! Thanks 😁 You can see in the blue images the classes: https://django-liveview.andros.dev/ I think this script is too interesting not to be in the documentation. I take this opportunity to ask a problem that I will have later. How do you add target="_blank" to links? With a similar function?
I'm glad it works.
I like the design of your website.
First website built with one.el not by me :) This is really cool!
How do you add target="_blank" to links? With a similar function?
I'll look a this soon and follow up in that issue. I think this possible in a similar way, but I need to play a bit with org-mode keywords to see how.
I'm glad it works.
I like the design of your website.
Thanks 😊
First website built with one.el not by me :) This is really cool!
I feel very lucky! I have added a link to the project in the footer to give it some visibility. (I don't know why it hasn't occurred to me before)
I'll look a this soon and follow up in that issue. I think this possible in a similar way, but I need to play a bit with org-mode keywords to see how.
Perfect!