\n"
616 | (concat "\n" (org-html-close-tag "br" nil info) "\n"
617 | "%s\n"))
618 | (org-export-data subtitle info))
619 | "")))))
620 | contents
621 | (format "%s>\n" (nth 1 (assq 'content (plist-get info :html-divs))))
622 | ))
623 | (tempFile (make-temp-file "canvas-html-export" nil ".html" rawHtml)))
624 | (call-process "juice" nil "*juice-process*" nil "--css" org-canvas-html-css-file tempFile tempFile)
625 | (with-temp-buffer
626 | (insert-file-contents tempFile)
627 | (buffer-string))))
628 |
629 | (defun org-canvas-html-inner-template (contents info)
630 | "Return body of document string after HTML conversion.
631 | CONTENTS is the transcoded contents string. INFO is a plist
632 | holding export options."
633 | (let* ((rawHtml
634 | (concat
635 | ;; Table of contents.
636 | (let ((depth (plist-get info :with-toc)))
637 | (when depth (org-html-toc depth info)))
638 | ;; Document contents.
639 | contents
640 | ;; Footnotes section.
641 | (org-html-footnote-section info)))
642 | (tempFile (make-temp-file "canvas-html-export" nil ".html" rawHtml)))
643 | (call-process "juice" nil "*juice-process*" nil "--css" org-canvas-html-css-file tempFile tempFile)
644 | (with-temp-buffer
645 | (insert-file-contents tempFile)
646 | (buffer-string))))
647 | ;; Add the template functions:1 ends here
648 |
649 | ;; [[file:ox-canvashtml.org::*Add the export-to and export-as functions][Add the export-to and export-as functions:1]]
650 | ;;; End-user functions
651 |
652 | ;;;###autoload
653 | (defun org-canvas-html-export-as-html
654 | (&optional async subtreep visible-only body-only ext-plist)
655 | "Export current buffer to an HTML buffer.
656 |
657 | If narrowing is active in the current buffer, only export its
658 | narrowed part.
659 |
660 | If a region is active, export that region.
661 |
662 | A non-nil optional argument ASYNC means the process should happen
663 | asynchronously. The resulting buffer should be accessible
664 | through the `org-export-stack' interface.
665 |
666 | When optional argument SUBTREEP is non-nil, export the sub-tree
667 | at point, extracting information from the headline properties
668 | first.
669 |
670 | When optional argument VISIBLE-ONLY is non-nil, don't export
671 | contents of hidden elements.
672 |
673 | When optional argument BODY-ONLY is non-nil, only write code
674 | between \"\" and \"\" tags.
675 |
676 | EXT-PLIST, when provided, is a property list with external
677 | parameters overriding Org default settings, but still inferior to
678 | file-local settings.
679 |
680 | Export is done in a buffer named \"*Org HTML Export*\", which
681 | will be displayed when `org-export-show-temporary-export-buffer'
682 | is non-nil."
683 | (interactive)
684 | (org-export-to-buffer 'canvas-html "*Org HTML Export*"
685 | async subtreep visible-only body-only ext-plist
686 | (lambda () (set-auto-mode t)))
687 | ;; (save-excursion
688 | ;; (set-buffer (get-buffer "*Org HTML Export*"))
689 | ;; (call-process-region nil nil "python" t t (t nil) nil "-m" "premailer"))
690 | )
691 |
692 | ;;;###autoload
693 | (defun org-canvas-html-export-to-html
694 | (&optional async subtreep visible-only body-only ext-plist)
695 | "Export current buffer to a HTML file.
696 |
697 | If narrowing is active in the current buffer, only export its
698 | narrowed part.
699 |
700 | If a region is active, export that region.
701 |
702 | A non-nil optional argument ASYNC means the process should happen
703 | asynchronously. The resulting file should be accessible through
704 | the `org-export-stack' interface.
705 |
706 | When optional argument SUBTREEP is non-nil, export the sub-tree
707 | at point, extracting information from the headline properties
708 | first.
709 |
710 | When optional argument VISIBLE-ONLY is non-nil, don't export
711 | contents of hidden elements.
712 |
713 | When optional argument BODY-ONLY is non-nil, only write code
714 | between \"\" and \"\" tags.
715 |
716 | EXT-PLIST, when provided, is a property list with external
717 | parameters overriding Org default settings, but still inferior to
718 | file-local settings.
719 |
720 | Return output file's name."
721 | (interactive)
722 | (let* ((extension (concat
723 | (when (> (length org-html-extension) 0) ".")
724 | (or (plist-get ext-plist :html-extension)
725 | org-html-extension
726 | "html")))
727 | (file (org-export-output-file-name extension subtreep))
728 | (org-export-coding-system org-html-coding-system))
729 | (org-export-to-file 'canvas-html file
730 | async subtreep visible-only body-only ext-plist)
731 | ;; (call-process "juice" nil "*juice-process*" nil file file)
732 | ;;file
733 | ))
734 | ;; Add the export-to and export-as functions:1 ends here
735 |
736 | ;; [[file:ox-canvashtml.org::*Provide the library][Provide the library:1]]
737 | (provide 'ox-canvashtml)
738 | ;; Provide the library:1 ends here
739 |
--------------------------------------------------------------------------------
/ox-canvashtml.org:
--------------------------------------------------------------------------------
1 | #+PROPERTY: header-args :tangle yes :comments link
2 | * Some background about Quercus CSS
3 | :PROPERTIES:
4 | :header-args: :tangle no
5 | :END:
6 |
7 | Here's a short list of classes & some smaple code to give a bit of a sense of what is possible.
8 |
9 | - there's an ~element toggler~ script that allows elements to toggle display of some other element on click by virtue of ~aria~ attributes. The code looks like this:
10 |
11 | #+begin_quote
12 | aria-label="Toggler toggle list visibility" aria-expanded="true" aria-controls="group_n"
13 | #+end_quote
14 |
15 | Here's some actual (bloated) code:
16 | #+begin_src html :tangle no
17 |
Librarians
18 |
19 |
Librarians are an indispensable resource for helping your students gain confidence and skill in locating and evaluating information. Consult the list of Faculty Liaison Librarians to see who could act as a resource to help you prepare your course syllabus (e.g. identify and locate e-resources and readings), help students understand and navigate research tools in your field (e.g. demo a search tool for your students), or assist with teaching your students key information literacy skills (provide information to be included in an online module in Quercus, or as part of an assignment, etc.).
20 | #+end_src
21 |
22 | I'm not going to try to deal with those ~img~ tags today, as they're a uge time suck. But we can simplify a fair bitmap
23 | #+begin_src html
24 |
27 | Librarians
28 |
29 |
30 |
31 | Librarians are an indispensable resource for helping your students gain confidence and skill in locating and evaluating information. Consult the list of
32 |
33 | Faculty Liaison Librarians
34 |
35 | to see who could act as a resource to help you prepare your course syllabus (e.g. identify and locate e-resources and readings), help students understand and navigate research tools in your field (e.g. demo a search tool for your students), or assist with teaching your students key information literacy skills (provide information to be included in an online module in Quercus, or as part of an assignment, etc.).
36 |
37 |
38 | #+end_src
39 | with an ~ATTR_CANVAS: togglesection~ it wouldn't be too hard to do those toggling bits somewhat.
40 |
41 | #+RESULTS:
42 | : org-canvashtml-toggler-make-aria
43 |
44 | Meanwhile, we could also cluster some of the classes to make set of options, e.g.:
45 |
46 | | class name | function |
47 | |--------------+--------------------|
48 | | content-box | fat margins |
49 | | pad-box-mini | fat padding |
50 | | border-round | mild borde-rradius |
51 | | border | 1px greay borer |
52 | | | |
53 | make a ~ATTR_CANVASHTML: :fat t~ or something like that.
54 | * Derived backend for Canvas LMS Pages
55 |
56 | Canvas LMS accepts HTML text, but it quite frustratingly strips out ~link~ and ~style~ tags, so all css has to be inlined. going to try now to add an inliner, let's see how it goes.
57 |
58 |
59 | ** Requirements
60 | :PROPERTIES:
61 | :ID: 9ffb3305-9a22-4698-b7ac-a8fd9ba7618d
62 | :END:
63 | #+begin_src emacs-lisp
64 | (require 'ox-html)
65 | #+end_src
66 |
67 | ** Add a link type for internal canvas links
68 | :PROPERTIES:
69 | :ID: 078cb4eb-cc8a-4583-99c4-16a105fd89a9
70 | :END:
71 | #+begin_src emacs-lisp
72 | ;;; ol-canvas.el - Support for links to man pages in Org mode
73 | (require 'ol)
74 |
75 | (org-link-set-parameters "canvas"
76 | ;;:follow #'org-canvas-open
77 | :follow #'org-id-open
78 | :export #'org-canvas-export
79 | :store #'org-canvas-store-link)
80 |
81 | (defcustom org-canvas-command 'canvas
82 | "The Emacs command to be used to display a canvas page."
83 | :group 'org-link
84 | :type '(choice (const man) (const woman)))
85 |
86 | (defun org-canvas-open (path _)
87 | "Visit the canvas page on PATH.
88 | PATH should be a topic that can be thrown at the man command."
89 | (browse-url path)
90 | ;; (funcall org-canvas-command path)
91 | )
92 | ;; old version
93 | (defun org-canvas-get-url (id _)
94 | (save-window-excursion
95 | ;; add widen to it
96 | ;;(org-id-open id _)
97 | (let ((m (org-id-find id 'marker)))
98 | (unless m
99 | (error "Cannot find entry with ID \"%s\"" id))
100 | (pop-to-buffer-same-window (marker-buffer m))
101 | (save-restriction
102 | (widen)
103 | (goto-char m)
104 | (move-marker m nil)
105 | (org-show-context)
106 | (org-id-goto id)
107 | (or
108 | (org-entry-get nil "CANVAS_HTML_URL")
109 | (org-entry-get nil "ORG_LMS_PREVIEW_URL")
110 | (org-entry-get nil "ORG_LMS_ANNOUNCEMENT_URL")
111 | (org-entry-get nil "MODULE_ITEM_EXTERNAL_URL"))))))
112 |
113 |
114 | (defun org-canvas-store-link ()
115 | "Store a link to the current entry, using its ID .
116 |
117 | If before first heading store first title-keyword as description
118 | or filename if no title."
119 | (interactive)
120 | (when (and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode)
121 | (and (symbolp 'org-lms-mode) (symbol-value 'org-lms-mode )))
122 | (let* ((link (concat "canvas:" (org-id-get-create)))
123 | (case-fold-search nil)
124 |
125 | (desc (save-excursion
126 | (org-back-to-heading-or-point-min t)
127 | (cond ((org-before-first-heading-p)
128 | (let ((keywords (org-collect-keywords '("TITLE"))))
129 | (if keywords
130 | (cadr (assoc "TITLE" keywords))
131 | (file-name-nondirectory
132 | (buffer-file-name (buffer-base-buffer))))))
133 | ((looking-at org-complex-heading-regexp)
134 | (if (match-end 4)
135 | (match-string 4)
136 | (match-string 0)))
137 | (t link)))))
138 | (org-link-store-props :link link :description desc :type "canvas")
139 | link)))
140 |
141 |
142 |
143 | (defun org-canvas-export (link description format &optional _)
144 | "Export a canvas page link from Org files."
145 | (let ((path (org-canvas-get-url link _))
146 | (desc (or description link)))
147 | (pcase format
148 | ('html (if path
149 | (format "%s" path desc)
150 | desc))
151 | ('latex (if path
152 | (format "\\href{%s}{%s}" path desc)
153 | des))
154 | ('texinfo (if path
155 | (format "@uref{%s,%s}" path desc)
156 | desc))
157 | ('ascii (if path
158 | (format "%s (%s)" desc path)
159 | desc))
160 | (t desc))))
161 |
162 |
163 |
164 |
165 | #+end_src
166 |
167 | #+RESULTS:
168 | : org-canvas-export
169 |
170 | [[id:]]
171 | #+begin_src emacs-lisp :tangle nil :raw
172 | (org-canvas-export "b14b684e-7fa8-4dd6-abed-8ce66b4d0ff2" "some link" 'canvas-html)
173 | #+end_src
174 |
175 | #+RESULTS:
176 | : some link
177 |
178 | ** define the derived backend
179 | :PROPERTIES:
180 | :ID: a662351a-f34d-4349-b47c-e677a9201153
181 | :END:
182 | #+begin_src emacs-lisp
183 | (org-export-define-derived-backend 'canvas-html 'html
184 | :translate-alist '((template . canvas-html-template)
185 | (inner-template . org-canvas-html-inner-template)
186 | (section . org-canvas-html-section)
187 | (headline . org-canvas-html-headline))
188 | :menu-entry
189 | '(?2 "Export to HTML"
190 | ((?H "As HTML buffer" org-canvas-html-export-as-html)
191 | (?h "As HTML file" org-canvas-html-export-to-html)
192 | (?o "As HTML file and open"
193 | (lambda (a s v b)
194 | (if a (org-canvas-html-export-to-html t s v b)
195 | (org-open-file (org-canvas-html-export-to-html nil s v b)))))))
196 |
197 | )
198 | #+end_src
199 |
200 | ** Replace the link function so we can update local image links at least
201 | this requires rewriting 2-3 functionss. So far, I have not plugged them in, because I'm not quite sure how to do the logic, but basically:
202 | - create a url for the branch that we're on
203 | - make sure that the current version of the file is committed and pushed (!)
204 | - generate a link to that file and insert.
205 | -
206 | #+begin_src emacs-lisp
207 | (defun org-canvashtml-link (link desc info)
208 | "Transcode a LINK object from Org to HTML.
209 | DESC is the description part of the link, or the empty string.
210 | INFO is a plist holding contextual information. See
211 | `org-export-data'."
212 | (let* ((html-ext (plist-get info :html-extension))
213 | (dot (when (> (length html-ext) 0) "."))
214 | (link-org-files-as-html-maybe
215 | (lambda (raw-path info)
216 | ;; Treat links to `file.org' as links to `file.html', if
217 | ;; needed. See `org-html-link-org-files-as-html'.
218 | (cond
219 | ((and (plist-get info :html-link-org-files-as-html)
220 | (string= ".org"
221 | (downcase (file-name-extension raw-path "."))))
222 | (concat (file-name-sans-extension raw-path) dot html-ext))
223 | (t raw-path))))
224 | (type (org-element-property :type link))
225 | (raw-path (org-element-property :path link))
226 | ;; Ensure DESC really exists, or set it to nil.
227 | (desc (org-string-nw-p desc))
228 | (path
229 | (cond
230 | ((member type '("http" "https" "ftp" "mailto" "news"))
231 | (url-encode-url (concat type ":" raw-path)))
232 | ((string= "file" type)
233 | ;; During publishing, turn absolute file names belonging
234 | ;; to base directory into relative file names. Otherwise,
235 | ;; append "file" protocol to absolute file name.
236 | (setq raw-path
237 | (org-export-file-uri
238 | (org-publish-file-relative-name raw-path info)))
239 | ;; Possibly append `:html-link-home' to relative file
240 | ;; name.
241 | (let ((home (and (plist-get info :html-link-home)
242 | (org-trim (plist-get info :html-link-home)))))
243 | (when (and home
244 | (plist-get info :html-link-use-abs-url)
245 | (file-name-absolute-p raw-path))
246 | (setq raw-path (concat (file-name-as-directory home) raw-path))))
247 | ;; Maybe turn ".org" into ".html".
248 | (setq raw-path (funcall link-org-files-as-html-maybe raw-path info))
249 | ;; Add search option, if any. A search option can be
250 | ;; relative to a custom-id, a headline title, a name or
251 | ;; a target.
252 | (let ((option (org-element-property :search-option link)))
253 | (if (not option) raw-path
254 | (let ((path (org-element-property :path link)))
255 | (concat raw-path
256 | "#"
257 | (org-publish-resolve-external-link option path t))))))
258 | (t raw-path)))
259 | (attributes-plist
260 | (org-combine-plists
261 | ;; Extract attributes from parent's paragraph. HACK: Only
262 | ;; do this for the first link in parent (inner image link
263 | ;; for inline images). This is needed as long as
264 | ;; attributes cannot be set on a per link basis.
265 | (let* ((parent (org-export-get-parent-element link))
266 | (link (let ((container (org-export-get-parent link)))
267 | (if (and (eq 'link (org-element-type container))
268 | (org-html-inline-image-p link info))
269 | container
270 | link))))
271 | (and (eq link (org-element-map parent 'link #'identity info t))
272 | (org-export-read-attribute :attr_html parent)))
273 | ;; Also add attributes from link itself. Currently, those
274 | ;; need to be added programmatically before `org-html-link'
275 | ;; is invoked, for example, by backends building upon HTML
276 | ;; export.
277 | (org-export-read-attribute :attr_html link)))
278 | (attributes
279 | (let ((attr (org-html--make-attribute-string attributes-plist)))
280 | (if (org-string-nw-p attr) (concat " " attr) ""))))
281 | (cond
282 | ;; Link type is handled by a special function.
283 | ((org-export-custom-protocol-maybe link desc 'html info))
284 | ;; Image file.
285 | ((and (plist-get info :html-inline-images)
286 | (org-export-inline-image-p
287 | link (plist-get info :html-inline-image-rules)))
288 | (org-html--format-image path attributes-plist info))
289 | ;; Radio target: Transcode target's contents and use them as
290 | ;; link's description.
291 | ((string= type "radio")
292 | (let ((destination (org-export-resolve-radio-link link info)))
293 | (if (not destination) desc
294 | (format "%s"
295 | (org-export-get-reference destination info)
296 | attributes
297 | desc))))
298 | ;; Links pointing to a headline: Find destination and build
299 | ;; appropriate referencing command.
300 | ((member type '("custom-id" "fuzzy" "id"))
301 | (let ((destination (if (string= type "fuzzy")
302 | (org-export-resolve-fuzzy-link link info)
303 | (org-export-resolve-id-link link info))))
304 | (pcase (org-element-type destination)
305 | ;; ID link points to an external file.
306 | (`plain-text
307 | (let ((fragment (concat "ID-" path))
308 | ;; Treat links to ".org" files as ".html", if needed.
309 | (path (funcall link-org-files-as-html-maybe
310 | destination info)))
311 | (format "%s"
312 | path fragment attributes (or desc destination))))
313 | ;; Fuzzy link points nowhere.
314 | (`nil
315 | (format "%s"
316 | (or desc
317 | (org-export-data
318 | (org-element-property :raw-link link) info))))
319 | ;; Link points to a headline.
320 | (`headline
321 | (let ((href (org-html--reference destination info))
322 | ;; What description to use?
323 | (desc
324 | ;; Case 1: Headline is numbered and LINK has no
325 | ;; description. Display section number.
326 | (if (and (org-export-numbered-headline-p destination info)
327 | (not desc))
328 | (mapconcat #'number-to-string
329 | (org-export-get-headline-number
330 | destination info) ".")
331 | ;; Case 2: Either the headline is un-numbered or
332 | ;; LINK has a custom description. Display LINK's
333 | ;; description or headline's title.
334 | (or desc
335 | (org-export-data
336 | (org-element-property :title destination) info)))))
337 | (format "%s" href attributes desc)))
338 | ;; Fuzzy link points to a target or an element.
339 | (_
340 | (if (and destination
341 | (memq (plist-get info :with-latex) '(mathjax t))
342 | (eq 'latex-environment (org-element-type destination))
343 | (eq 'math (org-latex--environment-type destination)))
344 | ;; Caption and labels are introduced within LaTeX
345 | ;; environment. Use "ref" or "eqref" macro, depending on user
346 | ;; preference to refer to those in the document.
347 | (format (plist-get info :html-equation-reference-format)
348 | (org-html--reference destination info))
349 | (let* ((ref (org-html--reference destination info))
350 | (org-html-standalone-image-predicate
351 | #'org-html--has-caption-p)
352 | (counter-predicate
353 | (if (eq 'latex-environment (org-element-type destination))
354 | #'org-html--math-environment-p
355 | #'org-html--has-caption-p))
356 | (number
357 | (cond
358 | (desc nil)
359 | ((org-html-standalone-image-p destination info)
360 | (org-export-get-ordinal
361 | (org-element-map destination 'link #'identity info t)
362 | info 'link 'org-html-standalone-image-p))
363 | (t (org-export-get-ordinal
364 | destination info nil counter-predicate))))
365 | (desc
366 | (cond (desc)
367 | ((not number) "No description for this link")
368 | ((numberp number) (number-to-string number))
369 | (t (mapconcat #'number-to-string number ".")))))
370 | (format "%s" ref attributes desc)))))))
371 | ;; Coderef: replace link with the reference name or the
372 | ;; equivalent line number.
373 | ((string= type "coderef")
374 | (let ((fragment (concat "coderef-" (org-html-encode-plain-text path))))
375 | (format "%s"
376 | fragment
377 | (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \
378 | '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
379 | fragment fragment)
380 | attributes
381 | (format (org-export-get-coderef-format path desc)
382 | (org-export-resolve-coderef path info)))))
383 | ;; External link with a description part.
384 | ((and path desc)
385 | (format "%s"
386 | (org-html-encode-plain-text path)
387 | attributes
388 | desc))
389 | ;; External link without a description part.
390 | (path
391 | (let ((path (org-html-encode-plain-text path)))
392 | (format "%s" path attributes path)))
393 | ;; No path, only description. Try to do something useful.
394 | (t
395 | (format "%s" desc)))))
396 |
397 |
398 | (defun org-canvashtml--format-image (source attributes info)
399 | "Return \"img\" tag with given SOURCE and ATTRIBUTES.
400 | SOURCE is a string specifying the location of the image.
401 | ATTRIBUTES is a plist, as returned by
402 | `org-export-read-attribute'. INFO is a plist used as
403 | a communication channel."
404 | ;; (org-html--svg-image source attributes info)
405 | (org-html-close-tag
406 | "img"
407 | (org-html--make-attribute-string
408 | (org-combine-plists
409 | (list :src source
410 | :alt (if (string-match-p "^ltxpng/" source)
411 | (org-html-encode-plain-text
412 | (org-find-text-property-in-string 'org-latex-src source))
413 | (file-name-nondirectory source)))
414 | attributes))
415 | info))
416 |
417 | (defun org-canvashtml--image-rewrite-path (path info)
418 | "Copy local images and pdfs to the static/bundle directory if needed.
419 | Also update the link paths to match those.
420 |
421 | PATH is the path to the image or any other attachment.
422 |
423 | INFO is a plist used as a communication channel."
424 | ;; (message "[ox-hugo attachment DBG] The Hugo section is: %s" (plist-get info :hugo-section))
425 | ;; (message "[ox-hugo attachment DBG] The Hugo base dir is: %s" (plist-get info :hugo-base-dir))
426 | (let* ((path-unhexified (url-unhex-string path))
427 | (path-true (file-truename path-unhexified))
428 | (dest-dir (or bundle-dir static-dir))
429 | ret)
430 | (unless (file-directory-p static-dir)
431 | (user-error "Please create the %s directory" static-dir))
432 | (if (and (file-exists-p path-true)
433 | (member (file-name-extension path-unhexified) exportables)
434 | (file-directory-p dest-dir))
435 | (progn
436 | ;; Check if `path-true' is already inside `dest-dir'.
437 | (if (string-match (regexp-quote dest-dir) path-true)
438 | (progn
439 | ;; If so, return *only* the path considering the
440 | ;; destination directory as root.
441 | (setq ret (concat "/" (substring path-true (match-end 0)))))
442 | (let* ((file-name-relative-path
443 | (cond
444 | ((string-match "/static/" path-true)
445 | ;; `path-true' is "/foo/static/bar/baz.png",
446 | ;; return "bar/baz.png".
447 | ;; (message "[ox-hugo DBG attch rewrite] path contains static")
448 | ;; If path-true contains "/static/", set the
449 | ;; `dest-dir' to `static-dir' (even if this is a
450 | ;; page bundle).
451 | (setq dest-dir static-dir)
452 | (substring path-true (match-end 0)))
453 | (bundle-dir
454 | (cond
455 | ((string-match (concat "/" (regexp-quote bundle-name) "/") path-true)
456 | ;; This is a page bundle. `bundle-name' is
457 | ;; "", `path-true' is
458 | ;; "/bar//zoo/baz.png",
459 | ;; return "zoo/baz.png".
460 | ;; (message "[ox-hugo DBG attch rewrite BUNDLE 1] bundle-name: %s" bundle-name)
461 | ;; (message "[ox-hugo DBG attch rewrite BUNDLE 1] attch along with Org content: %s"
462 | ;; (substring path-true (match-end 0)))
463 | (substring path-true (match-end 0)))
464 | ((string-match (regexp-quote default-directory) path-true)
465 | ;; This is a page bundle. `default-path' is
466 | ;; "/", `path-true' is
467 | ;; "/bar/baz.png", return
468 | ;; "bar/baz.png".
469 | ;; (message "[ox-hugo DBG attch rewrite BUNDLE 2] attch along with Org content: %s"
470 | ;; (substring path-true (match-end 0)))
471 | (substring path-true (match-end 0)))
472 | (t
473 | ;; This is a page bundle. `default-path' is
474 | ;; "/", `path-true' is
475 | ;; "/foo/bar/baz.png", return "baz.png".
476 | ;; (message "[ox-hugo DBG attch rewrite BUNDLE 3] attch neither in static nor in Org file dir")
477 | (file-name-nondirectory path-unhexified))))
478 | (t
479 | ;; Else, `path-true' is "/foo/bar/baz.png",
480 | ;; return "ox-hugo/baz.png". "ox-hugo" is the
481 | ;; default value of
482 | ;; `org-hugo-default-static-subdirectory-for-externals'.
483 | ;; (message "[ox-hugo DBG attch rewrite] neither BUNDLE nor contains static")
484 | (concat
485 | (file-name-as-directory org-hugo-default-static-subdirectory-for-externals)
486 | (file-name-nondirectory path-unhexified)))))
487 | (dest-path (concat dest-dir file-name-relative-path))
488 | (dest-path-dir (file-name-directory dest-path)))
489 | ;; The `dest-dir' would already exist. But if
490 | ;; `file-name-relative-path' is "images/image.png" or
491 | ;; "foo/bar.txt", it's likely that "`dest-dir'/images"
492 | ;; or "`dest-dir'/foo" might not exist. So create those
493 | ;; if needed below.
494 | (unless (file-exists-p dest-path-dir)
495 | (mkdir dest-path-dir :parents))
496 | ;; (message "[ox-hugo DBG attch rewrite] file-name-relative-path: %s" file-name-relative-path)
497 | ;; (message "[ox-hugo DBG attch rewrite] dest-path: %s" dest-path)
498 | ;; (message "[ox-hugo DBG attch rewrite] dest-path-dir: %s" dest-path-dir)
499 |
500 | ;; Do the copy only if the file to be copied is newer or
501 | ;; doesn't exist in the static dir.
502 | (when (file-newer-than-file-p path-true dest-path)
503 | (message "[ox-hugo] Copied %S to %S" path-true dest-path)
504 | (copy-file path-true dest-path :ok-if-already-exists))
505 | (setq ret (if (and bundle-dir
506 | (string= bundle-dir dest-dir))
507 | ;; If attachments are copied to the bundle
508 | ;; directory, don't prefix the path as "/"
509 | ;; as those paths won't exist at the site
510 | ;; base URL.
511 | file-name-relative-path
512 | (concat "/" file-name-relative-path))))))
513 | (setq ret path))
514 | ;; (message "[ox-hugo DBG attch rewrite] returned path: %s" ret)
515 | ret))
516 | #+end_src
517 |
518 | ** Replace the section function
519 | :PROPERTIES:
520 | :ID: a84571f5-06cc-43f6-b2bb-c884d38f8cef
521 | :END:
522 |
523 | allow disabling of section text container
524 | #+begin_src emacs-lisp
525 | ;;;; Section
526 |
527 | (defun org-canvas-html-section (section contents info)
528 | "Transcode a SECTION element from Org to HTML.
529 | CONTENTS holds the contents of the section. INFO is a plist
530 | holding contextual information."
531 | (let ((parent (org-export-get-parent-headline section)))
532 | ;; Before first headline: no container, just return CONTENTS.
533 | (if (not parent) contents
534 | ;; Get div's class and id references.
535 | (let* ((class-num (+ (org-export-get-relative-level parent info)
536 | (1- (plist-get info :html-toplevel-hlevel))))
537 | (section-number
538 | (and (org-export-numbered-headline-p parent info)
539 | (mapconcat
540 | #'number-to-string
541 | (org-export-get-headline-number parent info) "-"))))
542 | ;; Build return value.
543 | ;; at least for now, we have two special conditions
544 | ;; the CANVAS_NO_INNERDIV property is set; in this case
545 | ;; there's no enclosing foldable section, so the two are incompatible
546 | ;; the second special conditions is that the headline has a
547 | ;; CANVAS_FAT property. BUt that's nothing to worry about here actually --
548 | ;; nothing to change!
549 | (if (org-element-property :CANVAS_NO_INNERDIV parent)
550 | (format "%s\n" (or contents ""))
551 | (format "
\n%s
\n"
552 | class-num
553 | (or (org-element-property :CUSTOM_ID parent)
554 | section-number
555 | (org-export-get-reference parent info))
556 | "" ;; for now, moving this to the new div
557 | ;; (when (or (org-element-property :CANVAS_HTML_TOGGLE parent)
558 | ;; (org-export-read-attribute :attr_canvashtml parent :toggle))
559 | ;; "style=\"display:none;\"")
560 | (or contents "")))))))
561 |
562 | #+end_src
563 |
564 | #+RESULTS:
565 | : org-canvas-html-section
566 |
567 | ** Define some options here
568 | :PROPERTIES:
569 | :ID: 2e23db5c-8981-43ea-8115-ac19d527e65e
570 | :END:
571 |
572 | #+begin_src emacs-lisp
573 | (defcustom org-canvas-html-css-file
574 | (expand-file-name "canvas-styles.css" default-directory )
575 | "CSS styles to apply on export to canvas-html")
576 |
577 | (defvar org-canvas-html-fat-classes
578 | "content-box pad-box-mini border border-round"
579 | "Classs that together make a nice fat block element")
580 | (defvar org-canvas-html-toggler-classes
581 | "element_toggler"
582 | "class to turn on toggling in a headline")
583 |
584 | (defun org-canvashtml-toggler-make-aria (id)
585 | "assemble the aria-classes for the element toggler"
586 | (format " aria-controls=\"contents-%s\" aria-label=\"Toggler toggle list visibility\""
587 | id))
588 |
589 | #+end_src
590 |
591 | #+RESULTS:
592 | : org-canvashtml-toggler-make-aria
593 |
594 | ** Unfortunately, have to replace the headline function too :-(
595 | :PROPERTIES:
596 | :ID: 24d0c2e6-def5-461c-9b2e-737b422dc6dd
597 | :END:
598 | .. to use the new section function...
599 |
600 | also gonna add the capacity to just add an additional div to that sweeps the whoe section up
601 |
602 | Good thing we did ahtat before though as we have to modify it now anyway for folding
603 | #+begin_src emacs-lisp
604 | ;;;; Headline
605 |
606 | (defun org-canvas-html-headline (headline contents info)
607 | "Transcode a HEADLINE element from Org to HTML.
608 | CONTENTS holds the contents of the headline. INFO is a plist
609 | holding contextual information."
610 | (unless (org-element-property :footnote-section-p headline)
611 | (let* ((numberedp (org-export-numbered-headline-p headline info))
612 | (numbers (org-export-get-headline-number headline info))
613 | (level (+ (org-export-get-relative-level headline info)
614 | (1- (plist-get info :html-toplevel-hlevel))))
615 | (todo (and (plist-get info :with-todo-keywords)
616 | (let ((todo (org-element-property :todo-keyword headline)))
617 | (and todo (org-export-data todo info)))))
618 | (todo-type (and todo (org-element-property :todo-type headline)))
619 | (priority (and (plist-get info :with-priority)
620 | (org-element-property :priority headline)))
621 | (text (org-export-data (org-element-property :title headline) info))
622 | (tags (and (plist-get info :with-tags)
623 | (org-export-get-tags headline info)))
624 | (full-text (funcall (plist-get info :html-format-headline-function)
625 | todo todo-type priority text tags info))
626 | (contents (or contents ""))
627 | (id (org-html--reference headline info))
628 | (fat-classes (when (or (org-export-read-attribute :attr_canvashtml headline :fat)
629 | (org-element-property :CANVAS_HTML_FAT headline)
630 | (org-export-read-attribute :attr_canvashtml headline :fat))
631 | org-canvas-html-fat-classes))
632 | (add-toggler (or (org-element-property :CANVAS_HTML_TOGGLE headline)
633 | (org-export-read-attribute :attr_canvashtml headline :toggle)))
634 | (show-toggled (or (org-element-property :CANVAS_HTML_SHOW headline)
635 | (org-export-read-attribute :attr_canvashtml headline :show)))
636 | (formatted-text
637 | (if (plist-get info :html-self-link-headlines)
638 | (format "%s" id full-text)
639 | full-text)))
640 | (if (org-export-low-level-p headline info)
641 | ;; This is a deep sub-tree: export it as a list item.
642 | (let* ((html-type (if numberedp "ol" "ul")))
643 | (concat
644 | (and (org-export-first-sibling-p headline info)
645 | (apply #'format "<%s class=\"org-%s\">\n"
646 | (make-list 2 html-type)))
647 | (org-html-format-list-item
648 | contents (if numberedp 'ordered 'unordered)
649 | nil info nil
650 | (concat (org-html--anchor id nil nil info) formatted-text)) "\n"
651 | (and (org-export-last-sibling-p headline info)
652 | (format "%s>\n" html-type))))
653 | ;; Standard headline. Export it as a section.
654 | (let* ((extra-class
655 |
656 | (org-element-property :HTML_CONTAINER_CLASS headline))
657 | (headline-class (org-element-property :HTML_HEADLINE_CLASS headline))
658 | (headline-all-classes
659 | (concat (and fat-classes " ")
660 | fat-classes
661 | (and add-toggler " ")
662 | (when add-toggler org-canvas-html-toggler-classes)
663 | (and headline-class " ")
664 | headline-class))
665 | (first-content (car (org-element-contents headline))))
666 |
667 | (format "<%s id=\"%s\" class=\"%s\">%s%s%s>\n"
668 | (org-html--container headline info)
669 | (format "outline-container-%s" id)
670 | (concat (format "outline-%d" level)
671 | (and extra-class " ")
672 | extra-class)
673 | (format "\n%s\n"
674 | level
675 | id
676 | (if (not headline-all-classes) ""
677 | (format " class=\"%s\"" headline-all-classes))
678 | (if (not add-toggler) ""
679 | (org-canvashtml-toggler-make-aria id))
680 | (concat
681 | (and numberedp
682 | (format
683 | "%s "
684 | level
685 | (concat (mapconcat #'number-to-string numbers ".") ".")))
686 | formatted-text)
687 | level)
688 | ;; When there is no section, pretend there is an
689 | ;; empty one to get the correct