View raw

1 ;;; ox-slimhtml.el --- an HTML org export backend for the USWDS -*- lexical-binding: t; -*- 2 ;; Copyright (C) 2021 Marius Peter 3 4 ;; Author: Marius Peter (rot13 "?znevhf.crgre@ghgnabgn.pbz") 5 ;; Created: March 2021 6 ;; Package-Version: 0.1 7 ;; Keywords: org export publish html 8 ;; Homepage: http://www.smart-documents.org 9 10 ;; This file is not part of GNU Emacs. 11 12 ;;; License: 13 ;; This program is free software; you can redistribute it and/or modify 14 ;; it under the terms of the GNU General Public License as published by 15 ;; the Free Software Foundation, either version 3 of the License, or 16 ;; (at your option) any later version. 17 ;; 18 ;; This program is distributed in the hope that it will be useful, 19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 ;; GNU General Public License for more details. 22 ;; 23 ;; You should have received a copy of the GNU General Public License 24 ;; along with this file. If not, see <http://www.gnu.org/licenses/>. 25 26 ;;; Commentary: 27 ;; html-uswds is an Org mode export backend derived from the 28 ;; `ox-slimhtml' backend. It is intended to produce HTML compatible 29 ;; with the USWDS (https://designsystem.digital.gov/). A key feature 30 ;; of resulting web pages is their accessibility---the USWDS initially 31 ;; caters to American federal agencies wishing to adopt a common 32 ;; design language intelligible for all cultures and levels of 33 ;; computer literacy. 34 35 ;;; Code: 36 (require 'ox-html) 37 (require 'cl-lib) 38 39 ;; formatting 40 ;; #+BEGIN_EXAMPLE 41 ;; ,*bold* # <strong>bold</strong> 42 ;; /italic/ # <em>italic</em> 43 ;; =verbatim= # <kbd>verbatim</kbd> 44 ;; #+END_EXAMPLE 45 46 (defun ox-html-uswds-bold (bold contents info) 47 "Transcode BOLD from Org to HTML. 48 49 CONTENTS is the text with bold markup. 50 INFO is a plist holding contextual information." 51 (when contents (format "<strong>%s</strong>" contents))) 52 53 (defun ox-html-uswds-italic (italic contents info) 54 "Transcode ITALIC from Org to HTML. 55 56 CONTENTS is the text with italic markup. 57 INFO is a plist holding contextual information." 58 (when contents (format "<em>%s</em>" contents))) 59 60 (defun ox-html-uswds-verbatim (verbatim contents info) 61 "Transcode VERBATIM string from Org to HTML. 62 63 CONTENTS is nil. 64 INFO is a plist holding contextual information." 65 (let ((contents (org-html-encode-plain-text 66 (org-element-property :value verbatim)))) 67 (when contents (format "<kbd>%s</kbd>" contents)))) 68 69 ;; headlines 70 ;; #+BEGIN_EXAMPLE 71 ;; ,* headline text # <section class="container"> 72 ;; :PROPERTIES: # <h1 class="headline">headline text</h1> 73 ;; :attr_html: :class headline # </section> 74 ;; :html_container: section 75 ;; :html_container_class: container 76 ;; :END: 77 78 ;; ,#+OPTIONS: H:[headline level] 79 ;; ,#+HTML_CONTAINER: [default container] 80 ;; #+END_EXAMPLE 81 82 (defun ox-html-uswds-headline (headline contents info) 83 "Transcode HEADLINE from Org to HTML. 84 85 CONTENTS is the section as defined under the HEADLINE. 86 INFO is a plist holding contextual information." 87 (let* ((text (org-export-data (org-element-property :title headline) info)) 88 (level (org-export-get-relative-level headline info)) 89 (attributes (org-element-property :ATTR_HTML headline)) 90 (container (org-element-property :HTML_CONTAINER headline)) 91 (container-class (and container (org-element-property :HTML_CONTAINER_CLASS headline)))) 92 (when attributes 93 (setq attributes 94 (format " %s" (org-html--make-attribute-string 95 (org-export-read-attribute 'attr_html `(nil 96 (attr_html ,(split-string attributes)))))))) 97 (concat 98 (when (and container (not (string= "" container))) 99 (format "<%s%s>" container (if container-class (format " class=\"%s\"" container-class) ""))) 100 (if (not (org-export-low-level-p headline info)) 101 (format "<h%d%s>%s</h%d>%s" level (or attributes "") text level (or contents "")) 102 (concat 103 (when (org-export-first-sibling-p headline info) "<ul>") 104 (format "<li>%s%s</li>" text (or contents "")) 105 (when (org-export-last-sibling-p headline info) "</ul>"))) 106 (when (and container (not (string= "" container))) 107 (format "</%s>" (cl-subseq container 0 (cl-search " " container))))))) 108 109 ;; sections 110 111 (defun ox-html-uswds-section (section contents info) 112 "Transcode a SECTION element from Org to HTML. 113 114 CONTENTS is the contents of the section. 115 INFO is a plist holding contextual information. 116 117 Sections are child elements of org headlines; 118 'container' settings are found in slim-headlines." 119 contents) 120 121 ;; links 122 ;; #+BEGIN_EXAMPLE 123 ;; ,#+attr_html: :class link # <a href="link" class="link">content</a> 124 ;; [[link][content]] 125 126 ;; ,#+OPTIONS: html-link-org-files-as-html:[t/nil] || org-html-link-org-files-as-html 127 ;; ,#+HTML_EXTENSION: [html] || org-html-extension 128 129 ;; ,#+OPTIONS: html-link-use-abs-url:[t/nil] || org-html-link-use-abs-url 130 ;; #+END_EXAMPLE 131 132 (defun ox-html-uswds-link (link contents info) 133 "Transcode LINK from Org to HTML. 134 135 CONTENTS is the text of the link. 136 INFO is a plist holding contextual information." 137 (if (ox-html-uswds--immediate-child-of-p link 'link) (org-element-property :raw-link link) 138 (if (not contents) (format "<em>%s</em>" (org-element-property :path link)) 139 (let ((link-type (org-element-property :type link)) 140 (href (org-element-property :raw-link link)) 141 (attributes (if (ox-html-uswds--immediate-child-of-p link 'paragraph) 142 (ox-html-uswds--attr (org-export-get-parent link)) 143 "")) 144 (element "<a href=\"%s\"%s>%s</a>")) 145 (cond ((string= "file" link-type) 146 (let ((html-extension (or (plist-get info :html-extension) "")) 147 (use-abs-url (plist-get info :html-link-use-abs-url)) 148 (link-org-files-as-html (plist-get info :html-link-org-as-html)) 149 (path (or (org-element-property :path link) ""))) 150 (format element 151 (concat (if (and use-abs-url (file-name-absolute-p path)) "file:" "") 152 (if (and link-org-files-as-html (string= "org" (downcase (or (file-name-extension path) "")))) 153 (if (and html-extension (not (string= "" html-extension))) 154 (concat (file-name-sans-extension path) "." html-extension) 155 (file-name-sans-extension path)) 156 path)) 157 attributes contents))) 158 (t 159 (format element href attributes contents))))))) 160 161 ;; plain lists 162 ;; #+BEGIN_EXAMPLE 163 ;; ,#+attr_html: :class this # <ul class="this"> 164 ;; - item 1 # <li>item 1</li> 165 ;; - item 2 # <li>item 2</li> 166 ;; # </ul> 167 168 ;; + item 1 # <ol><li>item 1</li></ol> 169 ;; - definition :: list # <dl><dt>definition</dt><dd>list</dd></dl> 170 ;; #+END_EXAMPLE 171 172 (defun ox-html-uswds-plain-list (plain-list contents info) 173 "Transcode a PLAIN-LIST string from Org to HTML. 174 175 CONTENTS is the contents of the list element. 176 INFO is a plist holding contextual information." 177 (when contents 178 (let ((type (cl-case (org-element-property :type plain-list) 179 (ordered "ol") 180 (unordered "ul") 181 (descriptive "dl")))) 182 (format "<%s%s>%s</%s>" type (ox-html-uswds--attr plain-list) contents type)))) 183 184 ;; paragraphs 185 ;; #+BEGIN_EXAMPLE 186 ;; ,#+attr_html: :class this # <p class="this">content</p> 187 ;; content 188 ;; #+END_EXAMPLE 189 190 (defun ox-html-uswds-paragraph (paragraph contents info) 191 "Transcode a PARAGRAPH element from Org to HTML. 192 193 CONTENTS is the contents of the paragraph. 194 INFO is a plist holding contextual information." 195 (when contents 196 (if (or (ox-html-uswds--immediate-child-of-p paragraph 'item) 197 (ox-html-uswds--immediate-child-of-p paragraph 'special-block)) 198 contents 199 (if (ox-html-uswds--has-immediate-child-of-p paragraph 'link) 200 (format "<p>%s</p>" contents) 201 (format "<p%s>%s</p>" (ox-html-uswds--attr paragraph) contents))))) 202 203 ;; examples 204 ;; #+BEGIN_EXAMPLE 205 ;; ,#+BEGIN_EXAMPLE # content 206 ;; content 207 ;; ,#+END_EXAMPLE 208 ;; #+END_EXAMPLE 209 210 (defun ox-html-uswds-example-block (example-block contents info) 211 "Transcode an EXAMPLE-BLOCK element from Org to HTML. 212 213 CONTENTS is nil. INFO is a plist holding contextual information." 214 (let ((code (org-html-format-code example-block info))) 215 (when code 216 (format "<pre><code class=\"%s\">%s</code></pre>" 217 (or (org-element-property :language example-block) "example") 218 code)))) 219 220 ;; raw html 221 ;; #+BEGIN_EXAMPLE 222 ;; ,#+BEGIN_EXPORT html # <span>export block</span> 223 ;; <span>export block</span> 224 ;; ,#+END_EXPORT 225 226 ;; ,#+BEGIN_EXPORT javascript # <script>console.log()</script> 227 ;; console.log() 228 ;; ,#+END_EXPORT 229 230 ;; ,#+BEGIN_EXPORT css # <style type="text/css">span{}</style> 231 ;; span {} 232 ;; ,#+END_EXPORT 233 ;; #+END_EXAMPLE 234 235 (defun ox-html-uswds-export-block (export-block contents info) 236 "Transcode an EXPORT-BLOCK element from Org to HTML. 237 CONTENTS is nil. INFO is a plist holding contextual information." 238 (let ((contents (org-element-property :value export-block)) 239 (language (org-element-property :type export-block))) 240 (when contents 241 (cond ((string= "JAVASCRIPT" language) 242 (format "<script>%s</script>" contents)) 243 ((string= "CSS" language) 244 (format "<style type=\"text/css\">%s</style>" contents)) 245 (t 246 (org-remove-indentation contents)))))) 247 248 ;; snippet 249 ;; #+BEGIN_EXAMPLE 250 ;; @@html:<span>snippet</span>@@ # <span>snippet</span> 251 ;; #+END_EXAMPLE 252 253 (defun ox-html-uswds-export-snippet (export-snippet contents info) 254 "Transcode a EXPORT-SNIPPET object from Org to HTML. 255 256 CONTENTS is nil. INFO is a plist holding contextual information." 257 (let ((contents (org-element-property :value export-snippet))) 258 (when contents contents))) 259 260 ;; special block 261 ;; #+BEGIN_EXAMPLE 262 ;; ,#+attr_html: :type text/css # <style type="text/css"> 263 ;; ,#+BEGIN_STYLE # p { font-weight:500; } 264 ;; p { font-weight:500; } # </style> 265 ;; ,#+END_STYLE 266 ;; #+END_EXAMPLE 267 268 (load-file "./ox-html-uswds-components.el") 269 270 (defun ox-html-uswds-special-block (special-block contents info) 271 "Transcode SPECIAL-BLOCK from Org to HTML. 272 273 CONTENTS is the text within the #+BEGIN_ and #+END_ markers. 274 INFO is a plist holding contextual information." 275 (when contents 276 (let ((block-type (downcase (org-element-property :type special-block)))) 277 (cond ((string= "accordion" block-type)(uswds-component-accordion contents)) 278 ((string= "alert-info" block-type) (uswds-component-alert-info contents)) 279 ((string= "alert-warning" block-type) (uswds-component-alert-warning contents)) 280 ((string= "alert-error" block-type) (uswds-component-alert-error contents)) 281 ((string= "alert-success" block-type) (uswds-component-alert-success contents)) 282 ((string= "alert-slim" block-type) (uswds-component-alert-slim contents)) 283 ((string= "alert-no-icon" block-type) (uswds-component-alert-no-icon contents)) 284 ((string= "banner" block-type) (uswds-component-banner contents)) 285 ((string= "breadcrumb" block-type) (uswds-component-breadcrumb contents)) 286 ((string= "button" block-type) (uswds-component-button contents)) 287 ((string= "button-group" block-type) (uswds-component-button-group contents)) 288 ((string= "card" block-type) (uswds-component-card contents)) 289 ((string= "collection" block-type) (uswds-component-collection contents)) 290 ((string= "footer" block-type) (uswds-component-footer contents)) 291 ;; TODO form controls and templates 292 ((string= "grid" block-type) (uswds-component-grid contents)) 293 ((string= "header" block-type) (uswds-component-header contents)) 294 ;; TODO icons 295 ((string= "identifier" block-type) (uswds-component-identifier contents)) 296 ((string= "process-list" block-type) (uswds-component-process contents)) 297 ((string= "search" block-type) (uswds-component-search contents)) 298 ((string= "side-navigation" block-type) (uswds-component-side contents)) 299 ((string= "site-alert" block-type) (uswds-component-site-alert contents)) 300 ((string= "step-indicator" block-type) (uswds-component-step-indicator contents)) 301 ((string= "summary-box" block-type) (uswds-component-summary-box contents)) 302 ;; TODO table? 303 ((string= "tag" block-type) (uswds-component-tag contents)) 304 ((string= "tooltip" block-type) (uswds-component-tooltip contents)) 305 (t (format "<div>\n%s No suitable special block found. \n</div>" contents)))))) 306 307 ;; source code 308 ;; #+BEGIN_EXAMPLE 309 ;; ,#+BEGIN_SRC javascript # <pre> 310 ;; code # <code class="javascript">code</code> 311 ;; ,#+END_SRC # </pre> 312 ;; #+END_EXAMPLE 313 314 (defun ox-html-uswds-src-block (src-block contents info) 315 "Transcode SRC-BLOCK from Org to HTML. 316 317 CONTENTS is the text of a #+BEGIN_SRC...#+END_SRC block. 318 INFO is a plist holding contextual information." 319 (let ((code (org-html-format-code src-block info)) 320 (language (org-element-property :language src-block))) 321 (when code 322 (format "<pre><code class=\"%s\"%s>%s</code></pre>" 323 language (ox-html-uswds--attr src-block) code)))) 324 325 ;; body 326 ;; #+BEGIN_EXAMPLE 327 ;; ,#+HTML_PREAMBLE: preamble {{{macro}}} # preamble 328 ;; content # content 329 ;; ,#+HTML_POSTAMBLE: postamble {{{macro}}} # postamble 330 ;; #+END_EXAMPLE 331 332 (defun ox-html-uswds-inner-template (contents info) 333 "Return body of document string after HTML conversion. 334 335 CONTENTS is the transcoded contents string. 336 INFO is a plist holding export options." 337 (when (and contents (not (string= "" contents))) 338 (let ((container (plist-get info :html-container))) 339 (concat 340 (when (and container (not (string= "" container))) (format "<%s>" container)) 341 (or (ox-html-uswds--expand-macros (plist-get info :html-preamble) info) "") 342 contents 343 (or (ox-html-uswds--expand-macros (plist-get info :html-postamble) info) "") 344 (when (and container (not (string= "" container))) 345 (format "</%s>" (cl-subseq container 0 (cl-search " " container)))))))) 346 347 ;; html page 348 ;; #+BEGIN_EXAMPLE 349 ;; ,#+HTML_DOCTYPE: || org-html-doctype # <!DOCTYPE html> ; html5 350 ;; ,#+HTML_HEAD: || org-html-head # <html lang="en"> ; when language is set 351 ;; ,#+HTML_TITLE: %t # <head> 352 ;; ,#+HTML_HEAD_EXTRA: || org-html-head-extra # head 353 ;; ,#+HTML_BODY_ATTR: id="test" # <title>document title</title> 354 ;; ,#+HTML_HEADER: {{{macro}}} # head-extra 355 ;; ,#+HTML_FOOTER: {{{macro}}} # </head> 356 ;; # <body id="test"> 357 ;; # header 358 ;; # content 359 ;; # footer 360 ;; # </body> 361 ;; # </html> 362 363 ;; {{{macro}}} tokens can also be set in INFO; 364 ;; :html-head, :html-head-extra and :html-header. 365 366 ;; :html-title is a string with optional tokens; 367 ;; %t is the document's #+TITLE: property. 368 ;; #+END_EXAMPLE 369 370 (defun ox-html-uswds-template (contents info) 371 "Return full document string after HTML conversion. 372 373 CONTENTS is the transcoded contents string. 374 INFO is a plist holding export options." 375 (let ((doctype (assoc (plist-get info :html-doctype) org-html-doctype-alist)) 376 (language (plist-get info :language)) 377 (head (ox-html-uswds--expand-macros (plist-get info :html-head) info)) 378 (head-extra (ox-html-uswds--expand-macros (plist-get info :html-head-extra) info)) 379 (title (plist-get info :title)) 380 (title-format (plist-get info :html-title)) 381 (body-attr (plist-get info :html-body-attr)) 382 (header (plist-get info :html-header)) 383 (newline "\n")) 384 (when (listp title) 385 (setq title (car title))) 386 (concat 387 (when doctype (concat (cdr doctype) newline)) 388 "<html" (when language (concat " lang=\"" language "\"")) ">" newline 389 ;; Start if the document head. 390 "<head>" newline 391 (when (not (string= "" head)) (concat head newline)) 392 (when (and title (not (string= "" title))) 393 (if title-format 394 (format-spec (concat "<title>" title-format "</title>\n") 395 (format-spec-make ?t title)) 396 (concat "<title>" title "</title>" newline))) 397 (when (not (string= "" head-extra)) (concat head-extra newline)) 398 "<link rel=\"stylesheet\" href=\"../assets/uswds-2.10.1/css/uswds.min.css\" />" 399 "<link rel=\"stylesheet\" href=\"../assets/stylesheets/sd.css\" />" 400 ;; USWDS init 401 "<script src=\"../assets/uswds-2.10.1/js/uswds-init.min.js\" type=\"text/javascript\"></script>" 402 "</head>" newline 403 ;; Start of the document body. 404 "<body" (and body-attr (not (string= "" body-attr)) (format " %s" body-attr)) ">" 405 "<a class=\"usa-skipnav\" href=\"#main-content\">Skip to main content</a>" 406 "" 407 (when (and header (not (string= "" header))) 408 (or (ox-html-uswds--expand-macros header info) "")) 409 ;; When not the index page, add side navigation links. 410 ;; (when (not (string= (substring (buffer-name) 0 5) "index")) 411 ;; "<a class=\"usa-skipnav\" href=\"#main-content\">Skip to main content</a>" 412 ;; "<div class=\"usa-section\"> 413 ;; <div class=\"grid-container\"> 414 ;; <div class=\"grid-row grid-gap\"> 415 ;; <div class=\"usa-layout-docs__sidenav desktop:grid-col-3\"> 416 ;; <nav aria-label=\"Secondary navigation\"> 417 ;; <ul class=\"usa-sidenav sd-sidenav\"> 418 ;; <li class=\"usa-sidenav__item\"> 419 ;; <a href=\"\">Parent link</a> 420 ;; </li><li class=\"usa-sidenav__item\"> 421 ;; <a href=\"\" class=\"usa-current\">Current page</a><ul class=\"usa-sidenav__sublist\"> 422 ;; <li class=\"usa-sidenav__item\"> 423 ;; <a href=\"\">Child link</a> 424 ;; </li><li class=\"usa-sidenav__item\"> 425 ;; <a href=\"\" class=\"usa-current\">Child link</a><ul class=\"usa-sidenav__sublist\"> 426 ;; <li class=\"usa-sidenav__item\"> 427 ;; <a href=\"\">Grandchild link</a> 428 ;; </li><li class=\"usa-sidenav__item\"> 429 ;; <a href=\"\">Grandchild link</a> 430 ;; </li><li class=\"usa-sidenav__item\"> 431 ;; <a href=\"\" class=\"usa-current\">Grandchild link</a> 432 ;; </li><li class=\"usa-sidenav__item\"> 433 ;; <a href=\"\">Grandchild link</a> 434 ;; </li> 435 ;; </ul> 436 ;; </li><li class=\"usa-sidenav__item\"> 437 ;; <a href=\"\">Child link</a> 438 ;; </li><li class=\"usa-sidenav__item\"> 439 ;; <a href=\"\">Child link</a> 440 ;; </li><li class=\"usa-sidenav__item\"> 441 ;; <a href=\"\">Child link</a> 442 ;; </li> 443 ;; </ul> 444 ;; </li><li class=\"usa-sidenav__item\"> 445 ;; <a href=\"\">Parent link</a> 446 ;; </li> 447 ;; </ul> 448 ;; </nav> 449 450 ;; </div>) 451 contents 452 (or (ox-html-uswds--expand-macros (plist-get info :html-footer) info) "") 453 "<script src=\"../assets/uswds-2.10.1/js/uswds.min.js\"></script>" newline 454 "</body>" newline 455 "</html>"))) 456 457 ;; plain text 458 459 (defun ox-html-uswds-plain-text (plain-text info) 460 "Transcode a PLAIN-TEXT string from Org to HTML. 461 462 PLAIN-TEXT is the string to transcode. 463 INFO is a plist holding contextual information." 464 (org-html-encode-plain-text plain-text)) 465 466 ;; attributes 467 468 (defun ox-html-uswds--attr (element &optional property) 469 "Return ELEMENT's html attribute properties as a string. 470 471 When optional argument PROPERTY is non-nil, return the value of 472 that property within attributes." 473 (let ((attributes (org-export-read-attribute :attr_html element property))) 474 (if attributes (concat " " (org-html--make-attribute-string attributes)) ""))) 475 476 ;; is an immediate child of [element]? 477 478 (defun ox-html-uswds--immediate-child-of-p (element container-type) 479 "Is ELEMENT an immediate child of an org CONTAINER-TYPE element?" 480 (let ((container (org-export-get-parent element))) 481 (and (eq (org-element-type container) container-type) 482 (= (org-element-property :begin element) 483 (org-element-property :contents-begin container))))) 484 485 ;; has an immediate child of [element-type]? 486 487 (defun ox-html-uswds--has-immediate-child-of-p (element element-type) 488 "Does ELEMENT have an immediate ELEMENT-TYPE child?" 489 (org-element-map element element-type 490 (lambda (link) (= (org-element-property :begin link) 491 (org-element-property :contents-begin element))) 492 nil t)) 493 494 ;; expand macros 495 ;; Macro expansion takes place in a separate buffer - as such buffer local variables 496 ;; are not directly available, which might be important when using self-evaluating 497 ;; macros such as =,#+MACRO: x (eval (fn $1))=. To help with this, the original 498 ;; =buffer-file-name= is shadowed. 499 500 (defun ox-html-uswds--expand-macros (contents info) 501 "Return CONTENTS string, with macros expanded. 502 503 CONTENTS is a string, optionally with {{{macro}}} 504 tokens. INFO is a plist holding export options." 505 (if (cl-search "{{{" contents) 506 (let* ((author (org-element-interpret-data (plist-get info :author))) 507 (date (org-element-interpret-data (plist-get info :date))) 508 (email (or (plist-get info :email) "")) 509 (title (org-element-interpret-data (plist-get info :title))) 510 (export-specific-templates 511 (list (cons "author" author) 512 (cons "date" 513 (format "(eval (format-time-string \"$1\" '%s))" 514 (org-read-date nil t date nil))) 515 (cons "email" email) 516 (cons "title" title))) 517 (templates (org-combine-plists export-specific-templates 518 org-macro-templates)) 519 (buffer-name buffer-file-name)) 520 (with-temp-buffer (insert contents) 521 (let ((buffer-file-name buffer-name)) 522 (org-macro-replace-all templates)) 523 (buffer-string))) 524 contents)) 525 526 ;; org-mode publishing function 527 ;; #+BEGIN_EXAMPLE 528 ;; (setq org-publish-project-alist 529 ;; '(("project-name" 530 ;; :base-directory "~/src" 531 ;; :publishing-directory "~/public" 532 ;; :publishing-function ox-html-uswds-publish-to-html))) 533 ;; #+END_EXAMPLE 534 535 ;;;###autoload 536 (defun ox-html-uswds-publish-to-html (plist filename pub-dir) 537 "Publish an org file to HTML adapted for the USWDS. 538 539 PLIST is the property list for the given project. FILENAME 540 is the filename of the Org file to be published. PUB-DIR is 541 the publishing directory. 542 543 Return output file name." 544 (let ((html-extension (or (plist-get plist :html-extension) org-html-extension))) 545 (org-publish-org-to 'html-uswds 546 filename 547 (when (and html-extension (not (string= "" html-extension))) 548 (concat "." html-extension)) 549 plist 550 pub-dir))) 551 552 ;; org-export backend definition 553 (org-export-define-backend 554 'html-uswds 555 '((bold . ox-html-uswds-bold) 556 (example-block . ox-html-uswds-example-block) 557 (export-block . ox-html-uswds-export-block) 558 (export-snippet . ox-html-uswds-export-snippet) 559 (headline . ox-html-uswds-headline) 560 (inner-template . ox-html-uswds-inner-template) 561 (italic . ox-html-uswds-italic) 562 (item . org-html-item) 563 (link . ox-html-uswds-link) 564 (paragraph . ox-html-uswds-paragraph) 565 (plain-list . ox-html-uswds-plain-list) 566 (plain-text . ox-html-uswds-plain-text) 567 (section . ox-html-uswds-section) 568 (special-block . ox-html-uswds-special-block) 569 (src-block . ox-html-uswds-src-block) 570 (template . ox-html-uswds-template) 571 (verbatim . ox-html-uswds-verbatim)) 572 :menu-entry 573 '(?u "Export to html-uswds" 574 ((?U "As html-uswds buffer" ox-html-uswds-export-as-html) 575 (?u "As html-uswds file" ox-html-uswds-export-to-html))) 576 :options-alist 577 '((:html-extension "HTML_EXTENSION" nil org-html-extension) 578 (:html-link-org-as-html nil "html-link-org-files-as-html" org-html-link-org-files-as-html) 579 (:html-doctype "HTML_DOCTYPE" nil org-html-doctype) 580 (:html-container "HTML_CONTAINER" nil org-html-container-element t) 581 (:html-link-use-abs-url nil "html-link-use-abs-url" org-html-link-use-abs-url) 582 (:html-link-home "HTML_LINK_HOME" nil org-html-link-home) 583 (:html-preamble "HTML_PREAMBLE" nil "" newline) 584 (:html-postamble "HTML_POSTAMBLE" nil "" newline) 585 (:html-head "HTML_HEAD" nil org-html-head newline) 586 (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) 587 (:html-header "HTML_HEADER" nil "" newline) 588 (:html-footer "HTML_FOOTER" nil "" newline) 589 (:html-title "HTML_TITLE" nil "%t" t) 590 (:html-body-attr "HTML_BODY_ATTR" nil "" t))) 591 592 ;;;###autoload 593 (defun ox-html-uswds-export-as-html 594 (&optional async subtreep visible-only body-only ext-plist) 595 "Export current buffer to a HTML-USWDS buffer. 596 597 Export as `org-html-export-as-html' does, with html-uswds 598 org-export-backend. 599 600 If narrowing is active in the current buffer, only export its 601 narrowed part. 602 603 If a region is active, export that region. 604 605 A non-nil optional argument ASYNC means the process should happen 606 asynchronously. The resulting buffer should be accessible 607 through the `org-export-stack' interface. 608 609 When optional argument SUBTREEP is non-nil, export the sub-tree 610 at point, extracting information from the headline properties 611 first. 612 613 When optional argument VISIBLE-ONLY is non-nil, don't export 614 contents of hidden elements. 615 616 When optional argument BODY-ONLY is non-nil, only write code 617 between \"<body>\" and \"</body>\" tags. 618 619 EXT-PLIST, when provided, is a property list with external 620 parameters overriding Org default settings, but still inferior to 621 file-local settings. 622 623 Export is done in a buffer named \"*Org HTML-USWDS export*\", which 624 will be displayed when `org-export-show-temporary-export-buffer' 625 is non-nil." 626 (interactive) 627 (org-export-to-buffer 'html-uswds "*Org HTML-USWDS Export*" 628 async subtreep visible-only body-only ext-plist 629 (lambda () (set-auto-mode t)))) 630 631 ;;;###autoload 632 (defun ox-html-uswds-export-to-html (&optional async subtreep visible-only body-only ext-plist) 633 "Export current buffer to an HTML file. 634 635 Export as `org-html-export-as-html' does, with html-uswds 636 org-export-backend. 637 638 If narrowing is active in the current buffer, only export its 639 narrowed part. 640 641 If a region is active, export that region. 642 643 A non-nil optional argument ASYNC means the process should happen 644 asynchronously. The resulting file should be accessible through 645 the `org-export-stack' interface. 646 647 When optional argument SUBTREEP is non-nil, export the sub-tree 648 at point, extracting information from the headline properties 649 first. 650 651 When optional argument VISIBLE-ONLY is non-nil, don't export 652 contents of hidden elements. 653 654 When optional argument BODY-ONLY is non-nil, only write code 655 between \"<body>\" and \"</body>\" tags. 656 657 EXT-PLIST, when provided, is a property list with external 658 parameters overriding Org default settings, but still inferior to 659 file-local settings. 660 661 Return output file's name." 662 (interactive) 663 (let* ((extension (concat "." (or (plist-get ext-plist :html-extension) 664 org-html-extension 665 "html"))) 666 (file (org-export-output-file-name extension subtreep)) 667 (org-export-coding-system org-html-coding-system)) 668 (org-export-to-file 'html-uswds file 669 async subtreep visible-only body-only ext-plist))) 670 671 (provide 'ox-html.uswds) 672 ;;; ox-html-uswds.el ends here 673