ox.el (291444B)
1 ;;; ox.el --- Export Framework for Org Mode -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2012-2023 Free Software Foundation, Inc. 4 5 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr> 6 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr> 7 ;; Keywords: outlines, hypermedia, calendar, wp 8 9 ;; This file is part of GNU Emacs. 10 11 ;; GNU Emacs is free software: you can redistribute it and/or modify 12 ;; it under the terms of the GNU General Public License as published by 13 ;; the Free Software Foundation, either version 3 of the License, or 14 ;; (at your option) any later version. 15 16 ;; GNU Emacs is distributed in the hope that it will be useful, 17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 ;; GNU General Public License for more details. 20 21 ;; You should have received a copy of the GNU General Public License 22 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 23 24 ;;; Commentary: 25 ;; 26 ;; This library implements a generic export engine for Org, built on 27 ;; its syntactical parser: Org Elements. 28 ;; 29 ;; Besides that parser, the generic exporter is made of three distinct 30 ;; parts: 31 ;; 32 ;; - The communication channel consists of a property list, which is 33 ;; created and updated during the process. Its use is to offer 34 ;; every piece of information, would it be about initial environment 35 ;; or contextual data, all in a single place. 36 ;; 37 ;; - The transcoder walks the parse tree, ignores or treat as plain 38 ;; text elements and objects according to export options, and 39 ;; eventually calls back-end specific functions to do the real 40 ;; transcoding, concatenating their return value along the way. 41 ;; 42 ;; - The filter system is activated at the very beginning and the very 43 ;; end of the export process, and each time an element or an object 44 ;; has been converted. It is the entry point to fine-tune standard 45 ;; output from back-end transcoders. See "The Filter System" 46 ;; section for more information. 47 ;; 48 ;; The core functions is `org-export-as'. It returns the transcoded 49 ;; buffer as a string. Its derivatives are `org-export-to-buffer' and 50 ;; `org-export-to-file'. 51 ;; 52 ;; An export back-end is defined with `org-export-define-backend'. 53 ;; This function can also support specific buffer keywords, OPTION 54 ;; keyword's items and filters. Refer to function's documentation for 55 ;; more information. 56 ;; 57 ;; If the new back-end shares most properties with another one, 58 ;; `org-export-define-derived-backend' can be used to simplify the 59 ;; process. 60 ;; 61 ;; Any back-end can define its own variables. Among them, those 62 ;; customizable should belong to the `org-export-BACKEND' group. 63 ;; 64 ;; Tools for common tasks across back-ends are implemented in the 65 ;; following part of the file. 66 ;; 67 ;; Eventually, a dispatcher (`org-export-dispatch') is provided in the 68 ;; last one. 69 ;; 70 ;; See <https://orgmode.org/worg/dev/org-export-reference.html> for 71 ;; more information. 72 73 ;;; Code: 74 75 (require 'org-macs) 76 (org-assert-version) 77 78 (require 'cl-lib) 79 (require 'ob-exp) 80 (require 'oc) 81 (require 'ol) 82 (require 'org-element) 83 (require 'org-macro) 84 (require 'tabulated-list) 85 86 (declare-function org-src-coderef-format "org-src" (&optional element)) 87 (declare-function org-src-coderef-regexp "org-src" (fmt &optional label)) 88 (declare-function org-publish "ox-publish" (project &optional force async)) 89 (declare-function org-publish-all "ox-publish" (&optional force async)) 90 (declare-function org-publish-current-file "ox-publish" (&optional force async)) 91 (declare-function org-publish-current-project "ox-publish" (&optional force async)) 92 (declare-function org-at-heading-p "org" (&optional _)) 93 (declare-function org-back-to-heading "org" (&optional invisible-ok)) 94 (declare-function org-next-visible-heading "org" (arg)) 95 96 (defvar org-publish-project-alist) 97 (defvar org-table-number-fraction) 98 (defvar org-table-number-regexp) 99 100 101 ;;; Internal Variables 102 ;; 103 ;; Among internal variables, the most important is 104 ;; `org-export-options-alist'. This variable define the global export 105 ;; options, shared between every exporter, and how they are acquired. 106 107 (defconst org-export-max-depth 19 108 "Maximum nesting depth for headlines, counting from 0.") 109 110 (defconst org-export-options-alist 111 '((:title "TITLE" nil nil parse) 112 (:date "DATE" nil nil parse) 113 (:author "AUTHOR" nil user-full-name parse) 114 (:email "EMAIL" nil user-mail-address t) 115 (:language "LANGUAGE" nil org-export-default-language t) 116 (:select-tags "SELECT_TAGS" nil org-export-select-tags split) 117 (:exclude-tags "EXCLUDE_TAGS" nil org-export-exclude-tags split) 118 (:creator "CREATOR" nil org-export-creator-string) 119 (:headline-levels nil "H" org-export-headline-levels) 120 (:preserve-breaks nil "\\n" org-export-preserve-breaks) 121 (:section-numbers nil "num" org-export-with-section-numbers) 122 (:time-stamp-file nil "timestamp" org-export-time-stamp-file) 123 (:with-archived-trees nil "arch" org-export-with-archived-trees) 124 (:with-author nil "author" org-export-with-author) 125 (:with-broken-links nil "broken-links" org-export-with-broken-links) 126 (:with-clocks nil "c" org-export-with-clocks) 127 (:with-creator nil "creator" org-export-with-creator) 128 (:with-date nil "date" org-export-with-date) 129 (:with-drawers nil "d" org-export-with-drawers) 130 (:with-email nil "email" org-export-with-email) 131 (:with-emphasize nil "*" org-export-with-emphasize) 132 (:with-entities nil "e" org-export-with-entities) 133 (:with-fixed-width nil ":" org-export-with-fixed-width) 134 (:with-footnotes nil "f" org-export-with-footnotes) 135 (:with-inlinetasks nil "inline" org-export-with-inlinetasks) 136 (:with-latex nil "tex" org-export-with-latex) 137 (:with-planning nil "p" org-export-with-planning) 138 (:with-priority nil "pri" org-export-with-priority) 139 (:with-properties nil "prop" org-export-with-properties) 140 (:with-smart-quotes nil "'" org-export-with-smart-quotes) 141 (:with-special-strings nil "-" org-export-with-special-strings) 142 (:with-statistics-cookies nil "stat" org-export-with-statistics-cookies) 143 (:with-sub-superscript nil "^" org-export-with-sub-superscripts) 144 (:with-toc nil "toc" org-export-with-toc) 145 (:with-tables nil "|" org-export-with-tables) 146 (:with-tags nil "tags" org-export-with-tags) 147 (:with-tasks nil "tasks" org-export-with-tasks) 148 (:with-timestamps nil "<" org-export-with-timestamps) 149 (:with-title nil "title" org-export-with-title) 150 (:with-todo-keywords nil "todo" org-export-with-todo-keywords) 151 ;; Citations processing. 152 (:cite-export "CITE_EXPORT" nil org-cite-export-processors)) 153 "Alist between export properties and ways to set them. 154 155 The key of the alist is the property name, and the value is a list 156 like (KEYWORD OPTION DEFAULT BEHAVIOR) where: 157 158 KEYWORD is a string representing a buffer keyword, or nil. Each 159 property defined this way can also be set, during subtree 160 export, through a headline property named after the keyword 161 with the \"EXPORT_\" prefix (i.e. DATE keyword and EXPORT_DATE 162 property). 163 OPTION is a string that could be found in an #+OPTIONS: line. 164 DEFAULT is the default value for the property. 165 BEHAVIOR determines how Org should handle multiple keywords for 166 the same property. It is a symbol among: 167 nil Keep old value and discard the new one. 168 t Replace old value with the new one. 169 `space' Concatenate the values, separating them with a space. 170 `newline' Concatenate the values, separating them with 171 a newline. 172 `split' Split values at white spaces, and cons them to the 173 previous list. 174 `parse' Parse value as a list of strings and Org objects, 175 which can then be transcoded with, e.g., 176 `org-export-data'. It implies `space' behavior. 177 178 Values set through KEYWORD and OPTION have precedence over 179 DEFAULT. 180 181 All these properties should be back-end agnostic. Back-end 182 specific properties are set through `org-export-define-backend'. 183 Properties redefined there have precedence over these.") 184 185 (defconst org-export-filters-alist 186 '((:filter-body . org-export-filter-body-functions) 187 (:filter-bold . org-export-filter-bold-functions) 188 (:filter-babel-call . org-export-filter-babel-call-functions) 189 (:filter-center-block . org-export-filter-center-block-functions) 190 (:filter-clock . org-export-filter-clock-functions) 191 (:filter-code . org-export-filter-code-functions) 192 (:filter-diary-sexp . org-export-filter-diary-sexp-functions) 193 (:filter-drawer . org-export-filter-drawer-functions) 194 (:filter-dynamic-block . org-export-filter-dynamic-block-functions) 195 (:filter-entity . org-export-filter-entity-functions) 196 (:filter-example-block . org-export-filter-example-block-functions) 197 (:filter-export-block . org-export-filter-export-block-functions) 198 (:filter-export-snippet . org-export-filter-export-snippet-functions) 199 (:filter-final-output . org-export-filter-final-output-functions) 200 (:filter-fixed-width . org-export-filter-fixed-width-functions) 201 (:filter-footnote-definition . org-export-filter-footnote-definition-functions) 202 (:filter-footnote-reference . org-export-filter-footnote-reference-functions) 203 (:filter-headline . org-export-filter-headline-functions) 204 (:filter-horizontal-rule . org-export-filter-horizontal-rule-functions) 205 (:filter-inline-babel-call . org-export-filter-inline-babel-call-functions) 206 (:filter-inline-src-block . org-export-filter-inline-src-block-functions) 207 (:filter-inlinetask . org-export-filter-inlinetask-functions) 208 (:filter-italic . org-export-filter-italic-functions) 209 (:filter-item . org-export-filter-item-functions) 210 (:filter-keyword . org-export-filter-keyword-functions) 211 (:filter-latex-environment . org-export-filter-latex-environment-functions) 212 (:filter-latex-fragment . org-export-filter-latex-fragment-functions) 213 (:filter-line-break . org-export-filter-line-break-functions) 214 (:filter-link . org-export-filter-link-functions) 215 (:filter-node-property . org-export-filter-node-property-functions) 216 (:filter-options . org-export-filter-options-functions) 217 (:filter-paragraph . org-export-filter-paragraph-functions) 218 (:filter-parse-tree . org-export-filter-parse-tree-functions) 219 (:filter-plain-list . org-export-filter-plain-list-functions) 220 (:filter-plain-text . org-export-filter-plain-text-functions) 221 (:filter-planning . org-export-filter-planning-functions) 222 (:filter-property-drawer . org-export-filter-property-drawer-functions) 223 (:filter-quote-block . org-export-filter-quote-block-functions) 224 (:filter-radio-target . org-export-filter-radio-target-functions) 225 (:filter-section . org-export-filter-section-functions) 226 (:filter-special-block . org-export-filter-special-block-functions) 227 (:filter-src-block . org-export-filter-src-block-functions) 228 (:filter-statistics-cookie . org-export-filter-statistics-cookie-functions) 229 (:filter-strike-through . org-export-filter-strike-through-functions) 230 (:filter-subscript . org-export-filter-subscript-functions) 231 (:filter-superscript . org-export-filter-superscript-functions) 232 (:filter-table . org-export-filter-table-functions) 233 (:filter-table-cell . org-export-filter-table-cell-functions) 234 (:filter-table-row . org-export-filter-table-row-functions) 235 (:filter-target . org-export-filter-target-functions) 236 (:filter-timestamp . org-export-filter-timestamp-functions) 237 (:filter-underline . org-export-filter-underline-functions) 238 (:filter-verbatim . org-export-filter-verbatim-functions) 239 (:filter-verse-block . org-export-filter-verse-block-functions)) 240 "Alist between filters properties and initial values. 241 242 The key of each association is a property name accessible through 243 the communication channel. Its value is a configurable global 244 variable defining initial filters. 245 246 This list is meant to install user specified filters. Back-end 247 developers may install their own filters using 248 `org-export-define-backend'. Filters defined there will always 249 be prepended to the current list, so they always get applied 250 first.") 251 252 (defconst org-export-default-inline-image-rule 253 `(("file" . 254 ,(format "\\.%s\\'" 255 (regexp-opt 256 '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" 257 "xpm" "pbm" "pgm" "ppm") t)))) 258 "Default rule for link matching an inline image. 259 This rule applies to links with no description. By default, it 260 will be considered as an inline image if it targets a local file 261 whose extension is either \"png\", \"jpeg\", \"jpg\", \"gif\", 262 \"tiff\", \"tif\", \"xbm\", \"xpm\", \"pbm\", \"pgm\" or \"ppm\". 263 See `org-export-inline-image-p' for more information about 264 rules.") 265 266 (defconst org-export-ignored-local-variables 267 '( org-font-lock-keywords org-element--cache-change-tic 268 org-element--cache-change-tic org-element--cache-size 269 org-element--headline-cache-size 270 org-element--cache-sync-keys-value 271 org-element--cache-change-warning org-element--headline-cache 272 org-element--cache org-element--cache-sync-keys 273 org-element--cache-sync-requests org-element--cache-sync-timer) 274 "List of variables not copied through upon buffer duplication. 275 Export process takes place on a copy of the original buffer. 276 When this copy is created, all Org related local variables not in 277 this list are copied to the new buffer. Variables with an 278 unreadable value are also ignored.") 279 280 (defvar org-export-async-debug nil 281 "Non-nil means asynchronous export process should leave data behind. 282 283 This data is found in the appropriate \"*Org Export Process*\" 284 buffer, and in files prefixed with \"org-export-process\" and 285 located in `temporary-file-directory'. 286 287 When non-nil, it will also set `debug-on-error' to a non-nil 288 value in the external process.") 289 290 (defvar org-export-stack-contents nil 291 "Record asynchronously generated export results and processes. 292 This is an alist: its CAR is the source of the 293 result (destination file or buffer for a finished process, 294 original buffer for a running one) and its CDR is a list 295 containing the back-end used, as a symbol, and either a process 296 or the time at which it finished. It is used to build the menu 297 from `org-export-stack'.") 298 299 (defvar org-export-registered-backends nil 300 "List of backends currently available in the exporter. 301 This variable is set with `org-export-define-backend' and 302 `org-export-define-derived-backend' functions.") 303 304 (defvar org-export-dispatch-last-action nil 305 "Last command called from the dispatcher. 306 The value should be a list. Its CAR is the action, as a symbol, 307 and its CDR is a list of export options.") 308 309 (defvar org-export-dispatch-last-position (make-marker) 310 "The position where the last export command was created using the dispatcher. 311 This marker will be used with `\\[universal-argument] C-c C-e' to make sure export repetition 312 uses the same subtree if the previous command was restricted to a subtree.") 313 314 ;; For compatibility with Org < 8 315 (defvar org-export-current-backend nil 316 "Name, if any, of the back-end used during an export process. 317 318 Its value is a symbol such as `html', `latex', `ascii', or nil if 319 the back-end is anonymous (see `org-export-create-backend') or if 320 there is no export process in progress. 321 322 It can be used to teach Babel blocks how to act differently 323 according to the back-end used.") 324 325 326 327 ;;; User-configurable Variables 328 ;; 329 ;; Configuration for the masses. 330 ;; 331 ;; They should never be accessed directly, as their value is to be 332 ;; stored in a property list (cf. `org-export-options-alist'). 333 ;; Back-ends will read their value from there instead. 334 335 (defgroup org-export nil 336 "Options for exporting Org mode files." 337 :tag "Org Export" 338 :group 'org) 339 340 (defgroup org-export-general nil 341 "General options for export engine." 342 :tag "Org Export General" 343 :group 'org-export) 344 345 (defcustom org-export-with-archived-trees 'headline 346 "Whether sub-trees with the ARCHIVE tag should be exported. 347 348 This can have three different values: 349 nil Do not export, pretend this tree is not present. 350 t Do export the entire tree. 351 `headline' Only export the headline, but skip the tree below it. 352 353 This option can also be set with the OPTIONS keyword, 354 e.g. \"arch:nil\"." 355 :group 'org-export-general 356 :type '(choice 357 (const :tag "Not at all" nil) 358 (const :tag "Headline only" headline) 359 (const :tag "Entirely" t)) 360 :safe (lambda (x) (memq x '(t nil headline)))) 361 362 (defcustom org-export-with-author t 363 "Non-nil means insert author name into the exported file. 364 This option can also be set with the OPTIONS keyword, 365 e.g. \"author:nil\"." 366 :group 'org-export-general 367 :type 'boolean 368 :safe #'booleanp) 369 370 (defcustom org-export-with-clocks nil 371 "Non-nil means export CLOCK keywords. 372 This option can also be set with the OPTIONS keyword, 373 e.g. \"c:t\"." 374 :group 'org-export-general 375 :type 'boolean 376 :safe #'booleanp) 377 378 (defcustom org-export-with-creator nil 379 "Non-nil means the postamble should contain a creator sentence. 380 381 The sentence can be set in `org-export-creator-string', which 382 see. 383 384 This option can also be set with the OPTIONS keyword, e.g., 385 \"creator:t\"." 386 :group 'org-export-general 387 :version "26.1" 388 :package-version '(Org . "8.3") 389 :type 'boolean 390 :safe #'booleanp) 391 392 (defcustom org-export-with-date t 393 "Non-nil means insert date in the exported document. 394 This option can also be set with the OPTIONS keyword, 395 e.g. \"date:nil\"." 396 :group 'org-export-general 397 :type 'boolean 398 :safe #'booleanp) 399 400 (defcustom org-export-date-timestamp-format nil 401 "Time-stamp format string to use for DATE keyword. 402 403 The format string, when specified, only applies if date consists 404 in a single time-stamp. Otherwise its value will be ignored. 405 406 See `format-time-string' for details on how to build this 407 string." 408 :group 'org-export-general 409 :type '(choice 410 (string :tag "Time-stamp format string") 411 (const :tag "No format string" nil)) 412 :safe (lambda (x) (or (null x) (stringp x)))) 413 414 (defcustom org-export-creator-string 415 (format "Emacs %s (Org mode %s)" 416 emacs-version 417 (if (fboundp 'org-version) (org-version) "unknown version")) 418 "Information about the creator of the document. 419 This option can also be set on with the CREATOR keyword." 420 :group 'org-export-general 421 :type '(string :tag "Creator string") 422 :safe #'stringp) 423 424 (defcustom org-export-with-drawers '(not "LOGBOOK") 425 "Non-nil means export contents of standard drawers. 426 427 When t, all drawers are exported. This may also be a list of 428 drawer names to export, as strings. If that list starts with 429 `not', only drawers with such names will be ignored. 430 431 This variable doesn't apply to properties drawers. See 432 `org-export-with-properties' instead. 433 434 This option can also be set with the OPTIONS keyword, 435 e.g. \"d:nil\"." 436 :group 'org-export-general 437 :version "24.4" 438 :package-version '(Org . "8.0") 439 :type '(choice 440 (const :tag "All drawers" t) 441 (const :tag "None" nil) 442 (repeat :tag "Selected drawers" 443 (string :tag "Drawer name")) 444 (list :tag "Ignored drawers" 445 (const :format "" not) 446 (repeat :tag "Specify names of drawers to ignore during export" 447 :inline t 448 (string :tag "Drawer name")))) 449 :safe (lambda (x) (or (booleanp x) (consp x)))) 450 451 (defcustom org-export-with-email nil 452 "Non-nil means insert author email into the exported file. 453 This option can also be set with the OPTIONS keyword, 454 e.g. \"email:t\"." 455 :group 'org-export-general 456 :type 'boolean 457 :safe #'booleanp) 458 459 (defcustom org-export-with-emphasize t 460 "Non-nil means interpret *word*, /word/, _word_ and +word+. 461 462 If the export target supports emphasizing text, the word will be 463 typeset in bold, italic, with an underline or strike-through, 464 respectively. 465 466 This option can also be set with the OPTIONS keyword, 467 e.g. \"*:nil\"." 468 :group 'org-export-general 469 :type 'boolean 470 :safe #'booleanp) 471 472 (defcustom org-export-exclude-tags '("noexport") 473 "Tags that exclude a tree from export. 474 475 All trees carrying any of these tags will be excluded from 476 export. This is without condition, so even subtrees inside that 477 carry one of the `org-export-select-tags' will be removed. 478 479 This option can also be set with the EXCLUDE_TAGS keyword." 480 :group 'org-export-general 481 :type '(repeat (string :tag "Tag")) 482 :safe (lambda (x) (and (listp x) (cl-every #'stringp x)))) 483 484 (defcustom org-export-with-fixed-width t 485 "Non-nil means export lines starting with \":\". 486 This option can also be set with the OPTIONS keyword, 487 e.g. \"::nil\"." 488 :group 'org-export-general 489 :version "24.4" 490 :package-version '(Org . "8.0") 491 :type 'boolean 492 :safe #'booleanp) 493 494 (defcustom org-export-with-footnotes t 495 "Non-nil means Org footnotes should be exported. 496 This option can also be set with the OPTIONS keyword, 497 e.g. \"f:nil\"." 498 :group 'org-export-general 499 :type 'boolean 500 :safe #'booleanp) 501 502 (defcustom org-export-with-latex t 503 "Non-nil means process LaTeX environments and fragments. 504 505 This option can also be set with the OPTIONS line, 506 e.g. \"tex:verbatim\". Allowed values are: 507 508 nil Ignore math snippets. 509 `verbatim' Keep everything in verbatim. 510 t Allow export of math snippets." 511 :group 'org-export-general 512 :version "24.4" 513 :package-version '(Org . "8.0") 514 :type '(choice 515 (const :tag "Do not process math in any way" nil) 516 (const :tag "Interpret math snippets" t) 517 (const :tag "Leave math verbatim" verbatim)) 518 :safe (lambda (x) (memq x '(t nil verbatim)))) 519 520 (defcustom org-export-headline-levels 3 521 "The last level which is still exported as a headline. 522 523 Inferior levels will usually produce itemize or enumerate lists 524 when exported, but back-end behavior may differ. 525 526 This option can also be set with the OPTIONS keyword, 527 e.g. \"H:2\"." 528 :group 'org-export-general 529 :type 'integer 530 :safe #'integerp) 531 532 (defcustom org-export-default-language "en" 533 "The default language for export and clocktable translations, as a string. 534 This may have an association in 535 `org-clock-clocktable-language-setup', 536 `org-export-smart-quotes-alist' and `org-export-dictionary'. 537 This option can also be set with the LANGUAGE keyword." 538 :group 'org-export-general 539 :type '(string :tag "Language") 540 :safe #'stringp) 541 542 (defcustom org-export-preserve-breaks nil 543 "Non-nil means preserve all line breaks when exporting. 544 This option can also be set with the OPTIONS keyword, 545 e.g. \"\\n:t\"." 546 :group 'org-export-general 547 :type 'boolean 548 :safe #'booleanp) 549 550 (defcustom org-export-with-entities t 551 "Non-nil means interpret entities when exporting. 552 553 For example, HTML export converts \\alpha to α and \\AA to 554 Å. 555 556 For a list of supported names, see the constant `org-entities' 557 and the user option `org-entities-user'. 558 559 This option can also be set with the OPTIONS keyword, 560 e.g. \"e:nil\"." 561 :group 'org-export-general 562 :type 'boolean 563 :safe #'booleanp) 564 565 (defcustom org-export-with-inlinetasks t 566 "Non-nil means inlinetasks should be exported. 567 This option can also be set with the OPTIONS keyword, 568 e.g. \"inline:nil\"." 569 :group 'org-export-general 570 :version "24.4" 571 :package-version '(Org . "8.0") 572 :type 'boolean 573 :safe #'booleanp) 574 575 (defcustom org-export-with-planning nil 576 "Non-nil means include planning info in export. 577 578 Planning info is the line containing either SCHEDULED:, 579 DEADLINE:, CLOSED: time-stamps, or a combination of them. 580 581 This option can also be set with the OPTIONS keyword, 582 e.g. \"p:t\"." 583 :group 'org-export-general 584 :version "24.4" 585 :package-version '(Org . "8.0") 586 :type 'boolean 587 :safe #'booleanp) 588 589 (defcustom org-export-with-priority nil 590 "Non-nil means include priority cookies in export. 591 This option can also be set with the OPTIONS keyword, 592 e.g. \"pri:t\"." 593 :group 'org-export-general 594 :type 'boolean 595 :safe #'booleanp) 596 597 (defcustom org-export-with-properties nil 598 "Non-nil means export contents of properties drawers. 599 600 When t, all properties are exported. This may also be a list of 601 properties to export, as strings. 602 603 This option can also be set with the OPTIONS keyword, 604 e.g. \"prop:t\"." 605 :group 'org-export-general 606 :version "26.1" 607 :package-version '(Org . "8.3") 608 :type '(choice 609 (const :tag "All properties" t) 610 (const :tag "None" nil) 611 (repeat :tag "Selected properties" 612 (string :tag "Property name"))) 613 :safe (lambda (x) (or (booleanp x) 614 (and (listp x) (cl-every #'stringp x))))) 615 616 (defcustom org-export-with-section-numbers t 617 "Non-nil means add section numbers to headlines when exporting. 618 619 When set to an integer n, numbering will only happen for 620 headlines whose relative level is higher or equal to n. 621 622 This option can also be set with the OPTIONS keyword, 623 e.g. \"num:t\"." 624 :group 'org-export-general 625 :type 'boolean 626 :safe #'booleanp) 627 628 (defcustom org-export-select-tags '("export") 629 "Tags that select a tree for export. 630 631 If any such tag is found in a buffer, all trees that do not carry 632 one of these tags will be ignored during export. Inside trees 633 that are selected like this, you can still deselect a subtree by 634 tagging it with one of the `org-export-exclude-tags'. 635 636 This option can also be set with the SELECT_TAGS keyword." 637 :group 'org-export-general 638 :type '(repeat (string :tag "Tag")) 639 :safe (lambda (x) (and (listp x) (cl-every #'stringp x)))) 640 641 (defcustom org-export-with-smart-quotes nil 642 "Non-nil means activate smart quotes during export. 643 This option can also be set with the OPTIONS keyword, 644 e.g., \"\\=':t\". 645 646 When setting this to non-nil, you need to take care of 647 using the correct Babel package when exporting to LaTeX. 648 E.g., you can load Babel for french like this: 649 650 #+LATEX_HEADER: \\usepackage[french]{babel}" 651 :group 'org-export-general 652 :version "24.4" 653 :package-version '(Org . "8.0") 654 :type 'boolean 655 :safe #'booleanp) 656 657 (defcustom org-export-with-special-strings t 658 "Non-nil means interpret \"\\-\", \"--\" and \"---\" for export. 659 660 When this option is turned on, these strings will be exported as: 661 662 Org HTML LaTeX UTF-8 663 -----+----------+--------+------- 664 \\- ­ \\- 665 -- – -- – 666 --- — --- — 667 ... … \\ldots … 668 669 This option can also be set with the OPTIONS keyword, 670 e.g. \"-:nil\"." 671 :group 'org-export-general 672 :type 'boolean 673 :safe #'booleanp) 674 675 (defcustom org-export-with-statistics-cookies t 676 "Non-nil means include statistics cookies in export. 677 This option can also be set with the OPTIONS keyword, 678 e.g. \"stat:nil\"" 679 :group 'org-export-general 680 :version "24.4" 681 :package-version '(Org . "8.0") 682 :type 'boolean 683 :safe #'booleanp) 684 685 (defcustom org-export-with-sub-superscripts t 686 "Non-nil means interpret \"_\" and \"^\" for export. 687 688 If you want to control how Org displays those characters, see 689 `org-use-sub-superscripts'. `org-export-with-sub-superscripts' 690 used to be an alias for `org-use-sub-superscripts' in Org <8.0, 691 it is not anymore. 692 693 When this option is turned on, you can use TeX-like syntax for 694 sub- and superscripts and see them exported correctly. 695 696 You can also set the option with #+OPTIONS: ^:t 697 698 Several characters after \"_\" or \"^\" will be considered as a 699 single item - so grouping with {} is normally not needed. For 700 example, the following things will be parsed as single sub- or 701 superscripts: 702 703 10^24 or 10^tau several digits will be considered 1 item. 704 10^-12 or 10^-tau a leading sign with digits or a word 705 x^2-y^3 will be read as x^2 - y^3, because items are 706 terminated by almost any nonword/nondigit char. 707 x_{i^2} or x^(2-i) braces or parenthesis do grouping. 708 709 Still, ambiguity is possible. So when in doubt, use {} to enclose 710 the sub/superscript. If you set this variable to the symbol `{}', 711 the braces are *required* in order to trigger interpretations as 712 sub/superscript. This can be helpful in documents that need \"_\" 713 frequently in plain text." 714 :group 'org-export-general 715 :version "24.4" 716 :package-version '(Org . "8.0") 717 :type '(choice 718 (const :tag "Interpret them" t) 719 (const :tag "Curly brackets only" {}) 720 (const :tag "Do not interpret them" nil)) 721 :safe (lambda (x) (memq x '(t nil {})))) 722 723 (defcustom org-export-with-toc t 724 "Non-nil means create a table of contents in exported files. 725 726 The table of contents contains headlines with levels up to 727 `org-export-headline-levels'. 728 729 When this variable is set to an integer N, include levels up to 730 N in the table of contents. Although it may then be different 731 from `org-export-headline-levels', it is cannot be larger than 732 the number of headline levels. 733 734 When nil, no table of contents is created. 735 736 This option can also be set with the OPTIONS keyword, 737 e.g. \"toc:nil\" or \"toc:3\"." 738 :group 'org-export-general 739 :type '(choice 740 (const :tag "No Table of Contents" nil) 741 (const :tag "Full Table of Contents" t) 742 (integer :tag "TOC to level")) 743 :safe (lambda (x) 744 (or (booleanp x) 745 (integerp x)))) 746 747 (defcustom org-export-with-tables t 748 "Non-nil means export tables. 749 This option can also be set with the OPTIONS keyword, 750 e.g. \"|:nil\"." 751 :group 'org-export-general 752 :version "24.4" 753 :package-version '(Org . "8.0") 754 :type 'boolean 755 :safe #'booleanp) 756 757 (defcustom org-export-with-tags t 758 "If nil, do not export tags, just remove them from headlines. 759 760 If this is the symbol `not-in-toc', tags will be removed from 761 table of contents entries, but still be shown in the headlines of 762 the document. 763 764 This option can also be set with the OPTIONS keyword, 765 e.g. \"tags:nil\"." 766 :group 'org-export-general 767 :type '(choice 768 (const :tag "Off" nil) 769 (const :tag "Not in TOC" not-in-toc) 770 (const :tag "On" t)) 771 :safe (lambda (x) (memq x '(t nil not-in-toc)))) 772 773 (defcustom org-export-with-tasks t 774 "Non-nil means include TODO items for export. 775 776 This may have the following values: 777 t include tasks independent of state. 778 `todo' include only tasks that are not yet done. 779 `done' include only tasks that are already done. 780 nil ignore all tasks. 781 list of keywords include tasks with these keywords. 782 783 This option can also be set with the OPTIONS keyword, 784 e.g. \"tasks:nil\"." 785 :group 'org-export-general 786 :type '(choice 787 (const :tag "All tasks" t) 788 (const :tag "No tasks" nil) 789 (const :tag "Not-done tasks" todo) 790 (const :tag "Only done tasks" done) 791 (repeat :tag "Specific TODO keywords" 792 (string :tag "Keyword"))) 793 :safe (lambda (x) (or (memq x '(nil t todo done)) 794 (and (listp x) 795 (cl-every #'stringp x))))) 796 797 (defcustom org-export-with-title t 798 "Non-nil means print title into the exported file. 799 This option can also be set with the OPTIONS keyword, 800 e.g. \"title:nil\"." 801 :group 'org-export-general 802 :version "26.1" 803 :package-version '(Org . "8.3") 804 :type 'boolean 805 :safe #'booleanp) 806 807 (defcustom org-export-time-stamp-file t 808 "Non-nil means insert a time stamp into the exported file. 809 The time stamp shows when the file was created. This option can 810 also be set with the OPTIONS keyword, e.g. \"timestamp:nil\"." 811 :group 'org-export-general 812 :type 'boolean 813 :safe #'booleanp) 814 815 (defcustom org-export-with-timestamps t 816 "Non-nil means allow timestamps in export. 817 818 It can be set to any of the following values: 819 t export all timestamps. 820 `active' export active timestamps only. 821 `inactive' export inactive timestamps only. 822 nil do not export timestamps 823 824 This only applies to timestamps isolated in a paragraph 825 containing only timestamps. Other timestamps are always 826 exported. 827 828 This option can also be set with the OPTIONS keyword, e.g. 829 \"<:nil\"." 830 :group 'org-export-general 831 :type '(choice 832 (const :tag "All timestamps" t) 833 (const :tag "Only active timestamps" active) 834 (const :tag "Only inactive timestamps" inactive) 835 (const :tag "No timestamp" nil)) 836 :safe (lambda (x) (memq x '(t nil active inactive)))) 837 838 (defcustom org-export-with-todo-keywords t 839 "Non-nil means include TODO keywords in export. 840 When nil, remove all these keywords from the export. This option 841 can also be set with the OPTIONS keyword, e.g. \"todo:nil\"." 842 :group 'org-export-general 843 :type 'boolean) 844 845 (defcustom org-export-allow-bind-keywords nil 846 "Non-nil means BIND keywords can define local variable values. 847 This is a potential security risk, which is why the default value 848 is nil. You can also allow them through local buffer variables." 849 :group 'org-export-general 850 :version "24.4" 851 :package-version '(Org . "8.0") 852 :type 'boolean) 853 854 (defcustom org-export-with-broken-links nil 855 "Non-nil means do not raise an error on broken links. 856 857 When this variable is non-nil, broken links are ignored, without 858 stopping the export process. If it is set to `mark', broken 859 links are marked as such in the output, with a string like 860 861 [BROKEN LINK: path] 862 863 where PATH is the un-resolvable reference. 864 865 This option can also be set with the OPTIONS keyword, e.g., 866 \"broken-links:mark\"." 867 :group 'org-export-general 868 :version "26.1" 869 :package-version '(Org . "9.0") 870 :type '(choice 871 (const :tag "Ignore broken links" t) 872 (const :tag "Mark broken links in output" mark) 873 (const :tag "Raise an error" nil))) 874 875 (defcustom org-export-snippet-translation-alist nil 876 "Alist between export snippets back-ends and exporter back-ends. 877 878 This variable allows providing shortcuts for export snippets. 879 880 For example, with: 881 882 (setq org-export-snippet-translation-alist 883 \\='((\"h\" . \"html\"))) 884 885 the HTML back-end will recognize the contents of \"@@h:<b>@@\" as 886 HTML code while every other back-end will ignore it." 887 :group 'org-export-general 888 :version "24.4" 889 :package-version '(Org . "8.0") 890 :type '(repeat 891 (cons (string :tag "Shortcut") 892 (string :tag "Back-end"))) 893 :safe (lambda (x) 894 (and (listp x) 895 (cl-every #'consp x) 896 (cl-every #'stringp (mapcar #'car x)) 897 (cl-every #'stringp (mapcar #'cdr x))))) 898 899 (defcustom org-export-global-macros nil 900 "Alist between macro names and expansion templates. 901 902 This variable defines macro expansion templates available 903 globally. Associations follow the pattern 904 905 (NAME . TEMPLATE) 906 907 where NAME is a string beginning with a letter and consisting of 908 alphanumeric characters only. 909 910 TEMPLATE is the string to which the macro is going to be 911 expanded. Inside, \"$1\", \"$2\"... are place-holders for 912 macro's arguments. Moreover, if the template starts with 913 \"(eval\", it will be parsed as an Elisp expression and evaluated 914 accordingly." 915 :group 'org-export-general 916 :version "26.1" 917 :package-version '(Org . "9.1") 918 :type '(repeat 919 (cons (string :tag "Name") 920 (string :tag "Template")))) 921 922 (defcustom org-export-coding-system nil 923 "Coding system for the exported file." 924 :group 'org-export-general 925 :version "24.4" 926 :package-version '(Org . "8.0") 927 :type 'coding-system) 928 929 (defcustom org-export-copy-to-kill-ring nil 930 "Non-nil means pushing export output to the kill ring. 931 This variable is ignored during asynchronous export." 932 :group 'org-export-general 933 :version "26.1" 934 :package-version '(Org . "8.3") 935 :type '(choice 936 (const :tag "Always" t) 937 (const :tag "When export is done interactively" if-interactive) 938 (const :tag "Never" nil))) 939 940 (defcustom org-export-initial-scope 'buffer 941 "The initial scope when exporting with `org-export-dispatch'. 942 This variable can be either set to `buffer' or `subtree'." 943 :group 'org-export-general 944 :type '(choice 945 (const :tag "Export current buffer" buffer) 946 (const :tag "Export current subtree" subtree))) 947 948 (defcustom org-export-show-temporary-export-buffer t 949 "Non-nil means show buffer after exporting to temp buffer. 950 When Org exports to a file, the buffer visiting that file is never 951 shown, but remains buried. However, when exporting to 952 a temporary buffer, that buffer is popped up in a second window. 953 When this variable is nil, the buffer remains buried also in 954 these cases." 955 :group 'org-export-general 956 :type 'boolean) 957 958 (defcustom org-export-in-background nil 959 "Non-nil means export and publishing commands will run in background. 960 Results from an asynchronous export are never displayed 961 automatically. But you can retrieve them with `\\[org-export-stack]'." 962 :group 'org-export-general 963 :version "24.4" 964 :package-version '(Org . "8.0") 965 :type 'boolean) 966 967 (defcustom org-export-async-init-file nil 968 "File used to initialize external export process. 969 970 Value must be either nil or an absolute file name. When nil, the 971 external process is launched like a regular Emacs session, 972 loading user's initialization file and any site specific 973 configuration. If a file is provided, it, and only it, is loaded 974 at start-up. 975 976 Therefore, using a specific configuration makes the process to 977 load faster and the export more portable." 978 :group 'org-export-general 979 :version "24.4" 980 :package-version '(Org . "8.0") 981 :type '(choice 982 (const :tag "Regular startup" nil) 983 (file :tag "Specific start-up file" :must-match t))) 984 985 (defcustom org-export-dispatch-use-expert-ui nil 986 "Non-nil means using a non-intrusive `org-export-dispatch'. 987 In that case, no help buffer is displayed. Though, an indicator 988 for current export scope is added to the prompt (\"b\" when 989 output is restricted to body only, \"s\" when it is restricted to 990 the current subtree, \"v\" when only visible elements are 991 considered for export, \"f\" when publishing functions should be 992 passed the FORCE argument and \"a\" when the export should be 993 asynchronous). Also, [?] allows switching back to standard 994 mode." 995 :group 'org-export-general 996 :version "24.4" 997 :package-version '(Org . "8.0") 998 :type 'boolean) 999 1000 1001 1002 ;;; Defining Back-ends 1003 ;; 1004 ;; An export back-end is a structure with `org-export-backend' type 1005 ;; and `name', `parent', `transcoders', `options', `filters', `blocks' 1006 ;; and `menu' slots. 1007 ;; 1008 ;; At the lowest level, a back-end is created with 1009 ;; `org-export-create-backend' function. 1010 ;; 1011 ;; A named back-end can be registered with 1012 ;; `org-export-register-backend' function. A registered back-end can 1013 ;; later be referred to by its name, with `org-export-get-backend' 1014 ;; function. Also, such a back-end can become the parent of a derived 1015 ;; back-end from which slot values will be inherited by default. 1016 ;; `org-export-derived-backend-p' can check if a given back-end is 1017 ;; derived from a list of back-end names. 1018 ;; 1019 ;; `org-export-get-all-transcoders', `org-export-get-all-options' and 1020 ;; `org-export-get-all-filters' return the full alist of transcoders, 1021 ;; options and filters, including those inherited from ancestors. 1022 ;; 1023 ;; At a higher level, `org-export-define-backend' is the standard way 1024 ;; to define an export back-end. If the new back-end is similar to 1025 ;; a registered back-end, `org-export-define-derived-backend' may be 1026 ;; used instead. 1027 ;; 1028 ;; Eventually `org-export-barf-if-invalid-backend' returns an error 1029 ;; when a given back-end hasn't been registered yet. 1030 1031 (cl-defstruct (org-export-backend (:constructor org-export-create-backend) 1032 (:copier nil)) 1033 name parent transcoders options filters blocks menu) 1034 1035 ;;;###autoload 1036 (defun org-export-get-backend (name) 1037 "Return export back-end named after NAME. 1038 NAME is a symbol. Return nil if no such back-end is found." 1039 (cl-find-if (lambda (b) (and (eq name (org-export-backend-name b)))) 1040 org-export-registered-backends)) 1041 1042 (defun org-export-register-backend (backend) 1043 "Register BACKEND as a known export back-end. 1044 BACKEND is a structure with `org-export-backend' type." 1045 ;; Refuse to register an unnamed back-end. 1046 (unless (org-export-backend-name backend) 1047 (error "Cannot register a unnamed export back-end")) 1048 ;; Refuse to register a back-end with an unknown parent. 1049 (let ((parent (org-export-backend-parent backend))) 1050 (when (and parent (not (org-export-get-backend parent))) 1051 (error "Cannot use unknown \"%s\" back-end as a parent" parent))) 1052 ;; If a back-end with the same name as BACKEND is already 1053 ;; registered, replace it with BACKEND. Otherwise, simply add 1054 ;; BACKEND to the list of registered back-ends. 1055 (let ((old (org-export-get-backend (org-export-backend-name backend)))) 1056 (if old (setcar (memq old org-export-registered-backends) backend) 1057 (push backend org-export-registered-backends)))) 1058 1059 (defun org-export-barf-if-invalid-backend (backend) 1060 "Signal an error if BACKEND isn't defined." 1061 (unless (org-export-backend-p backend) 1062 (error "Unknown \"%s\" back-end: Aborting export" backend))) 1063 1064 ;;;###autoload 1065 (defun org-export-derived-backend-p (backend &rest backends) 1066 "Non-nil if BACKEND is derived from one of BACKENDS. 1067 BACKEND is an export back-end, as returned by, e.g., 1068 `org-export-create-backend', or a symbol referring to 1069 a registered back-end. BACKENDS is constituted of symbols." 1070 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 1071 (when backend 1072 (catch 'exit 1073 (while (org-export-backend-parent backend) 1074 (when (memq (org-export-backend-name backend) backends) 1075 (throw 'exit t)) 1076 (setq backend 1077 (org-export-get-backend (org-export-backend-parent backend)))) 1078 (memq (org-export-backend-name backend) backends)))) 1079 1080 (defun org-export-get-all-transcoders (backend) 1081 "Return full translation table for BACKEND. 1082 1083 BACKEND is an export back-end, as return by, e.g,, 1084 `org-export-create-backend'. Return value is an alist where 1085 keys are element or object types, as symbols, and values are 1086 transcoders. 1087 1088 Unlike to `org-export-backend-transcoders', this function 1089 also returns transcoders inherited from parent back-ends, 1090 if any." 1091 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 1092 (when backend 1093 (let ((transcoders (org-export-backend-transcoders backend)) 1094 parent) 1095 (while (setq parent (org-export-backend-parent backend)) 1096 (setq backend (org-export-get-backend parent)) 1097 (setq transcoders 1098 (append transcoders (org-export-backend-transcoders backend)))) 1099 transcoders))) 1100 1101 (defun org-export-get-all-options (backend) 1102 "Return export options for BACKEND. 1103 1104 BACKEND is an export back-end, as return by, e.g,, 1105 `org-export-create-backend'. See `org-export-options-alist' 1106 for the shape of the return value. 1107 1108 Unlike to `org-export-backend-options', this function also 1109 returns options inherited from parent back-ends, if any. 1110 1111 Return nil if BACKEND is unknown." 1112 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 1113 (when backend 1114 (let ((options (org-export-backend-options backend)) 1115 parent) 1116 (while (setq parent (org-export-backend-parent backend)) 1117 (setq backend (org-export-get-backend parent)) 1118 (setq options (append options (org-export-backend-options backend)))) 1119 options))) 1120 1121 (defun org-export-get-all-filters (backend) 1122 "Return complete list of filters for BACKEND. 1123 1124 BACKEND is an export back-end, as return by, e.g,, 1125 `org-export-create-backend'. Return value is an alist where 1126 keys are symbols and values lists of functions. 1127 1128 Unlike to `org-export-backend-filters', this function also 1129 returns filters inherited from parent back-ends, if any." 1130 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 1131 (when backend 1132 (let ((filters (org-export-backend-filters backend)) 1133 parent) 1134 (while (setq parent (org-export-backend-parent backend)) 1135 (setq backend (org-export-get-backend parent)) 1136 (setq filters (append filters (org-export-backend-filters backend)))) 1137 filters))) 1138 1139 (defun org-export-define-backend (backend transcoders &rest body) 1140 "Define a new back-end BACKEND. 1141 1142 TRANSCODERS is an alist between object or element types and 1143 functions handling them. 1144 1145 These functions should return a string without any trailing 1146 space, or nil. They must accept three arguments: the object or 1147 element itself, its contents or nil when it isn't recursive and 1148 the property list used as a communication channel. 1149 1150 Contents, when not nil, are stripped from any global indentation 1151 \(although the relative one is preserved). They also always end 1152 with a single newline character. 1153 1154 If, for a given type, no function is found, that element or 1155 object type will simply be ignored, along with any blank line or 1156 white space at its end. The same will happen if the function 1157 returns the nil value. If that function returns the empty 1158 string, the type will be ignored, but the blank lines or white 1159 spaces will be kept. 1160 1161 In addition to element and object types, one function can be 1162 associated to the `template' (or `inner-template') symbol and 1163 another one to the `plain-text' symbol. 1164 1165 The former returns the final transcoded string, and can be used 1166 to add a preamble and a postamble to document's body. It must 1167 accept two arguments: the transcoded string and the property list 1168 containing export options. A function associated to `template' 1169 will not be applied if export has option \"body-only\". 1170 A function associated to `inner-template' is always applied. 1171 1172 The latter, when defined, is to be called on every text not 1173 recognized as an element or an object. It must accept two 1174 arguments: the text string and the information channel. It is an 1175 appropriate place to protect special chars relative to the 1176 back-end. 1177 1178 BODY can start with pre-defined keyword arguments. The following 1179 keywords are understood: 1180 1181 :filters-alist 1182 1183 Alist between filters and function, or list of functions, 1184 specific to the back-end. See `org-export-filters-alist' for 1185 a list of all allowed filters. Filters defined here 1186 shouldn't make a back-end test, as it may prevent back-ends 1187 derived from this one to behave properly. 1188 1189 :menu-entry 1190 1191 Menu entry for the export dispatcher. It should be a list 1192 like: 1193 1194 (KEY DESCRIPTION-OR-ORDINAL ACTION-OR-MENU) 1195 1196 where : 1197 1198 KEY is a free character selecting the back-end. 1199 1200 DESCRIPTION-OR-ORDINAL is either a string or a number. 1201 1202 If it is a string, is will be used to name the back-end in 1203 its menu entry. If it is a number, the following menu will 1204 be displayed as a sub-menu of the back-end with the same 1205 KEY. Also, the number will be used to determine in which 1206 order such sub-menus will appear (lowest first). 1207 1208 ACTION-OR-MENU is either a function or an alist. 1209 1210 If it is an action, it will be called with four 1211 arguments (booleans): ASYNC, SUBTREEP, VISIBLE-ONLY and 1212 BODY-ONLY. See `org-export-as' for further explanations on 1213 some of them. 1214 1215 If it is an alist, associations should follow the 1216 pattern: 1217 1218 (KEY DESCRIPTION ACTION) 1219 1220 where KEY, DESCRIPTION and ACTION are described above. 1221 1222 Valid values include: 1223 1224 (?m \"My Special Back-end\" my-special-export-function) 1225 1226 or 1227 1228 (?l \"Export to LaTeX\" 1229 ((?p \"As PDF file\" org-latex-export-to-pdf) 1230 (?o \"As PDF file and open\" 1231 (lambda (a s v b) 1232 (if a (org-latex-export-to-pdf t s v b) 1233 (org-open-file 1234 (org-latex-export-to-pdf nil s v b))))))) 1235 1236 or the following, which will be added to the previous 1237 sub-menu, 1238 1239 (?l 1 1240 ((?B \"As TEX buffer (Beamer)\" org-beamer-export-as-latex) 1241 (?P \"As PDF file (Beamer)\" org-beamer-export-to-pdf))) 1242 1243 :options-alist 1244 1245 Alist between back-end specific properties introduced in 1246 communication channel and how their value are acquired. See 1247 `org-export-options-alist' for more information about 1248 structure of the values." 1249 (declare (indent 1)) 1250 (let (filters menu-entry options) 1251 (while (keywordp (car body)) 1252 (let ((keyword (pop body))) 1253 (pcase keyword 1254 (:filters-alist (setq filters (pop body))) 1255 (:menu-entry (setq menu-entry (pop body))) 1256 (:options-alist (setq options (pop body))) 1257 (_ (error "Unknown keyword: %s" keyword))))) 1258 (org-export-register-backend 1259 (org-export-create-backend :name backend 1260 :transcoders transcoders 1261 :options options 1262 :filters filters 1263 :menu menu-entry)))) 1264 1265 (defun org-export-define-derived-backend (child parent &rest body) 1266 "Create a new back-end as a variant of an existing one. 1267 1268 CHILD is the name of the derived back-end. PARENT is the name of 1269 the parent back-end. 1270 1271 BODY can start with pre-defined keyword arguments. The following 1272 keywords are understood: 1273 1274 :filters-alist 1275 1276 Alist of filters that will overwrite or complete filters 1277 defined in PARENT back-end. See `org-export-filters-alist' 1278 for a list of allowed filters. 1279 1280 :menu-entry 1281 1282 Menu entry for the export dispatcher. See 1283 `org-export-define-backend' for more information about the 1284 expected value. 1285 1286 :options-alist 1287 1288 Alist of back-end specific properties that will overwrite or 1289 complete those defined in PARENT back-end. Refer to 1290 `org-export-options-alist' for more information about 1291 structure of the values. 1292 1293 :translate-alist 1294 1295 Alist of element and object types and transcoders that will 1296 overwrite or complete transcode table from PARENT back-end. 1297 Refer to `org-export-define-backend' for detailed information 1298 about transcoders. 1299 1300 As an example, here is how one could define \"my-latex\" back-end 1301 as a variant of `latex' back-end with a custom template function: 1302 1303 (org-export-define-derived-backend \\='my-latex \\='latex 1304 :translate-alist \\='((template . my-latex-template-fun))) 1305 1306 The back-end could then be called with, for example: 1307 1308 (org-export-to-buffer \\='my-latex \"*Test my-latex*\")" 1309 (declare (indent 2)) 1310 (let (filters menu-entry options transcoders) 1311 (while (keywordp (car body)) 1312 (let ((keyword (pop body))) 1313 (pcase keyword 1314 (:filters-alist (setq filters (pop body))) 1315 (:menu-entry (setq menu-entry (pop body))) 1316 (:options-alist (setq options (pop body))) 1317 (:translate-alist (setq transcoders (pop body))) 1318 (_ (error "Unknown keyword: %s" keyword))))) 1319 (org-export-register-backend 1320 (org-export-create-backend :name child 1321 :parent parent 1322 :transcoders transcoders 1323 :options options 1324 :filters filters 1325 :menu menu-entry)))) 1326 1327 1328 1329 ;;; The Communication Channel 1330 ;; 1331 ;; During export process, every function has access to a number of 1332 ;; properties. They are of two types: 1333 ;; 1334 ;; 1. Environment options are collected once at the very beginning of 1335 ;; the process, out of the original buffer and configuration. 1336 ;; Collecting them is handled by `org-export-get-environment' 1337 ;; function. 1338 ;; 1339 ;; Most environment options are defined through the 1340 ;; `org-export-options-alist' variable. 1341 ;; 1342 ;; 2. Tree properties are extracted directly from the parsed tree, 1343 ;; just before export, by `org-export--collect-tree-properties'. 1344 1345 ;;;; Environment Options 1346 ;; 1347 ;; Environment options encompass all parameters defined outside the 1348 ;; scope of the parsed data. They come from five sources, in 1349 ;; increasing precedence order: 1350 ;; 1351 ;; - Global variables, 1352 ;; - Buffer's attributes, 1353 ;; - Options keyword symbols, 1354 ;; - Buffer keywords, 1355 ;; - Subtree properties. 1356 ;; 1357 ;; The central internal function with regards to environment options 1358 ;; is `org-export-get-environment'. It updates global variables with 1359 ;; "#+BIND:" keywords, then retrieve and prioritize properties from 1360 ;; the different sources. 1361 ;; 1362 ;; The internal functions doing the retrieval are: 1363 ;; `org-export--get-global-options', 1364 ;; `org-export--get-buffer-attributes', 1365 ;; `org-export--parse-option-keyword', 1366 ;; `org-export--get-subtree-options' and 1367 ;; `org-export--get-inbuffer-options' 1368 ;; 1369 ;; Also, `org-export--list-bound-variables' collects bound variables 1370 ;; along with their value in order to set them as buffer local 1371 ;; variables later in the process. 1372 1373 ;;;###autoload 1374 (defun org-export-get-environment (&optional backend subtreep ext-plist) 1375 "Collect export options from the current buffer. 1376 1377 Optional argument BACKEND is an export back-end, as returned by 1378 `org-export-create-backend'. 1379 1380 When optional argument SUBTREEP is non-nil, assume the export is 1381 done against the current sub-tree. 1382 1383 Third optional argument EXT-PLIST is a property list with 1384 external parameters overriding Org default settings, but still 1385 inferior to file-local settings." 1386 ;; First install #+BIND variables since these must be set before 1387 ;; global options are read. 1388 (dolist (pair (org-export--list-bound-variables)) 1389 (set (make-local-variable (car pair)) (nth 1 pair))) 1390 ;; Get and prioritize export options... 1391 (org-combine-plists 1392 ;; ... from global variables... 1393 (org-export--get-global-options backend) 1394 ;; ... from an external property list... 1395 ext-plist 1396 ;; ... from in-buffer settings... 1397 (org-export--get-inbuffer-options backend) 1398 ;; ... and from subtree, when appropriate. 1399 (and subtreep (org-export--get-subtree-options backend)))) 1400 1401 (defun org-export--parse-option-keyword (options &optional backend) 1402 "Parse an OPTIONS line and return values as a plist. 1403 Optional argument BACKEND is an export back-end, as returned by, 1404 e.g., `org-export-create-backend'. It specifies which back-end 1405 specific items to read, if any." 1406 (let ((line 1407 (let (alist) 1408 (with-temp-buffer 1409 (insert options) 1410 (goto-char (point-min)) 1411 (while (re-search-forward "\\s-*\\(.+?\\):" nil t) 1412 (when (looking-at-p "\\S-") 1413 (push (cons (match-string 1) 1414 (read (current-buffer))) ; moves point 1415 alist)))) 1416 alist)) 1417 ;; Priority is given to back-end specific options. 1418 (all (append (org-export-get-all-options backend) 1419 org-export-options-alist)) 1420 (plist)) 1421 (when line 1422 (dolist (entry all plist) 1423 (let ((item (nth 2 entry))) 1424 (when item 1425 (let ((v (assoc-string item line t))) 1426 (when v (setq plist (plist-put plist (car entry) (cdr v))))))))))) 1427 1428 (defun org-export--get-subtree-options (&optional backend) 1429 "Get export options in subtree at point. 1430 Optional argument BACKEND is an export back-end, as returned by, 1431 e.g., `org-export-create-backend'. It specifies back-end used 1432 for export. Return options as a plist." 1433 ;; For each buffer keyword, create a headline property setting the 1434 ;; same property in communication channel. The name for the 1435 ;; property is the keyword with "EXPORT_" appended to it. 1436 (org-with-wide-buffer 1437 ;; Make sure point is at a heading. 1438 (org-back-to-heading t) 1439 (let ((plist 1440 ;; EXPORT_OPTIONS are parsed in a non-standard way. Take 1441 ;; care of them right from the start. 1442 (let ((o (org-entry-get (point) "EXPORT_OPTIONS" 'selective))) 1443 (and o (org-export--parse-option-keyword o backend)))) 1444 ;; Take care of EXPORT_TITLE. If it isn't defined, use 1445 ;; headline's title (with no todo keyword, priority cookie or 1446 ;; tag) as its fallback value. 1447 (cache (list 1448 (cons "TITLE" 1449 (or (org-entry-get (point) "EXPORT_TITLE" 'selective) 1450 (let ((case-fold-search nil)) 1451 (looking-at org-complex-heading-regexp) 1452 (match-string-no-properties 4)))))) 1453 ;; Look for both general keywords and back-end specific 1454 ;; options, with priority given to the latter. 1455 (options (append (org-export-get-all-options backend) 1456 org-export-options-alist))) 1457 ;; Handle other keywords. Then return PLIST. 1458 (dolist (option options plist) 1459 (let ((property (car option)) 1460 (keyword (nth 1 option))) 1461 (when keyword 1462 (let ((value 1463 (or (cdr (assoc keyword cache)) 1464 (let ((v (org-entry-get (point) 1465 (concat "EXPORT_" keyword) 1466 'selective))) 1467 (push (cons keyword v) cache) v)))) 1468 (when value 1469 (setq plist 1470 (plist-put plist 1471 property 1472 (cl-case (nth 4 option) 1473 (parse 1474 (org-element-parse-secondary-string 1475 value (org-element-restriction 'keyword))) 1476 (split (split-string value)) 1477 (t value)))))))))))) 1478 1479 (defun org-export--get-inbuffer-options (&optional backend) 1480 "Return current buffer export options, as a plist. 1481 1482 Optional argument BACKEND, when non-nil, is an export back-end, 1483 as returned by, e.g., `org-export-create-backend'. It specifies 1484 which back-end specific options should also be read in the 1485 process. 1486 1487 Assume buffer is in Org mode. Narrowing, if any, is ignored." 1488 (let* ((case-fold-search t) 1489 (options (append 1490 ;; Priority is given to back-end specific options. 1491 (org-export-get-all-options backend) 1492 org-export-options-alist)) 1493 plist to-parse) 1494 (let ((find-properties 1495 (lambda (keyword) 1496 ;; Return all properties associated to KEYWORD. 1497 (let (properties) 1498 (dolist (option options properties) 1499 (when (equal (nth 1 option) keyword) 1500 (cl-pushnew (car option) properties))))))) 1501 ;; Read options in the current buffer and return value. 1502 (dolist (entry (org-collect-keywords 1503 (nconc (delq nil (mapcar #'cadr options)) 1504 '("FILETAGS" "OPTIONS")))) 1505 (pcase entry 1506 (`("OPTIONS" . ,values) 1507 (setq plist 1508 (apply #'org-combine-plists 1509 plist 1510 (mapcar (lambda (v) 1511 (org-export--parse-option-keyword v backend)) 1512 values)))) 1513 (`("FILETAGS" . ,values) 1514 (setq plist 1515 (plist-put plist 1516 :filetags 1517 (org-uniquify 1518 (cl-mapcan (lambda (v) (org-split-string v ":")) 1519 values))))) 1520 (`(,keyword . ,values) 1521 (dolist (property (funcall find-properties keyword)) 1522 (setq plist 1523 (plist-put 1524 plist property 1525 ;; Handle value depending on specified BEHAVIOR. 1526 (cl-case (nth 4 (assq property options)) 1527 (parse 1528 (unless (memq property to-parse) 1529 (push property to-parse)) 1530 ;; Even if `parse' implies `space' behavior, we 1531 ;; separate line with "\n" so as to preserve 1532 ;; line-breaks. 1533 (mapconcat #'identity values "\n")) 1534 (space 1535 (mapconcat #'identity values " ")) 1536 (newline 1537 (mapconcat #'identity values "\n")) 1538 (split 1539 (cl-mapcan (lambda (v) (split-string v)) values)) 1540 ((t) 1541 (org-last values)) 1542 (otherwise 1543 (car values))))))))) 1544 ;; Parse properties in TO-PARSE. Remove newline characters not 1545 ;; involved in line breaks to simulate `space' behavior. 1546 ;; Finally return options. 1547 (dolist (p to-parse plist) 1548 (let ((value (org-element-parse-secondary-string 1549 (plist-get plist p) 1550 (org-element-restriction 'keyword)))) 1551 (org-element-map value 'plain-text 1552 (lambda (s) 1553 (org-element-set-element 1554 s (replace-regexp-in-string "\n" " " s)))) 1555 (setq plist (plist-put plist p value))))))) 1556 1557 (defun org-export--get-export-attributes 1558 (&optional backend subtreep visible-only body-only) 1559 "Return properties related to export process, as a plist. 1560 Optional arguments BACKEND, SUBTREEP, VISIBLE-ONLY and BODY-ONLY 1561 are like the arguments with the same names of function 1562 `org-export-as'." 1563 (list :export-options (delq nil 1564 (list (and subtreep 'subtree) 1565 (and visible-only 'visible-only) 1566 (and body-only 'body-only))) 1567 :back-end backend 1568 :translate-alist (org-export-get-all-transcoders backend) 1569 :exported-data (make-hash-table :test #'eq :size 4001))) 1570 1571 (defun org-export--get-buffer-attributes () 1572 "Return properties related to buffer attributes, as a plist." 1573 (list :input-buffer (buffer-name (buffer-base-buffer)) 1574 :input-file (buffer-file-name (buffer-base-buffer)))) 1575 1576 (defun org-export--get-global-options (&optional backend) 1577 "Return global export options as a plist. 1578 Optional argument BACKEND, if non-nil, is an export back-end, as 1579 returned by, e.g., `org-export-create-backend'. It specifies 1580 which back-end specific export options should also be read in the 1581 process." 1582 (let (plist 1583 ;; Priority is given to back-end specific options. 1584 (all (append (org-export-get-all-options backend) 1585 org-export-options-alist))) 1586 (dolist (cell all plist) 1587 (let ((prop (car cell))) 1588 (unless (plist-member plist prop) 1589 (setq plist 1590 (plist-put 1591 plist 1592 prop 1593 ;; Evaluate default value provided. 1594 (let ((value (eval (nth 3 cell) t))) 1595 (if (eq (nth 4 cell) 'parse) 1596 (org-element-parse-secondary-string 1597 value (org-element-restriction 'keyword)) 1598 value))))))))) 1599 1600 (defun org-export--list-bound-variables () 1601 "Return variables bound from BIND keywords in current buffer. 1602 Also look for BIND keywords in setup files. The return value is 1603 an alist where associations are (VARIABLE-NAME VALUE)." 1604 (when org-export-allow-bind-keywords 1605 (pcase (org-collect-keywords '("BIND")) 1606 (`(("BIND" . ,values)) 1607 (mapcar (lambda (v) (read (format "(%s)" v))) 1608 values))))) 1609 1610 ;; defsubst org-export-get-parent must be defined before first use, 1611 ;; was originally defined in the topology section 1612 1613 (defsubst org-export-get-parent (blob) 1614 "Return BLOB parent or nil. 1615 BLOB is the element or object considered." 1616 (org-element-property :parent blob)) 1617 1618 ;;;; Tree Properties 1619 ;; 1620 ;; Tree properties are information extracted from parse tree. They 1621 ;; are initialized at the beginning of the transcoding process by 1622 ;; `org-export--collect-tree-properties'. 1623 ;; 1624 ;; Dedicated functions focus on computing the value of specific tree 1625 ;; properties during initialization. Thus, 1626 ;; `org-export--populate-ignore-list' lists elements and objects that 1627 ;; should be skipped during export, `org-export--get-min-level' gets 1628 ;; the minimal exportable level, used as a basis to compute relative 1629 ;; level for headlines. Eventually 1630 ;; `org-export--collect-headline-numbering' builds an alist between 1631 ;; headlines and their numbering. 1632 1633 (defun org-export--collect-tree-properties (data info) 1634 "Extract tree properties from parse tree. 1635 1636 DATA is the parse tree from which information is retrieved. INFO 1637 is a list holding export options. 1638 1639 Following tree properties are set or updated: 1640 1641 `:headline-offset' Offset between true level of headlines and 1642 local level. An offset of -1 means a headline 1643 of level 2 should be considered as a level 1644 1 headline in the context. 1645 1646 `:headline-numbering' Alist of all headlines as key and the 1647 associated numbering as value. 1648 1649 `:id-alist' Alist of all ID references as key and associated file 1650 as value. 1651 1652 Return updated plist." 1653 ;; Install the parse tree in the communication channel. 1654 (setq info (plist-put info :parse-tree data)) 1655 ;; Compute `:headline-offset' in order to be able to use 1656 ;; `org-export-get-relative-level'. 1657 (setq info 1658 (plist-put info 1659 :headline-offset 1660 (- 1 (org-export--get-min-level data info)))) 1661 ;; From now on, properties order doesn't matter: get the rest of the 1662 ;; tree properties. 1663 (org-combine-plists 1664 info 1665 (list :headline-numbering (org-export--collect-headline-numbering data info) 1666 :id-alist 1667 (org-element-map data 'link 1668 (lambda (l) 1669 (and (string= (org-element-property :type l) "id") 1670 (let* ((id (org-element-property :path l)) 1671 (file (car (org-id-find id)))) 1672 (and file (cons id (file-relative-name file)))))))))) 1673 1674 (defun org-export--get-min-level (data options) 1675 "Return minimum exportable headline's level in DATA. 1676 DATA is parsed tree as returned by `org-element-parse-buffer'. 1677 OPTIONS is a plist holding export options." 1678 (catch 'exit 1679 (let ((min-level 10000)) 1680 (dolist (datum (org-element-contents data)) 1681 (when (and (eq (org-element-type datum) 'headline) 1682 (not (org-element-property :footnote-section-p datum)) 1683 (not (memq datum (plist-get options :ignore-list)))) 1684 (setq min-level (min (org-element-property :level datum) min-level)) 1685 (when (= min-level 1) (throw 'exit 1)))) 1686 ;; If no headline was found, for the sake of consistency, set 1687 ;; minimum level to 1 nonetheless. 1688 (if (= min-level 10000) 1 min-level)))) 1689 1690 (defun org-export--collect-headline-numbering (data options) 1691 "Return numbering of all exportable, numbered headlines in a parse tree. 1692 1693 DATA is the parse tree. OPTIONS is the plist holding export 1694 options. 1695 1696 Return an alist whose key is a headline and value is its 1697 associated numbering \(in the shape of a list of numbers) or nil 1698 for a footnotes section." 1699 (let ((numbering (make-vector org-export-max-depth 0))) 1700 (org-element-map data 'headline 1701 (lambda (headline) 1702 (when (and (org-export-numbered-headline-p headline options) 1703 (not (org-element-property :footnote-section-p headline))) 1704 (let ((relative-level 1705 (1- (org-export-get-relative-level headline options)))) 1706 (cons 1707 headline 1708 (cl-loop 1709 for n across numbering 1710 for idx from 0 to org-export-max-depth 1711 when (< idx relative-level) collect n 1712 when (= idx relative-level) collect (aset numbering idx (1+ n)) 1713 when (> idx relative-level) do (aset numbering idx 0)))))) 1714 options))) 1715 1716 (defun org-export--selected-trees (data info) 1717 "List headlines and inlinetasks with a select tag in their tree. 1718 DATA is parsed data as returned by `org-element-parse-buffer'. 1719 INFO is a plist holding export options." 1720 (let ((select (cl-mapcan (lambda (tag) (org-tags-expand tag t)) 1721 (plist-get info :select-tags)))) 1722 (if (cl-some (lambda (tag) (member tag select)) (plist-get info :filetags)) 1723 ;; If FILETAGS contains a select tag, every headline or 1724 ;; inlinetask is returned. 1725 (org-element-map data '(headline inlinetask) #'identity) 1726 (letrec ((selected-trees nil) 1727 (walk-data 1728 (lambda (data genealogy) 1729 (let ((type (org-element-type data))) 1730 (cond 1731 ((memq type '(headline inlinetask)) 1732 (let ((tags (org-element-property :tags data))) 1733 (if (cl-some (lambda (tag) (member tag select)) tags) 1734 ;; When a select tag is found, mark full 1735 ;; genealogy and every headline within the 1736 ;; tree as acceptable. 1737 (setq selected-trees 1738 (append 1739 genealogy 1740 (org-element-map data '(headline inlinetask) 1741 #'identity) 1742 selected-trees)) 1743 ;; If at a headline, continue searching in 1744 ;; tree, recursively. 1745 (when (eq type 'headline) 1746 (dolist (el (org-element-contents data)) 1747 (funcall walk-data el (cons data genealogy))))))) 1748 ((or (eq type 'org-data) 1749 (memq type org-element-greater-elements)) 1750 (dolist (el (org-element-contents data)) 1751 (funcall walk-data el genealogy)))))))) 1752 (funcall walk-data data nil) 1753 selected-trees)))) 1754 1755 (defun org-export--skip-p (datum options selected excluded) 1756 "Non-nil when element or object DATUM should be skipped during export. 1757 OPTIONS is the plist holding export options. SELECTED, when 1758 non-nil, is a list of headlines or inlinetasks belonging to 1759 a tree with a select tag. EXCLUDED is a list of tags, as 1760 strings. Any headline or inlinetask marked with one of those is 1761 not exported." 1762 (cl-case (org-element-type datum) 1763 ((comment comment-block) 1764 ;; Skip all comments and comment blocks. Make to keep maximum 1765 ;; number of blank lines around the comment so as to preserve 1766 ;; local structure of the document upon interpreting it back into 1767 ;; Org syntax. 1768 (let* ((previous (org-export-get-previous-element datum options)) 1769 (before (or (org-element-property :post-blank previous) 0)) 1770 (after (or (org-element-property :post-blank datum) 0))) 1771 (when previous 1772 (org-element-put-property previous :post-blank (max before after 1)))) 1773 t) 1774 (clock (not (plist-get options :with-clocks))) 1775 (drawer 1776 (let ((with-drawers-p (plist-get options :with-drawers))) 1777 (or (not with-drawers-p) 1778 (and (consp with-drawers-p) 1779 ;; If `:with-drawers' value starts with `not', ignore 1780 ;; every drawer whose name belong to that list. 1781 ;; Otherwise, ignore drawers whose name isn't in that 1782 ;; list. 1783 (let ((name (org-element-property :drawer-name datum))) 1784 (if (eq (car with-drawers-p) 'not) 1785 (member-ignore-case name (cdr with-drawers-p)) 1786 (not (member-ignore-case name with-drawers-p)))))))) 1787 (fixed-width (not (plist-get options :with-fixed-width))) 1788 ((footnote-definition footnote-reference) 1789 (not (plist-get options :with-footnotes))) 1790 ((headline inlinetask) 1791 (let ((with-tasks (plist-get options :with-tasks)) 1792 (todo (org-element-property :todo-keyword datum)) 1793 (todo-type (org-element-property :todo-type datum)) 1794 (archived (plist-get options :with-archived-trees)) 1795 (tags (org-export-get-tags datum options nil t))) 1796 (or 1797 (and (eq (org-element-type datum) 'inlinetask) 1798 (not (plist-get options :with-inlinetasks))) 1799 ;; Ignore subtrees with an exclude tag. 1800 (cl-some (lambda (tag) (member tag excluded)) tags) 1801 ;; When a select tag is present in the buffer, ignore any tree 1802 ;; without it. 1803 (and selected (not (memq datum selected))) 1804 ;; Ignore commented sub-trees. 1805 (org-element-property :commentedp datum) 1806 ;; Ignore archived subtrees if `:with-archived-trees' is nil. 1807 (and (not archived) (org-element-property :archivedp datum)) 1808 ;; Ignore tasks, if specified by `:with-tasks' property. 1809 (and todo 1810 (or (not with-tasks) 1811 (and (memq with-tasks '(todo done)) 1812 (not (eq todo-type with-tasks))) 1813 (and (consp with-tasks) (not (member todo with-tasks)))))))) 1814 ((latex-environment latex-fragment) (not (plist-get options :with-latex))) 1815 (node-property 1816 (let ((properties-set (plist-get options :with-properties))) 1817 (cond ((null properties-set) t) 1818 ((consp properties-set) 1819 (not (member-ignore-case (org-element-property :key datum) 1820 properties-set)))))) 1821 (planning (not (plist-get options :with-planning))) 1822 (property-drawer (not (plist-get options :with-properties))) 1823 (statistics-cookie (not (plist-get options :with-statistics-cookies))) 1824 (table (not (plist-get options :with-tables))) 1825 (table-cell 1826 (and (org-export-table-has-special-column-p 1827 (org-export-get-parent-table datum)) 1828 (org-export-first-sibling-p datum options))) 1829 (table-row (org-export-table-row-is-special-p datum options)) 1830 (timestamp 1831 ;; `:with-timestamps' only applies to isolated timestamps 1832 ;; objects, i.e. timestamp objects in a paragraph containing only 1833 ;; timestamps and whitespaces. 1834 (when (let ((parent (org-export-get-parent-element datum))) 1835 (and (memq (org-element-type parent) '(paragraph verse-block)) 1836 (not (org-element-map parent 1837 (cons 'plain-text 1838 (remq 'timestamp org-element-all-objects)) 1839 (lambda (obj) 1840 (or (not (stringp obj)) (org-string-nw-p obj))) 1841 options t)))) 1842 (cl-case (plist-get options :with-timestamps) 1843 ((nil) t) 1844 (active 1845 (not (memq (org-element-property :type datum) '(active active-range)))) 1846 (inactive 1847 (not (memq (org-element-property :type datum) 1848 '(inactive inactive-range))))))))) 1849 1850 1851 ;;; The Transcoder 1852 ;; 1853 ;; `org-export-data' reads a parse tree (obtained with, i.e. 1854 ;; `org-element-parse-buffer') and transcodes it into a specified 1855 ;; back-end output. It takes care of filtering out elements or 1856 ;; objects according to export options and organizing the output blank 1857 ;; lines and white space are preserved. The function memoizes its 1858 ;; results, so it is cheap to call it within transcoders. 1859 ;; 1860 ;; It is possible to modify locally the back-end used by 1861 ;; `org-export-data' or even use a temporary back-end by using 1862 ;; `org-export-data-with-backend'. 1863 ;; 1864 ;; `org-export-transcoder' is an accessor returning appropriate 1865 ;; translator function for a given element or object. 1866 1867 (defun org-export-transcoder (blob info) 1868 "Return appropriate transcoder for BLOB. 1869 INFO is a plist containing export directives." 1870 (let ((type (org-element-type blob))) 1871 ;; Return contents only for complete parse trees. 1872 (if (eq type 'org-data) (lambda (_datum contents _info) contents) 1873 (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) 1874 (and (functionp transcoder) transcoder))))) 1875 1876 ;;;###autoload 1877 (defun org-export-data (data info) 1878 "Convert DATA into current back-end format. 1879 1880 DATA is a parse tree, an element or an object or a secondary 1881 string. INFO is a plist holding export options. 1882 1883 Return a string." 1884 (or (gethash data (plist-get info :exported-data)) 1885 ;; Handle broken links according to 1886 ;; `org-export-with-broken-links'. 1887 (cl-macrolet 1888 ((broken-link-handler 1889 (&rest body) 1890 `(condition-case err 1891 (progn ,@body) 1892 (org-link-broken 1893 (pcase (plist-get info :with-broken-links) 1894 (`nil (user-error "Unable to resolve link: %S" (nth 1 err))) 1895 (`mark (org-export-data 1896 (format "[BROKEN LINK: %s]" (nth 1 err)) info)) 1897 (_ nil)))))) 1898 (let* ((type (org-element-type data)) 1899 (parent (org-export-get-parent data)) 1900 (results 1901 (cond 1902 ;; Ignored element/object. 1903 ((memq data (plist-get info :ignore-list)) nil) 1904 ;; Raw code. 1905 ((eq type 'raw) (car (org-element-contents data))) 1906 ;; Plain text. 1907 ((eq type 'plain-text) 1908 (org-export-filter-apply-functions 1909 (plist-get info :filter-plain-text) 1910 (let ((transcoder (org-export-transcoder data info))) 1911 (if transcoder (funcall transcoder data info) data)) 1912 info)) 1913 ;; Secondary string. 1914 ((not type) 1915 (mapconcat (lambda (obj) (org-export-data obj info)) data "")) 1916 ;; Element/Object without contents or, as a special 1917 ;; case, headline with archive tag and archived trees 1918 ;; restricted to title only. 1919 ((or (not (org-element-contents data)) 1920 (and (eq type 'headline) 1921 (eq (plist-get info :with-archived-trees) 'headline) 1922 (org-element-property :archivedp data))) 1923 (let ((transcoder (org-export-transcoder data info))) 1924 (or (and (functionp transcoder) 1925 (if (eq type 'link) 1926 (broken-link-handler 1927 (funcall transcoder data nil info)) 1928 (funcall transcoder data nil info))) 1929 ;; Export snippets never return a nil value so 1930 ;; that white spaces following them are never 1931 ;; ignored. 1932 (and (eq type 'export-snippet) "")))) 1933 ;; Element/Object with contents. 1934 (t 1935 (let ((transcoder (org-export-transcoder data info))) 1936 (when transcoder 1937 (let* ((greaterp (memq type org-element-greater-elements)) 1938 (objectp 1939 (and (not greaterp) 1940 (memq type org-element-recursive-objects))) 1941 (contents 1942 (mapconcat 1943 (lambda (element) (org-export-data element info)) 1944 (org-element-contents 1945 (if (or greaterp objectp) data 1946 ;; Elements directly containing 1947 ;; objects must have their indentation 1948 ;; normalized first. 1949 (org-element-normalize-contents 1950 data 1951 ;; When normalizing first paragraph 1952 ;; of an item or 1953 ;; a footnote-definition, ignore 1954 ;; first line's indentation. 1955 (and 1956 (eq type 'paragraph) 1957 (memq (org-element-type parent) 1958 '(footnote-definition item)) 1959 (eq (car (org-element-contents parent)) 1960 data) 1961 (eq (org-element-property :pre-blank parent) 1962 0))))) 1963 ""))) 1964 (broken-link-handler 1965 (funcall transcoder data 1966 (if (not greaterp) contents 1967 (org-element-normalize-string contents)) 1968 info))))))))) 1969 ;; Final result will be memoized before being returned. 1970 (puthash 1971 data 1972 (cond 1973 ((not results) "") 1974 ((memq type '(nil org-data plain-text raw)) results) 1975 ;; Append the same white space between elements or objects 1976 ;; as in the original buffer, and call appropriate filters. 1977 (t 1978 (org-export-filter-apply-functions 1979 (plist-get info (intern (format ":filter-%s" type))) 1980 (let ((blank (or (org-element-property :post-blank data) 0))) 1981 (if (eq (org-element-class data parent) 'object) 1982 (concat results (make-string blank ?\s)) 1983 (concat (org-element-normalize-string results) 1984 (make-string blank ?\n)))) 1985 info))) 1986 (plist-get info :exported-data)))))) 1987 1988 (defun org-export-data-with-backend (data backend info) 1989 "Convert DATA into BACKEND format. 1990 1991 DATA is an element, an object, a secondary string or a string. 1992 BACKEND is a symbol. INFO is a plist used as a communication 1993 channel. 1994 1995 Unlike to `org-export-with-backend', this function will 1996 recursively convert DATA using BACKEND translation table." 1997 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 1998 ;; Set-up a new communication channel with translations defined in 1999 ;; BACKEND as the translate table and a new hash table for 2000 ;; memoization. 2001 (let ((new-info 2002 (org-combine-plists 2003 info 2004 (list :back-end backend 2005 :translate-alist (org-export-get-all-transcoders backend) 2006 ;; Size of the hash table is reduced since this 2007 ;; function will probably be used on small trees. 2008 :exported-data (make-hash-table :test 'eq :size 401))))) 2009 (prog1 (org-export-data data new-info) 2010 ;; Preserve `:internal-references', as those do not depend on 2011 ;; the back-end used; we need to make sure that any new 2012 ;; reference when the temporary back-end was active gets through 2013 ;; the default one. 2014 (plist-put info :internal-references 2015 (plist-get new-info :internal-references))))) 2016 2017 (defun org-export-expand (blob contents &optional with-affiliated) 2018 "Expand a parsed element or object to its original state. 2019 2020 BLOB is either an element or an object. CONTENTS is its 2021 contents, as a string or nil. 2022 2023 When optional argument WITH-AFFILIATED is non-nil, add affiliated 2024 keywords before output." 2025 (let ((type (org-element-type blob))) 2026 (concat (and with-affiliated 2027 (eq (org-element-class blob) 'element) 2028 (org-element--interpret-affiliated-keywords blob)) 2029 (funcall (intern (format "org-element-%s-interpreter" type)) 2030 blob contents)))) 2031 2032 2033 2034 ;;; The Filter System 2035 ;; 2036 ;; Filters allow end-users to tweak easily the transcoded output. 2037 ;; They are the functional counterpart of hooks, as every filter in 2038 ;; a set is applied to the return value of the previous one. 2039 ;; 2040 ;; Every set is back-end agnostic. Although, a filter is always 2041 ;; called, in addition to the string it applies to, with the back-end 2042 ;; used as argument, so it's easy for the end-user to add back-end 2043 ;; specific filters in the set. The communication channel, as 2044 ;; a plist, is required as the third argument. 2045 ;; 2046 ;; From the developer side, filters sets can be installed in the 2047 ;; process with the help of `org-export-define-backend', which 2048 ;; internally stores filters as an alist. Each association has a key 2049 ;; among the following symbols and a function or a list of functions 2050 ;; as value. 2051 ;; 2052 ;; - `:filter-options' applies to the property list containing export 2053 ;; options. Unlike to other filters, functions in this list accept 2054 ;; two arguments instead of three: the property list containing 2055 ;; export options and the back-end. Users can set its value through 2056 ;; `org-export-filter-options-functions' variable. 2057 ;; 2058 ;; - `:filter-parse-tree' applies directly to the complete parsed 2059 ;; tree. Users can set it through 2060 ;; `org-export-filter-parse-tree-functions' variable. 2061 ;; 2062 ;; - `:filter-body' applies to the body of the output, before template 2063 ;; translator chimes in. Users can set it through 2064 ;; `org-export-filter-body-functions' variable. 2065 ;; 2066 ;; - `:filter-final-output' applies to the final transcoded string. 2067 ;; Users can set it with `org-export-filter-final-output-functions' 2068 ;; variable. 2069 ;; 2070 ;; - `:filter-plain-text' applies to any string not recognized as Org 2071 ;; syntax. `org-export-filter-plain-text-functions' allows users to 2072 ;; configure it. 2073 ;; 2074 ;; - `:filter-TYPE' applies on the string returned after an element or 2075 ;; object of type TYPE has been transcoded. A user can modify 2076 ;; `org-export-filter-TYPE-functions' to install these filters. 2077 ;; 2078 ;; All filters sets are applied with 2079 ;; `org-export-filter-apply-functions' function. Filters in a set are 2080 ;; applied in a LIFO fashion. It allows developers to be sure that 2081 ;; their filters will be applied first. 2082 ;; 2083 ;; Filters properties are installed in communication channel with 2084 ;; `org-export-install-filters' function. 2085 ;; 2086 ;; Eventually, two hooks (`org-export-before-processing-hook' and 2087 ;; `org-export-before-parsing-hook') are run at the beginning of the 2088 ;; export process and just before parsing to allow for heavy structure 2089 ;; modifications. 2090 2091 2092 ;;;; Hooks 2093 2094 (defvar org-export-before-processing-functions nil 2095 "Abnormal hook run at the beginning of the export process. 2096 2097 This is run before include keywords and macros are expanded and 2098 Babel code blocks executed, on a copy of the original buffer 2099 being exported. Visibility and narrowing are preserved. Point 2100 is at the beginning of the buffer. 2101 2102 Every function in this hook will be called with one argument: the 2103 back-end currently used, as a symbol.") 2104 2105 (defvar org-export-before-parsing-functions nil 2106 "Abnormal hook run before parsing an export buffer. 2107 2108 This is run after include keywords and macros have been expanded 2109 and Babel code blocks executed, on a copy of the original buffer 2110 being exported. Visibility and narrowing are preserved. Point 2111 is at the beginning of the buffer. 2112 2113 Every function in this hook will be called with one argument: the 2114 back-end currently used, as a symbol.") 2115 2116 2117 ;;;; Special Filters 2118 2119 (defvar org-export-filter-options-functions nil 2120 "List of functions applied to the export options. 2121 Each filter is called with two arguments: the export options, as 2122 a plist, and the back-end, as a symbol. It must return 2123 a property list containing export options.") 2124 2125 (defvar org-export-filter-parse-tree-functions nil 2126 "List of functions applied to the parsed tree. 2127 Each filter is called with three arguments: the parse tree, as 2128 returned by `org-element-parse-buffer', the back-end, as 2129 a symbol, and the communication channel, as a plist. It must 2130 return the modified parse tree to transcode.") 2131 2132 (defvar org-export-filter-plain-text-functions nil 2133 "List of functions applied to plain text. 2134 Each filter is called with three arguments: a string which 2135 contains no Org syntax, the back-end, as a symbol, and the 2136 communication channel, as a plist. It must return a string or 2137 nil.") 2138 2139 (defvar org-export-filter-body-functions nil 2140 "List of functions applied to transcoded body. 2141 Each filter is called with three arguments: a string which 2142 contains no Org syntax, the back-end, as a symbol, and the 2143 communication channel, as a plist. It must return a string or 2144 nil.") 2145 2146 (defvar org-export-filter-final-output-functions nil 2147 "List of functions applied to the transcoded string. 2148 Each filter is called with three arguments: the full transcoded 2149 string, the back-end, as a symbol, and the communication channel, 2150 as a plist. It must return a string that will be used as the 2151 final export output.") 2152 2153 2154 ;;;; Elements Filters 2155 2156 (defvar org-export-filter-babel-call-functions nil 2157 "List of functions applied to a transcoded babel-call. 2158 Each filter is called with three arguments: the transcoded data, 2159 as a string, the back-end, as a symbol, and the communication 2160 channel, as a plist. It must return a string or nil.") 2161 2162 (defvar org-export-filter-center-block-functions nil 2163 "List of functions applied to a transcoded center block. 2164 Each filter is called with three arguments: the transcoded data, 2165 as a string, the back-end, as a symbol, and the communication 2166 channel, as a plist. It must return a string or nil.") 2167 2168 (defvar org-export-filter-clock-functions nil 2169 "List of functions applied to a transcoded clock. 2170 Each filter is called with three arguments: the transcoded data, 2171 as a string, the back-end, as a symbol, and the communication 2172 channel, as a plist. It must return a string or nil.") 2173 2174 (defvar org-export-filter-diary-sexp-functions nil 2175 "List of functions applied to a transcoded diary-sexp. 2176 Each filter is called with three arguments: the transcoded data, 2177 as a string, the back-end, as a symbol, and the communication 2178 channel, as a plist. It must return a string or nil.") 2179 2180 (defvar org-export-filter-drawer-functions nil 2181 "List of functions applied to a transcoded drawer. 2182 Each filter is called with three arguments: the transcoded data, 2183 as a string, the back-end, as a symbol, and the communication 2184 channel, as a plist. It must return a string or nil.") 2185 2186 (defvar org-export-filter-dynamic-block-functions nil 2187 "List of functions applied to a transcoded dynamic-block. 2188 Each filter is called with three arguments: the transcoded data, 2189 as a string, the back-end, as a symbol, and the communication 2190 channel, as a plist. It must return a string or nil.") 2191 2192 (defvar org-export-filter-example-block-functions nil 2193 "List of functions applied to a transcoded example-block. 2194 Each filter is called with three arguments: the transcoded data, 2195 as a string, the back-end, as a symbol, and the communication 2196 channel, as a plist. It must return a string or nil.") 2197 2198 (defvar org-export-filter-export-block-functions nil 2199 "List of functions applied to a transcoded export-block. 2200 Each filter is called with three arguments: the transcoded data, 2201 as a string, the back-end, as a symbol, and the communication 2202 channel, as a plist. It must return a string or nil.") 2203 2204 (defvar org-export-filter-fixed-width-functions nil 2205 "List of functions applied to a transcoded fixed-width. 2206 Each filter is called with three arguments: the transcoded data, 2207 as a string, the back-end, as a symbol, and the communication 2208 channel, as a plist. It must return a string or nil.") 2209 2210 (defvar org-export-filter-footnote-definition-functions nil 2211 "List of functions applied to a transcoded footnote-definition. 2212 Each filter is called with three arguments: the transcoded data, 2213 as a string, the back-end, as a symbol, and the communication 2214 channel, as a plist. It must return a string or nil.") 2215 2216 (defvar org-export-filter-headline-functions nil 2217 "List of functions applied to a transcoded headline. 2218 Each filter is called with three arguments: the transcoded data, 2219 as a string, the back-end, as a symbol, and the communication 2220 channel, as a plist. It must return a string or nil.") 2221 2222 (defvar org-export-filter-horizontal-rule-functions nil 2223 "List of functions applied to a transcoded horizontal-rule. 2224 Each filter is called with three arguments: the transcoded data, 2225 as a string, the back-end, as a symbol, and the communication 2226 channel, as a plist. It must return a string or nil.") 2227 2228 (defvar org-export-filter-inlinetask-functions nil 2229 "List of functions applied to a transcoded inlinetask. 2230 Each filter is called with three arguments: the transcoded data, 2231 as a string, the back-end, as a symbol, and the communication 2232 channel, as a plist. It must return a string or nil.") 2233 2234 (defvar org-export-filter-item-functions nil 2235 "List of functions applied to a transcoded item. 2236 Each filter is called with three arguments: the transcoded data, 2237 as a string, the back-end, as a symbol, and the communication 2238 channel, as a plist. It must return a string or nil.") 2239 2240 (defvar org-export-filter-keyword-functions nil 2241 "List of functions applied to a transcoded keyword. 2242 Each filter is called with three arguments: the transcoded data, 2243 as a string, the back-end, as a symbol, and the communication 2244 channel, as a plist. It must return a string or nil.") 2245 2246 (defvar org-export-filter-latex-environment-functions nil 2247 "List of functions applied to a transcoded latex-environment. 2248 Each filter is called with three arguments: the transcoded data, 2249 as a string, the back-end, as a symbol, and the communication 2250 channel, as a plist. It must return a string or nil.") 2251 2252 (defvar org-export-filter-node-property-functions nil 2253 "List of functions applied to a transcoded node-property. 2254 Each filter is called with three arguments: the transcoded data, 2255 as a string, the back-end, as a symbol, and the communication 2256 channel, as a plist. It must return a string or nil.") 2257 2258 (defvar org-export-filter-paragraph-functions nil 2259 "List of functions applied to a transcoded paragraph. 2260 Each filter is called with three arguments: the transcoded data, 2261 as a string, the back-end, as a symbol, and the communication 2262 channel, as a plist. It must return a string or nil.") 2263 2264 (defvar org-export-filter-plain-list-functions nil 2265 "List of functions applied to a transcoded plain-list. 2266 Each filter is called with three arguments: the transcoded data, 2267 as a string, the back-end, as a symbol, and the communication 2268 channel, as a plist. It must return a string or nil.") 2269 2270 (defvar org-export-filter-planning-functions nil 2271 "List of functions applied to a transcoded planning. 2272 Each filter is called with three arguments: the transcoded data, 2273 as a string, the back-end, as a symbol, and the communication 2274 channel, as a plist. It must return a string or nil.") 2275 2276 (defvar org-export-filter-property-drawer-functions nil 2277 "List of functions applied to a transcoded property-drawer. 2278 Each filter is called with three arguments: the transcoded data, 2279 as a string, the back-end, as a symbol, and the communication 2280 channel, as a plist. It must return a string or nil.") 2281 2282 (defvar org-export-filter-quote-block-functions nil 2283 "List of functions applied to a transcoded quote block. 2284 Each filter is called with three arguments: the transcoded quote 2285 data, as a string, the back-end, as a symbol, and the 2286 communication channel, as a plist. It must return a string or 2287 nil.") 2288 2289 (defvar org-export-filter-section-functions nil 2290 "List of functions applied to a transcoded section. 2291 Each filter is called with three arguments: the transcoded data, 2292 as a string, the back-end, as a symbol, and the communication 2293 channel, as a plist. It must return a string or nil.") 2294 2295 (defvar org-export-filter-special-block-functions nil 2296 "List of functions applied to a transcoded special block. 2297 Each filter is called with three arguments: the transcoded data, 2298 as a string, the back-end, as a symbol, and the communication 2299 channel, as a plist. It must return a string or nil.") 2300 2301 (defvar org-export-filter-src-block-functions nil 2302 "List of functions applied to a transcoded src-block. 2303 Each filter is called with three arguments: the transcoded data, 2304 as a string, the back-end, as a symbol, and the communication 2305 channel, as a plist. It must return a string or nil.") 2306 2307 (defvar org-export-filter-table-functions nil 2308 "List of functions applied to a transcoded table. 2309 Each filter is called with three arguments: the transcoded data, 2310 as a string, the back-end, as a symbol, and the communication 2311 channel, as a plist. It must return a string or nil.") 2312 2313 (defvar org-export-filter-table-cell-functions nil 2314 "List of functions applied to a transcoded table-cell. 2315 Each filter is called with three arguments: the transcoded data, 2316 as a string, the back-end, as a symbol, and the communication 2317 channel, as a plist. It must return a string or nil.") 2318 2319 (defvar org-export-filter-table-row-functions nil 2320 "List of functions applied to a transcoded table-row. 2321 Each filter is called with three arguments: the transcoded data, 2322 as a string, the back-end, as a symbol, and the communication 2323 channel, as a plist. It must return a string or nil.") 2324 2325 (defvar org-export-filter-verse-block-functions nil 2326 "List of functions applied to a transcoded verse block. 2327 Each filter is called with three arguments: the transcoded data, 2328 as a string, the back-end, as a symbol, and the communication 2329 channel, as a plist. It must return a string or nil.") 2330 2331 2332 ;;;; Objects Filters 2333 2334 (defvar org-export-filter-bold-functions nil 2335 "List of functions applied to transcoded bold text. 2336 Each filter is called with three arguments: the transcoded data, 2337 as a string, the back-end, as a symbol, and the communication 2338 channel, as a plist. It must return a string or nil.") 2339 2340 (defvar org-export-filter-code-functions nil 2341 "List of functions applied to transcoded code text. 2342 Each filter is called with three arguments: the transcoded data, 2343 as a string, the back-end, as a symbol, and the communication 2344 channel, as a plist. It must return a string or nil.") 2345 2346 (defvar org-export-filter-entity-functions nil 2347 "List of functions applied to a transcoded entity. 2348 Each filter is called with three arguments: the transcoded data, 2349 as a string, the back-end, as a symbol, and the communication 2350 channel, as a plist. It must return a string or nil.") 2351 2352 (defvar org-export-filter-export-snippet-functions nil 2353 "List of functions applied to a transcoded export-snippet. 2354 Each filter is called with three arguments: the transcoded data, 2355 as a string, the back-end, as a symbol, and the communication 2356 channel, as a plist. It must return a string or nil.") 2357 2358 (defvar org-export-filter-footnote-reference-functions nil 2359 "List of functions applied to a transcoded footnote-reference. 2360 Each filter is called with three arguments: the transcoded data, 2361 as a string, the back-end, as a symbol, and the communication 2362 channel, as a plist. It must return a string or nil.") 2363 2364 (defvar org-export-filter-inline-babel-call-functions nil 2365 "List of functions applied to a transcoded inline-babel-call. 2366 Each filter is called with three arguments: the transcoded data, 2367 as a string, the back-end, as a symbol, and the communication 2368 channel, as a plist. It must return a string or nil.") 2369 2370 (defvar org-export-filter-inline-src-block-functions nil 2371 "List of functions applied to a transcoded inline-src-block. 2372 Each filter is called with three arguments: the transcoded data, 2373 as a string, the back-end, as a symbol, and the communication 2374 channel, as a plist. It must return a string or nil.") 2375 2376 (defvar org-export-filter-italic-functions nil 2377 "List of functions applied to transcoded italic text. 2378 Each filter is called with three arguments: the transcoded data, 2379 as a string, the back-end, as a symbol, and the communication 2380 channel, as a plist. It must return a string or nil.") 2381 2382 (defvar org-export-filter-latex-fragment-functions nil 2383 "List of functions applied to a transcoded latex-fragment. 2384 Each filter is called with three arguments: the transcoded data, 2385 as a string, the back-end, as a symbol, and the communication 2386 channel, as a plist. It must return a string or nil.") 2387 2388 (defvar org-export-filter-line-break-functions nil 2389 "List of functions applied to a transcoded line-break. 2390 Each filter is called with three arguments: the transcoded data, 2391 as a string, the back-end, as a symbol, and the communication 2392 channel, as a plist. It must return a string or nil.") 2393 2394 (defvar org-export-filter-link-functions nil 2395 "List of functions applied to a transcoded link. 2396 Each filter is called with three arguments: the transcoded data, 2397 as a string, the back-end, as a symbol, and the communication 2398 channel, as a plist. It must return a string or nil.") 2399 2400 (defvar org-export-filter-radio-target-functions nil 2401 "List of functions applied to a transcoded radio-target. 2402 Each filter is called with three arguments: the transcoded data, 2403 as a string, the back-end, as a symbol, and the communication 2404 channel, as a plist. It must return a string or nil.") 2405 2406 (defvar org-export-filter-statistics-cookie-functions nil 2407 "List of functions applied to a transcoded statistics-cookie. 2408 Each filter is called with three arguments: the transcoded data, 2409 as a string, the back-end, as a symbol, and the communication 2410 channel, as a plist. It must return a string or nil.") 2411 2412 (defvar org-export-filter-strike-through-functions nil 2413 "List of functions applied to transcoded strike-through text. 2414 Each filter is called with three arguments: the transcoded data, 2415 as a string, the back-end, as a symbol, and the communication 2416 channel, as a plist. It must return a string or nil.") 2417 2418 (defvar org-export-filter-subscript-functions nil 2419 "List of functions applied to a transcoded subscript. 2420 Each filter is called with three arguments: the transcoded data, 2421 as a string, the back-end, as a symbol, and the communication 2422 channel, as a plist. It must return a string or nil.") 2423 2424 (defvar org-export-filter-superscript-functions nil 2425 "List of functions applied to a transcoded superscript. 2426 Each filter is called with three arguments: the transcoded data, 2427 as a string, the back-end, as a symbol, and the communication 2428 channel, as a plist. It must return a string or nil.") 2429 2430 (defvar org-export-filter-target-functions nil 2431 "List of functions applied to a transcoded target. 2432 Each filter is called with three arguments: the transcoded data, 2433 as a string, the back-end, as a symbol, and the communication 2434 channel, as a plist. It must return a string or nil.") 2435 2436 (defvar org-export-filter-timestamp-functions nil 2437 "List of functions applied to a transcoded timestamp. 2438 Each filter is called with three arguments: the transcoded data, 2439 as a string, the back-end, as a symbol, and the communication 2440 channel, as a plist. It must return a string or nil.") 2441 2442 (defvar org-export-filter-underline-functions nil 2443 "List of functions applied to transcoded underline text. 2444 Each filter is called with three arguments: the transcoded data, 2445 as a string, the back-end, as a symbol, and the communication 2446 channel, as a plist. It must return a string or nil.") 2447 2448 (defvar org-export-filter-verbatim-functions nil 2449 "List of functions applied to transcoded verbatim text. 2450 Each filter is called with three arguments: the transcoded data, 2451 as a string, the back-end, as a symbol, and the communication 2452 channel, as a plist. It must return a string or nil.") 2453 2454 2455 ;;;; Filters Tools 2456 ;; 2457 ;; Internal function `org-export-install-filters' installs filters 2458 ;; hard-coded in back-ends (developer filters) and filters from global 2459 ;; variables (user filters) in the communication channel. 2460 ;; 2461 ;; Internal function `org-export-filter-apply-functions' takes care 2462 ;; about applying each filter in order to a given data. It ignores 2463 ;; filters returning a nil value but stops whenever a filter returns 2464 ;; an empty string. 2465 2466 (defun org-export-filter-apply-functions (filters value info) 2467 "Call every function in FILTERS. 2468 2469 Functions are called with three arguments: a value, the export 2470 back-end name and the communication channel. First function in 2471 FILTERS is called with VALUE as its first argument. Second 2472 function in FILTERS is called with the previous result as its 2473 value, etc. 2474 2475 Functions returning nil are skipped. Any function returning the 2476 empty string ends the process, which returns the empty string. 2477 2478 Call is done in a LIFO fashion, to be sure that developer 2479 specified filters, if any, are called first." 2480 (catch :exit 2481 (let* ((backend (plist-get info :back-end)) 2482 (backend-name (and backend (org-export-backend-name backend)))) 2483 (dolist (filter filters value) 2484 (let ((result (funcall filter value backend-name info))) 2485 (cond ((not result)) 2486 ((equal result "") (throw :exit "")) 2487 (t (setq value result)))))))) 2488 2489 (defun org-export-install-filters (info) 2490 "Install filters properties in communication channel. 2491 INFO is a plist containing the current communication channel. 2492 Return the updated communication channel." 2493 (let (plist) 2494 ;; Install user-defined filters with `org-export-filters-alist' 2495 ;; and filters already in INFO (through ext-plist mechanism). 2496 (dolist (p org-export-filters-alist) 2497 (let* ((prop (car p)) 2498 (info-value (plist-get info prop)) 2499 (default-value (symbol-value (cdr p)))) 2500 (setq plist 2501 (plist-put plist prop 2502 ;; Filters in INFO will be called 2503 ;; before those user provided. 2504 (append (if (listp info-value) info-value 2505 (list info-value)) 2506 default-value))))) 2507 ;; Prepend back-end specific filters to that list. 2508 (dolist (p (org-export-get-all-filters (plist-get info :back-end))) 2509 ;; Single values get consed, lists are appended. 2510 (let ((key (car p)) (value (cdr p))) 2511 (when value 2512 (setq plist 2513 (plist-put 2514 plist key 2515 (if (atom value) (cons value (plist-get plist key)) 2516 (append value (plist-get plist key)))))))) 2517 ;; Return new communication channel. 2518 (org-combine-plists info plist))) 2519 2520 2521 2522 ;;; Core functions 2523 ;; 2524 ;; This is the room for the main function, `org-export-as', along with 2525 ;; its derivative, `org-export-string-as'. 2526 ;; `org-export--copy-to-kill-ring-p' determines if output of these 2527 ;; function should be added to kill ring. 2528 ;; 2529 ;; Note that `org-export-as' doesn't really parse the current buffer, 2530 ;; but a copy of it (with the same buffer-local variables and 2531 ;; visibility), where macros and include keywords are expanded and 2532 ;; Babel blocks are executed, if appropriate. 2533 ;; `org-export-with-buffer-copy' macro prepares that copy. 2534 ;; 2535 ;; File inclusion is taken care of by 2536 ;; `org-export-expand-include-keyword' and 2537 ;; `org-export--prepare-file-contents'. Structure wise, including 2538 ;; a whole Org file in a buffer often makes little sense. For 2539 ;; example, if the file contains a headline and the include keyword 2540 ;; was within an item, the item should contain the headline. That's 2541 ;; why file inclusion should be done before any structure can be 2542 ;; associated to the file, that is before parsing. 2543 ;; 2544 ;; `org-export-insert-default-template' is a command to insert 2545 ;; a default template (or a back-end specific template) at point or in 2546 ;; current subtree. 2547 2548 (cl-defun org-export-copy-buffer (&key to-buffer drop-visibility 2549 drop-narrowing drop-contents 2550 drop-locals) 2551 "Return a copy of the current buffer. 2552 The copy preserves Org buffer-local variables, visibility and 2553 narrowing. 2554 2555 IMPORTANT: The buffer copy may also have `buffer-file-name' copied. 2556 To prevent Emacs overwriting the original buffer file, 2557 `write-contents-functions' is set to (always). Do not alter this 2558 variable and do not do anything that might alter it (like calling a 2559 major mode) to prevent data corruption. Also, do note that Emacs may 2560 jump into the created buffer if the original file buffer is closed and 2561 then re-opened. Making edits in the buffer copy may also trigger 2562 Emacs save dialog. Prefer using `org-export-with-buffer-copy' macro 2563 when possible. 2564 2565 When optional key `:to-buffer' is non-nil, copy into BUFFER. 2566 2567 Optional keys `:drop-visibility', `:drop-narrowing', `:drop-contents', 2568 and `:drop-locals' are passed to `org-export--generate-copy-script'." 2569 (let ((copy-buffer-fun (org-export--generate-copy-script 2570 (current-buffer) 2571 :copy-unreadable 'do-not-check 2572 :drop-visibility drop-visibility 2573 :drop-narrowing drop-narrowing 2574 :drop-contents drop-contents 2575 :drop-locals drop-locals)) 2576 (new-buf (or to-buffer (generate-new-buffer (buffer-name))))) 2577 (with-current-buffer new-buf 2578 (funcall copy-buffer-fun) 2579 (set-buffer-modified-p nil)) 2580 new-buf)) 2581 2582 (cl-defmacro org-export-with-buffer-copy ( &rest body 2583 &key to-buffer drop-visibility 2584 drop-narrowing drop-contents 2585 drop-locals 2586 &allow-other-keys) 2587 "Apply BODY in a copy of the current buffer. 2588 The copy preserves local variables, visibility and contents of 2589 the original buffer. Point is at the beginning of the buffer 2590 when BODY is applied. 2591 2592 Optional keys can modify what is being copied and the generated buffer 2593 copy. `:to-buffer', `:drop-visibility', `:drop-narrowing', 2594 `:drop-contents', and `:drop-locals' are passed as arguments to 2595 `org-export-copy-buffer'." 2596 (declare (debug t)) 2597 (org-with-gensyms (buf-copy) 2598 `(let ((,buf-copy (org-export-copy-buffer 2599 :to-buffer ,to-buffer 2600 :drop-visibility ,drop-visibility 2601 :drop-narrowing ,drop-narrowing 2602 :drop-contents ,drop-contents 2603 :drop-locals ,drop-locals))) 2604 (unwind-protect 2605 (with-current-buffer ,buf-copy 2606 (goto-char (point-min)) 2607 (prog1 2608 (progn ,@body) 2609 ;; `org-export-copy-buffer' carried the value of 2610 ;; `buffer-file-name' from the original buffer. When not 2611 ;; killed, the new buffer copy may become a target of 2612 ;; `find-file'. Prevent this. 2613 (setq buffer-file-name nil))) 2614 (and (buffer-live-p ,buf-copy) 2615 ;; Kill copy without confirmation. 2616 (progn (with-current-buffer ,buf-copy 2617 (restore-buffer-modified-p nil)) 2618 (unless ,to-buffer 2619 (kill-buffer ,buf-copy)))))))) 2620 2621 (cl-defun org-export--generate-copy-script (buffer 2622 &key 2623 copy-unreadable 2624 drop-visibility 2625 drop-narrowing 2626 drop-contents 2627 drop-locals) 2628 "Generate a function duplicating BUFFER. 2629 2630 The copy will preserve local variables, visibility, contents and 2631 narrowing of the original buffer. If a region was active in 2632 BUFFER, contents will be narrowed to that region instead. 2633 2634 When optional key `:copy-unreadable' is non-nil, do not ensure that all 2635 the copied local variables will be readable in another Emacs session. 2636 2637 When optional keys `:drop-visibility', `:drop-narrowing', 2638 `:drop-contents', or `:drop-locals' are non-nil, do not preserve 2639 visibility, narrowing, contents, or local variables correspondingly. 2640 2641 The resulting function can be evaluated at a later time, from 2642 another buffer, effectively cloning the original buffer there. 2643 2644 The function assumes BUFFER's major mode is `org-mode'." 2645 (with-current-buffer buffer 2646 (let ((str (unless drop-contents (org-with-wide-buffer (buffer-string)))) 2647 (narrowing 2648 (unless drop-narrowing 2649 (if (org-region-active-p) 2650 (list (region-beginning) (region-end)) 2651 (list (point-min) (point-max))))) 2652 (pos (point)) 2653 (varvals 2654 (unless drop-locals 2655 (let ((bound-variables (org-export--list-bound-variables)) 2656 (varvals nil)) 2657 (dolist (entry (buffer-local-variables (buffer-base-buffer))) 2658 (when (consp entry) 2659 (let ((var (car entry)) 2660 (val (cdr entry))) 2661 (and (not (memq var org-export-ignored-local-variables)) 2662 (or (memq var 2663 '(default-directory 2664 ;; Required to convert file 2665 ;; links in the #+INCLUDEd 2666 ;; files. See 2667 ;; `org-export--prepare-file-contents'. 2668 buffer-file-name 2669 buffer-file-coding-system 2670 ;; Needed to preserve folding state 2671 char-property-alias-alist)) 2672 (assq var bound-variables) 2673 (string-match "^\\(org-\\|orgtbl-\\)" 2674 (symbol-name var))) 2675 ;; Skip unreadable values, as they cannot be 2676 ;; sent to external process. 2677 (or copy-unreadable (not val) 2678 (ignore-errors (read (format "%S" val)))) 2679 (push (cons var val) varvals))))) 2680 varvals))) 2681 (ols 2682 (unless drop-visibility 2683 (let (ov-set) 2684 (dolist (ov (overlays-in (point-min) (point-max))) 2685 (let ((invis-prop (overlay-get ov 'invisible))) 2686 (when invis-prop 2687 (push (list (overlay-start ov) (overlay-end ov) 2688 invis-prop) 2689 ov-set)))) 2690 ov-set)))) 2691 (lambda () 2692 (let ((inhibit-modification-hooks t)) 2693 ;; Set major mode. Ignore `org-mode-hook' and other hooks as 2694 ;; they have been run already in BUFFER. 2695 (unless (eq major-mode 'org-mode) 2696 (delay-mode-hooks 2697 (let ((org-inhibit-startup t)) (org-mode)))) 2698 ;; Copy specific buffer local variables and variables set 2699 ;; through BIND keywords. 2700 (pcase-dolist (`(,var . ,val) varvals) 2701 (set (make-local-variable var) val)) 2702 ;; Whole buffer contents when requested. 2703 (when str (erase-buffer) (insert str)) 2704 ;; Make org-element-cache not complain about changed buffer 2705 ;; state. 2706 (org-element-cache-reset nil 'no-persistence) 2707 ;; Narrowing. 2708 (when narrowing 2709 (apply #'narrow-to-region narrowing)) 2710 ;; Current position of point. 2711 (goto-char pos) 2712 ;; Overlays with invisible property. 2713 (pcase-dolist (`(,start ,end ,invis) ols) 2714 (overlay-put (make-overlay start end) 'invisible invis)) 2715 ;; Never write the buffer copy to disk, despite 2716 ;; `buffer-file-name' not being nil. 2717 (setq write-contents-functions (list (lambda (&rest _) t)))))))) 2718 2719 (defun org-export--delete-comment-trees () 2720 "Delete commented trees and commented inlinetasks in the buffer. 2721 Narrowing, if any, is ignored." 2722 (org-with-wide-buffer 2723 (goto-char (point-min)) 2724 (let* ((case-fold-search t) 2725 (regexp (concat org-outline-regexp-bol ".*" org-comment-string))) 2726 (while (re-search-forward regexp nil t) 2727 (let ((element (org-element-at-point))) 2728 (when (org-element-property :commentedp element) 2729 (delete-region (org-element-property :begin element) 2730 (org-element-property :end element)))))))) 2731 2732 (defun org-export--prune-tree (data info) 2733 "Prune non exportable elements from DATA. 2734 DATA is the parse tree to traverse. INFO is the plist holding 2735 export info. Also set `:ignore-list' in INFO to a list of 2736 objects which should be ignored during export, but not removed 2737 from tree." 2738 (letrec ((ignore nil) 2739 ;; First find trees containing a select tag, if any. 2740 (selected (org-export--selected-trees data info)) 2741 ;; List tags that prevent export of headlines. 2742 (excluded (cl-mapcan (lambda (tag) (org-tags-expand tag t)) 2743 (plist-get info :exclude-tags))) 2744 (walk-data 2745 (lambda (data) 2746 ;; Prune non-exportable elements and objects from tree. 2747 ;; As a special case, special rows and cells from tables 2748 ;; are stored in IGNORE, as they still need to be 2749 ;; accessed during export. 2750 (when data 2751 (let ((type (org-element-type data))) 2752 (if (org-export--skip-p data info selected excluded) 2753 (if (memq type '(table-cell table-row)) (push data ignore) 2754 (org-element-extract-element data)) 2755 (if (and (eq type 'headline) 2756 (eq (plist-get info :with-archived-trees) 2757 'headline) 2758 (org-element-property :archivedp data)) 2759 ;; If headline is archived but tree below has 2760 ;; to be skipped, remove contents. 2761 (org-element-set-contents data) 2762 ;; Move into recursive objects/elements. 2763 (mapc walk-data (org-element-contents data))) 2764 ;; Move into secondary string, if any. 2765 (dolist (p (cdr (assq type 2766 org-element-secondary-value-alist))) 2767 (mapc walk-data (org-element-property p data)))))))) 2768 (definitions 2769 ;; Collect definitions before possibly pruning them so as 2770 ;; to avoid parsing them again if they are required. 2771 (org-element-map data '(footnote-definition footnote-reference) 2772 (lambda (f) 2773 (cond 2774 ((eq 'footnote-definition (org-element-type f)) f) 2775 ((and (eq 'inline (org-element-property :type f)) 2776 (org-element-property :label f)) 2777 f) 2778 (t nil)))))) 2779 ;; If a select tag is active, also ignore the section before the 2780 ;; first headline, if any. 2781 (when selected 2782 (let ((first-element (car (org-element-contents data)))) 2783 (when (eq (org-element-type first-element) 'section) 2784 (org-element-extract-element first-element)))) 2785 ;; Prune tree and communication channel. 2786 (funcall walk-data data) 2787 (dolist (entry (append 2788 ;; Priority is given to back-end specific options. 2789 (org-export-get-all-options (plist-get info :back-end)) 2790 org-export-options-alist)) 2791 (when (eq (nth 4 entry) 'parse) 2792 (funcall walk-data (plist-get info (car entry))))) 2793 (let ((missing (org-export--missing-definitions data definitions))) 2794 (funcall walk-data missing) 2795 (org-export--install-footnote-definitions missing data)) 2796 ;; Eventually set `:ignore-list'. 2797 (plist-put info :ignore-list ignore))) 2798 2799 (defun org-export--missing-definitions (tree definitions) 2800 "List footnote definitions missing from TREE. 2801 Missing definitions are searched within DEFINITIONS, which is 2802 a list of footnote definitions or in the widened buffer." 2803 (let* ((list-labels 2804 (lambda (data) 2805 ;; List all footnote labels encountered in DATA. Inline 2806 ;; footnote references are ignored. 2807 (org-element-map data 'footnote-reference 2808 (lambda (reference) 2809 (and (eq (org-element-property :type reference) 'standard) 2810 (org-element-property :label reference)))))) 2811 defined undefined missing-definitions) 2812 ;; Partition DIRECT-REFERENCES between DEFINED and UNDEFINED 2813 ;; references. 2814 (let ((known-definitions 2815 (org-element-map tree '(footnote-reference footnote-definition) 2816 (lambda (f) 2817 (and (or (eq (org-element-type f) 'footnote-definition) 2818 (eq (org-element-property :type f) 'inline)) 2819 (org-element-property :label f))))) 2820 ) ;; seen 2821 (dolist (l (funcall list-labels tree)) 2822 (cond ;; ((member l seen)) 2823 ((member l known-definitions) (push l defined)) 2824 (t (push l undefined))))) 2825 ;; Complete MISSING-DEFINITIONS by finding the definition of every 2826 ;; undefined label, first by looking into DEFINITIONS, then by 2827 ;; searching the widened buffer. This is a recursive process 2828 ;; since definitions found can themselves contain an undefined 2829 ;; reference. 2830 (while undefined 2831 (let* ((label (pop undefined)) 2832 (definition 2833 (cond 2834 ((cl-some 2835 (lambda (d) (and (equal (org-element-property :label d) label) 2836 d)) 2837 definitions)) 2838 ((pcase (org-footnote-get-definition label) 2839 (`(,_ ,beg . ,_) 2840 (org-with-wide-buffer 2841 (goto-char beg) 2842 (let ((datum (org-element-context))) 2843 (if (eq (org-element-type datum) 'footnote-reference) 2844 datum 2845 ;; Parse definition with contents. 2846 (save-restriction 2847 (narrow-to-region 2848 (org-element-property :begin datum) 2849 (org-element-property :end datum)) 2850 (org-element-map (org-element-parse-buffer) 2851 'footnote-definition #'identity nil t)))))) 2852 (_ nil))) 2853 (t (user-error "Definition not found for footnote %s" label))))) 2854 (push label defined) 2855 (push definition missing-definitions) 2856 ;; Look for footnote references within DEFINITION, since 2857 ;; we may need to also find their definition. 2858 (dolist (l (funcall list-labels definition)) 2859 (unless (or (member l defined) ;Known label 2860 (member l undefined)) ;Processed later 2861 (push l undefined))))) 2862 ;; MISSING-DEFINITIONS may contain footnote references with inline 2863 ;; definitions. Make sure those are changed into real footnote 2864 ;; definitions. 2865 (mapcar (lambda (d) 2866 (if (eq (org-element-type d) 'footnote-definition) d 2867 (let ((label (org-element-property :label d))) 2868 (apply #'org-element-create 2869 'footnote-definition `(:label ,label :post-blank 1) 2870 (org-element-contents d))))) 2871 missing-definitions))) 2872 2873 (defun org-export--install-footnote-definitions (definitions tree) 2874 "Install footnote definitions in tree. 2875 2876 DEFINITIONS is the list of footnote definitions to install. TREE 2877 is the parse tree. 2878 2879 If there is a footnote section in TREE, definitions found are 2880 appended to it. If `org-footnote-section' is non-nil, a new 2881 footnote section containing all definitions is inserted in TREE. 2882 Otherwise, definitions are appended at the end of the section 2883 containing their first reference." 2884 (cond 2885 ((null definitions)) 2886 ;; If there is a footnote section, insert definitions there. 2887 ((let ((footnote-section 2888 (org-element-map tree 'headline 2889 (lambda (h) (and (org-element-property :footnote-section-p h) h)) 2890 nil t))) 2891 (and footnote-section 2892 (apply #'org-element-adopt-elements 2893 footnote-section 2894 (nreverse definitions))))) 2895 ;; If there should be a footnote section, create one containing all 2896 ;; the definitions at the end of the tree. 2897 (org-footnote-section 2898 (org-element-adopt-elements 2899 tree 2900 (org-element-create 'headline 2901 (list :footnote-section-p t 2902 :level 1 2903 :title org-footnote-section 2904 :raw-value org-footnote-section) 2905 (apply #'org-element-create 2906 'section 2907 nil 2908 (nreverse definitions))))) 2909 ;; Otherwise add each definition at the end of the section where it 2910 ;; is first referenced. 2911 (t 2912 (letrec ((seen nil) 2913 (insert-definitions 2914 (lambda (data) 2915 ;; Insert footnote definitions in the same section as 2916 ;; their first reference in DATA. 2917 (org-element-map data 'footnote-reference 2918 (lambda (reference) 2919 (when (eq (org-element-property :type reference) 'standard) 2920 (let ((label (org-element-property :label reference))) 2921 (unless (member label seen) 2922 (push label seen) 2923 (let ((definition 2924 (cl-some 2925 (lambda (d) 2926 (and (equal (org-element-property :label d) 2927 label) 2928 d)) 2929 definitions))) 2930 (org-element-adopt-elements 2931 (org-element-lineage reference '(section)) 2932 definition) 2933 ;; Also insert definitions for nested 2934 ;; references, if any. 2935 (funcall insert-definitions definition)))))))))) 2936 (funcall insert-definitions tree))))) 2937 2938 (defun org-export--remove-uninterpreted-data (data info) 2939 "Change uninterpreted elements back into Org syntax. 2940 DATA is a parse tree or a secondary string. INFO is a plist 2941 containing export options. It is modified by side effect and 2942 returned by the function." 2943 (org-element-map data 2944 '(entity bold italic latex-environment latex-fragment strike-through 2945 subscript superscript underline) 2946 (lambda (datum) 2947 (let* ((type (org-element-type datum)) 2948 (post-blank 2949 (pcase (org-element-property :post-blank datum) 2950 (`nil nil) 2951 (n (make-string n (if (eq type 'latex-environment) ?\n ?\s))))) 2952 (new 2953 (cl-case type 2954 ;; ... entities... 2955 (entity 2956 (and (not (plist-get info :with-entities)) 2957 (list (concat (org-export-expand datum nil) 2958 post-blank)))) 2959 ;; ... emphasis... 2960 ((bold italic strike-through underline) 2961 (and (not (plist-get info :with-emphasize)) 2962 (let ((marker (cl-case type 2963 (bold "*") 2964 (italic "/") 2965 (strike-through "+") 2966 (underline "_")))) 2967 (append 2968 (list marker) 2969 (org-element-contents datum) 2970 (list (concat marker post-blank)))))) 2971 ;; ... LaTeX environments and fragments... 2972 ((latex-environment latex-fragment) 2973 (and (eq (plist-get info :with-latex) 'verbatim) 2974 (list (concat (org-export-expand datum nil) 2975 post-blank)))) 2976 ;; ... sub/superscripts... 2977 ((subscript superscript) 2978 (let ((sub/super-p (plist-get info :with-sub-superscript)) 2979 (bracketp (org-element-property :use-brackets-p datum))) 2980 (and (or (not sub/super-p) 2981 (and (eq sub/super-p '{}) (not bracketp))) 2982 (append 2983 (list (concat (if (eq type 'subscript) "_" "^") 2984 (and bracketp "{"))) 2985 (org-element-contents datum) 2986 (list (concat (and bracketp "}") 2987 post-blank))))))))) 2988 (when new 2989 ;; Splice NEW at DATUM location in parse tree. 2990 (dolist (e new (org-element-extract-element datum)) 2991 (unless (equal e "") (org-element-insert-before e datum)))))) 2992 info nil nil t) 2993 ;; Return modified parse tree. 2994 data) 2995 2996 ;;;###autoload 2997 (defun org-export-as 2998 (backend &optional subtreep visible-only body-only ext-plist) 2999 "Transcode current Org buffer into BACKEND code. 3000 3001 BACKEND is either an export back-end, as returned by, e.g., 3002 `org-export-create-backend', or a symbol referring to 3003 a registered back-end. 3004 3005 If narrowing is active in the current buffer, only transcode its 3006 narrowed part. 3007 3008 If a region is active, transcode that region. 3009 3010 When optional argument SUBTREEP is non-nil, transcode the 3011 sub-tree at point, extracting information from the headline 3012 properties first. 3013 3014 When optional argument VISIBLE-ONLY is non-nil, don't export 3015 contents of hidden elements. 3016 3017 When optional argument BODY-ONLY is non-nil, only return body 3018 code, without surrounding template. 3019 3020 Optional argument EXT-PLIST, when provided, is a property list 3021 with external parameters overriding Org default settings, but 3022 still inferior to file-local settings. 3023 3024 Return code as a string." 3025 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 3026 (org-export-barf-if-invalid-backend backend) 3027 (org-fold-core-ignore-modifications 3028 (save-excursion 3029 (save-restriction 3030 ;; Narrow buffer to an appropriate region or subtree for 3031 ;; parsing. If parsing subtree, be sure to remove main 3032 ;; headline, planning data and property drawer. 3033 (cond ((org-region-active-p) 3034 (narrow-to-region (region-beginning) (region-end))) 3035 (subtreep 3036 (org-narrow-to-subtree) 3037 (goto-char (point-min)) 3038 (org-end-of-meta-data) 3039 ;; Make the region include top heading in the subtree. 3040 ;; This way, we will be able to retrieve its export 3041 ;; options when calling 3042 ;; `org-export--get-subtree-options'. 3043 (backward-char) 3044 (narrow-to-region (point) (point-max)))) 3045 ;; Initialize communication channel with original buffer 3046 ;; attributes, unavailable in its copy. 3047 (let* ((org-export-current-backend (org-export-backend-name backend)) 3048 (info (org-combine-plists 3049 (org-export--get-export-attributes 3050 backend subtreep visible-only body-only) 3051 (org-export--get-buffer-attributes))) 3052 (parsed-keywords 3053 (delq nil 3054 (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o))) 3055 (append (org-export-get-all-options backend) 3056 org-export-options-alist)))) 3057 tree modified-tick) 3058 ;; Update communication channel and get parse tree. Buffer 3059 ;; isn't parsed directly. Instead, all buffer modifications 3060 ;; and consequent parsing are undertaken in a temporary copy. 3061 (org-export-with-buffer-copy 3062 (font-lock-mode -1) 3063 ;; Run first hook with current back-end's name as argument. 3064 (run-hook-with-args 'org-export-before-processing-hook 3065 (org-export-backend-name backend)) 3066 (org-export-expand-include-keyword) 3067 (org-export--delete-comment-trees) 3068 (org-macro-initialize-templates org-export-global-macros) 3069 (org-macro-replace-all org-macro-templates parsed-keywords) 3070 ;; Refresh buffer properties and radio targets after previous 3071 ;; potentially invasive changes. 3072 (org-set-regexps-and-options) 3073 (org-update-radio-target-regexp) 3074 (setq modified-tick (buffer-chars-modified-tick)) 3075 ;; Possibly execute Babel code. Re-run a macro expansion 3076 ;; specifically for {{{results}}} since inline source blocks 3077 ;; may have generated some more. Refresh buffer properties 3078 ;; and radio targets another time. 3079 (when org-export-use-babel 3080 (org-babel-exp-process-buffer) 3081 (org-macro-replace-all '(("results" . "$1")) parsed-keywords) 3082 (unless (eq modified-tick (buffer-chars-modified-tick)) 3083 (org-set-regexps-and-options) 3084 (org-update-radio-target-regexp)) 3085 (setq modified-tick (buffer-chars-modified-tick))) 3086 ;; Run last hook with current back-end's name as argument. 3087 ;; Update buffer properties and radio targets one last time 3088 ;; before parsing. 3089 (goto-char (point-min)) 3090 (save-excursion 3091 (run-hook-with-args 'org-export-before-parsing-hook 3092 (org-export-backend-name backend))) 3093 (unless (eq modified-tick (buffer-chars-modified-tick)) 3094 (org-set-regexps-and-options) 3095 (org-update-radio-target-regexp)) 3096 (setq modified-tick (buffer-chars-modified-tick)) 3097 ;; Update communication channel with environment. 3098 (setq info 3099 (org-combine-plists 3100 info (org-export-get-environment backend subtreep ext-plist))) 3101 ;; Pre-process citations environment, i.e. install 3102 ;; bibliography list, and citation processor in INFO. 3103 (org-cite-store-bibliography info) 3104 (org-cite-store-export-processor info) 3105 ;; De-activate uninterpreted data from parsed keywords. 3106 (dolist (entry (append (org-export-get-all-options backend) 3107 org-export-options-alist)) 3108 (pcase entry 3109 (`(,p ,_ ,_ ,_ parse) 3110 (let ((value (plist-get info p))) 3111 (plist-put info 3112 p 3113 (org-export--remove-uninterpreted-data value info)))) 3114 (_ nil))) 3115 ;; Install user's and developer's filters. 3116 (setq info (org-export-install-filters info)) 3117 ;; Call options filters and update export options. We do not 3118 ;; use `org-export-filter-apply-functions' here since the 3119 ;; arity of such filters is different. 3120 (let ((backend-name (org-export-backend-name backend))) 3121 (dolist (filter (plist-get info :filter-options)) 3122 (let ((result (funcall filter info backend-name))) 3123 (when result (setq info result))))) 3124 ;; Parse buffer. 3125 (setq tree (org-element-parse-buffer nil visible-only)) 3126 ;; Prune tree from non-exported elements and transform 3127 ;; uninterpreted elements or objects in both parse tree and 3128 ;; communication channel. 3129 (org-export--prune-tree tree info) 3130 (org-export--remove-uninterpreted-data tree info) 3131 ;; Call parse tree filters. 3132 (setq tree 3133 (org-export-filter-apply-functions 3134 (plist-get info :filter-parse-tree) tree info)) 3135 ;; Now tree is complete, compute its properties and add them 3136 ;; to communication channel. 3137 (setq info (org-export--collect-tree-properties tree info)) 3138 ;; Process citations and bibliography. Replace each citation 3139 ;; and "print_bibliography" keyword in the parse tree with 3140 ;; the output of the selected citation export processor. 3141 (org-cite-process-citations info) 3142 (org-cite-process-bibliography info) 3143 ;; Eventually transcode TREE. Wrap the resulting string into 3144 ;; a template. 3145 (let* ((body (org-element-normalize-string 3146 (or (org-export-data tree info) ""))) 3147 (inner-template (cdr (assq 'inner-template 3148 (plist-get info :translate-alist)))) 3149 (full-body (org-export-filter-apply-functions 3150 (plist-get info :filter-body) 3151 (if (not (functionp inner-template)) body 3152 (funcall inner-template body info)) 3153 info)) 3154 (template (cdr (assq 'template 3155 (plist-get info :translate-alist)))) 3156 (output 3157 (if (or (not (functionp template)) body-only) full-body 3158 (funcall template full-body info)))) 3159 ;; Call citation export finalizer. 3160 (setq output (org-cite-finalize-export output info)) 3161 ;; Remove all text properties since they cannot be 3162 ;; retrieved from an external process. Finally call 3163 ;; final-output filter and return result. 3164 (org-no-properties 3165 (org-export-filter-apply-functions 3166 (plist-get info :filter-final-output) 3167 output info))))))))) 3168 3169 ;;;###autoload 3170 (defun org-export-string-as (string backend &optional body-only ext-plist) 3171 "Transcode STRING into BACKEND code. 3172 3173 BACKEND is either an export back-end, as returned by, e.g., 3174 `org-export-create-backend', or a symbol referring to 3175 a registered back-end. 3176 3177 When optional argument BODY-ONLY is non-nil, only return body 3178 code, without preamble nor postamble. 3179 3180 Optional argument EXT-PLIST, when provided, is a property list 3181 with external parameters overriding Org default settings, but 3182 still inferior to file-local settings. 3183 3184 Return code as a string." 3185 (with-temp-buffer 3186 (insert string) 3187 (let ((org-inhibit-startup t)) (org-mode)) 3188 (org-export-as backend nil nil body-only ext-plist))) 3189 3190 ;;;###autoload 3191 (defun org-export-replace-region-by (backend) 3192 "Replace the active region by its export to BACKEND. 3193 BACKEND is either an export back-end, as returned by, e.g., 3194 `org-export-create-backend', or a symbol referring to 3195 a registered back-end." 3196 (unless (org-region-active-p) (user-error "No active region to replace")) 3197 (insert 3198 (org-export-string-as 3199 (delete-and-extract-region (region-beginning) (region-end)) backend t))) 3200 3201 ;;;###autoload 3202 (defun org-export-insert-default-template (&optional backend subtreep) 3203 "Insert all export keywords with default values at beginning of line. 3204 3205 BACKEND is a symbol referring to the name of a registered export 3206 back-end, for which specific export options should be added to 3207 the template, or `default' for default template. When it is nil, 3208 the user will be prompted for a category. 3209 3210 If SUBTREEP is non-nil, export configuration will be set up 3211 locally for the subtree through node properties." 3212 (interactive) 3213 (unless (derived-mode-p 'org-mode) (user-error "Not in an Org mode buffer")) 3214 (when (and subtreep (org-before-first-heading-p)) 3215 (user-error "No subtree to set export options for")) 3216 (let ((node (and subtreep (save-excursion (org-back-to-heading t) (point)))) 3217 (backend 3218 (or backend 3219 (intern 3220 (org-completing-read 3221 "Options category: " 3222 (cons "default" 3223 (mapcar (lambda (b) 3224 (symbol-name (org-export-backend-name b))) 3225 org-export-registered-backends)) 3226 nil t)))) 3227 options keywords) 3228 ;; Populate OPTIONS and KEYWORDS. 3229 (dolist (entry (cond ((eq backend 'default) org-export-options-alist) 3230 ((org-export-backend-p backend) 3231 (org-export-backend-options backend)) 3232 (t (org-export-backend-options 3233 (org-export-get-backend backend))))) 3234 (let ((keyword (nth 1 entry)) 3235 (option (nth 2 entry))) 3236 (cond 3237 (keyword (unless (assoc keyword keywords) 3238 (let ((value 3239 (if (eq (nth 4 entry) 'split) 3240 (mapconcat #'identity (eval (nth 3 entry) t) " ") 3241 (eval (nth 3 entry) t)))) 3242 (push (cons keyword value) keywords)))) 3243 (option (unless (assoc option options) 3244 (push (cons option (eval (nth 3 entry) t)) options)))))) 3245 ;; Move to an appropriate location in order to insert options. 3246 (unless subtreep (beginning-of-line)) 3247 ;; First (multiple) OPTIONS lines. Never go past fill-column. 3248 (when options 3249 (let ((items 3250 (mapcar 3251 (lambda (opt) (format "%s:%S" (car opt) (cdr opt))) 3252 (sort options (lambda (k1 k2) (string< (car k1) (car k2))))))) 3253 (if subtreep 3254 (org-entry-put 3255 node "EXPORT_OPTIONS" (mapconcat #'identity items " ")) 3256 (while items 3257 (insert "#+options:") 3258 (let ((width 10)) 3259 (while (and items 3260 (< (+ width (length (car items)) 1) fill-column)) 3261 (let ((item (pop items))) 3262 (insert " " item) 3263 (cl-incf width (1+ (length item)))))) 3264 (insert "\n"))))) 3265 ;; Then the rest of keywords, in the order specified in either 3266 ;; `org-export-options-alist' or respective export back-ends. 3267 (dolist (key (nreverse keywords)) 3268 (let ((val (cond ((equal (car key) "DATE") 3269 (or (cdr key) 3270 (with-temp-buffer 3271 (org-insert-time-stamp nil)))) 3272 ((equal (car key) "TITLE") 3273 (or (let ((visited-file 3274 (buffer-file-name (buffer-base-buffer)))) 3275 (and visited-file 3276 (file-name-sans-extension 3277 (file-name-nondirectory visited-file)))) 3278 (buffer-name (buffer-base-buffer)))) 3279 (t (cdr key))))) 3280 (if subtreep (org-entry-put node (concat "EXPORT_" (car key)) val) 3281 (insert 3282 (format "#+%s:%s\n" 3283 (downcase (car key)) 3284 (if (org-string-nw-p val) (format " %s" val) "")))))))) 3285 3286 (defun org-export-expand-include-keyword (&optional included dir footnotes) 3287 "Expand every include keyword in buffer. 3288 Optional argument INCLUDED is a list of included file names along 3289 with their line restriction, when appropriate. It is used to 3290 avoid infinite recursion. Optional argument DIR is the current 3291 working directory. It is used to properly resolve relative 3292 paths. Optional argument FOOTNOTES is a hash-table used for 3293 storing and resolving footnotes. It is created automatically." 3294 (let ((includer-file (buffer-file-name (buffer-base-buffer))) 3295 (case-fold-search t) 3296 (file-prefix (make-hash-table :test #'equal)) 3297 (current-prefix 0) 3298 (footnotes (or footnotes (make-hash-table :test #'equal))) 3299 (include-re "^[ \t]*#\\+INCLUDE:")) 3300 ;; If :minlevel is not set the text-property 3301 ;; `:org-include-induced-level' will be used to determine the 3302 ;; relative level when expanding INCLUDE. 3303 ;; Only affects included Org documents. 3304 (goto-char (point-min)) 3305 (while (re-search-forward include-re nil t) 3306 (put-text-property (line-beginning-position) (line-end-position) 3307 :org-include-induced-level 3308 (1+ (org-reduced-level (or (org-current-level) 0))))) 3309 ;; Expand INCLUDE keywords. 3310 (goto-char (point-min)) 3311 (while (re-search-forward include-re nil t) 3312 (unless (org-in-commented-heading-p) 3313 (let ((element (save-match-data (org-element-at-point)))) 3314 (when (eq (org-element-type element) 'keyword) 3315 (beginning-of-line) 3316 ;; Extract arguments from keyword's value. 3317 (let* ((value (org-element-property :value element)) 3318 (ind (org-current-text-indentation)) 3319 location 3320 (coding-system-for-read 3321 (or (and (string-match ":coding +\\(\\S-+\\)>" value) 3322 (prog1 (intern (match-string 1 value)) 3323 (setq value (replace-match "" nil nil value)))) 3324 coding-system-for-read)) 3325 (file 3326 (and (string-match "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" 3327 value) 3328 (prog1 3329 (save-match-data 3330 (let ((matched (match-string 1 value)) 3331 stripped) 3332 (when (string-match "\\(::\\(.*?\\)\\)\"?\\'" 3333 matched) 3334 (setq location (match-string 2 matched)) 3335 (setq matched 3336 (replace-match "" nil nil matched 1))) 3337 (setq stripped (org-strip-quotes matched)) 3338 (if (org-url-p stripped) 3339 stripped 3340 (expand-file-name stripped dir)))) 3341 (setq value (replace-match "" nil nil value))))) 3342 (only-contents 3343 (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?" 3344 value) 3345 (prog1 (org-not-nil (match-string 1 value)) 3346 (setq value (replace-match "" nil nil value))))) 3347 (lines 3348 (and (string-match 3349 ":lines +\"\\([0-9]*-[0-9]*\\)\"" 3350 value) 3351 (prog1 (match-string 1 value) 3352 (setq value (replace-match "" nil nil value))))) 3353 (env (cond 3354 ((string-match "\\<example\\>" value) 'literal) 3355 ((string-match "\\<export\\(?: +\\(.*\\)\\)?" value) 3356 'literal) 3357 ((string-match "\\<src\\(?: +\\(.*\\)\\)?" value) 3358 'literal))) 3359 ;; Minimal level of included file defaults to the 3360 ;; child level of the current headline, if any, or 3361 ;; one. It only applies is the file is meant to be 3362 ;; included as an Org one. 3363 (minlevel 3364 (and (not env) 3365 (if (string-match ":minlevel +\\([0-9]+\\)" value) 3366 (prog1 (string-to-number (match-string 1 value)) 3367 (setq value (replace-match "" nil nil value))) 3368 (get-text-property (point) 3369 :org-include-induced-level)))) 3370 (args (and (eq env 'literal) (match-string 1 value))) 3371 (block (and (string-match "\\<\\(\\S-+\\)\\>" value) 3372 (match-string 1 value)))) 3373 ;; Remove keyword. 3374 (delete-region (point) (line-beginning-position 2)) 3375 (cond 3376 ((not file) nil) 3377 ((and (not (org-url-p file)) (not (file-readable-p file))) 3378 (error "Cannot include file %s" file)) 3379 ;; Check if files has already been parsed. Look after 3380 ;; inclusion lines too, as different parts of the same 3381 ;; file can be included too. 3382 ((member (list file lines) included) 3383 (error "Recursive file inclusion: %s" file)) 3384 (t 3385 (cond 3386 ((eq env 'literal) 3387 (insert 3388 (let ((ind-str (make-string ind ?\s)) 3389 (arg-str (if (stringp args) (format " %s" args) "")) 3390 (contents 3391 (org-escape-code-in-string 3392 (org-export--prepare-file-contents file lines)))) 3393 (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n" 3394 ind-str block arg-str contents ind-str block)))) 3395 ((stringp block) 3396 (insert 3397 (let ((ind-str (make-string ind ?\s)) 3398 (contents 3399 (org-export--prepare-file-contents file lines))) 3400 (format "%s#+BEGIN_%s\n%s%s#+END_%s\n" 3401 ind-str block contents ind-str block)))) 3402 (t 3403 (insert 3404 (with-temp-buffer 3405 (let ((org-inhibit-startup t) 3406 (lines 3407 (if location 3408 (org-export--inclusion-absolute-lines 3409 file location only-contents lines) 3410 lines))) 3411 (org-mode) 3412 (insert 3413 (org-export--prepare-file-contents 3414 file lines ind minlevel 3415 (or (gethash file file-prefix) 3416 (puthash file 3417 (cl-incf current-prefix) 3418 file-prefix)) 3419 footnotes 3420 includer-file))) 3421 (org-export-expand-include-keyword 3422 (cons (list file lines) included) 3423 (unless (org-url-p file) 3424 (file-name-directory file)) 3425 footnotes) 3426 (buffer-string))))) 3427 ;; Expand footnotes after all files have been 3428 ;; included. Footnotes are stored at end of buffer. 3429 (unless included 3430 (org-with-wide-buffer 3431 (goto-char (point-max)) 3432 (maphash (lambda (k v) 3433 (insert (format "\n[fn:%s] %s\n" k v))) 3434 footnotes)))))))))))) 3435 3436 (defun org-export--inclusion-absolute-lines (file location only-contents lines) 3437 "Resolve absolute lines for an included file with file-link. 3438 3439 FILE is string file-name of the file to include. LOCATION is a 3440 string name within FILE to be included (located via 3441 `org-link-search'). If ONLY-CONTENTS is non-nil only the 3442 contents of the named element will be included, as determined 3443 Org-Element. If LINES is non-nil only those lines are included. 3444 3445 Return a string of lines to be included in the format expected by 3446 `org-export--prepare-file-contents'." 3447 (with-temp-buffer 3448 (insert (org-file-contents file)) 3449 (unless (eq major-mode 'org-mode) 3450 (let ((org-inhibit-startup t)) (org-mode))) 3451 (condition-case err 3452 ;; Enforce consistent search. 3453 (let ((org-link-search-must-match-exact-headline nil)) 3454 (org-link-search location)) 3455 (error 3456 (error "%s for %s::%s" (error-message-string err) file location))) 3457 (let* ((element (org-element-at-point)) 3458 (contents-begin 3459 (and only-contents (org-element-property :contents-begin element)))) 3460 (narrow-to-region 3461 (or contents-begin (org-element-property :begin element)) 3462 (org-element-property (if contents-begin :contents-end :end) element)) 3463 (when (and only-contents 3464 (memq (org-element-type element) '(headline inlinetask))) 3465 ;; Skip planning line and property-drawer. 3466 (goto-char (point-min)) 3467 (when (looking-at-p org-planning-line-re) (forward-line)) 3468 (when (looking-at org-property-drawer-re) (goto-char (match-end 0))) 3469 (unless (bolp) (forward-line)) 3470 (narrow-to-region (point) (point-max)))) 3471 (when lines 3472 (org-skip-whitespace) 3473 (beginning-of-line) 3474 (let* ((lines (split-string lines "-")) 3475 (lbeg (string-to-number (car lines))) 3476 (lend (string-to-number (cadr lines))) 3477 (beg (if (zerop lbeg) (point-min) 3478 (goto-char (point-min)) 3479 (forward-line (1- lbeg)) 3480 (point))) 3481 (end (if (zerop lend) (point-max) 3482 (goto-char beg) 3483 (forward-line (1- lend)) 3484 (point)))) 3485 (narrow-to-region beg end))) 3486 (let ((end (point-max))) 3487 (goto-char (point-min)) 3488 (widen) 3489 (let ((start-line (line-number-at-pos))) 3490 (format "%d-%d" 3491 start-line 3492 (save-excursion 3493 (+ start-line 3494 (let ((counter 0)) 3495 (while (< (point) end) (cl-incf counter) (forward-line)) 3496 counter)))))))) 3497 3498 (defun org-export--update-included-link (file-dir includer-dir) 3499 "Update relative file name of link at point, if possible. 3500 3501 FILE-DIR is the directory of the file being included. 3502 INCLUDER-DIR is the directory of the file where the inclusion is 3503 going to happen. 3504 3505 Move point after the link." 3506 (let* ((link (org-element-link-parser)) 3507 (path (org-element-property :path link))) 3508 (if (or (not (string= "file" (org-element-property :type link))) 3509 (file-remote-p path) 3510 (file-name-absolute-p path)) 3511 (goto-char (org-element-property :end link)) 3512 (let ((new-path (file-relative-name (expand-file-name path file-dir) 3513 includer-dir)) 3514 (new-link (org-element-copy link))) 3515 (org-element-put-property new-link :path new-path) 3516 (when (org-element-property :contents-begin link) 3517 (org-element-adopt-elements new-link 3518 (buffer-substring 3519 (org-element-property :contents-begin link) 3520 (org-element-property :contents-end link)))) 3521 (delete-region (org-element-property :begin link) 3522 (org-element-property :end link)) 3523 (insert (org-element-interpret-data new-link)))))) 3524 3525 (defun org-export--prepare-file-contents 3526 (file &optional lines ind minlevel id footnotes includer) 3527 "Prepare contents of FILE for inclusion and return it as a string. 3528 3529 When optional argument LINES is a string specifying a range of 3530 lines, include only those lines. 3531 3532 Optional argument IND, when non-nil, is an integer specifying the 3533 global indentation of returned contents. Since its purpose is to 3534 allow an included file to stay in the same environment it was 3535 created (e.g., a list item), it doesn't apply past the first 3536 headline encountered. 3537 3538 Optional argument MINLEVEL, when non-nil, is an integer 3539 specifying the level that any top-level headline in the included 3540 file should have. 3541 3542 Optional argument ID is an integer that will be inserted before 3543 each footnote definition and reference if FILE is an Org file. 3544 This is useful to avoid conflicts when more than one Org file 3545 with footnotes is included in a document. 3546 3547 Optional argument FOOTNOTES is a hash-table to store footnotes in 3548 the included document. 3549 3550 Optional argument INCLUDER is the file name where the inclusion 3551 is to happen." 3552 (with-temp-buffer 3553 (insert (org-file-contents file)) 3554 (when lines 3555 (let* ((lines (split-string lines "-")) 3556 (lbeg (string-to-number (car lines))) 3557 (lend (string-to-number (cadr lines))) 3558 (beg (if (zerop lbeg) (point-min) 3559 (goto-char (point-min)) 3560 (forward-line (1- lbeg)) 3561 (point))) 3562 (end (if (zerop lend) (point-max) 3563 (goto-char (point-min)) 3564 (forward-line (1- lend)) 3565 (point)))) 3566 (narrow-to-region beg end))) 3567 ;; Adapt all file links within the included document that contain 3568 ;; relative paths in order to make these paths relative to the 3569 ;; base document, or absolute. 3570 (when includer 3571 (let ((file-dir (file-name-directory file)) 3572 (includer-dir (file-name-directory includer))) 3573 (unless (file-equal-p file-dir includer-dir) 3574 (goto-char (point-min)) 3575 (unless (eq major-mode 'org-mode) 3576 (let ((org-inhibit-startup t)) (org-mode))) ;set regexps 3577 (let ((regexp (concat org-link-plain-re "\\|" org-link-angle-re))) 3578 (while (re-search-forward org-link-any-re nil t) 3579 (let ((link (save-excursion 3580 (forward-char -1) 3581 (save-match-data (org-element-context))))) 3582 (when (eq 'link (org-element-type link)) 3583 ;; Look for file links within link's description. 3584 ;; Org doesn't support such construct, but 3585 ;; `org-export-insert-image-links' may activate 3586 ;; them. 3587 (let ((contents-begin 3588 (org-element-property :contents-begin link)) 3589 (begin (org-element-property :begin link))) 3590 (when contents-begin 3591 (save-excursion 3592 (goto-char (org-element-property :contents-end link)) 3593 (while (re-search-backward regexp contents-begin t) 3594 (save-match-data 3595 (org-export--update-included-link 3596 file-dir includer-dir)) 3597 (goto-char (match-beginning 0))))) 3598 ;; Update current link, if necessary. 3599 (when (string= "file" (org-element-property :type link)) 3600 (goto-char begin) 3601 (org-export--update-included-link 3602 file-dir includer-dir)))))))))) 3603 ;; Remove blank lines at beginning and end of contents. The logic 3604 ;; behind that removal is that blank lines around include keyword 3605 ;; override blank lines in included file. 3606 (goto-char (point-min)) 3607 (org-skip-whitespace) 3608 (beginning-of-line) 3609 (delete-region (point-min) (point)) 3610 (goto-char (point-max)) 3611 (skip-chars-backward " \r\t\n") 3612 (forward-line) 3613 (delete-region (point) (point-max)) 3614 ;; If IND is set, preserve indentation of include keyword until 3615 ;; the first headline encountered. 3616 (when (and ind (> ind 0)) 3617 (unless (eq major-mode 'org-mode) 3618 (let ((org-inhibit-startup t)) (org-mode))) 3619 (goto-char (point-min)) 3620 (let ((ind-str (make-string ind ?\s))) 3621 (while (not (or (eobp) (looking-at org-outline-regexp-bol))) 3622 ;; Do not move footnote definitions out of column 0. 3623 (unless (and (looking-at org-footnote-definition-re) 3624 (eq (org-element-type (org-element-at-point)) 3625 'footnote-definition)) 3626 (insert ind-str)) 3627 (forward-line)))) 3628 ;; When MINLEVEL is specified, compute minimal level for headlines 3629 ;; in the file (CUR-MIN), and remove stars to each headline so 3630 ;; that headlines with minimal level have a level of MINLEVEL. 3631 (when minlevel 3632 (unless (eq major-mode 'org-mode) 3633 (let ((org-inhibit-startup t)) (org-mode))) 3634 (org-with-limited-levels 3635 (let ((levels (org-map-entries 3636 (lambda () (org-reduced-level (org-current-level)))))) 3637 (when levels 3638 (let ((offset (- minlevel (apply #'min levels)))) 3639 (unless (zerop offset) 3640 (when org-odd-levels-only (setq offset (* offset 2))) 3641 ;; Only change stars, don't bother moving whole 3642 ;; sections. 3643 (org-map-entries 3644 (lambda () 3645 (if (< offset 0) (delete-char (abs offset)) 3646 (insert (make-string offset ?*))))))))))) 3647 ;; Append ID to all footnote references and definitions, so they 3648 ;; become file specific and cannot collide with footnotes in other 3649 ;; included files. Further, collect relevant footnote definitions 3650 ;; outside of LINES, in order to reintroduce them later. 3651 (when id 3652 (let ((marker-min (point-min-marker)) 3653 (marker-max (point-max-marker)) 3654 (get-new-label 3655 (lambda (label) 3656 ;; Generate new label from LABEL by prefixing it with 3657 ;; "-ID-". 3658 (format "-%d-%s" id label))) 3659 (set-new-label 3660 (lambda (f old new) 3661 ;; Replace OLD label with NEW in footnote F. 3662 (save-excursion 3663 (goto-char (+ (org-element-property :begin f) 4)) 3664 (looking-at (regexp-quote old)) 3665 (replace-match new)))) 3666 (seen-alist)) 3667 (goto-char (point-min)) 3668 (while (re-search-forward org-footnote-re nil t) 3669 (let ((footnote (save-excursion 3670 (backward-char) 3671 (org-element-context)))) 3672 (when (memq (org-element-type footnote) 3673 '(footnote-definition footnote-reference)) 3674 (let* ((label (org-element-property :label footnote))) 3675 ;; Update the footnote-reference at point and collect 3676 ;; the new label, which is only used for footnotes 3677 ;; outsides LINES. 3678 (when label 3679 (let ((seen (cdr (assoc label seen-alist)))) 3680 (if seen (funcall set-new-label footnote label seen) 3681 (let ((new (funcall get-new-label label))) 3682 (push (cons label new) seen-alist) 3683 (org-with-wide-buffer 3684 (let* ((def (org-footnote-get-definition label)) 3685 (beg (nth 1 def))) 3686 (when (and def 3687 (or (< beg marker-min) 3688 (>= beg marker-max))) 3689 ;; Store since footnote-definition is 3690 ;; outside of LINES. 3691 (puthash new 3692 (org-element-normalize-string (nth 3 def)) 3693 footnotes)))) 3694 (funcall set-new-label footnote label new))))))))) 3695 (set-marker marker-min nil) 3696 (set-marker marker-max nil))) 3697 (org-element-normalize-string (buffer-string)))) 3698 3699 (defun org-export--copy-to-kill-ring-p () 3700 "Return a non-nil value when output should be added to the kill ring. 3701 See also `org-export-copy-to-kill-ring'." 3702 (if (eq org-export-copy-to-kill-ring 'if-interactive) 3703 (not (or executing-kbd-macro noninteractive)) 3704 (eq org-export-copy-to-kill-ring t))) 3705 3706 3707 3708 ;;; Tools For Back-Ends 3709 ;; 3710 ;; A whole set of tools is available to help build new exporters. Any 3711 ;; function general enough to have its use across many back-ends 3712 ;; should be added here. 3713 3714 ;;;; For Affiliated Keywords 3715 ;; 3716 ;; `org-export-read-attribute' reads a property from a given element 3717 ;; as a plist. It can be used to normalize affiliated keywords' 3718 ;; syntax. 3719 ;; 3720 ;; Since captions can span over multiple lines and accept dual values, 3721 ;; their internal representation is a bit tricky. Therefore, 3722 ;; `org-export-get-caption' transparently returns a given element's 3723 ;; caption as a secondary string. 3724 3725 (defun org-export-read-attribute (attribute element &optional property) 3726 "Turn ATTRIBUTE property from ELEMENT into a plist. 3727 3728 When optional argument PROPERTY is non-nil, return the value of 3729 that property within attributes. 3730 3731 This function assumes attributes are defined as \":keyword 3732 value\" pairs. It is appropriate for `:attr_html' like 3733 properties. 3734 3735 All values will become strings except the empty string and 3736 \"nil\", which will become nil. Also, values containing only 3737 double quotes will be read as-is, which means that \"\" value 3738 will become the empty string." 3739 (let* ((prepare-value 3740 (lambda (str) 3741 (save-match-data 3742 (cond ((member str '(nil "" "nil")) nil) 3743 ((string-match "^\"\\(\"+\\)?\"$" str) 3744 (or (match-string 1 str) "")) 3745 (t str))))) 3746 (attributes 3747 (let ((value (org-element-property attribute element))) 3748 (when value 3749 (let ((s (mapconcat #'identity value " ")) result) 3750 (while (string-match 3751 "\\(?:^\\|[ \t]+\\)\\(:[-a-zA-Z0-9_]+\\)\\([ \t]+\\|$\\)" 3752 s) 3753 (let ((value (substring s 0 (match-beginning 0)))) 3754 (push (funcall prepare-value value) result)) 3755 (push (intern (match-string 1 s)) result) 3756 (setq s (substring s (match-end 0)))) 3757 ;; Ignore any string before first property with `cdr'. 3758 (cdr (nreverse (cons (funcall prepare-value s) result)))))))) 3759 (if property (plist-get attributes property) attributes))) 3760 3761 (defun org-export-get-caption (element &optional short) 3762 "Return caption from ELEMENT as a secondary string. 3763 3764 When optional argument SHORT is non-nil, return short caption, as 3765 a secondary string, instead. 3766 3767 Caption lines are separated by a white space." 3768 (let ((full-caption (org-element-property :caption element)) 3769 (get (if short #'cdr #'car)) 3770 caption) 3771 (dolist (line full-caption) 3772 (pcase (funcall get line) 3773 (`nil nil) 3774 (c 3775 (setq caption 3776 (nconc (list " ") 3777 (copy-sequence c) caption))))) 3778 (cdr caption))) 3779 3780 3781 ;;;; For Derived Back-ends 3782 ;; 3783 ;; `org-export-with-backend' is a function allowing to locally use 3784 ;; another back-end to transcode some object or element. In a derived 3785 ;; back-end, it may be used as a fall-back function once all specific 3786 ;; cases have been treated. 3787 3788 (defun org-export-with-backend (backend data &optional contents info) 3789 "Call a transcoder from BACKEND on DATA. 3790 BACKEND is an export back-end, as returned by, e.g., 3791 `org-export-create-backend', or a symbol referring to 3792 a registered back-end. DATA is an Org element, object, secondary 3793 string or string. CONTENTS, when non-nil, is the transcoded 3794 contents of DATA element, as a string. INFO, when non-nil, is 3795 the communication channel used for export, as a plist." 3796 (when (symbolp backend) (setq backend (org-export-get-backend backend))) 3797 (org-export-barf-if-invalid-backend backend) 3798 (let ((type (org-element-type data))) 3799 (when (memq type '(nil org-data raw)) 3800 (error "No foreign transcoder available")) 3801 (let* ((all-transcoders (org-export-get-all-transcoders backend)) 3802 (transcoder (cdr (assq type all-transcoders)))) 3803 (unless (functionp transcoder) (error "No foreign transcoder available")) 3804 (let ((new-info 3805 (org-combine-plists 3806 info (list 3807 :back-end backend 3808 :translate-alist all-transcoders 3809 :exported-data (make-hash-table :test #'eq :size 401))))) 3810 ;; `:internal-references' are shared across back-ends. 3811 (prog1 (if (eq type 'plain-text) 3812 (funcall transcoder data new-info) 3813 (funcall transcoder data contents new-info)) 3814 (plist-put info :internal-references 3815 (plist-get new-info :internal-references))))))) 3816 3817 3818 ;;;; For Export Snippets 3819 ;; 3820 ;; Every export snippet is transmitted to the back-end. Though, the 3821 ;; latter will only retain one type of export-snippet, ignoring 3822 ;; others, based on the former's target back-end. The function 3823 ;; `org-export-snippet-backend' returns that back-end for a given 3824 ;; export-snippet. 3825 3826 (defun org-export-snippet-backend (export-snippet) 3827 "Return EXPORT-SNIPPET targeted back-end as a symbol. 3828 Translation, with `org-export-snippet-translation-alist', is 3829 applied." 3830 (let ((back-end (org-element-property :back-end export-snippet))) 3831 (intern 3832 (or (cdr (assoc back-end org-export-snippet-translation-alist)) 3833 back-end)))) 3834 3835 3836 ;;;; For Footnotes 3837 ;; 3838 ;; `org-export-collect-footnote-definitions' is a tool to list 3839 ;; actually used footnotes definitions in the whole parse tree, or in 3840 ;; a headline, in order to add footnote listings throughout the 3841 ;; transcoded data. 3842 ;; 3843 ;; `org-export-footnote-first-reference-p' is a predicate used by some 3844 ;; back-ends, when they need to attach the footnote definition only to 3845 ;; the first occurrence of the corresponding label. 3846 ;; 3847 ;; `org-export-get-footnote-definition' and 3848 ;; `org-export-get-footnote-number' provide easier access to 3849 ;; additional information relative to a footnote reference. 3850 3851 (defun org-export-get-footnote-definition (footnote-reference info) 3852 "Return definition of FOOTNOTE-REFERENCE as parsed data. 3853 INFO is the plist used as a communication channel. If no such 3854 definition can be found, raise an error." 3855 (let ((label (org-element-property :label footnote-reference))) 3856 (if (not label) (org-element-contents footnote-reference) 3857 (let ((cache (or (plist-get info :footnote-definition-cache) 3858 (let ((hash (make-hash-table :test #'equal))) 3859 ;; Cache all the footnotes in document for 3860 ;; later search. 3861 (org-element-map (plist-get info :parse-tree) 3862 '(footnote-definition footnote-reference) 3863 (lambda (f) 3864 ;; Skip any standard footnote reference 3865 ;; since those cannot contain a 3866 ;; definition. 3867 (unless (eq (org-element-property :type f) 'standard) 3868 (puthash 3869 (cons :element (org-element-property :label f)) 3870 f 3871 hash))) 3872 info) 3873 (plist-put info :footnote-definition-cache hash) 3874 hash)))) 3875 (or 3876 (gethash label cache) 3877 (puthash label 3878 (let ((hashed (gethash (cons :element label) cache))) 3879 (when hashed 3880 (or (org-element-contents hashed) 3881 ;; Even if the contents are empty, we can not 3882 ;; return nil since that would eventually raise 3883 ;; the error. Instead, return the equivalent 3884 ;; empty string. 3885 ""))) 3886 cache) 3887 (error "Definition not found for footnote %s" label)))))) 3888 3889 (defun org-export--footnote-reference-map 3890 (function data info &optional body-first) 3891 "Apply FUNCTION on every footnote reference in DATA. 3892 INFO is a plist containing export state. By default, as soon as 3893 a new footnote reference is encountered, FUNCTION is called onto 3894 its definition. However, if BODY-FIRST is non-nil, this step is 3895 delayed until the end of the process." 3896 (letrec ((definitions nil) 3897 (seen-refs nil) 3898 (search-ref 3899 (lambda (data delayp) 3900 ;; Search footnote references through DATA, filling 3901 ;; SEEN-REFS along the way. When DELAYP is non-nil, 3902 ;; store footnote definitions so they can be entered 3903 ;; later. 3904 (org-element-map data 'footnote-reference 3905 (lambda (f) 3906 (funcall function f) 3907 (let ((--label (org-element-property :label f))) 3908 (unless (and --label (member --label seen-refs)) 3909 (when --label (push --label seen-refs)) 3910 ;; Search for subsequent references in footnote 3911 ;; definition so numbering follows reading 3912 ;; logic, unless DELAYP in non-nil. 3913 (cond 3914 (delayp 3915 (push (org-export-get-footnote-definition f info) 3916 definitions)) 3917 ;; Do not force entering inline definitions, 3918 ;; since `org-element-map' already traverses 3919 ;; them at the right time. 3920 ((eq (org-element-property :type f) 'inline)) 3921 (t (funcall search-ref 3922 (org-export-get-footnote-definition f info) 3923 nil)))))) 3924 info nil 3925 ;; Don't enter footnote definitions since it will 3926 ;; happen when their first reference is found. 3927 ;; Moreover, if DELAYP is non-nil, make sure we 3928 ;; postpone entering definitions of inline references. 3929 (if delayp '(footnote-definition footnote-reference) 3930 'footnote-definition))))) 3931 (funcall search-ref data body-first) 3932 (funcall search-ref (nreverse definitions) nil))) 3933 3934 (defun org-export-collect-footnote-definitions (info &optional data body-first) 3935 "Return an alist between footnote numbers, labels and definitions. 3936 3937 INFO is the current export state, as a plist. 3938 3939 Definitions are collected throughout the whole parse tree, or 3940 DATA when non-nil. 3941 3942 Sorting is done by order of references. As soon as a new 3943 reference is encountered, other references are searched within 3944 its definition. However, if BODY-FIRST is non-nil, this step is 3945 delayed after the whole tree is checked. This alters results 3946 when references are found in footnote definitions. 3947 3948 Definitions either appear as Org data or as a secondary string 3949 for inlined footnotes. Unreferenced definitions are ignored." 3950 (let ((n 0) labels alist) 3951 (org-export--footnote-reference-map 3952 (lambda (f) 3953 ;; Collect footnote number, label and definition. 3954 (let ((l (org-element-property :label f))) 3955 (unless (and l (member l labels)) 3956 (cl-incf n) 3957 (push (list n l (org-export-get-footnote-definition f info)) alist)) 3958 (when l (push l labels)))) 3959 (or data (plist-get info :parse-tree)) info body-first) 3960 (nreverse alist))) 3961 3962 (defun org-export-footnote-first-reference-p 3963 (footnote-reference info &optional data body-first) 3964 "Non-nil when a footnote reference is the first one for its label. 3965 3966 FOOTNOTE-REFERENCE is the footnote reference being considered. 3967 INFO is a plist containing current export state. 3968 3969 Search is done throughout the whole parse tree, or DATA when 3970 non-nil. 3971 3972 By default, as soon as a new footnote reference is encountered, 3973 other references are searched within its definition. However, if 3974 BODY-FIRST is non-nil, this step is delayed after the whole tree 3975 is checked. This alters results when references are found in 3976 footnote definitions." 3977 (let ((label (org-element-property :label footnote-reference))) 3978 ;; Anonymous footnotes are always a first reference. 3979 (or (not label) 3980 (catch 'exit 3981 (org-export--footnote-reference-map 3982 (lambda (f) 3983 (let ((l (org-element-property :label f))) 3984 (when (and l label (string= label l)) 3985 (throw 'exit (eq footnote-reference f))))) 3986 (or data (plist-get info :parse-tree)) info body-first))))) 3987 3988 (defun org-export-get-footnote-number (footnote info &optional data body-first) 3989 "Return number associated to a footnote. 3990 3991 FOOTNOTE is either a footnote reference or a footnote definition. 3992 INFO is the plist containing export state. 3993 3994 Number is unique throughout the whole parse tree, or DATA, when 3995 non-nil. 3996 3997 By default, as soon as a new footnote reference is encountered, 3998 counting process moves into its definition. However, if 3999 BODY-FIRST is non-nil, this step is delayed until the end of the 4000 process, leading to a different order when footnotes are nested." 4001 (let ((count 0) 4002 (seen) 4003 (label (org-element-property :label footnote))) 4004 (catch 'exit 4005 (org-export--footnote-reference-map 4006 (lambda (f) 4007 (let ((l (org-element-property :label f))) 4008 (cond 4009 ;; Anonymous footnote match: return number. 4010 ((and (not l) (not label) (eq footnote f)) (throw 'exit (1+ count))) 4011 ;; Labels match: return number. 4012 ((and label l (string= label l)) (throw 'exit (1+ count))) 4013 ;; Otherwise store label and increase counter if label 4014 ;; wasn't encountered yet. 4015 ((not l) (cl-incf count)) 4016 ((not (member l seen)) (push l seen) (cl-incf count))))) 4017 (or data (plist-get info :parse-tree)) info body-first)))) 4018 4019 4020 ;;;; For Headlines 4021 ;; 4022 ;; `org-export-get-relative-level' is a shortcut to get headline 4023 ;; level, relatively to the lower headline level in the parsed tree. 4024 ;; 4025 ;; `org-export-get-headline-number' returns the section number of an 4026 ;; headline, while `org-export-number-to-roman' allows it to be 4027 ;; converted to roman numbers. With an optional argument, 4028 ;; `org-export-get-headline-number' returns a number to unnumbered 4029 ;; headlines (used for internal id). 4030 ;; 4031 ;; `org-export-low-level-p', `org-export-first-sibling-p' and 4032 ;; `org-export-last-sibling-p' are three useful predicates when it 4033 ;; comes to fulfill the `:headline-levels' property. 4034 ;; 4035 ;; `org-export-get-tags', `org-export-get-category' and 4036 ;; `org-export-get-node-property' extract useful information from an 4037 ;; headline or a parent headline. They all handle inheritance. 4038 ;; 4039 ;; `org-export-get-alt-title' tries to retrieve an alternative title, 4040 ;; as a secondary string, suitable for table of contents. It falls 4041 ;; back onto default title. 4042 4043 (defun org-export-get-relative-level (headline info) 4044 "Return HEADLINE relative level within current parsed tree. 4045 INFO is a plist holding contextual information." 4046 (+ (org-element-property :level headline) 4047 (or (plist-get info :headline-offset) 0))) 4048 4049 (defun org-export-low-level-p (headline info) 4050 "Non-nil when HEADLINE is considered as low level. 4051 4052 INFO is a plist used as a communication channel. 4053 4054 A low level headlines has a relative level greater than 4055 `:headline-levels' property value. 4056 4057 Return value is the difference between HEADLINE relative level 4058 and the last level being considered as high enough, or nil." 4059 (let ((limit (plist-get info :headline-levels))) 4060 (when (wholenump limit) 4061 (let ((level (org-export-get-relative-level headline info))) 4062 (and (> level limit) (- level limit)))))) 4063 4064 (defun org-export-get-headline-number (headline info) 4065 "Return numbered HEADLINE numbering as a list of numbers. 4066 INFO is a plist holding contextual information." 4067 (and (org-export-numbered-headline-p headline info) 4068 (cdr (assq headline (plist-get info :headline-numbering))))) 4069 4070 (defun org-export-numbered-headline-p (headline info) 4071 "Return a non-nil value if HEADLINE element should be numbered. 4072 INFO is a plist used as a communication channel." 4073 (unless (org-not-nil (org-export-get-node-property :UNNUMBERED headline t)) 4074 (let ((sec-num (plist-get info :section-numbers)) 4075 (level (org-export-get-relative-level headline info))) 4076 (if (wholenump sec-num) (<= level sec-num) sec-num)))) 4077 4078 (defun org-export-number-to-roman (n) 4079 "Convert integer N into a roman numeral." 4080 (let ((roman '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD") 4081 ( 100 . "C") ( 90 . "XC") ( 50 . "L") ( 40 . "XL") 4082 ( 10 . "X") ( 9 . "IX") ( 5 . "V") ( 4 . "IV") 4083 ( 1 . "I"))) 4084 (res "")) 4085 (if (<= n 0) 4086 (number-to-string n) 4087 (while roman 4088 (if (>= n (caar roman)) 4089 (setq n (- n (caar roman)) 4090 res (concat res (cdar roman))) 4091 (pop roman))) 4092 res))) 4093 4094 (defun org-export-get-tags (element info &optional tags inherited) 4095 "Return list of tags associated to ELEMENT. 4096 4097 ELEMENT has either an `headline' or an `inlinetask' type. INFO 4098 is a plist used as a communication channel. 4099 4100 When non-nil, optional argument TAGS should be a list of strings. 4101 Any tag belonging to this list will also be removed. 4102 4103 When optional argument INHERITED is non-nil, tags can also be 4104 inherited from parent headlines and FILETAGS keywords." 4105 (cl-remove-if 4106 (lambda (tag) (member tag tags)) 4107 (if (not inherited) (org-element-property :tags element) 4108 ;; Build complete list of inherited tags. 4109 (let ((current-tag-list (org-element-property :tags element))) 4110 (dolist (parent (org-element-lineage element)) 4111 (dolist (tag (org-element-property :tags parent)) 4112 (when (and (memq (org-element-type parent) '(headline inlinetask)) 4113 (not (member tag current-tag-list))) 4114 (push tag current-tag-list)))) 4115 ;; Add FILETAGS keywords and return results. 4116 (org-uniquify (append (plist-get info :filetags) current-tag-list)))))) 4117 4118 (defun org-export-get-node-property (property datum &optional inherited) 4119 "Return node PROPERTY value for DATUM. 4120 4121 PROPERTY is an upcase symbol (e.g., `:COOKIE_DATA'). DATUM is an 4122 element or object. 4123 4124 If optional argument INHERITED is non-nil, the value can be 4125 inherited from a parent headline. 4126 4127 Return value is a string or nil." 4128 (let ((headline (if (eq (org-element-type datum) 'headline) datum 4129 (org-export-get-parent-headline datum)))) 4130 (if (not inherited) (org-element-property property datum) 4131 (let ((parent headline)) 4132 (catch 'found 4133 (while parent 4134 (when (plist-member (nth 1 parent) property) 4135 (throw 'found (org-element-property property parent))) 4136 (setq parent (org-element-property :parent parent)))))))) 4137 4138 (defun org-export-get-category (blob info) 4139 "Return category for element or object BLOB. 4140 4141 INFO is a plist used as a communication channel. 4142 4143 CATEGORY is automatically inherited from a parent headline, from 4144 #+CATEGORY: keyword or created out of original file name. If all 4145 fail, the fall-back value is \"???\"." 4146 (or (org-export-get-node-property :CATEGORY blob t) 4147 (org-element-map (plist-get info :parse-tree) 'keyword 4148 (lambda (kwd) 4149 (when (equal (org-element-property :key kwd) "CATEGORY") 4150 (org-element-property :value kwd))) 4151 info 'first-match) 4152 (let ((file (plist-get info :input-file))) 4153 (and file (file-name-sans-extension (file-name-nondirectory file)))) 4154 "???")) 4155 4156 (defun org-export-get-alt-title (headline _) 4157 "Return alternative title for HEADLINE, as a secondary string. 4158 If no optional title is defined, fall-back to the regular title." 4159 (let ((alt (org-element-property :ALT_TITLE headline))) 4160 (if alt (org-element-parse-secondary-string 4161 alt (org-element-restriction 'headline) headline) 4162 (org-element-property :title headline)))) 4163 4164 (defun org-export-first-sibling-p (blob info) 4165 "Non-nil when BLOB is the first sibling in its parent. 4166 BLOB is an element or an object. If BLOB is a headline, non-nil 4167 means it is the first sibling in the sub-tree. INFO is a plist 4168 used as a communication channel." 4169 (memq (org-element-type (org-export-get-previous-element blob info)) 4170 '(nil section))) 4171 4172 (defun org-export-last-sibling-p (datum info) 4173 "Non-nil when DATUM is the last sibling in its parent. 4174 DATUM is an element or an object. INFO is a plist used as 4175 a communication channel." 4176 (let ((next (org-export-get-next-element datum info))) 4177 (or (not next) 4178 (and (eq 'headline (org-element-type datum)) 4179 (> (org-element-property :level datum) 4180 (org-element-property :level next)))))) 4181 4182 4183 ;;;; For Keywords 4184 ;; 4185 ;; `org-export-get-date' returns a date appropriate for the document 4186 ;; to about to be exported. In particular, it takes care of 4187 ;; `org-export-date-timestamp-format'. 4188 4189 (defun org-export-get-date (info &optional fmt) 4190 "Return date value for the current document. 4191 4192 INFO is a plist used as a communication channel. FMT, when 4193 non-nil, is a time format string that will be applied on the date 4194 if it consists in a single timestamp object. It defaults to 4195 `org-export-date-timestamp-format' when nil. 4196 4197 A proper date can be a secondary string, a string or nil. It is 4198 meant to be translated with `org-export-data' or alike." 4199 (let ((date (plist-get info :date)) 4200 (fmt (or fmt org-export-date-timestamp-format))) 4201 (cond ((not date) nil) 4202 ((and fmt 4203 (not (cdr date)) 4204 (eq (org-element-type (car date)) 'timestamp)) 4205 (org-format-timestamp (car date) fmt)) 4206 (t date)))) 4207 4208 4209 ;;;; For Links 4210 ;; 4211 ;; `org-export-custom-protocol-maybe' handles custom protocol defined 4212 ;; in `org-link-parameters'. 4213 ;; 4214 ;; `org-export-get-coderef-format' returns an appropriate format 4215 ;; string for coderefs. 4216 ;; 4217 ;; `org-export-inline-image-p' returns a non-nil value when the link 4218 ;; provided should be considered as an inline image. 4219 ;; 4220 ;; `org-export-resolve-fuzzy-link' searches destination of fuzzy links 4221 ;; (i.e. links with "fuzzy" as type) within the parsed tree, and 4222 ;; returns an appropriate unique identifier. 4223 ;; 4224 ;; `org-export-resolve-id-link' returns the first headline with 4225 ;; specified id or custom-id in parse tree, the path to the external 4226 ;; file with the id. 4227 ;; 4228 ;; `org-export-resolve-link' searches for the destination of a link 4229 ;; within the parsed tree and returns the element. 4230 ;; 4231 ;; `org-export-resolve-coderef' associates a reference to a line 4232 ;; number in the element it belongs, or returns the reference itself 4233 ;; when the element isn't numbered. 4234 ;; 4235 ;; `org-export-file-uri' expands a filename as stored in :path value 4236 ;; of a "file" link into a file URI. 4237 ;; 4238 ;; Broken links raise a `org-link-broken' error, which is caught by 4239 ;; `org-export-data' for further processing, depending on 4240 ;; `org-export-with-broken-links' value. 4241 4242 (define-error 'org-link-broken "Unable to resolve link; aborting") 4243 4244 (defun org-export-custom-protocol-maybe (link desc backend &optional info) 4245 "Try exporting LINK object with a dedicated function. 4246 4247 DESC is its description, as a string, or nil. BACKEND is the 4248 back-end used for export, as a symbol. 4249 4250 Return output as a string, or nil if no protocol handles LINK. 4251 4252 A custom protocol has precedence over regular back-end export. 4253 The function ignores links with an implicit type (e.g., 4254 \"custom-id\")." 4255 (let ((type (org-element-property :type link))) 4256 (unless (or (member type '("coderef" "custom-id" "fuzzy" "radio" nil)) 4257 (not backend)) 4258 (let ((protocol (org-link-get-parameter type :export)) 4259 (path (org-element-property :path link))) 4260 (and (functionp protocol) 4261 (condition-case nil 4262 (funcall protocol path desc backend info) 4263 ;; XXX: The function used (< Org 9.4) to accept only 4264 ;; three mandatory arguments. Type-specific `:export' 4265 ;; functions in the wild may not handle current 4266 ;; signature. Provide backward compatibility support 4267 ;; for them. 4268 (wrong-number-of-arguments 4269 (funcall protocol path desc backend)))))))) 4270 4271 (defun org-export-get-coderef-format (path desc) 4272 "Return format string for code reference link. 4273 PATH is the link path. DESC is its description." 4274 (save-match-data 4275 (cond ((not desc) "%s") 4276 ((string-match (regexp-quote (concat "(" path ")")) desc) 4277 (replace-match "%s" t t desc)) 4278 (t desc)))) 4279 4280 (defun org-export-inline-image-p (link &optional rules) 4281 "Non-nil if LINK object points to an inline image. 4282 4283 Optional argument is a set of RULES defining inline images. It 4284 is an alist where associations have the following shape: 4285 4286 (TYPE . REGEXP) 4287 4288 Applying a rule means apply REGEXP against LINK's path when its 4289 type is TYPE. The function will return a non-nil value if any of 4290 the provided rules is non-nil. The default rule is 4291 `org-export-default-inline-image-rule'. 4292 4293 This only applies to links without a description." 4294 (and (not (org-element-contents link)) 4295 (let ((case-fold-search t)) 4296 (cl-some (lambda (rule) 4297 (and (string= (org-element-property :type link) (car rule)) 4298 (string-match-p (cdr rule) 4299 (org-element-property :path link)))) 4300 (or rules org-export-default-inline-image-rule))))) 4301 4302 (defun org-export-insert-image-links (data info &optional rules) 4303 "Insert image links in DATA. 4304 4305 Org syntax does not support nested links. Nevertheless, some 4306 export back-ends support images as descriptions of links. Since 4307 images are really links to image files, we need to make an 4308 exception about links nesting. 4309 4310 This function recognizes links whose contents are really images 4311 and turn them into proper nested links. It is meant to be used 4312 as a parse tree filter in back-ends supporting such constructs. 4313 4314 DATA is a parse tree. INFO is the current state of the export 4315 process, as a plist. 4316 4317 A description is a valid images if it matches any rule in RULES, 4318 if non-nil, or `org-export-default-inline-image-rule' otherwise. 4319 See `org-export-inline-image-p' for more information about the 4320 structure of RULES. 4321 4322 Return modified DATA." 4323 (let ((link-re (format "\\`\\(?:%s\\|%s\\)\\'" 4324 org-link-plain-re 4325 org-link-angle-re)) 4326 (case-fold-search t)) 4327 (org-element-map data 'link 4328 (lambda (l) 4329 (let ((contents (org-element-interpret-data (org-element-contents l)))) 4330 (when (and (org-string-nw-p contents) 4331 (string-match link-re contents)) 4332 (let ((type (match-string 1 contents)) 4333 (path (match-string 2 contents))) 4334 (when (cl-some (lambda (rule) 4335 (and (string= type (car rule)) 4336 (string-match-p (cdr rule) path))) 4337 (or rules org-export-default-inline-image-rule)) 4338 ;; Replace contents with image link. 4339 (org-element-adopt-elements 4340 (org-element-set-contents l nil) 4341 (with-temp-buffer 4342 (save-excursion (insert contents)) 4343 (org-element-link-parser)))))))) 4344 info nil nil t)) 4345 data) 4346 4347 (defun org-export-resolve-coderef (ref info) 4348 "Resolve a code reference REF. 4349 4350 INFO is a plist used as a communication channel. 4351 4352 Return associated line number in source code, or REF itself, 4353 depending on src-block or example element's switches. Throw an 4354 error if no block contains REF." 4355 (or (org-element-map (plist-get info :parse-tree) '(example-block src-block) 4356 (lambda (el) 4357 (with-temp-buffer 4358 (insert (org-trim (org-element-property :value el))) 4359 (let* ((label-fmt (or (org-element-property :label-fmt el) 4360 org-coderef-label-format)) 4361 (ref-re (org-src-coderef-regexp label-fmt ref))) 4362 ;; Element containing REF is found. Resolve it to 4363 ;; either a label or a line number, as needed. 4364 (when (re-search-backward ref-re nil t) 4365 (if (org-element-property :use-labels el) ref 4366 (+ (or (org-export-get-loc el info) 0) 4367 (line-number-at-pos))))))) 4368 info 'first-match) 4369 (signal 'org-link-broken (list ref)))) 4370 4371 (defun org-export-search-cells (datum) 4372 "List search cells for element or object DATUM. 4373 4374 A search cell follows the pattern (TYPE . SEARCH) where 4375 4376 TYPE is a symbol among `headline', `custom-id', `target' and 4377 `other'. 4378 4379 SEARCH is the string a link is expected to match. More 4380 accurately, it is 4381 4382 - headline's title, as a list of strings, if TYPE is 4383 `headline'. 4384 4385 - CUSTOM_ID value, as a string, if TYPE is `custom-id'. 4386 4387 - target's or radio-target's name as a list of strings if 4388 TYPE is `target'. 4389 4390 - NAME or RESULTS affiliated keyword if TYPE is `other'. 4391 4392 A search cell is the internal representation of a fuzzy link. It 4393 ignores white spaces and statistics cookies, if applicable." 4394 (pcase (org-element-type datum) 4395 (`headline 4396 (let ((title (split-string 4397 (replace-regexp-in-string 4398 "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" " " 4399 (org-element-property :raw-value datum))))) 4400 (delq nil 4401 (list 4402 (cons 'headline title) 4403 (cons 'other title) 4404 (let ((custom-id (org-element-property :custom-id datum))) 4405 (and custom-id (cons 'custom-id custom-id))))))) 4406 (`target 4407 (list (cons 'target (split-string (org-element-property :value datum))))) 4408 ((and (let name (or (org-element-property :name datum) 4409 (car (org-element-property :results datum)))) 4410 (guard name)) 4411 (list (cons 'other (split-string name)))) 4412 (_ nil))) 4413 4414 (defun org-export-string-to-search-cell (s) 4415 "Return search cells associated to string S. 4416 S is either the path of a fuzzy link or a search option, i.e., it 4417 tries to match either a headline (through custom ID or title), 4418 a target or a named element." 4419 (pcase (string-to-char s) 4420 (?* (list (cons 'headline (split-string (substring s 1))))) 4421 (?# (list (cons 'custom-id (substring s 1)))) 4422 ((let search (split-string s)) 4423 (list (cons 'target search) (cons 'other search))))) 4424 4425 (defun org-export-match-search-cell-p (datum cells) 4426 "Non-nil when DATUM matches search cells CELLS. 4427 DATUM is an element or object. CELLS is a list of search cells, 4428 as returned by `org-export-search-cells'." 4429 (let ((targets (org-export-search-cells datum))) 4430 (and targets (cl-some (lambda (cell) (member cell targets)) cells)))) 4431 4432 (defun org-export-resolve-fuzzy-link (link info &rest pseudo-types) 4433 "Return LINK destination. 4434 4435 INFO is a plist holding contextual information. 4436 4437 Return value can be an object or an element: 4438 4439 - If LINK path matches a target object (i.e. <<path>>) return it. 4440 4441 - If LINK path exactly matches the name or results affiliated keyword 4442 (i.e. #+NAME: path or #+RESULTS: name) of an element, return that 4443 element. 4444 4445 - If LINK path exactly matches any headline name, return that 4446 element. 4447 4448 - Otherwise, throw an error. 4449 4450 PSEUDO-TYPES are pseudo-elements types, i.e., elements defined 4451 specifically in an export back-end, that could have a name 4452 affiliated keyword. 4453 4454 Assume LINK type is \"fuzzy\". White spaces are not 4455 significant." 4456 (let* ((search-cells (org-export-string-to-search-cell 4457 (org-element-property :path link))) 4458 (link-cache (or (plist-get info :resolve-fuzzy-link-cache) 4459 (let ((table (make-hash-table :test #'equal))) 4460 ;; Cache all the element search cells. 4461 (org-element-map (plist-get info :parse-tree) 4462 (append pseudo-types '(target) org-element-all-elements) 4463 (lambda (datum) 4464 (dolist (cell (org-export-search-cells datum)) 4465 (if (gethash cell table) 4466 (push datum (gethash cell table)) 4467 (puthash cell (list datum) table))))) 4468 (plist-put info :resolve-fuzzy-link-cache table) 4469 table))) 4470 (cached (gethash search-cells link-cache 'not-found))) 4471 (if (not (eq cached 'not-found)) cached 4472 (let ((matches 4473 (let (result) 4474 (dolist (search-cell search-cells) 4475 (setq result 4476 (nconc 4477 result 4478 (gethash search-cell link-cache)))) 4479 (delq nil result)))) 4480 (unless matches 4481 (signal 'org-link-broken (list (org-element-property :path link)))) 4482 (puthash 4483 search-cells 4484 ;; There can be multiple matches for un-typed searches, i.e., 4485 ;; for searches not starting with # or *. In this case, 4486 ;; prioritize targets and names over headline titles. 4487 ;; Matching both a name and a target is not valid, and 4488 ;; therefore undefined. 4489 (or (cl-some (lambda (datum) 4490 (and (not (eq (org-element-type datum) 'headline)) 4491 datum)) 4492 matches) 4493 (car matches)) 4494 link-cache))))) 4495 4496 (defun org-export-resolve-id-link (link info) 4497 "Return headline referenced as LINK destination. 4498 4499 INFO is a plist used as a communication channel. 4500 4501 Return value can be the headline element matched in current parse 4502 tree or a file name. Assume LINK type is either \"id\" or 4503 \"custom-id\". Throw an error if no match is found." 4504 (let ((id (org-element-property :path link))) 4505 ;; First check if id is within the current parse tree. 4506 (or (let ((local-ids (or (plist-get info :id-local-cache) 4507 (let ((table (make-hash-table :test #'equal))) 4508 (org-element-map 4509 (plist-get info :parse-tree) 4510 'headline 4511 (lambda (headline) 4512 (let ((id (org-element-property :ID headline)) 4513 (custom-id (org-element-property :CUSTOM_ID headline))) 4514 (when id 4515 (unless (gethash id table) 4516 (puthash id headline table))) 4517 (when custom-id 4518 (unless (gethash custom-id table) 4519 (puthash custom-id headline table))))) 4520 info) 4521 (plist-put info :id-local-cache table) 4522 table)))) 4523 (gethash id local-ids)) 4524 ;; Otherwise, look for external files. 4525 (cdr (assoc id (plist-get info :id-alist))) 4526 (signal 'org-link-broken (list id))))) 4527 4528 (defun org-export-resolve-radio-link (link info) 4529 "Return radio-target object referenced as LINK destination. 4530 4531 INFO is a plist used as a communication channel. 4532 4533 Return value can be a radio-target object or nil. Assume LINK 4534 has type \"radio\"." 4535 (let ((path (org-string-clean-whitespace (org-element-property :path link)))) 4536 (org-element-map (plist-get info :parse-tree) 'radio-target 4537 (lambda (radio) 4538 (and (org-string-equal-ignore-case 4539 (org-string-clean-whitespace (org-element-property :value radio)) 4540 path) 4541 radio)) 4542 info 'first-match))) 4543 4544 (defun org-export-resolve-link (link info) 4545 "Return LINK destination. 4546 4547 LINK is a string or a link object. 4548 4549 INFO is a plist holding contextual information. 4550 4551 Return value can be an object or an element: 4552 4553 - If LINK path matches an ID or a custom ID, return the headline. 4554 4555 - If LINK path matches a fuzzy link, return its destination. 4556 4557 - Otherwise, throw an error." 4558 ;; Convert string links to link objects. 4559 (when (stringp link) 4560 (setq link (with-temp-buffer 4561 (save-excursion 4562 (insert (org-link-make-string link))) 4563 (org-element-link-parser)))) 4564 (pcase (org-element-property :type link) 4565 ((or "custom-id" "id") (org-export-resolve-id-link link info)) 4566 ("fuzzy" (org-export-resolve-fuzzy-link link info)) 4567 (_ (signal 'org-link-broken (list (org-element-property :path link)))))) 4568 4569 (defun org-export-file-uri (filename) 4570 "Return file URI associated to FILENAME." 4571 (cond ((string-prefix-p "//" filename) (concat "file:" filename)) 4572 ((not (file-name-absolute-p filename)) filename) 4573 ((file-remote-p filename) (concat "file:/" filename)) 4574 (t 4575 (let ((fullname (expand-file-name filename))) 4576 (concat (if (string-prefix-p "/" fullname) "file://" "file:///") 4577 fullname))))) 4578 4579 (defun org-export-link-remote-p (link) 4580 "Returns non-nil if the link refers to a remote resource." 4581 (or (member (org-element-property :type link) '("http" "https" "ftp")) 4582 (and (string= (org-element-property :type link) "file") 4583 (file-remote-p (org-element-property :path link))))) 4584 4585 (defun org-export-link--remote-local-copy (link) 4586 "Download the remote resource specified by LINK, and return its local path." 4587 ;; TODO work this into ol.el as a link parameter, say :download. 4588 (let* ((location-type 4589 (pcase (org-element-property :type link) 4590 ((or "http" "https" "ftp") 'url) 4591 ((and "file" (guard (file-remote-p 4592 (org-element-property :path link)))) 4593 'file) 4594 (_ (error "Cannot copy %s:%s to a local file" 4595 (org-element-property :type link) 4596 (org-element-property :path link))))) 4597 (path 4598 (pcase location-type 4599 ('url 4600 (concat (org-element-property :type link) 4601 ":" (org-element-property :path link))) 4602 ('file 4603 (org-element-property :path link))))) 4604 (or (org-persist-read location-type path) 4605 (org-persist-register location-type path 4606 :write-immediately t)))) 4607 4608 (require 'subr-x) ;; FIXME: For `thread-first' in Emacs 26. 4609 (defun org-export-link-localise (link) 4610 "Convert remote LINK to local link. 4611 If LINK refers to a remote resource, modify it to point to a local 4612 downloaded copy. Otherwise, return unchanged LINK." 4613 (when (org-export-link-remote-p link) 4614 (let* ((local-path (org-export-link--remote-local-copy link))) 4615 (if local-path 4616 (setcdr link 4617 (thread-first (cadr link) 4618 (plist-put :type "file") 4619 (plist-put :path local-path) 4620 (plist-put :raw-link (concat "file:" local-path)) 4621 list)) 4622 (display-warning 4623 '(org export) 4624 (format "unable to obtain local copy of %s" 4625 (org-element-property :raw-link link)))))) 4626 link) 4627 4628 ;;;; For References 4629 ;; 4630 ;; `org-export-get-reference' associate a unique reference for any 4631 ;; object or element. It uses `org-export-new-reference' and 4632 ;; `org-export-format-reference' to, respectively, generate new 4633 ;; internal references and turn them into a string suitable for 4634 ;; output. 4635 ;; 4636 ;; `org-export-get-ordinal' associates a sequence number to any object 4637 ;; or element. 4638 4639 (defun org-export-new-reference (references) 4640 "Return a unique reference, among REFERENCES. 4641 REFERENCES is an alist whose values are in-use references, as 4642 numbers. Returns a number, which is the internal representation 4643 of a reference. See also `org-export-format-reference'." 4644 ;; Generate random 7 digits hexadecimal numbers. Collisions 4645 ;; increase exponentially with the numbers of references. However, 4646 ;; the odds for encountering at least one collision with 1000 active 4647 ;; references in the same document are roughly 0.2%, so this 4648 ;; shouldn't be the bottleneck. 4649 (let ((new (random #x10000000))) 4650 (while (rassq new references) (setq new (random #x10000000))) 4651 new)) 4652 4653 (defun org-export-format-reference (reference) 4654 "Format REFERENCE into a string. 4655 REFERENCE is a number representing a reference, as returned by 4656 `org-export-new-reference', which see." 4657 (format "org%07x" reference)) 4658 4659 (defun org-export-get-reference (datum info) 4660 "Return a unique reference for DATUM, as a string. 4661 4662 DATUM is either an element or an object. INFO is the current 4663 export state, as a plist. 4664 4665 References for the current document are stored in 4666 `:internal-references' property. Its value is an alist with 4667 associations of the following types: 4668 4669 (REFERENCE . DATUM) and (SEARCH-CELL . ID) 4670 4671 REFERENCE is the reference string to be used for object or 4672 element DATUM. SEARCH-CELL is a search cell, as returned by 4673 `org-export-search-cells'. ID is a number or a string uniquely 4674 identifying DATUM within the document. 4675 4676 This function also checks `:crossrefs' property for search cells 4677 matching DATUM before creating a new reference." 4678 (let ((cache (plist-get info :internal-references))) 4679 (or (car (rassq datum cache)) 4680 (let* ((crossrefs (plist-get info :crossrefs)) 4681 (cells (org-export-search-cells datum)) 4682 ;; Preserve any pre-existing association between 4683 ;; a search cell and a reference, i.e., when some 4684 ;; previously published document referenced a location 4685 ;; within current file (see 4686 ;; `org-publish-resolve-external-link'). 4687 ;; 4688 ;; However, there is no guarantee that search cells are 4689 ;; unique, e.g., there might be duplicate custom ID or 4690 ;; two headings with the same title in the file. 4691 ;; 4692 ;; As a consequence, before re-using any reference to 4693 ;; an element or object, we check that it doesn't refer 4694 ;; to a previous element or object. 4695 (new (or (cl-some 4696 (lambda (cell) 4697 (let ((stored (cdr (assoc cell crossrefs)))) 4698 (when stored 4699 (let ((old (org-export-format-reference stored))) 4700 (and (not (assoc old cache)) stored))))) 4701 cells) 4702 (org-export-new-reference cache))) 4703 (reference-string (org-export-format-reference new))) 4704 ;; Cache contains both data already associated to 4705 ;; a reference and in-use internal references, so as to make 4706 ;; unique references. 4707 (dolist (cell cells) (push (cons cell new) cache)) 4708 ;; Retain a direct association between reference string and 4709 ;; DATUM since (1) not every object or element can be given 4710 ;; a search cell (2) it permits quick lookup. 4711 (push (cons reference-string datum) cache) 4712 (plist-put info :internal-references cache) 4713 reference-string)))) 4714 4715 (defun org-export-get-ordinal (element info &optional types predicate) 4716 "Return ordinal number of an element or object. 4717 4718 ELEMENT is the element or object considered. INFO is the plist 4719 used as a communication channel. 4720 4721 Optional argument TYPES, when non-nil, is a list of element or 4722 object types, as symbols, that should also be counted in. 4723 Otherwise, only provided element's type is considered. 4724 4725 Optional argument PREDICATE is a function returning a non-nil 4726 value if the current element or object should be counted in. It 4727 accepts two arguments: the element or object being considered and 4728 the plist used as a communication channel. This allows counting 4729 only a certain type of object (i.e. inline images). 4730 4731 Return value is a list of numbers if ELEMENT is a headline or an 4732 item. It is nil for keywords. It represents the footnote number 4733 for footnote definitions and footnote references. If ELEMENT is 4734 a target, return the same value as if ELEMENT was the closest 4735 table, item or headline containing the target. In any other 4736 case, return the sequence number of ELEMENT among elements or 4737 objects of the same type." 4738 ;; Ordinal of a target object refer to the ordinal of the closest 4739 ;; table, item, or headline containing the object. 4740 (when (eq (org-element-type element) 'target) 4741 (setq element 4742 (org-element-lineage 4743 element 4744 '(footnote-definition footnote-reference headline item table)))) 4745 (cl-case (org-element-type element) 4746 ;; Special case 1: A headline returns its number as a list. 4747 (headline (org-export-get-headline-number element info)) 4748 ;; Special case 2: An item returns its number as a list. 4749 (item (let ((struct (org-element-property :structure element))) 4750 (org-list-get-item-number 4751 (org-element-property :begin element) 4752 struct 4753 (org-list-prevs-alist struct) 4754 (org-list-parents-alist struct)))) 4755 ((footnote-definition footnote-reference) 4756 (org-export-get-footnote-number element info)) 4757 (otherwise 4758 (let ((counter 0)) 4759 ;; Increment counter until ELEMENT is found again. 4760 (org-element-map (plist-get info :parse-tree) 4761 (or (and types (cons (org-element-type element) types)) 4762 (org-element-type element)) 4763 (lambda (el) 4764 (let ((cached (org-element-property :org-export--counter el))) 4765 (cond 4766 ((eq element el) (1+ counter)) 4767 ;; Use cached result. 4768 ((and cached 4769 (equal predicate (car cached)) 4770 (equal types (cadr cached))) 4771 (setq counter (nth 2 cached)) 4772 nil) 4773 ((not predicate) 4774 (cl-incf counter) 4775 (org-element-put-property 4776 el :org-export--counter (list predicate types counter)) 4777 nil) 4778 ((funcall predicate el info) 4779 (cl-incf counter) 4780 (org-element-put-property 4781 el :org-export--counter (list predicate types counter)) 4782 nil)))) 4783 info 'first-match))))) 4784 4785 ;;;; For Raw objects 4786 ;; 4787 ;; `org-export-raw-string' builds a pseudo-object out of a string 4788 ;; that any export back-end returns as-is. 4789 4790 ;;;###autoload 4791 (defun org-export-raw-string (s) 4792 "Return a raw object containing string S. 4793 A raw string is exported as-is, with no additional processing 4794 from the export back-end." 4795 (unless (stringp s) (error "Wrong raw contents type: %S" s)) 4796 (org-element-create 'raw nil s)) 4797 4798 ;;;; For Src-Blocks 4799 ;; 4800 ;; `org-export-get-loc' counts number of code lines accumulated in 4801 ;; src-block or example-block elements with a "+n" switch until 4802 ;; a given element, excluded. Note: "-n" switches reset that count. 4803 ;; 4804 ;; `org-export-unravel-code' extracts source code (along with a code 4805 ;; references alist) from an `example-block' or `src-block' type 4806 ;; element. 4807 ;; 4808 ;; `org-export-format-code' applies a formatting function to each line 4809 ;; of code, providing relative line number and code reference when 4810 ;; appropriate. Since it doesn't access the original element from 4811 ;; which the source code is coming, it expects from the code calling 4812 ;; it to know if lines should be numbered and if code references 4813 ;; should appear. 4814 ;; 4815 ;; Eventually, `org-export-format-code-default' is a higher-level 4816 ;; function (it makes use of the two previous functions) which handles 4817 ;; line numbering and code references inclusion, and returns source 4818 ;; code in a format suitable for plain text or verbatim output. 4819 4820 (defun org-export-get-loc (element info) 4821 "Return count of lines of code before ELEMENT. 4822 4823 ELEMENT is an example-block or src-block element. INFO is the 4824 plist used as a communication channel. 4825 4826 Count includes every line of code in example-block or src-block 4827 with a \"+n\" or \"-n\" switch before block. Return nil if 4828 ELEMENT doesn't allow line numbering." 4829 (pcase (org-element-property :number-lines element) 4830 (`(new . ,n) n) 4831 (`(continued . ,n) 4832 (let ((loc 0)) 4833 (org-element-map (plist-get info :parse-tree) '(src-block example-block) 4834 (lambda (el) 4835 ;; ELEMENT is reached: Quit loop and return locs. 4836 (if (eq el element) (+ loc n) 4837 ;; Only count lines from src-block and example-block 4838 ;; elements with a "+n" or "-n" switch. 4839 (let ((linum (org-element-property :number-lines el))) 4840 (when linum 4841 (let ((lines (org-count-lines 4842 (org-element-property :value el)))) 4843 ;; Accumulate locs or reset them. 4844 (pcase linum 4845 (`(new . ,n) (setq loc (+ n lines))) 4846 (`(continued . ,n) (cl-incf loc (+ n lines))))))) 4847 nil)) ;Return nil to stay in the loop. 4848 info 'first-match))))) 4849 4850 (defun org-export-unravel-code (element) 4851 "Clean source code and extract references out of it. 4852 4853 ELEMENT has either a `src-block' an `example-block' type. 4854 4855 Return a cons cell whose CAR is the source code, cleaned from any 4856 reference, protective commas and spurious indentation, and CDR is 4857 an alist between relative line number (integer) and name of code 4858 reference on that line (string)." 4859 (let* ((line 0) refs 4860 (value (org-element-property :value element)) 4861 ;; Remove global indentation from code, if necessary. Also 4862 ;; remove final newline character, since it doesn't belongs 4863 ;; to the code proper. 4864 (code (replace-regexp-in-string 4865 "\n\\'" "" 4866 (if (or org-src-preserve-indentation 4867 (org-element-property :preserve-indent element)) 4868 value 4869 (org-remove-indentation value)))) 4870 ;; Build a regexp matching a loc with a reference. 4871 (ref-re (org-src-coderef-regexp (org-src-coderef-format element)))) 4872 ;; Return value. 4873 (cons 4874 ;; Code with references removed. 4875 (mapconcat 4876 (lambda (loc) 4877 (cl-incf line) 4878 (if (not (string-match ref-re loc)) loc 4879 ;; Ref line: remove ref, and add its position in REFS. 4880 (push (cons line (match-string 3 loc)) refs) 4881 (replace-match "" nil nil loc 1))) 4882 (split-string code "\n") "\n") 4883 ;; Reference alist. 4884 refs))) 4885 4886 (defun org-export-format-code (code fun &optional num-lines ref-alist) 4887 "Format CODE by applying FUN line-wise and return it. 4888 4889 CODE is a string representing the code to format. FUN is 4890 a function. It must accept three arguments: a line of 4891 code (string), the current line number (integer) or nil and the 4892 reference associated to the current line (string) or nil. 4893 4894 Optional argument NUM-LINES can be an integer representing the 4895 number of code lines accumulated until the current code. Line 4896 numbers passed to FUN will take it into account. If it is nil, 4897 FUN's second argument will always be nil. This number can be 4898 obtained with `org-export-get-loc' function. 4899 4900 Optional argument REF-ALIST can be an alist between relative line 4901 number (i.e. ignoring NUM-LINES) and the name of the code 4902 reference on it. If it is nil, FUN's third argument will always 4903 be nil. It can be obtained through the use of 4904 `org-export-unravel-code' function." 4905 (let ((--locs (split-string code "\n")) 4906 (--line 0)) 4907 (concat 4908 (mapconcat 4909 (lambda (--loc) 4910 (cl-incf --line) 4911 (let ((--ref (cdr (assq --line ref-alist)))) 4912 (funcall fun --loc (and num-lines (+ num-lines --line)) --ref))) 4913 --locs "\n") 4914 "\n"))) 4915 4916 (defun org-export-format-code-default (element info) 4917 "Return source code from ELEMENT, formatted in a standard way. 4918 4919 ELEMENT is either a `src-block' or `example-block' element. INFO 4920 is a plist used as a communication channel. 4921 4922 This function takes care of line numbering and code references 4923 inclusion. Line numbers, when applicable, appear at the 4924 beginning of the line, separated from the code by two white 4925 spaces. Code references, on the other hand, appear flushed to 4926 the right, separated by six white spaces from the widest line of 4927 code." 4928 ;; Extract code and references. 4929 (let* ((code-info (org-export-unravel-code element)) 4930 (code (car code-info)) 4931 (code-lines (split-string code "\n"))) 4932 (if (null code-lines) "" 4933 (let* ((refs (and (org-element-property :retain-labels element) 4934 (cdr code-info))) 4935 ;; Handle line numbering. 4936 (num-start (org-export-get-loc element info)) 4937 (num-fmt 4938 (and num-start 4939 (format "%%%ds " 4940 (length (number-to-string 4941 (+ (length code-lines) num-start)))))) 4942 ;; Prepare references display, if required. Any reference 4943 ;; should start six columns after the widest line of code, 4944 ;; wrapped with parenthesis. 4945 (max-width 4946 (+ (apply #'max (mapcar #'length code-lines)) 4947 (if (not num-start) 0 (length (format num-fmt num-start)))))) 4948 (org-export-format-code 4949 code 4950 (lambda (loc line-num ref) 4951 (let ((number-str (and num-fmt (format num-fmt line-num)))) 4952 (concat 4953 number-str 4954 loc 4955 (and ref 4956 (concat (make-string (- (+ 6 max-width) 4957 (+ (length loc) (length number-str))) 4958 ?\s) 4959 (format "(%s)" ref)))))) 4960 num-start refs))))) 4961 4962 4963 ;;;; For Tables 4964 ;; 4965 ;; `org-export-table-has-special-column-p' and 4966 ;; `org-export-table-row-is-special-p' are predicates used to look for 4967 ;; meta-information about the table structure. 4968 ;; 4969 ;; `org-export-table-cell-width', `org-export-table-cell-alignment' 4970 ;; and `org-export-table-cell-borders' extract information from 4971 ;; a table-cell element. 4972 ;; 4973 ;; `org-export-table-dimensions' gives the number on rows and columns 4974 ;; in the table, ignoring horizontal rules and special columns. 4975 ;; `org-export-table-cell-address', given a table-cell object, returns 4976 ;; the absolute address of a cell. On the other hand, 4977 ;; `org-export-get-table-cell-at' does the contrary. 4978 ;; 4979 ;; `org-export-table-cell-starts-colgroup-p', 4980 ;; `org-export-table-cell-ends-colgroup-p', 4981 ;; `org-export-table-row-starts-rowgroup-p', 4982 ;; `org-export-table-row-ends-rowgroup-p', 4983 ;; `org-export-table-row-starts-header-p', 4984 ;; `org-export-table-row-ends-header-p' and 4985 ;; `org-export-table-row-in-header-p' indicate position of current row 4986 ;; or cell within the table. 4987 4988 (defun org-export-table-has-special-column-p (table) 4989 "Non-nil when TABLE has a special column. 4990 All special columns will be ignored during export." 4991 ;; The table has a special column when every first cell of every row 4992 ;; has an empty value or contains a symbol among "/", "#", "!", "$", 4993 ;; "*" "_" and "^". Though, do not consider a first column 4994 ;; containing only empty cells as special. 4995 (let ((special-column? 'empty)) 4996 (catch 'exit 4997 (dolist (row (org-element-contents table)) 4998 (when (eq (org-element-property :type row) 'standard) 4999 (let ((value (org-element-contents 5000 (car (org-element-contents row))))) 5001 (cond ((member value 5002 '(("/") ("#") ("!") ("$") ("*") ("_") ("^"))) 5003 (setq special-column? 'special)) 5004 ((null value)) 5005 (t (throw 'exit nil)))))) 5006 (eq special-column? 'special)))) 5007 5008 (defun org-export-table-has-header-p (table info) 5009 "Non-nil when TABLE has a header. 5010 5011 INFO is a plist used as a communication channel. 5012 5013 A table has a header when it contains at least two row groups." 5014 (let* ((cache (or (plist-get info :table-header-cache) 5015 (let ((table (make-hash-table :test #'eq))) 5016 (plist-put info :table-header-cache table) 5017 table))) 5018 (cached (gethash table cache 'no-cache))) 5019 (if (not (eq cached 'no-cache)) cached 5020 (let ((rowgroup 1) row-flag) 5021 (puthash table 5022 (org-element-map table 'table-row 5023 (lambda (row) 5024 (cond 5025 ((> rowgroup 1) t) 5026 ((and row-flag 5027 (eq (org-element-property :type row) 'rule)) 5028 (cl-incf rowgroup) 5029 (setq row-flag nil)) 5030 ((and (not row-flag) 5031 (eq (org-element-property :type row) 'standard)) 5032 (setq row-flag t) 5033 nil))) 5034 info 'first-match) 5035 cache))))) 5036 5037 (defun org-export-table-row-is-special-p (table-row _) 5038 "Non-nil if TABLE-ROW is considered special. 5039 All special rows will be ignored during export." 5040 (when (eq (org-element-property :type table-row) 'standard) 5041 (let ((first-cell (org-element-contents 5042 (car (org-element-contents table-row))))) 5043 ;; A row is special either when... 5044 (or 5045 ;; ... it starts with a field only containing "/", 5046 (equal first-cell '("/")) 5047 ;; ... the table contains a special column and the row start 5048 ;; with a marking character among, "^", "_", "$" or "!", 5049 (and (org-export-table-has-special-column-p 5050 (org-export-get-parent table-row)) 5051 (member first-cell '(("^") ("_") ("$") ("!")))) 5052 ;; ... it contains only alignment cookies and empty cells. 5053 (let ((special-row-p 'empty)) 5054 (catch 'exit 5055 (dolist (cell (org-element-contents table-row)) 5056 (let ((value (org-element-contents cell))) 5057 ;; Since VALUE is a secondary string, the following 5058 ;; checks avoid expanding it with `org-export-data'. 5059 (cond ((not value)) 5060 ((and (not (cdr value)) 5061 (stringp (car value)) 5062 (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'" 5063 (car value))) 5064 (setq special-row-p 'cookie)) 5065 (t (throw 'exit nil))))) 5066 (eq special-row-p 'cookie))))))) 5067 5068 (defun org-export-table-row-group (table-row info) 5069 "Return TABLE-ROW's group number, as an integer. 5070 5071 INFO is a plist used as the communication channel. 5072 5073 Return value is the group number, as an integer, or nil for 5074 special rows and rows separators. First group is also table's 5075 header." 5076 (when (eq (org-element-property :type table-row) 'standard) 5077 (let* ((cache (or (plist-get info :table-row-group-cache) 5078 (let ((table (make-hash-table :test #'eq))) 5079 (plist-put info :table-row-group-cache table) 5080 table))) 5081 (cached (gethash table-row cache 'no-cache))) 5082 (if (not (eq cached 'no-cache)) cached 5083 ;; First time a row is queried, populate cache with all the 5084 ;; rows from the table. 5085 (let ((group 0) row-flag) 5086 (org-element-map (org-export-get-parent table-row) 'table-row 5087 (lambda (row) 5088 (if (eq (org-element-property :type row) 'rule) 5089 (setq row-flag nil) 5090 (unless row-flag (cl-incf group) (setq row-flag t)) 5091 (puthash row group cache))) 5092 info)) 5093 (gethash table-row cache))))) 5094 5095 (defun org-export-table-cell-width (table-cell info) 5096 "Return TABLE-CELL contents width. 5097 5098 INFO is a plist used as the communication channel. 5099 5100 Return value is the width given by the last width cookie in the 5101 same column as TABLE-CELL, or nil." 5102 (let* ((row (org-export-get-parent table-cell)) 5103 (table (org-export-get-parent row)) 5104 (cells (org-element-contents row)) 5105 (columns (length cells)) 5106 (column (- columns (length (memq table-cell cells)))) 5107 (cache (or (plist-get info :table-cell-width-cache) 5108 (let ((table (make-hash-table :test #'eq))) 5109 (plist-put info :table-cell-width-cache table) 5110 table))) 5111 (width-vector (or (gethash table cache) 5112 (puthash table (make-vector columns 'empty) cache)))) 5113 ;; Table rows may not have the same number of cells. Extend 5114 ;; WIDTH-VECTOR appropriately if we encounter a row larger than 5115 ;; expected. 5116 (when (>= column (length width-vector)) 5117 (setq width-vector 5118 (vconcat width-vector 5119 (make-list (- (1+ column) (length width-vector)) 5120 'empty))) 5121 (puthash table width-vector cache)) 5122 (pcase (aref width-vector column) 5123 (`empty 5124 (catch 'found 5125 (dolist (row (org-element-contents table)) 5126 (when (org-export-table-row-is-special-p row info) 5127 ;; In a special row, try to find a width cookie at 5128 ;; COLUMN. The following checks avoid expanding 5129 ;; unnecessarily the cell with `org-export-data'. 5130 (pcase (org-element-contents 5131 (elt (org-element-contents row) column)) 5132 (`(,(and (pred stringp) cookie)) 5133 (when (string-match "\\`<[lrc]?\\([0-9]+\\)>\\'" cookie) 5134 (let ((w (string-to-number (match-string 1 cookie)))) 5135 (throw 'found (aset width-vector column w)))))))) 5136 (aset width-vector column nil))) 5137 (value value)))) 5138 5139 (defun org-export-table-cell-alignment (table-cell info) 5140 "Return TABLE-CELL contents alignment. 5141 5142 INFO is a plist used as the communication channel. 5143 5144 Return alignment as specified by the last alignment cookie in the 5145 same column as TABLE-CELL. If no such cookie is found, a default 5146 alignment value will be deduced from fraction of numbers in the 5147 column (see `org-table-number-fraction' for more information). 5148 Possible values are `left', `right' and `center'." 5149 ;; Load `org-table-number-fraction' and `org-table-number-regexp'. 5150 (require 'org-table) 5151 (let* ((row (org-export-get-parent table-cell)) 5152 (table (org-export-get-parent row)) 5153 (cells (org-element-contents row)) 5154 (columns (length cells)) 5155 (column (- columns (length (memq table-cell cells)))) 5156 (cache (or (plist-get info :table-cell-alignment-cache) 5157 (let ((table (make-hash-table :test #'eq))) 5158 (plist-put info :table-cell-alignment-cache table) 5159 table))) 5160 (align-vector (or (gethash table cache) 5161 (puthash table (make-vector columns nil) cache)))) 5162 ;; Table rows may not have the same number of cells. Extend 5163 ;; ALIGN-VECTOR appropriately if we encounter a row larger than 5164 ;; expected. 5165 (when (>= column (length align-vector)) 5166 (setq align-vector 5167 (vconcat align-vector 5168 (make-list (- (1+ column) (length align-vector)) 5169 nil))) 5170 (puthash table align-vector cache)) 5171 (or (aref align-vector column) 5172 (let ((number-cells 0) 5173 (total-cells 0) 5174 cookie-align 5175 previous-cell-number-p) 5176 (dolist (row (org-element-contents (org-export-get-parent row))) 5177 (cond 5178 ;; In a special row, try to find an alignment cookie at 5179 ;; COLUMN. 5180 ((org-export-table-row-is-special-p row info) 5181 (let ((value (org-element-contents 5182 (elt (org-element-contents row) column)))) 5183 ;; Since VALUE is a secondary string, the following 5184 ;; checks avoid useless expansion through 5185 ;; `org-export-data'. 5186 (when (and value 5187 (not (cdr value)) 5188 (stringp (car value)) 5189 (string-match "\\`<\\([lrc]\\)?\\([0-9]+\\)?>\\'" 5190 (car value)) 5191 (match-string 1 (car value))) 5192 (setq cookie-align (match-string 1 (car value)))))) 5193 ;; Ignore table rules. 5194 ((eq (org-element-property :type row) 'rule)) 5195 ;; In a standard row, check if cell's contents are 5196 ;; expressing some kind of number. Increase NUMBER-CELLS 5197 ;; accordingly. Though, don't bother if an alignment 5198 ;; cookie has already defined cell's alignment. 5199 ((not cookie-align) 5200 (let ((value (org-export-data 5201 (org-element-contents 5202 (elt (org-element-contents row) column)) 5203 info))) 5204 (cl-incf total-cells) 5205 ;; Treat an empty cell as a number if it follows 5206 ;; a number. 5207 (if (not (or (string-match org-table-number-regexp value) 5208 (and (string= value "") previous-cell-number-p))) 5209 (setq previous-cell-number-p nil) 5210 (setq previous-cell-number-p t) 5211 (cl-incf number-cells)))))) 5212 ;; Return value. Alignment specified by cookies has 5213 ;; precedence over alignment deduced from cell's contents. 5214 (aset align-vector 5215 column 5216 (cond ((equal cookie-align "l") 'left) 5217 ((equal cookie-align "r") 'right) 5218 ((equal cookie-align "c") 'center) 5219 ((>= (/ (float number-cells) total-cells) 5220 org-table-number-fraction) 5221 'right) 5222 (t 'left))))))) 5223 5224 (defun org-export-table-cell-borders (table-cell info) 5225 "Return TABLE-CELL borders. 5226 5227 INFO is a plist used as a communication channel. 5228 5229 Return value is a list of symbols, or nil. Possible values are: 5230 `top', `bottom', `above', `below', `left' and `right'. Note: 5231 `top' (resp. `bottom') only happen for a cell in the first 5232 row (resp. last row) of the table, ignoring table rules, if any. 5233 5234 Returned borders ignore special rows." 5235 (let* ((row (org-export-get-parent table-cell)) 5236 (table (org-export-get-parent-table table-cell)) 5237 borders) 5238 ;; Top/above border? TABLE-CELL has a border above when a rule 5239 ;; used to demarcate row groups can be found above. Hence, 5240 ;; finding a rule isn't sufficient to push `above' in BORDERS: 5241 ;; another regular row has to be found above that rule. 5242 (let (rule-flag) 5243 (catch 'exit 5244 ;; Look at every row before the current one. 5245 (dolist (row (cdr (memq row (reverse (org-element-contents table))))) 5246 (cond ((eq (org-element-property :type row) 'rule) 5247 (setq rule-flag t)) 5248 ((not (org-export-table-row-is-special-p row info)) 5249 (if rule-flag (throw 'exit (push 'above borders)) 5250 (throw 'exit nil))))) 5251 ;; No rule above, or rule found starts the table (ignoring any 5252 ;; special row): TABLE-CELL is at the top of the table. 5253 (when rule-flag (push 'above borders)) 5254 (push 'top borders))) 5255 ;; Bottom/below border? TABLE-CELL has a border below when next 5256 ;; non-regular row below is a rule. 5257 (let (rule-flag) 5258 (catch 'exit 5259 ;; Look at every row after the current one. 5260 (dolist (row (cdr (memq row (org-element-contents table)))) 5261 (cond ((eq (org-element-property :type row) 'rule) 5262 (setq rule-flag t)) 5263 ((not (org-export-table-row-is-special-p row info)) 5264 (if rule-flag (throw 'exit (push 'below borders)) 5265 (throw 'exit nil))))) 5266 ;; No rule below, or rule found ends the table (modulo some 5267 ;; special row): TABLE-CELL is at the bottom of the table. 5268 (when rule-flag (push 'below borders)) 5269 (push 'bottom borders))) 5270 ;; Right/left borders? They can only be specified by column 5271 ;; groups. Column groups are defined in a row starting with "/". 5272 ;; Also a column groups row only contains "<", "<>", ">" or blank 5273 ;; cells. 5274 (catch 'exit 5275 (let ((column (let ((cells (org-element-contents row))) 5276 (- (length cells) (length (memq table-cell cells)))))) 5277 ;; Table rows are read in reverse order so last column groups 5278 ;; row has precedence over any previous one. 5279 (dolist (row (reverse (org-element-contents table))) 5280 (unless (eq (org-element-property :type row) 'rule) 5281 (when (equal (org-element-contents 5282 (car (org-element-contents row))) 5283 '("/")) 5284 (let ((column-groups 5285 (mapcar 5286 (lambda (cell) 5287 (let ((value (org-element-contents cell))) 5288 (when (member value '(("<") ("<>") (">") nil)) 5289 (car value)))) 5290 (org-element-contents row)))) 5291 ;; There's a left border when previous cell, if 5292 ;; any, ends a group, or current one starts one. 5293 (when (or (and (not (zerop column)) 5294 (member (elt column-groups (1- column)) 5295 '(">" "<>"))) 5296 (member (elt column-groups column) '("<" "<>"))) 5297 (push 'left borders)) 5298 ;; There's a right border when next cell, if any, 5299 ;; starts a group, or current one ends one. 5300 (when (or (and (/= (1+ column) (length column-groups)) 5301 (member (elt column-groups (1+ column)) 5302 '("<" "<>"))) 5303 (member (elt column-groups column) '(">" "<>"))) 5304 (push 'right borders)) 5305 (throw 'exit nil))))))) 5306 ;; Return value. 5307 borders)) 5308 5309 (defun org-export-table-cell-starts-colgroup-p (table-cell info) 5310 "Non-nil when TABLE-CELL is at the beginning of a column group. 5311 INFO is a plist used as a communication channel." 5312 ;; A cell starts a column group either when it is at the beginning 5313 ;; of a row (or after the special column, if any) or when it has 5314 ;; a left border. 5315 (or (eq (org-element-map (org-export-get-parent table-cell) 'table-cell 5316 'identity info 'first-match) 5317 table-cell) 5318 (memq 'left (org-export-table-cell-borders table-cell info)))) 5319 5320 (defun org-export-table-cell-ends-colgroup-p (table-cell info) 5321 "Non-nil when TABLE-CELL is at the end of a column group. 5322 INFO is a plist used as a communication channel." 5323 ;; A cell ends a column group either when it is at the end of a row 5324 ;; or when it has a right border. 5325 (or (eq (car (last (org-element-contents 5326 (org-export-get-parent table-cell)))) 5327 table-cell) 5328 (memq 'right (org-export-table-cell-borders table-cell info)))) 5329 5330 (defun org-export-table-row-starts-rowgroup-p (table-row info) 5331 "Non-nil when TABLE-ROW is at the beginning of a row group. 5332 INFO is a plist used as a communication channel." 5333 (unless (or (eq (org-element-property :type table-row) 'rule) 5334 (org-export-table-row-is-special-p table-row info)) 5335 (let ((borders (org-export-table-cell-borders 5336 (car (org-element-contents table-row)) info))) 5337 (or (memq 'top borders) (memq 'above borders))))) 5338 5339 (defun org-export-table-row-ends-rowgroup-p (table-row info) 5340 "Non-nil when TABLE-ROW is at the end of a row group. 5341 INFO is a plist used as a communication channel." 5342 (unless (or (eq (org-element-property :type table-row) 'rule) 5343 (org-export-table-row-is-special-p table-row info)) 5344 (let ((borders (org-export-table-cell-borders 5345 (car (org-element-contents table-row)) info))) 5346 (or (memq 'bottom borders) (memq 'below borders))))) 5347 5348 (defun org-export-table-row-in-header-p (table-row info) 5349 "Non-nil when TABLE-ROW is located within table's header. 5350 INFO is a plist used as a communication channel. Always return 5351 nil for special rows and rows separators." 5352 (and (org-export-table-has-header-p 5353 (org-export-get-parent-table table-row) info) 5354 (eql (org-export-table-row-group table-row info) 1))) 5355 5356 (defun org-export-table-row-starts-header-p (table-row info) 5357 "Non-nil when TABLE-ROW is the first table header's row. 5358 INFO is a plist used as a communication channel." 5359 (and (org-export-table-row-in-header-p table-row info) 5360 (org-export-table-row-starts-rowgroup-p table-row info))) 5361 5362 (defun org-export-table-row-ends-header-p (table-row info) 5363 "Non-nil when TABLE-ROW is the last table header's row. 5364 INFO is a plist used as a communication channel." 5365 (and (org-export-table-row-in-header-p table-row info) 5366 (org-export-table-row-ends-rowgroup-p table-row info))) 5367 5368 (defun org-export-table-row-number (table-row info) 5369 "Return TABLE-ROW number. 5370 INFO is a plist used as a communication channel. Return value is 5371 zero-indexed and ignores separators. The function returns nil 5372 for special rows and separators." 5373 (when (eq (org-element-property :type table-row) 'standard) 5374 (let* ((cache (or (plist-get info :table-row-number-cache) 5375 (let ((table (make-hash-table :test #'eq))) 5376 (plist-put info :table-row-number-cache table) 5377 table))) 5378 (cached (gethash table-row cache 'no-cache))) 5379 (if (not (eq cached 'no-cache)) cached 5380 ;; First time a row is queried, populate cache with all the 5381 ;; rows from the table. 5382 (let ((number -1)) 5383 (org-element-map (org-export-get-parent-table table-row) 'table-row 5384 (lambda (row) 5385 (when (eq (org-element-property :type row) 'standard) 5386 (puthash row (cl-incf number) cache))) 5387 info)) 5388 (gethash table-row cache))))) 5389 5390 (defun org-export-table-dimensions (table info) 5391 "Return TABLE dimensions. 5392 5393 INFO is a plist used as a communication channel. 5394 5395 Return value is a CONS like (ROWS . COLUMNS) where 5396 ROWS (resp. COLUMNS) is the number of exportable 5397 rows (resp. columns)." 5398 (let (first-row (columns 0) (rows 0)) 5399 ;; Set number of rows, and extract first one. 5400 (org-element-map table 'table-row 5401 (lambda (row) 5402 (when (eq (org-element-property :type row) 'standard) 5403 (cl-incf rows) 5404 (unless first-row (setq first-row row)))) 5405 info) 5406 ;; Set number of columns. 5407 (org-element-map first-row 'table-cell (lambda (_) (cl-incf columns)) info) 5408 ;; Return value. 5409 (cons rows columns))) 5410 5411 (defun org-export-table-cell-address (table-cell info) 5412 "Return address of a regular TABLE-CELL object. 5413 5414 TABLE-CELL is the cell considered. INFO is a plist used as 5415 a communication channel. 5416 5417 Address is a CONS cell (ROW . COLUMN), where ROW and COLUMN are 5418 zero-based index. Only exportable cells are considered. The 5419 function returns nil for other cells." 5420 (let* ((table-row (org-export-get-parent table-cell)) 5421 (row-number (org-export-table-row-number table-row info))) 5422 (when row-number 5423 (cons row-number 5424 (let ((col-count 0)) 5425 (org-element-map table-row 'table-cell 5426 (lambda (cell) 5427 (if (eq cell table-cell) col-count (cl-incf col-count) nil)) 5428 info 'first-match)))))) 5429 5430 (defun org-export-get-table-cell-at (address table info) 5431 "Return regular table-cell object at ADDRESS in TABLE. 5432 5433 Address is a CONS cell (ROW . COLUMN), where ROW and COLUMN are 5434 zero-based index. TABLE is a table type element. INFO is 5435 a plist used as a communication channel. 5436 5437 If no table-cell, among exportable cells, is found at ADDRESS, 5438 return nil." 5439 (let ((column-pos (cdr address)) (column-count 0)) 5440 (org-element-map 5441 ;; Row at (car address) or nil. 5442 (let ((row-pos (car address)) (row-count 0)) 5443 (org-element-map table 'table-row 5444 (lambda (row) 5445 (cond ((eq (org-element-property :type row) 'rule) nil) 5446 ((= row-count row-pos) row) 5447 (t (cl-incf row-count) nil))) 5448 info 'first-match)) 5449 'table-cell 5450 (lambda (cell) 5451 (if (= column-count column-pos) cell 5452 (cl-incf column-count) nil)) 5453 info 'first-match))) 5454 5455 5456 ;;;; For Tables of Contents 5457 ;; 5458 ;; `org-export-collect-headlines' builds a list of all exportable 5459 ;; headline elements, maybe limited to a certain depth. One can then 5460 ;; easily parse it and transcode it. 5461 ;; 5462 ;; Building lists of tables, figures or listings is quite similar. 5463 ;; Once the generic function `org-export-collect-elements' is defined, 5464 ;; `org-export-collect-tables', `org-export-collect-figures' and 5465 ;; `org-export-collect-listings' can be derived from it. 5466 ;; 5467 ;; `org-export-toc-entry-backend' builds a special anonymous back-end 5468 ;; useful to export table of contents' entries. 5469 5470 (defun org-export-collect-headlines (info &optional n scope) 5471 "Collect headlines in order to build a table of contents. 5472 5473 INFO is a plist used as a communication channel. 5474 5475 When optional argument N is an integer, it specifies the depth of 5476 the table of contents. Otherwise, it is set to the value of the 5477 last headline level. See `org-export-headline-levels' for more 5478 information. 5479 5480 Optional argument SCOPE, when non-nil, is an element. If it is 5481 a headline, only children of SCOPE are collected. Otherwise, 5482 collect children of the headline containing provided element. If 5483 there is no such headline, collect all headlines. In any case, 5484 argument N becomes relative to the level of that headline. 5485 5486 Return a list of all exportable headlines as parsed elements. 5487 Footnote sections are ignored." 5488 (let* ((scope (cond ((not scope) (plist-get info :parse-tree)) 5489 ((eq (org-element-type scope) 'headline) scope) 5490 ((org-export-get-parent-headline scope)) 5491 (t (plist-get info :parse-tree)))) 5492 (limit (plist-get info :headline-levels)) 5493 (n (if (not (wholenump n)) limit 5494 (min (if (eq (org-element-type scope) 'org-data) n 5495 (+ (org-export-get-relative-level scope info) n)) 5496 limit)))) 5497 (org-element-map (org-element-contents scope) 'headline 5498 (lambda (h) 5499 (and (not (org-element-property :footnote-section-p h)) 5500 (not (equal "notoc" 5501 (org-export-get-node-property :UNNUMBERED h t))) 5502 (>= n (org-export-get-relative-level h info)) 5503 h)) 5504 info))) 5505 5506 (defun org-export-collect-elements (type info &optional predicate) 5507 "Collect referenceable elements of a determined type. 5508 5509 TYPE can be a symbol or a list of symbols specifying element 5510 types to search. Only elements with a caption are collected. 5511 5512 INFO is a plist used as a communication channel. 5513 5514 When non-nil, optional argument PREDICATE is a function accepting 5515 one argument, an element of type TYPE. It returns a non-nil 5516 value when that element should be collected. 5517 5518 Return a list of all elements found, in order of appearance." 5519 (org-element-map (plist-get info :parse-tree) type 5520 (lambda (element) 5521 (and (org-element-property :caption element) 5522 (or (not predicate) (funcall predicate element)) 5523 element)) 5524 info)) 5525 5526 (defun org-export-collect-tables (info) 5527 "Build a list of tables. 5528 INFO is a plist used as a communication channel. 5529 5530 Return a list of table elements with a caption." 5531 (org-export-collect-elements 'table info)) 5532 5533 (defun org-export-collect-figures (info predicate) 5534 "Build a list of figures. 5535 5536 INFO is a plist used as a communication channel. PREDICATE is 5537 a function which accepts one argument: a paragraph element and 5538 whose return value is non-nil when that element should be 5539 collected. 5540 5541 A figure is a paragraph type element, with a caption, verifying 5542 PREDICATE. The latter has to be provided since a \"figure\" is 5543 a vague concept that may depend on back-end. 5544 5545 Return a list of elements recognized as figures." 5546 (org-export-collect-elements 'paragraph info predicate)) 5547 5548 (defun org-export-collect-listings (info) 5549 "Build a list of source blocks. 5550 5551 INFO is a plist used as a communication channel. 5552 5553 Return a list of `src-block' elements with a caption." 5554 (org-export-collect-elements 'src-block info)) 5555 5556 (defun org-export-excluded-from-toc-p (headline info) 5557 "Non-nil if HEADLINE should be excluded from tables of contents. 5558 5559 INFO is a plist used as a communication channel. 5560 5561 Note that such headlines are already excluded from 5562 `org-export-collect-headlines'. Therefore, this function is not 5563 necessary if you only need to list headlines in the table of 5564 contents. However, it is useful if some additional processing is 5565 required on headlines excluded from table of contents." 5566 (or (org-element-property :footnote-section-p headline) 5567 (org-export-low-level-p headline info) 5568 (equal "notoc" (org-export-get-node-property :UNNUMBERED headline t)))) 5569 5570 (defun org-export-toc-entry-backend (parent &rest transcoders) 5571 "Return an export back-end appropriate for table of contents entries. 5572 5573 PARENT is an export back-end the returned back-end should inherit 5574 from. 5575 5576 By default, the back-end removes footnote references and targets. 5577 It also changes links and radio targets into regular text. 5578 TRANSCODERS optional argument, when non-nil, specifies additional 5579 transcoders. A transcoder follows the pattern (TYPE . FUNCTION) 5580 where type is an element or object type and FUNCTION the function 5581 transcoding it." 5582 (declare (indent 1)) 5583 (org-export-create-backend 5584 :parent parent 5585 :transcoders 5586 (append transcoders 5587 `((footnote-reference . ,#'ignore) 5588 (link . ,(lambda (l c i) 5589 (or c 5590 (org-export-data 5591 (org-element-property :raw-link l) 5592 i)))) 5593 (radio-target . ,(lambda (_r c _) c)) 5594 (target . ,#'ignore))))) 5595 5596 5597 ;;;; Smart Quotes 5598 ;; 5599 ;; The main function for the smart quotes sub-system is 5600 ;; `org-export-activate-smart-quotes', which replaces every quote in 5601 ;; a given string from the parse tree with its "smart" counterpart. 5602 ;; 5603 ;; Dictionary for smart quotes is stored in 5604 ;; `org-export-smart-quotes-alist'. 5605 5606 (defconst org-export-smart-quotes-alist 5607 '(("ar" 5608 (primary-opening 5609 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5610 :texinfo "@guillemetleft{}") 5611 (primary-closing 5612 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5613 :texinfo "@guillemetright{}") 5614 (secondary-opening :utf-8 "‹" :html "‹" :latex "\\guilsinglleft{}" 5615 :texinfo "@guilsinglleft{}") 5616 (secondary-closing :utf-8 "›" :html "›" :latex "\\guilsinglright{}" 5617 :texinfo "@guilsinglright{}") 5618 (apostrophe :utf-8 "’" :html "’")) 5619 ("da" 5620 ;; one may use: »...«, "...", ›...‹, or '...'. 5621 ;; https://sproget.dk/raad-og-regler/retskrivningsregler/retskrivningsregler/a7-40-60/a7-58-anforselstegn/ 5622 ;; LaTeX quotes require Babel! 5623 (primary-opening 5624 :utf-8 "»" :html "»" :latex ">>" :texinfo "@guillemetright{}") 5625 (primary-closing 5626 :utf-8 "«" :html "«" :latex "<<" :texinfo "@guillemetleft{}") 5627 (secondary-opening 5628 :utf-8 "›" :html "›" :latex "\\frq{}" :texinfo "@guilsinglright{}") 5629 (secondary-closing 5630 :utf-8 "‹" :html "‹" :latex "\\flq{}" :texinfo "@guilsingleft{}") 5631 (apostrophe :utf-8 "’" :html "’")) 5632 ("de" 5633 (primary-opening 5634 :utf-8 "„" :html "„" :latex "\"`" :texinfo "@quotedblbase{}") 5635 (primary-closing 5636 :utf-8 "“" :html "“" :latex "\"'" :texinfo "@quotedblleft{}") 5637 (secondary-opening 5638 :utf-8 "‚" :html "‚" :latex "\\glq{}" :texinfo "@quotesinglbase{}") 5639 (secondary-closing 5640 :utf-8 "‘" :html "‘" :latex "\\grq{}" :texinfo "@quoteleft{}") 5641 (apostrophe :utf-8 "’" :html "’")) 5642 ("el" 5643 (primary-opening 5644 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5645 :texinfo "@guillemetleft{}") 5646 (primary-closing 5647 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5648 :texinfo "@guillemetright{}") 5649 (secondary-opening :utf-8 "“" :html "“" :latex "``" :texinfo "``") 5650 (secondary-closing :utf-8 "”" :html "”" :latex "''" :texinfo "''") 5651 (apostrophe :utf-8 "’" :html "’")) 5652 ("en" 5653 (primary-opening :utf-8 "“" :html "“" :latex "``" :texinfo "``") 5654 (primary-closing :utf-8 "”" :html "”" :latex "''" :texinfo "''") 5655 (secondary-opening :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") 5656 (secondary-closing :utf-8 "’" :html "’" :latex "'" :texinfo "'") 5657 (apostrophe :utf-8 "’" :html "’")) 5658 ("es" 5659 (primary-opening 5660 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5661 :texinfo "@guillemetleft{}") 5662 (primary-closing 5663 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5664 :texinfo "@guillemetright{}") 5665 (secondary-opening :utf-8 "“" :html "“" :latex "``" :texinfo "``") 5666 (secondary-closing :utf-8 "”" :html "”" :latex "''" :texinfo "''") 5667 (apostrophe :utf-8 "’" :html "’")) 5668 ("fa" 5669 (primary-opening 5670 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5671 :texinfo "@guillemetleft{}") 5672 (primary-closing 5673 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5674 :texinfo "@guillemetright{}") 5675 (secondary-opening :utf-8 "‹" :html "‹" :latex "\\guilsinglleft{}" 5676 :texinfo "@guilsinglleft{}") 5677 (secondary-closing :utf-8 "›" :html "›" :latex "\\guilsinglright{}" 5678 :texinfo "@guilsinglright{}") 5679 (apostrophe :utf-8 "’" :html "’")) 5680 ("fr" 5681 (primary-opening 5682 :utf-8 "« " :html "« " :latex "\\og " 5683 :texinfo "@guillemetleft{}@tie{}") 5684 (primary-closing 5685 :utf-8 " »" :html " »" :latex "\\fg{}" 5686 :texinfo "@tie{}@guillemetright{}") 5687 (secondary-opening 5688 :utf-8 "« " :html "« " :latex "\\og " 5689 :texinfo "@guillemetleft{}@tie{}") 5690 (secondary-closing :utf-8 " »" :html " »" :latex "\\fg{}" 5691 :texinfo "@tie{}@guillemetright{}") 5692 (apostrophe :utf-8 "’" :html "’")) 5693 ("is" 5694 (primary-opening 5695 :utf-8 "„" :html "„" :latex "\"`" :texinfo "@quotedblbase{}") 5696 (primary-closing 5697 :utf-8 "“" :html "“" :latex "\"'" :texinfo "@quotedblleft{}") 5698 (secondary-opening 5699 :utf-8 "‚" :html "‚" :latex "\\glq{}" :texinfo "@quotesinglbase{}") 5700 (secondary-closing 5701 :utf-8 "‘" :html "‘" :latex "\\grq{}" :texinfo "@quoteleft{}") 5702 (apostrophe :utf-8 "’" :html "’")) 5703 ("it" 5704 (primary-opening :utf-8 "“" :html "“" :latex "``" :texinfo "``") 5705 (primary-closing :utf-8 "”" :html "”" :latex "''" :texinfo "''") 5706 (secondary-opening :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") 5707 (secondary-closing :utf-8 "’" :html "’" :latex "'" :texinfo "'") 5708 (apostrophe :utf-8 "’" :html "’")) 5709 ("no" 5710 ;; https://nn.wikipedia.org/wiki/Sitatteikn 5711 (primary-opening 5712 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5713 :texinfo "@guillemetleft{}") 5714 (primary-closing 5715 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5716 :texinfo "@guillemetright{}") 5717 (secondary-opening :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") 5718 (secondary-closing :utf-8 "’" :html "’" :latex "'" :texinfo "'") 5719 (apostrophe :utf-8 "’" :html "’")) 5720 ("nb" 5721 ;; https://nn.wikipedia.org/wiki/Sitatteikn 5722 (primary-opening 5723 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5724 :texinfo "@guillemetleft{}") 5725 (primary-closing 5726 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5727 :texinfo "@guillemetright{}") 5728 (secondary-opening :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") 5729 (secondary-closing :utf-8 "’" :html "’" :latex "'" :texinfo "'") 5730 (apostrophe :utf-8 "’" :html "’")) 5731 ("nn" 5732 ;; https://nn.wikipedia.org/wiki/Sitatteikn 5733 (primary-opening 5734 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5735 :texinfo "@guillemetleft{}") 5736 (primary-closing 5737 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5738 :texinfo "@guillemetright{}") 5739 (secondary-opening :utf-8 "‘" :html "‘" :latex "`" :texinfo "`") 5740 (secondary-closing :utf-8 "’" :html "’" :latex "'" :texinfo "'") 5741 (apostrophe :utf-8 "’" :html "’")) 5742 ("ro" 5743 (primary-opening 5744 :utf-8 "„" :html "„" :latex "\"`" :texinfo "@quotedblbase{}") 5745 (primary-closing :utf-8 "”" :html "”" :latex "''" :texinfo "''") 5746 (secondary-opening 5747 :utf-8 "«" :html "«" :latex "\\guillemotleft{}" 5748 :texinfo "@guillemetleft{}") 5749 (secondary-closing 5750 :utf-8 "»" :html "»" :latex "\\guillemotright{}" 5751 :texinfo "@guillemetright{}") 5752 (apostrophe :utf-8 "’" :html "’")) 5753 ("ru" 5754 ;; https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%B2%D1%8B%D1%87%D0%BA%D0%B8#.D0.9A.D0.B0.D0.B2.D1.8B.D1.87.D0.BA.D0.B8.2C_.D0.B8.D1.81.D0.BF.D0.BE.D0.BB.D1.8C.D0.B7.D1.83.D0.B5.D0.BC.D1.8B.D0.B5_.D0.B2_.D1.80.D1.83.D1.81.D1.81.D0.BA.D0.BE.D0.BC_.D1.8F.D0.B7.D1.8B.D0.BA.D0.B5 5755 ;; https://www.artlebedev.ru/kovodstvo/sections/104/ 5756 (primary-opening :utf-8 "«" :html "«" :latex "{}<<" 5757 :texinfo "@guillemetleft{}") 5758 (primary-closing :utf-8 "»" :html "»" :latex ">>{}" 5759 :texinfo "@guillemetright{}") 5760 (secondary-opening 5761 :utf-8 "„" :html "„" :latex "\\glqq{}" :texinfo "@quotedblbase{}") 5762 (secondary-closing 5763 :utf-8 "“" :html "“" :latex "\\grqq{}" :texinfo "@quotedblleft{}") 5764 (apostrophe :utf-8 "’" :html: "'")) 5765 ("sl" 5766 ;; Based on https://sl.wikipedia.org/wiki/Narekovaj 5767 (primary-opening :utf-8 "«" :html "«" :latex "{}<<" 5768 :texinfo "@guillemetleft{}") 5769 (primary-closing :utf-8 "»" :html "»" :latex ">>{}" 5770 :texinfo "@guillemetright{}") 5771 (secondary-opening 5772 :utf-8 "„" :html "„" :latex "\\glqq{}" :texinfo "@quotedblbase{}") 5773 (secondary-closing 5774 :utf-8 "“" :html "“" :latex "\\grqq{}" :texinfo "@quotedblleft{}") 5775 (apostrophe :utf-8 "’" :html "’")) 5776 ("sv" 5777 ;; Based on https://sv.wikipedia.org/wiki/Citattecken 5778 (primary-opening :utf-8 "”" :html "”" :latex "’’" :texinfo "’’") 5779 (primary-closing :utf-8 "”" :html "”" :latex "’’" :texinfo "’’") 5780 (secondary-opening :utf-8 "’" :html "’" :latex "’" :texinfo "`") 5781 (secondary-closing :utf-8 "’" :html "’" :latex "’" :texinfo "'") 5782 (apostrophe :utf-8 "’" :html "’"))) 5783 "Smart quotes translations. 5784 5785 Alist whose CAR is a language string and CDR is an alist with 5786 quote type as key and a plist associating various encodings to 5787 their translation as value. 5788 5789 A quote type can be any symbol among `primary-opening', 5790 `primary-closing', `secondary-opening', `secondary-closing' and 5791 `apostrophe'. 5792 5793 Valid encodings include `:utf-8', `:html', `:latex' and 5794 `:texinfo'. 5795 5796 If no translation is found, the quote character is left as-is.") 5797 5798 (defun org-export--smart-quote-status (s info) 5799 "Return smart quote status at the beginning of string S. 5800 INFO is the current export state, as a plist." 5801 (let* ((parent (org-element-property :parent s)) 5802 (cache (or (plist-get info :smart-quote-cache) 5803 (let ((table (make-hash-table :test #'eq))) 5804 (plist-put info :smart-quote-cache table) 5805 table))) 5806 (value (gethash parent cache 'missing-data))) 5807 (if (not (eq value 'missing-data)) (cdr (assq s value)) 5808 (let (level1-open full-status) 5809 (org-element-map 5810 (let ((secondary (org-element-secondary-p s))) 5811 (if secondary (org-element-property secondary parent) 5812 (org-element-contents parent))) 5813 'plain-text 5814 (lambda (text) 5815 (let ((start 0) current-status) 5816 (while (setq start (string-match "['\"]" text start)) 5817 (push 5818 (cond 5819 ((equal (match-string 0 text) "\"") 5820 (setf level1-open (not level1-open)) 5821 (if level1-open 'primary-opening 'primary-closing)) 5822 ;; Not already in a level 1 quote: this is an 5823 ;; apostrophe. 5824 ((not level1-open) 'apostrophe) 5825 ;; Extract previous char and next char. As 5826 ;; a special case, they can also be set to `blank', 5827 ;; `no-blank' or nil. Then determine if current 5828 ;; match is allowed as an opening quote or a closing 5829 ;; quote. 5830 (t 5831 (let* ((previous 5832 (if (> start 0) (substring text (1- start) start) 5833 (let ((p (org-export-get-previous-element 5834 text info))) 5835 (cond ((not p) nil) 5836 ((stringp p) (substring p -1)) 5837 ((memq (org-element-property :post-blank p) 5838 '(0 nil)) 5839 'no-blank) 5840 (t 'blank))))) 5841 (next 5842 (if (< (1+ start) (length text)) 5843 (substring text (1+ start) (+ start 2)) 5844 (let ((n (org-export-get-next-element text info))) 5845 (cond ((not n) nil) 5846 ((stringp n) (substring n 0 1)) 5847 (t 'no-blank))))) 5848 (allow-open 5849 (and (if (stringp previous) 5850 (string-match "\\s\"\\|\\s-\\|\\s(" 5851 previous) 5852 (memq previous '(blank nil))) 5853 (if (stringp next) 5854 (string-match "\\w\\|\\s.\\|\\s_" next) 5855 (eq next 'no-blank)))) 5856 (allow-close 5857 (and (if (stringp previous) 5858 (string-match "\\w\\|\\s.\\|\\s_" previous) 5859 (eq previous 'no-blank)) 5860 (if (stringp next) 5861 (string-match "\\s-\\|\\s)\\|\\s.\\|\\s\"" 5862 next) 5863 (memq next '(blank nil)))))) 5864 (cond 5865 ((and allow-open allow-close) (error "Should not happen")) 5866 (allow-open 'secondary-opening) 5867 (allow-close 'secondary-closing) 5868 (t 'apostrophe))))) 5869 current-status) 5870 (cl-incf start)) 5871 (when current-status 5872 (push (cons text (nreverse current-status)) full-status)))) 5873 info nil org-element-recursive-objects) 5874 (puthash parent full-status cache) 5875 (cdr (assq s full-status)))))) 5876 5877 (defun org-export-activate-smart-quotes (s encoding info &optional original) 5878 "Replace regular quotes with \"smart\" quotes in string S. 5879 5880 ENCODING is a symbol among `:html', `:latex', `:texinfo' and 5881 `:utf-8'. INFO is a plist used as a communication channel. 5882 5883 The function has to retrieve information about string 5884 surroundings in parse tree. It can only happen with an 5885 unmodified string. Thus, if S has already been through another 5886 process, a non-nil ORIGINAL optional argument will provide that 5887 original string. 5888 5889 Return the new string." 5890 (let ((quote-status 5891 (copy-sequence (org-export--smart-quote-status (or original s) info)))) 5892 (replace-regexp-in-string 5893 "['\"]" 5894 (lambda (match) 5895 (or (plist-get 5896 (cdr (assq (pop quote-status) 5897 (cdr (assoc (plist-get info :language) 5898 org-export-smart-quotes-alist)))) 5899 encoding) 5900 match)) 5901 s nil t))) 5902 5903 ;;;; Topology 5904 ;; 5905 ;; Here are various functions to retrieve information about the 5906 ;; neighborhood of a given element or object. Neighbors of interest 5907 ;; are direct parent (`org-export-get-parent'), parent headline 5908 ;; (`org-export-get-parent-headline'), first element containing an 5909 ;; object, (`org-export-get-parent-element'), parent table 5910 ;; (`org-export-get-parent-table'), previous element or object 5911 ;; (`org-export-get-previous-element') and next element or object 5912 ;; (`org-export-get-next-element'). 5913 5914 ;; defsubst org-export-get-parent must be defined before first use 5915 5916 (defun org-export-get-parent-headline (blob) 5917 "Return BLOB parent headline or nil. 5918 BLOB is the element or object being considered." 5919 (org-element-lineage blob '(headline))) 5920 5921 (defun org-export-get-parent-element (object) 5922 "Return first element containing OBJECT or nil. 5923 OBJECT is the object to consider." 5924 (org-element-lineage object org-element-all-elements)) 5925 5926 (defun org-export-get-parent-table (object) 5927 "Return OBJECT parent table or nil. 5928 OBJECT is either a `table-cell' or `table-element' type object." 5929 (org-element-lineage object '(table))) 5930 5931 (defun org-export-get-previous-element (blob info &optional n) 5932 "Return previous element or object. 5933 5934 BLOB is an element or object. INFO is a plist used as 5935 a communication channel. Return previous exportable element or 5936 object, a string, or nil. 5937 5938 When optional argument N is a positive integer, return a list 5939 containing up to N siblings before BLOB, from farthest to 5940 closest. With any other non-nil value, return a list containing 5941 all of them." 5942 (let* ((secondary (org-element-secondary-p blob)) 5943 (parent (org-export-get-parent blob)) 5944 (siblings 5945 (if secondary (org-element-property secondary parent) 5946 (org-element-contents parent))) 5947 prev) 5948 (catch 'exit 5949 (dolist (obj (cdr (memq blob (reverse siblings))) prev) 5950 (cond ((memq obj (plist-get info :ignore-list))) 5951 ((null n) (throw 'exit obj)) 5952 ((not (wholenump n)) (push obj prev)) 5953 ((zerop n) (throw 'exit prev)) 5954 (t (cl-decf n) (push obj prev))))))) 5955 5956 (defun org-export-get-next-element (blob info &optional n) 5957 "Return next element or object. 5958 5959 BLOB is an element or object. INFO is a plist used as 5960 a communication channel. Return next exportable element or 5961 object, a string, or nil. 5962 5963 When optional argument N is a positive integer, return a list 5964 containing up to N siblings after BLOB, from closest to farthest. 5965 With any other non-nil value, return a list containing all of 5966 them." 5967 (let* ((secondary (org-element-secondary-p blob)) 5968 (parent (org-export-get-parent blob)) 5969 (siblings 5970 (cdr (memq blob 5971 (if secondary (org-element-property secondary parent) 5972 (org-element-contents parent))))) 5973 next) 5974 (catch 'exit 5975 (dolist (obj siblings (nreverse next)) 5976 (cond ((memq obj (plist-get info :ignore-list))) 5977 ((null n) (throw 'exit obj)) 5978 ((not (wholenump n)) (push obj next)) 5979 ((zerop n) (throw 'exit (nreverse next))) 5980 (t (cl-decf n) (push obj next))))))) 5981 5982 5983 ;;;; Translation 5984 ;; 5985 ;; `org-export-translate' translates a string according to the language 5986 ;; specified by the LANGUAGE keyword. `org-export-dictionary' contains 5987 ;; the dictionary used for the translation. 5988 5989 (defconst org-export-dictionary 5990 '(("%e %n: %c" 5991 ("fr" :default "%e %n : %c" :html "%e %n : %c")) 5992 ("Author" 5993 ("ar" :default "تأليف") 5994 ("ca" :default "Autor") 5995 ("cs" :default "Autor") 5996 ("da" :default "Forfatter") 5997 ("de" :default "Autor") 5998 ("eo" :html "Aŭtoro") 5999 ("es" :default "Autor") 6000 ("et" :default "Autor") 6001 ("fa" :default "نویسنده") 6002 ("fi" :html "Tekijä") 6003 ("fr" :default "Auteur") 6004 ("hu" :default "Szerzõ") 6005 ("is" :html "Höfundur") 6006 ("it" :default "Autore") 6007 ("ja" :default "著者" :html "著者") 6008 ("nl" :default "Auteur") 6009 ("no" :default "Forfatter") 6010 ("nb" :default "Forfatter") 6011 ("nn" :default "Forfattar") 6012 ("pl" :default "Autor") 6013 ("pt_BR" :default "Autor") 6014 ("ro" :default "Autor") 6015 ("ru" :html "Автор" :utf-8 "Автор") 6016 ("sl" :default "Avtor") 6017 ("sv" :html "Författare") 6018 ("tr" :default "Yazar") 6019 ("uk" :html "Автор" :utf-8 "Автор") 6020 ("zh-CN" :html "作者" :utf-8 "作者") 6021 ("zh-TW" :html "作者" :utf-8 "作者")) 6022 ("Continued from previous page" 6023 ("ar" :default "تتمة الصفحة السابقة") 6024 ("cs" :default "Pokračování z předchozí strany") 6025 ("de" :default "Fortsetzung von vorheriger Seite") 6026 ("es" :html "Continúa de la página anterior" :ascii "Continua de la pagina anterior" :default "Continúa de la página anterior") 6027 ("fa" :default "ادامه از صفحهٔ قبل") 6028 ("fr" :default "Suite de la page précédente") 6029 ("it" :default "Continua da pagina precedente") 6030 ("ja" :default "前ページからの続き") 6031 ("nl" :default "Vervolg van vorige pagina") 6032 ("pl" :default "Ciąg dalszy poprzedniej strony") 6033 ("pt" :default "Continuação da página anterior") 6034 ("pt_BR" :html "Continuação da página anterior" :ascii "Continuacao da pagina anterior" :default "Continuação da página anterior") 6035 ("ro" :default "Continuare de pe pagina precedentă") 6036 ("ru" :html "(Продолжение)" 6037 :utf-8 "(Продолжение)") 6038 ("sl" :default "Nadaljevanje s prejšnje strani") 6039 ("tr" :default "Önceki sayfadan devam ediyor")) 6040 ("Continued on next page" 6041 ("ar" :default "التتمة في الصفحة التالية") 6042 ("cs" :default "Pokračuje na další stránce") 6043 ("de" :default "Fortsetzung nächste Seite") 6044 ("es" :html "Continúa en la siguiente página" :ascii "Continua en la siguiente pagina" :default "Continúa en la siguiente página") 6045 ("fa" :default "ادامه در صفحهٔ بعد") 6046 ("fr" :default "Suite page suivante") 6047 ("it" :default "Continua alla pagina successiva") 6048 ("ja" :default "次ページに続く") 6049 ("nl" :default "Vervolg op volgende pagina") 6050 ("pl" :default "Kontynuacja na następnej stronie") 6051 ("pt" :default "Continua na página seguinte") 6052 ("pt_BR" :html "Continua na próxima página" :ascii "Continua na proxima pagina" :default "Continua na próxima página") 6053 ("ro" :default "Continuare pe pagina următoare") 6054 ("ru" :html "(Продолжение следует)" 6055 :utf-8 "(Продолжение следует)") 6056 ("sl" :default "Nadaljevanje na naslednji strani") 6057 ("tr" :default "Devamı sonraki sayfada")) 6058 ("Created" 6059 ("cs" :default "Vytvořeno") 6060 ("fa" :default "ساخته شده") 6061 ("nl" :default "Gemaakt op") ;; must be followed by a date or date+time 6062 ("pt_BR" :default "Criado em") 6063 ("ro" :default "Creat") 6064 ("sl" :default "Ustvarjeno") 6065 ("tr" :default "Oluşturuldu")) 6066 ("Date" 6067 ("ar" :default "بتاريخ") 6068 ("ca" :default "Data") 6069 ("cs" :default "Datum") 6070 ("da" :default "Dato") 6071 ("de" :default "Datum") 6072 ("eo" :default "Dato") 6073 ("es" :default "Fecha") 6074 ("et" :html "Kuupäev" :utf-8 "Kuupäev") 6075 ("fa" :default "تاریخ") 6076 ("fi" :html "Päivämäärä") 6077 ("hu" :html "Dátum") 6078 ("is" :default "Dagsetning") 6079 ("it" :default "Data") 6080 ("ja" :default "日付" :html "日付") 6081 ("nl" :default "Datum") 6082 ("no" :default "Dato") 6083 ("nb" :default "Dato") 6084 ("nn" :default "Dato") 6085 ("pl" :default "Data") 6086 ("ro" :default "Data") 6087 ("pt_BR" :default "Data") 6088 ("ru" :html "Дата" :utf-8 "Дата") 6089 ("sl" :default "Datum") 6090 ("sv" :default "Datum") 6091 ("tr" :default "Tarih") 6092 ("uk" :html "Дата" :utf-8 "Дата") 6093 ("zh-CN" :html "日期" :utf-8 "日期") 6094 ("zh-TW" :html "日期" :utf-8 "日期")) 6095 ("Equation" 6096 ("ar" :default "معادلة") 6097 ("cs" :default "Rovnice") 6098 ("da" :default "Ligning") 6099 ("de" :default "Gleichung") 6100 ("es" :ascii "Ecuacion" :html "Ecuación" :default "Ecuación") 6101 ("et" :html "Võrrand" :utf-8 "Võrrand") 6102 ("fa" :default "معادله") 6103 ("fr" :ascii "Equation" :default "Équation") 6104 ("is" :default "Jafna") 6105 ("ja" :default "方程式") 6106 ("nl" :default "Vergelijking") 6107 ("no" :default "Ligning") 6108 ("nb" :default "Ligning") 6109 ("nn" :default "Likning") 6110 ("pt_BR" :html "Equação" :default "Equação" :ascii "Equacao") 6111 ("ro" :default "Ecuația") 6112 ("ru" :html "Уравнение" 6113 :utf-8 "Уравнение") 6114 ("sl" :default "Enačba") 6115 ("sv" :default "Ekvation") 6116 ("tr" :default "Eşitlik") 6117 ("zh-CN" :html "方程" :utf-8 "方程")) 6118 ("Figure" 6119 ("ar" :default "شكل") 6120 ("cs" :default "Obrázek") 6121 ("da" :default "Figur") 6122 ("de" :default "Abbildung") 6123 ("es" :default "Figura") 6124 ("et" :default "Joonis") 6125 ("fa" :default "شکل") 6126 ("is" :default "Mynd") 6127 ("it" :default "Figura") 6128 ("ja" :default "図" :html "図") 6129 ("nl" :default "Figuur") 6130 ("no" :default "Illustrasjon") 6131 ("nb" :default "Illustrasjon") 6132 ("nn" :default "Illustrasjon") 6133 ("pt_BR" :default "Figura") 6134 ("ro" :default "Imaginea") 6135 ("ru" :html "Рисунок" :utf-8 "Рисунок") 6136 ("sv" :default "Illustration") 6137 ("tr" :default "Şekil") 6138 ("zh-CN" :html "图" :utf-8 "图")) 6139 ("Figure %d:" 6140 ("ar" :default "شكل %d:") 6141 ("cs" :default "Obrázek %d:") 6142 ("da" :default "Figur %d") 6143 ("de" :default "Abbildung %d:") 6144 ("es" :default "Figura %d:") 6145 ("et" :default "Joonis %d:") 6146 ("fa" :default "شکل %d:") 6147 ("fr" :default "Figure %d :" :html "Figure %d :") 6148 ("is" :default "Mynd %d") 6149 ("it" :default "Figura %d:") 6150 ("ja" :default "図%d: " :html "図%d: ") 6151 ("nl" :default "Figuur %d:" :html "Figuur %d:") 6152 ("no" :default "Illustrasjon %d") 6153 ("nb" :default "Illustrasjon %d") 6154 ("nn" :default "Illustrasjon %d") 6155 ("pt_BR" :default "Figura %d:") 6156 ("ro" :default "Imaginea %d:") 6157 ("ru" :html "Рис. %d.:" :utf-8 "Рис. %d.:") 6158 ("sl" :default "Slika %d") 6159 ("sv" :default "Illustration %d") 6160 ("tr" :default "Şekil %d:") 6161 ("zh-CN" :html "图%d " :utf-8 "图%d ")) 6162 ("Footnotes" 6163 ("ar" :default "الهوامش") 6164 ("ca" :html "Peus de pàgina") 6165 ("cs" :default "Poznámky pod čarou") 6166 ("da" :default "Fodnoter") 6167 ("de" :html "Fußnoten" :default "Fußnoten") 6168 ("eo" :default "Piednotoj") 6169 ("es" :ascii "Notas al pie de pagina" :html "Notas al pie de página" :default "Notas al pie de página") 6170 ("et" :html "Allmärkused" :utf-8 "Allmärkused") 6171 ("fa" :default "پانوشتها") 6172 ("fi" :default "Alaviitteet") 6173 ("fr" :default "Notes de bas de page") 6174 ("hu" :html "Lábjegyzet") 6175 ("is" :html "Aftanmálsgreinar") 6176 ("it" :html "Note a piè di pagina") 6177 ("ja" :default "脚注" :html "脚注") 6178 ("nl" :default "Voetnoten") 6179 ("no" :default "Fotnoter") 6180 ("nb" :default "Fotnoter") 6181 ("nn" :default "Fotnotar") 6182 ("pl" :default "Przypis") 6183 ("pt_BR" :html "Notas de Rodapé" :default "Notas de Rodapé" :ascii "Notas de Rodape") 6184 ("ro" :default "Note de subsol") 6185 ("ru" :html "Сноски" :utf-8 "Сноски") 6186 ("sl" :default "Opombe") 6187 ("sv" :default "Fotnoter") 6188 ("tr" :default "Dipnotlar") 6189 ("uk" :html "Примітки" 6190 :utf-8 "Примітки") 6191 ("zh-CN" :html "脚注" :utf-8 "脚注") 6192 ("zh-TW" :html "腳註" :utf-8 "腳註")) 6193 ("List of Listings" 6194 ("ar" :default "قائمة بالبرامج") 6195 ("cs" :default "Seznam programů") 6196 ("da" :default "Programmer") 6197 ("de" :default "Programmauflistungsverzeichnis") 6198 ("es" :ascii "Indice de Listados de programas" :html "Índice de Listados de programas" :default "Índice de Listados de programas") 6199 ("et" :default "Loendite nimekiri") 6200 ("fa" :default "فهرست برنامهریزیها") 6201 ("fr" :default "Liste des programmes") 6202 ("ja" :default "ソースコード目次") 6203 ("nl" :default "Lijst van programma's") 6204 ("no" :default "Dataprogrammer") 6205 ("nb" :default "Dataprogrammer") 6206 ("pt_BR" :html "Índice de Listagens" :default "Índice de Listagens" :ascii "Indice de Listagens") 6207 ("ru" :html "Список распечаток" 6208 :utf-8 "Список распечаток") 6209 ("sl" :default "Seznam programskih izpisov") 6210 ("tr" :default "Program Listesi") 6211 ("zh-CN" :html "代码目录" :utf-8 "代码目录")) 6212 ("List of Tables" 6213 ("ar" :default "قائمة بالجداول") 6214 ("cs" :default "Seznam tabulek") 6215 ("da" :default "Tabeller") 6216 ("de" :default "Tabellenverzeichnis") 6217 ("es" :ascii "Indice de tablas" :html "Índice de tablas" :default "Índice de tablas") 6218 ("et" :default "Tabelite nimekiri") 6219 ("fa" :default "فهرست جدولها") 6220 ("fr" :default "Liste des tableaux") 6221 ("is" :default "Töfluskrá" :html "Töfluskrá") 6222 ("it" :default "Indice delle tabelle") 6223 ("ja" :default "表目次") 6224 ("nl" :default "Lijst van tabellen") 6225 ("no" :default "Tabeller") 6226 ("nb" :default "Tabeller") 6227 ("nn" :default "Tabeller") 6228 ("pt_BR" :html "Índice de Tabelas" :default "Índice de Tabelas" :ascii "Indice de Tabelas") 6229 ("ro" :default "Tabele") 6230 ("ru" :html "Список таблиц" 6231 :utf-8 "Список таблиц") 6232 ("sl" :default "Seznam tabel") 6233 ("sv" :default "Tabeller") 6234 ("tr" :default "Tablo Listesi") 6235 ("zh-CN" :html "表格目录" :utf-8 "表格目录")) 6236 ("Listing" 6237 ("ar" :default "برنامج") 6238 ("cs" :default "Program") 6239 ("da" :default "Program") 6240 ("de" :default "Programmlisting") 6241 ("es" :default "Listado de programa") 6242 ("et" :default "Loend") 6243 ("fa" :default "برنامهریزی") 6244 ("fr" :default "Programme" :html "Programme") 6245 ("it" :default "Listato") 6246 ("ja" :default "ソースコード") 6247 ("nl" :default "Programma") 6248 ("no" :default "Dataprogram") 6249 ("nb" :default "Dataprogram") 6250 ("pt_BR" :default "Listagem") 6251 ("ro" :default "Lista") 6252 ("ru" :html "Распечатка" 6253 :utf-8 "Распечатка") 6254 ("sl" :default "Izpis programa") 6255 ("tr" :default "Program") 6256 ("zh-CN" :html "代码" :utf-8 "代码")) 6257 ("Listing %d:" 6258 ("ar" :default "برنامج %d:") 6259 ("cs" :default "Program %d:") 6260 ("da" :default "Program %d") 6261 ("de" :default "Programmlisting %d") 6262 ("es" :default "Listado de programa %d") 6263 ("et" :default "Loend %d") 6264 ("fa" :default "برنامهریزی %d:") 6265 ("fr" :default "Programme %d :" :html "Programme %d :") 6266 ("it" :default "Listato %d :") 6267 ("ja" :default "ソースコード%d:") 6268 ("nl" :default "Programma %d:" :html "Programma %d:") 6269 ("no" :default "Dataprogram %d") 6270 ("nb" :default "Dataprogram %d") 6271 ("ro" :default "Lista %d") 6272 ("pt_BR" :default "Listagem %d:") 6273 ("ru" :html "Распечатка %d.:" 6274 :utf-8 "Распечатка %d.:") 6275 ("sl" :default "Izpis programa %d") 6276 ("tr" :default "Program %d:") 6277 ("zh-CN" :html "代码%d " :utf-8 "代码%d ")) 6278 ("References" 6279 ("ar" :default "المراجع") 6280 ("cs" :default "Reference") 6281 ("de" :default "Quellen") 6282 ("es" :default "Referencias") 6283 ("fa" :default "منابع") 6284 ("fr" :ascii "References" :default "Références") 6285 ("it" :default "Riferimenti") 6286 ("nl" :default "Bronverwijzingen") 6287 ("pt_BR" :html "Referências" :default "Referências" :ascii "Referencias") 6288 ("ro" :default "Bibliografie") 6289 ("sl" :default "Reference") 6290 ("tr" :default "Referanslar")) 6291 ("See figure %s" 6292 ("cs" :default "Viz obrázek %s") 6293 ("fa" :default "نمایش شکل %s") 6294 ("fr" :default "cf. figure %s" 6295 :html "cf. figure %s" :latex "cf.~figure~%s") 6296 ("it" :default "Vedi figura %s") 6297 ("nl" :default "Zie figuur %s" 6298 :html "Zie figuur %s" :latex "Zie figuur~%s") 6299 ("pt_BR" :default "Veja a figura %s") 6300 ("ro" :default "Vezi figura %s") 6301 ("sl" :default "Glej sliko %s") 6302 ("tr" :default "bkz. şekil %s")) 6303 ("See listing %s" 6304 ("cs" :default "Viz program %s") 6305 ("fa" :default "نمایش برنامهریزی %s") 6306 ("fr" :default "cf. programme %s" 6307 :html "cf. programme %s" :latex "cf.~programme~%s") 6308 ("nl" :default "Zie programma %s" 6309 :html "Zie programma %s" :latex "Zie programma~%s") 6310 ("pt_BR" :default "Veja a listagem %s") 6311 ("ro" :default "Vezi tabelul %s") 6312 ("sl" :default "Glej izpis programa %s") 6313 ("tr" :default "bkz. program %s")) 6314 ("See section %s" 6315 ("ar" :default "انظر قسم %s") 6316 ("cs" :default "Viz sekce %s") 6317 ("da" :default "jævnfør afsnit %s") 6318 ("de" :default "siehe Abschnitt %s") 6319 ("es" :ascii "Vea seccion %s" :html "Vea sección %s" :default "Vea sección %s") 6320 ("et" :html "Vaata peatükki %s" :utf-8 "Vaata peatükki %s") 6321 ("fa" :default "نمایش بخش %s") 6322 ("fr" :default "cf. section %s") 6323 ("it" :default "Vedi sezione %s") 6324 ("ja" :default "セクション %s を参照") 6325 ("nl" :default "Zie sectie %s" 6326 :html "Zie sectie %s" :latex "Zie sectie~%s") 6327 ("pt_BR" :html "Veja a seção %s" :default "Veja a seção %s" 6328 :ascii "Veja a secao %s") 6329 ("ro" :default "Vezi secțiunea %s") 6330 ("ru" :html "См. раздел %s" 6331 :utf-8 "См. раздел %s") 6332 ("sl" :default "Glej poglavje %d") 6333 ("tr" :default "bkz. bölüm %s") 6334 ("zh-CN" :html "参见第%s节" :utf-8 "参见第%s节")) 6335 ("See table %s" 6336 ("cs" :default "Viz tabulka %s") 6337 ("fa" :default "نمایش جدول %s") 6338 ("fr" :default "cf. tableau %s" 6339 :html "cf. tableau %s" :latex "cf.~tableau~%s") 6340 ("it" :default "Vedi tabella %s") 6341 ("nl" :default "Zie tabel %s" 6342 :html "Zie tabel %s" :latex "Zie tabel~%s") 6343 ("pt_BR" :default "Veja a tabela %s") 6344 ("ro" :default "Vezi tabelul %s") 6345 ("sl" :default "Glej tabelo %s") 6346 ("tr" :default "bkz. tablo %s")) 6347 ("Table" 6348 ("ar" :default "جدول") 6349 ("cs" :default "Tabulka") 6350 ("de" :default "Tabelle") 6351 ("es" :default "Tabla") 6352 ("et" :default "Tabel") 6353 ("fa" :default "جدول") 6354 ("fr" :default "Tableau") 6355 ("is" :default "Tafla") 6356 ("it" :default "Tabella") 6357 ("ja" :default "表" :html "表") 6358 ("nl" :default "Tabel") 6359 ("pt_BR" :default "Tabela") 6360 ("ro" :default "Tabel") 6361 ("ru" :html "Таблица" 6362 :utf-8 "Таблица") 6363 ("tr" :default "Tablo") 6364 ("zh-CN" :html "表" :utf-8 "表")) 6365 ("Table %d:" 6366 ("ar" :default "جدول %d:") 6367 ("cs" :default "Tabulka %d:") 6368 ("da" :default "Tabel %d") 6369 ("de" :default "Tabelle %d") 6370 ("es" :default "Tabla %d") 6371 ("et" :default "Tabel %d") 6372 ("fa" :default "جدول %d") 6373 ("fr" :default "Tableau %d :") 6374 ("is" :default "Tafla %d") 6375 ("it" :default "Tabella %d:") 6376 ("ja" :default "表%d:" :html "表%d:") 6377 ("nl" :default "Tabel %d:" :html "Tabel %d:") 6378 ("no" :default "Tabell %d") 6379 ("nb" :default "Tabell %d") 6380 ("nn" :default "Tabell %d") 6381 ("pt_BR" :default "Tabela %d:") 6382 ("ro" :default "Tabel %d") 6383 ("ru" :html "Таблица %d.:" 6384 :utf-8 "Таблица %d.:") 6385 ("sl" :default "Tabela %d") 6386 ("sv" :default "Tabell %d") 6387 ("tr" :default "Tablo %d") 6388 ("zh-CN" :html "表%d " :utf-8 "表%d ")) 6389 ("Table of Contents" 6390 ("ar" :default "قائمة المحتويات") 6391 ("ca" :html "Índex") 6392 ("cs" :default "Obsah") 6393 ("da" :default "Indhold") 6394 ("de" :default "Inhaltsverzeichnis") 6395 ("eo" :default "Enhavo") 6396 ("es" :ascii "Indice" :html "Índice" :default "Índice") 6397 ("et" :default "Sisukord") 6398 ("fa" :default "فهرست") 6399 ("fi" :html "Sisällysluettelo") 6400 ("fr" :ascii "Sommaire" :default "Table des matières") 6401 ("hu" :html "Tartalomjegyzék") 6402 ("is" :default "Efnisyfirlit") 6403 ("it" :default "Indice") 6404 ("ja" :default "目次" :html "目次") 6405 ("nl" :default "Inhoudsopgave") 6406 ("no" :default "Innhold") 6407 ("nb" :default "Innhold") 6408 ("nn" :default "Innhald") 6409 ("pl" :html "Spis treści") 6410 ("pt_BR" :html "Índice" :utf8 "Índice" :ascii "Indice") 6411 ("ro" :default "Cuprins") 6412 ("ru" :html "Содержание" 6413 :utf-8 "Содержание") 6414 ("sl" :default "Kazalo") 6415 ("sv" :html "Innehåll") 6416 ("tr" :default "İçindekiler") 6417 ("uk" :html "Зміст" :utf-8 "Зміст") 6418 ("zh-CN" :html "目录" :utf-8 "目录") 6419 ("zh-TW" :html "目錄" :utf-8 "目錄")) 6420 ("Unknown reference" 6421 ("ar" :default "مرجع غير معرّف") 6422 ("da" :default "ukendt reference") 6423 ("de" :default "Unbekannter Verweis") 6424 ("es" :default "Referencia desconocida") 6425 ("et" :default "Tundmatu viide") 6426 ("fa" :default "منبع ناشناس") 6427 ("fr" :ascii "Destination inconnue" :default "Référence inconnue") 6428 ("it" :default "Riferimento sconosciuto") 6429 ("ja" :default "不明な参照先") 6430 ("nl" :default "Onbekende verwijzing") 6431 ("pt_BR" :html "Referência desconhecida" :default "Referência desconhecida" :ascii "Referencia desconhecida") 6432 ("ro" :default "Referință necunoscută") 6433 ("ru" :html "Неизвестная ссылка" 6434 :utf-8 "Неизвестная ссылка") 6435 ("sl" :default "Neznana referenca") 6436 ("tr" :default "Bilinmeyen referans") 6437 ("zh-CN" :html "未知引用" :utf-8 "未知引用"))) 6438 "Dictionary for export engine. 6439 6440 Alist whose car is the string to translate and cdr is an alist 6441 whose car is the language string and cdr is a plist whose 6442 properties are possible charsets and values translated terms. 6443 6444 It is used as a database for `org-export-translate'. Since this 6445 function returns the string as-is if no translation was found, 6446 the variable only needs to record values different from the 6447 entry.") 6448 6449 (defun org-export-translate (s encoding info) 6450 "Translate string S according to language specification. 6451 6452 ENCODING is a symbol among `:ascii', `:html', `:latex', `:latin1' 6453 and `:utf-8'. INFO is a plist used as a communication channel. 6454 6455 Translation depends on `:language' property. Return the 6456 translated string. If no translation is found, try to fall back 6457 to `:default' encoding. If it fails, return S." 6458 (let* ((lang (plist-get info :language)) 6459 (translations (cdr (assoc lang 6460 (cdr (assoc s org-export-dictionary)))))) 6461 (or (plist-get translations encoding) 6462 (plist-get translations :default) 6463 s))) 6464 6465 6466 6467 ;;; Asynchronous Export 6468 ;; 6469 ;; `org-export-async-start' is the entry point for asynchronous 6470 ;; export. It recreates current buffer (including visibility, 6471 ;; narrowing and visited file) in an external Emacs process, and 6472 ;; evaluates a command there. It then applies a function on the 6473 ;; returned results in the current process. 6474 ;; 6475 ;; At a higher level, `org-export-to-buffer' and `org-export-to-file' 6476 ;; allow exporting to a buffer or a file, asynchronously or not. 6477 ;; 6478 ;; `org-export-output-file-name' is an auxiliary function meant to be 6479 ;; used with `org-export-to-file'. With a given extension, it tries 6480 ;; to provide a canonical file name to write export output to. 6481 ;; 6482 ;; Asynchronously generated results are never displayed directly. 6483 ;; Instead, they are stored in `org-export-stack-contents'. They can 6484 ;; then be retrieved by calling `org-export-stack'. 6485 ;; 6486 ;; Export Stack is viewed through a dedicated major mode 6487 ;;`org-export-stack-mode' and tools: `org-export-stack-refresh', 6488 ;;`org-export-stack-remove', `org-export-stack-view' and 6489 ;;`org-export-stack-clear'. 6490 ;; 6491 ;; For back-ends, `org-export-add-to-stack' add a new source to stack. 6492 ;; It should be used whenever `org-export-async-start' is called. 6493 6494 (defun org-export-async-start (fun body) 6495 "Call function FUN on the results returned by BODY evaluation. 6496 6497 FUN is an anonymous function of one argument. BODY should be a valid 6498 ELisp source expression. BODY evaluation happens in an asynchronous process, 6499 from a buffer which is an exact copy of the current one. 6500 6501 Use `org-export-add-to-stack' in FUN in order to register results 6502 in the stack. 6503 6504 This is a low level function. See also `org-export-to-buffer' 6505 and `org-export-to-file' for more specialized functions." 6506 (declare (indent 1)) 6507 ;; Write the full sexp evaluating BODY in a copy of the current 6508 ;; buffer to a temporary file, as it may be too long for program 6509 ;; args in `start-process'. 6510 (with-temp-message "Initializing asynchronous export process" 6511 (let ((copy-fun (org-export--generate-copy-script (current-buffer))) 6512 (temp-file (make-temp-file "org-export-process"))) 6513 (let ((coding-system-for-write 'utf-8-emacs-unix)) 6514 (write-region 6515 ;; Null characters (from variable values) are inserted 6516 ;; within the file. As a consequence, coding system for 6517 ;; buffer contents could fail to be recognized properly. 6518 (format ";; -*- coding: utf-8-emacs-unix; lexical-binding:t -*-\n%S" 6519 `(with-temp-buffer 6520 ,(when org-export-async-debug '(setq debug-on-error t)) 6521 ;; Ignore `kill-emacs-hook' and code evaluation 6522 ;; queries from Babel as we need a truly 6523 ;; non-interactive process. 6524 (setq kill-emacs-hook nil 6525 org-babel-confirm-evaluate-answer-no t) 6526 ;; Initialize export framework. 6527 (require 'ox) 6528 ;; Re-create current buffer there. 6529 (funcall ',copy-fun) 6530 (restore-buffer-modified-p nil) 6531 ;; Sexp to evaluate in the buffer. 6532 (print ,body))) 6533 nil temp-file nil 'silent)) 6534 ;; Start external process. 6535 (let* ((process-connection-type nil) 6536 (proc-buffer (generate-new-buffer-name "*Org Export Process*")) 6537 (process 6538 (apply 6539 #'start-process 6540 (append 6541 (list "org-export-process" 6542 proc-buffer 6543 (expand-file-name invocation-name invocation-directory) 6544 "--batch") 6545 (if org-export-async-init-file 6546 (list "-Q" "-l" org-export-async-init-file) 6547 (list "-l" user-init-file)) 6548 (list "-l" temp-file))))) 6549 ;; Register running process in stack. 6550 (org-export-add-to-stack (get-buffer proc-buffer) nil process) 6551 ;; Set-up sentinel in order to catch results. 6552 (let ((handler fun)) 6553 (set-process-sentinel 6554 process 6555 (lambda (p _status) 6556 (let ((proc-buffer (process-buffer p))) 6557 (when (eq (process-status p) 'exit) 6558 (unwind-protect 6559 (if (zerop (process-exit-status p)) 6560 (unwind-protect 6561 (let ((results 6562 (with-current-buffer proc-buffer 6563 (goto-char (point-max)) 6564 (backward-sexp) 6565 (read (current-buffer))))) 6566 (funcall handler results)) 6567 (unless org-export-async-debug 6568 (and (get-buffer proc-buffer) 6569 (kill-buffer proc-buffer)))) 6570 (org-export-add-to-stack proc-buffer nil p) 6571 (ding) 6572 (message "Process `%s' exited abnormally" p)) 6573 (unless org-export-async-debug 6574 (delete-file temp-file)))))))))))) 6575 6576 ;;;###autoload 6577 (defun org-export-to-buffer 6578 (backend buffer 6579 &optional async subtreep visible-only body-only ext-plist 6580 post-process) 6581 "Call `org-export-as' with output to a specified buffer. 6582 6583 BACKEND is either an export back-end, as returned by, e.g., 6584 `org-export-create-backend', or a symbol referring to 6585 a registered back-end. 6586 6587 BUFFER is the name of the output buffer. If it already exists, 6588 it will be erased first, otherwise, it will be created. 6589 6590 A non-nil optional argument ASYNC means the process should happen 6591 asynchronously. The resulting buffer should then be accessible 6592 through the `org-export-stack' interface. When ASYNC is nil, the 6593 buffer is displayed if `org-export-show-temporary-export-buffer' 6594 is non-nil. 6595 6596 Optional arguments SUBTREEP, VISIBLE-ONLY, BODY-ONLY and 6597 EXT-PLIST are similar to those used in `org-export-as', which 6598 see. 6599 6600 Optional argument POST-PROCESS is a function which should accept 6601 no argument. It is always called within the current process, 6602 from BUFFER, with point at its beginning. Export back-ends can 6603 use it to set a major mode there, e.g, 6604 6605 (defun org-latex-export-as-latex 6606 (&optional async subtreep visible-only body-only ext-plist) 6607 (interactive) 6608 (org-export-to-buffer \\='latex \"*Org LATEX Export*\" 6609 async subtreep visible-only body-only ext-plist 6610 #'LaTeX-mode)) 6611 6612 When expressed as an anonymous function, using `lambda', 6613 POST-PROCESS needs to be quoted. 6614 6615 This function returns BUFFER." 6616 (declare (indent 2)) 6617 (if async 6618 (org-export-async-start 6619 (let ((cs buffer-file-coding-system)) 6620 (lambda (output) 6621 (with-current-buffer (get-buffer-create buffer) 6622 (erase-buffer) 6623 (setq buffer-file-coding-system cs) 6624 (insert output) 6625 (goto-char (point-min)) 6626 (org-export-add-to-stack (current-buffer) backend) 6627 (ignore-errors (funcall post-process))))) 6628 `(org-export-as 6629 ',backend ,subtreep ,visible-only ,body-only ',ext-plist)) 6630 (let ((output 6631 (org-export-as backend subtreep visible-only body-only ext-plist)) 6632 (buffer (get-buffer-create buffer)) 6633 (encoding buffer-file-coding-system)) 6634 (when (and (org-string-nw-p output) (org-export--copy-to-kill-ring-p)) 6635 (org-kill-new output)) 6636 (with-current-buffer buffer 6637 (erase-buffer) 6638 (setq buffer-file-coding-system encoding) 6639 (insert output) 6640 (goto-char (point-min)) 6641 (and (functionp post-process) (funcall post-process))) 6642 (when org-export-show-temporary-export-buffer 6643 (switch-to-buffer-other-window buffer)) 6644 buffer))) 6645 6646 ;;;###autoload 6647 (defun org-export-to-file 6648 (backend file &optional async subtreep visible-only body-only ext-plist 6649 post-process) 6650 "Call `org-export-as' with output to a specified file. 6651 6652 BACKEND is either an export back-end, as returned by, e.g., 6653 `org-export-create-backend', or a symbol referring to 6654 a registered back-end. FILE is the name of the output file, as 6655 a string. 6656 6657 A non-nil optional argument ASYNC means the process should happen 6658 asynchronously. The resulting buffer will then be accessible 6659 through the `org-export-stack' interface. 6660 6661 Optional arguments SUBTREEP, VISIBLE-ONLY, BODY-ONLY and 6662 EXT-PLIST are similar to those used in `org-export-as', which 6663 see. 6664 6665 Optional argument POST-PROCESS is called with FILE as its 6666 argument and happens asynchronously when ASYNC is non-nil. It 6667 has to return a file name, or nil. Export back-ends can use this 6668 to send the output file through additional processing, e.g, 6669 6670 (defun org-latex-export-to-latex 6671 (&optional async subtreep visible-only body-only ext-plist) 6672 (interactive) 6673 (let ((outfile (org-export-output-file-name \".tex\" subtreep))) 6674 (org-export-to-file \\='latex outfile 6675 async subtreep visible-only body-only ext-plist 6676 #\\='org-latex-compile))) 6677 6678 When expressed as an anonymous function, using `lambda', 6679 POST-PROCESS needs to be quoted. 6680 6681 The function returns either a file name returned by POST-PROCESS, 6682 or FILE." 6683 (declare (indent 2)) 6684 (if (not (file-writable-p file)) (error "Output file not writable") 6685 (let ((ext-plist (org-combine-plists `(:output-file ,file) ext-plist)) 6686 (encoding (or org-export-coding-system buffer-file-coding-system))) 6687 (if async 6688 (org-export-async-start 6689 (lambda (file) 6690 (org-export-add-to-stack (expand-file-name file) backend)) 6691 `(let ((output 6692 (org-export-as 6693 ',backend ,subtreep ,visible-only ,body-only 6694 ',ext-plist))) 6695 (with-temp-buffer 6696 (insert output) 6697 (let ((coding-system-for-write ',encoding)) 6698 (write-region (point-min) (point-max) ,file))) 6699 (or (ignore-errors (funcall ',post-process ,file)) ,file))) 6700 (let ((output (org-export-as 6701 backend subtreep visible-only body-only ext-plist))) 6702 (with-temp-buffer 6703 (insert output) 6704 (let ((coding-system-for-write encoding)) 6705 (write-region (point-min) (point-max) file))) 6706 (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) 6707 (org-kill-new output)) 6708 ;; Get proper return value. 6709 (or (and (functionp post-process) (funcall post-process file)) 6710 file)))))) 6711 6712 (defun org-export-output-file-name (extension &optional subtreep pub-dir) 6713 "Return output file's name according to buffer specifications. 6714 6715 EXTENSION is a string representing the output file extension, 6716 with the leading dot. 6717 6718 With a non-nil optional argument SUBTREEP, try to determine 6719 output file's name by looking for \"EXPORT_FILE_NAME\" property 6720 of subtree at point. 6721 6722 When optional argument PUB-DIR is set, use it as the publishing 6723 directory. 6724 6725 Return file name as a string." 6726 (let* ((visited-file (buffer-file-name (buffer-base-buffer))) 6727 (base-name 6728 (concat 6729 (file-name-sans-extension 6730 (or 6731 ;; Check EXPORT_FILE_NAME subtree property. 6732 (and subtreep (org-entry-get nil "EXPORT_FILE_NAME" 'selective)) 6733 ;; Check #+EXPORT_FILE_NAME keyword. 6734 (org-with-point-at (point-min) 6735 (catch :found 6736 (let ((case-fold-search t)) 6737 (while (re-search-forward 6738 "^[ \t]*#\\+EXPORT_FILE_NAME:[ \t]+\\S-" nil t) 6739 (let ((element (org-element-at-point))) 6740 (when (eq 'keyword (org-element-type element)) 6741 (throw :found 6742 (org-element-property :value element)))))))) 6743 ;; Extract from buffer's associated file, if any. 6744 (and visited-file 6745 (file-name-nondirectory 6746 ;; For a .gpg visited file, remove the .gpg extension: 6747 (replace-regexp-in-string "\\.gpg\\'" "" visited-file))) 6748 ;; Can't determine file name on our own: ask user. 6749 (read-file-name 6750 "Output file: " pub-dir nil nil nil 6751 (lambda (n) (string= extension (file-name-extension n t)))))) 6752 extension)) 6753 (output-file 6754 ;; Build file name. Enforce EXTENSION over whatever user 6755 ;; may have come up with. PUB-DIR, if defined, always has 6756 ;; precedence over any provided path. 6757 (cond 6758 (pub-dir (concat (file-name-as-directory pub-dir) 6759 (file-name-nondirectory base-name))) 6760 (t base-name)))) 6761 ;; If writing to OUTPUT-FILE would overwrite original file, append 6762 ;; EXTENSION another time to final name. 6763 (if (and visited-file (file-equal-p visited-file output-file)) 6764 (concat output-file extension) 6765 output-file))) 6766 6767 (defun org-export-add-to-stack (source backend &optional process) 6768 "Add a new result to export stack if not present already. 6769 6770 SOURCE is a buffer or a file name containing export results. 6771 BACKEND is a symbol representing export back-end used to generate 6772 it. 6773 6774 Entries already pointing to SOURCE and unavailable entries are 6775 removed beforehand. Return the new stack." 6776 (setq org-export-stack-contents 6777 (cons (list source backend (or process (current-time))) 6778 (org-export-stack-remove source)))) 6779 6780 (defun org-export-stack () 6781 "Menu for asynchronous export results and running processes." 6782 (interactive) 6783 (let ((buffer (get-buffer-create "*Org Export Stack*"))) 6784 (with-current-buffer buffer 6785 (org-export-stack-mode) 6786 (tabulated-list-print t)) 6787 (pop-to-buffer buffer)) 6788 (message "Type \"q\" to quit, \"?\" for help")) 6789 6790 (defun org-export-stack-clear () 6791 "Remove all entries from export stack." 6792 (interactive) 6793 (setq org-export-stack-contents nil)) 6794 6795 (defun org-export-stack-refresh () 6796 "Refresh the export stack." 6797 (interactive) 6798 (tabulated-list-print t)) 6799 6800 (defun org-export-stack-remove (&optional source) 6801 "Remove export results at point from stack. 6802 If optional argument SOURCE is non-nil, remove it instead." 6803 (interactive) 6804 (let ((source (or source (org-export--stack-source-at-point)))) 6805 (setq org-export-stack-contents 6806 (cl-remove-if (lambda (el) (equal (car el) source)) 6807 org-export-stack-contents)))) 6808 6809 (defun org-export-stack-view (&optional in-emacs) 6810 "View export results at point in stack. 6811 With an optional prefix argument IN-EMACS, force viewing files 6812 within Emacs." 6813 (interactive "P") 6814 (let ((source (org-export--stack-source-at-point))) 6815 (cond ((processp source) 6816 (org-switch-to-buffer-other-window (process-buffer source))) 6817 ((bufferp source) (org-switch-to-buffer-other-window source)) 6818 (t (org-open-file source in-emacs))))) 6819 6820 (defvar org-export-stack-mode-map 6821 (let ((km (make-sparse-keymap))) 6822 (set-keymap-parent km tabulated-list-mode-map) 6823 (define-key km " " #'next-line) 6824 (define-key km "\C-n" #'next-line) 6825 (define-key km [down] #'next-line) 6826 (define-key km "\C-p" #'previous-line) 6827 (define-key km "\C-?" #'previous-line) 6828 (define-key km [up] #'previous-line) 6829 (define-key km "C" #'org-export-stack-clear) 6830 (define-key km "v" #'org-export-stack-view) 6831 (define-key km (kbd "RET") #'org-export-stack-view) 6832 (define-key km "d" #'org-export-stack-remove) 6833 km) 6834 "Keymap for Org Export Stack.") 6835 6836 (define-derived-mode org-export-stack-mode tabulated-list-mode "Org-Stack" 6837 "Mode for displaying asynchronous export stack. 6838 6839 Type `\\[org-export-stack]' to visualize the asynchronous export 6840 stack. 6841 6842 In an Org Export Stack buffer, use \ 6843 \\<org-export-stack-mode-map>`\\[org-export-stack-view]' to view export output 6844 on current line, `\\[org-export-stack-remove]' to remove it from the stack and \ 6845 `\\[org-export-stack-clear]' to clear 6846 stack completely. 6847 6848 Removing entries in a stack buffer does not affect files 6849 or buffers, only display. 6850 6851 \\{org-export-stack-mode-map}" 6852 (setq tabulated-list-format 6853 (vector (list "#" 4 #'org-export--stack-num-predicate) 6854 (list "Back-End" 12 t) 6855 (list "Age" 6 nil) 6856 (list "Source" 0 nil))) 6857 (setq tabulated-list-sort-key (cons "#" nil)) 6858 (setq tabulated-list-entries #'org-export--stack-generate) 6859 (add-hook 'tabulated-list-revert-hook #'org-export--stack-generate nil t) 6860 (add-hook 'post-command-hook #'org-export-stack-refresh nil t) 6861 (tabulated-list-init-header)) 6862 6863 (defun org-export--stack-generate () 6864 "Generate the asynchronous export stack for display. 6865 Unavailable sources are removed from the list. Return a list 6866 appropriate for `tabulated-list-print'." 6867 ;; Clear stack from exited processes, dead buffers or non-existent 6868 ;; files. 6869 (setq org-export-stack-contents 6870 (cl-remove-if-not 6871 (lambda (el) 6872 (if (processp (nth 2 el)) 6873 (buffer-live-p (process-buffer (nth 2 el))) 6874 (let ((source (car el))) 6875 (if (bufferp source) (buffer-live-p source) 6876 (file-exists-p source))))) 6877 org-export-stack-contents)) 6878 ;; Update `tabulated-list-entries'. 6879 (let ((counter 0)) 6880 (mapcar 6881 (lambda (entry) 6882 (let ((source (car entry))) 6883 (list source 6884 (vector 6885 ;; Counter. 6886 (number-to-string (cl-incf counter)) 6887 ;; Back-End. 6888 (if (nth 1 entry) (symbol-name (nth 1 entry)) "") 6889 ;; Age. 6890 (let ((info (nth 2 entry))) 6891 (if (processp info) (symbol-name (process-status info)) 6892 (format-seconds "%h:%.2m" (float-time (time-since info))))) 6893 ;; Source. 6894 (if (stringp source) source (buffer-name source)))))) 6895 org-export-stack-contents))) 6896 6897 (defun org-export--stack-num-predicate (a b) 6898 (< (string-to-number (aref (nth 1 a) 0)) 6899 (string-to-number (aref (nth 1 b) 0)))) 6900 6901 (defun org-export--stack-source-at-point () 6902 "Return source from export results at point in stack." 6903 (let ((source (car (nth (1- (org-current-line)) org-export-stack-contents)))) 6904 (if (not source) (error "Source unavailable, please refresh buffer") 6905 (let ((source-name (if (stringp source) source (buffer-name source)))) 6906 (if (save-excursion 6907 (beginning-of-line) 6908 (looking-at-p (concat ".* +" (regexp-quote source-name) "$"))) 6909 source 6910 ;; SOURCE is not consistent with current line. The stack 6911 ;; view is outdated. 6912 (error (substitute-command-keys 6913 "Source unavailable; type `\\[org-export-stack-refresh]' \ 6914 to refresh buffer"))))))) 6915 6916 6917 6918 ;;; The Dispatcher 6919 ;; 6920 ;; `org-export-dispatch' is the standard interactive way to start an 6921 ;; export process. It uses `org-export--dispatch-ui' as a subroutine 6922 ;; for its interface, which, in turn, delegates response to key 6923 ;; pressed to `org-export--dispatch-action'. 6924 6925 ;;;###autoload 6926 (defun org-export-dispatch (&optional arg) 6927 "Export dispatcher for Org mode. 6928 6929 It provides an access to common export related tasks in a buffer. 6930 Its interface comes in two flavors: standard and expert. 6931 6932 While both share the same set of bindings, only the former 6933 displays the valid keys associations in a dedicated buffer. 6934 Scrolling (resp. line-wise motion) in this buffer is done with 6935 SPC and DEL (resp. C-n and C-p) keys. 6936 6937 Set variable `org-export-dispatch-use-expert-ui' to switch to one 6938 flavor or the other. 6939 6940 When ARG is `\\[universal-argument]', repeat the last export action, with the\ 6941 same 6942 set of options used back then, on the current buffer. 6943 6944 When ARG is `\\[universal-argument] \\[universal-argument]', display the \ 6945 asynchronous export stack." 6946 (interactive "P") 6947 (let* ((input 6948 (cond ((equal arg '(16)) '(stack)) 6949 ((and arg org-export-dispatch-last-action)) 6950 (t (save-window-excursion 6951 (unwind-protect 6952 (progn 6953 ;; Remember where we are 6954 (move-marker org-export-dispatch-last-position 6955 (point) 6956 (org-base-buffer (current-buffer))) 6957 ;; Get and store an export command 6958 (setq org-export-dispatch-last-action 6959 (org-export--dispatch-ui 6960 (list org-export-initial-scope 6961 (and org-export-in-background 'async)) 6962 nil 6963 org-export-dispatch-use-expert-ui))) 6964 (and (get-buffer "*Org Export Dispatcher*") 6965 (kill-buffer "*Org Export Dispatcher*"))))))) 6966 (action (car input)) 6967 (optns (cdr input))) 6968 (unless (memq 'subtree optns) 6969 (move-marker org-export-dispatch-last-position nil)) 6970 (cl-case action 6971 ;; First handle special hard-coded actions. 6972 (template (org-export-insert-default-template nil optns)) 6973 (stack (org-export-stack)) 6974 (publish-current-file 6975 (org-publish-current-file (memq 'force optns) (memq 'async optns))) 6976 (publish-current-project 6977 (org-publish-current-project (memq 'force optns) (memq 'async optns))) 6978 (publish-choose-project 6979 (org-publish (assoc (completing-read 6980 "Publish project: " 6981 org-publish-project-alist nil t) 6982 org-publish-project-alist) 6983 (memq 'force optns) 6984 (memq 'async optns))) 6985 (publish-all (org-publish-all (memq 'force optns) (memq 'async optns))) 6986 (otherwise 6987 (save-excursion 6988 (when arg 6989 ;; Repeating command, maybe move cursor to restore subtree 6990 ;; context. 6991 (if (eq (marker-buffer org-export-dispatch-last-position) 6992 (org-base-buffer (current-buffer))) 6993 (goto-char org-export-dispatch-last-position) 6994 ;; We are in a different buffer, forget position. 6995 (move-marker org-export-dispatch-last-position nil))) 6996 (funcall action 6997 ;; Return a symbol instead of a list to ease 6998 ;; asynchronous export macro use. 6999 (and (memq 'async optns) t) 7000 (and (memq 'subtree optns) t) 7001 (and (memq 'visible optns) t) 7002 (and (memq 'body optns) t))))))) 7003 7004 (defun org-export--dispatch-ui (options first-key expertp) 7005 "Handle interface for `org-export-dispatch'. 7006 7007 OPTIONS is a list containing current interactive options set for 7008 export. It can contain any of the following symbols: 7009 `body' toggles a body-only export 7010 `subtree' restricts export to current subtree 7011 `visible' restricts export to visible part of buffer. 7012 `force' force publishing files. 7013 `async' use asynchronous export process 7014 7015 FIRST-KEY is the key pressed to select the first level menu. It 7016 is nil when this menu hasn't been selected yet. 7017 7018 EXPERTP, when non-nil, triggers expert UI. In that case, no help 7019 buffer is provided, but indications about currently active 7020 options are given in the prompt. Moreover, [?] allows switching 7021 back to standard interface." 7022 (let* ((fontify-key 7023 (lambda (key &optional access-key) 7024 ;; Fontify KEY string. Optional argument ACCESS-KEY, when 7025 ;; non-nil is the required first-level key to activate 7026 ;; KEY. When its value is t, activate KEY independently 7027 ;; on the first key, if any. A nil value means KEY will 7028 ;; only be activated at first level. 7029 (if (or (eq access-key t) (eq access-key first-key)) 7030 (propertize key 'face 'org-dispatcher-highlight) 7031 key))) 7032 (fontify-value 7033 (lambda (value) 7034 ;; Fontify VALUE string. 7035 (propertize value 'face 'font-lock-variable-name-face))) 7036 ;; Prepare menu entries by extracting them from registered 7037 ;; back-ends and sorting them by access key and by ordinal, 7038 ;; if any. 7039 (entries 7040 (sort (sort (delq nil 7041 (mapcar #'org-export-backend-menu 7042 org-export-registered-backends)) 7043 (lambda (a b) 7044 (let ((key-a (nth 1 a)) 7045 (key-b (nth 1 b))) 7046 (cond ((and (numberp key-a) (numberp key-b)) 7047 (< key-a key-b)) 7048 ((numberp key-b) t))))) 7049 #'car-less-than-car)) 7050 ;; Compute a list of allowed keys based on the first key 7051 ;; pressed, if any. Some keys 7052 ;; (?^B, ?^V, ?^S, ?^F, ?^A, ?&, ?# and ?q) are always 7053 ;; available. 7054 (allowed-keys 7055 (nconc (list 2 22 19 6 1) 7056 (if (not first-key) (org-uniquify (mapcar #'car entries)) 7057 (let (sub-menu) 7058 (dolist (entry entries (sort (mapcar #'car sub-menu) #'<)) 7059 (when (eq (car entry) first-key) 7060 (setq sub-menu (append (nth 2 entry) sub-menu)))))) 7061 (cond ((eq first-key ?P) (list ?f ?p ?x ?a)) 7062 ((not first-key) (list ?P))) 7063 (list ?& ?#) 7064 (when expertp (list ??)) 7065 (list ?q))) 7066 ;; Build the help menu for standard UI. 7067 (help 7068 (unless expertp 7069 (concat 7070 ;; Options are hard-coded. 7071 (format "[%s] Body only: %s [%s] Visible only: %s 7072 \[%s] Export scope: %s [%s] Force publishing: %s 7073 \[%s] Async export: %s\n\n" 7074 (funcall fontify-key "C-b" t) 7075 (funcall fontify-value 7076 (if (memq 'body options) "On " "Off")) 7077 (funcall fontify-key "C-v" t) 7078 (funcall fontify-value 7079 (if (memq 'visible options) "On " "Off")) 7080 (funcall fontify-key "C-s" t) 7081 (funcall fontify-value 7082 (if (memq 'subtree options) "Subtree" "Buffer ")) 7083 (funcall fontify-key "C-f" t) 7084 (funcall fontify-value 7085 (if (memq 'force options) "On " "Off")) 7086 (funcall fontify-key "C-a" t) 7087 (funcall fontify-value 7088 (if (memq 'async options) "On " "Off"))) 7089 ;; Display registered back-end entries. When a key 7090 ;; appears for the second time, do not create another 7091 ;; entry, but append its sub-menu to existing menu. 7092 (let (last-key) 7093 (mapconcat 7094 (lambda (entry) 7095 (let ((top-key (car entry))) 7096 (concat 7097 (unless (eq top-key last-key) 7098 (setq last-key top-key) 7099 (format "\n[%s] %s\n" 7100 (funcall fontify-key (char-to-string top-key)) 7101 (nth 1 entry))) 7102 (let ((sub-menu (nth 2 entry))) 7103 (unless (functionp sub-menu) 7104 ;; Split sub-menu into two columns. 7105 (let ((index -1)) 7106 (concat 7107 (mapconcat 7108 (lambda (sub-entry) 7109 (cl-incf index) 7110 (format 7111 (if (zerop (mod index 2)) " [%s] %-26s" 7112 "[%s] %s\n") 7113 (funcall fontify-key 7114 (char-to-string (car sub-entry)) 7115 top-key) 7116 (nth 1 sub-entry))) 7117 sub-menu "") 7118 (when (zerop (mod index 2)) "\n")))))))) 7119 entries "")) 7120 ;; Publishing menu is hard-coded. 7121 (format "\n[%s] Publish 7122 [%s] Current file [%s] Current project 7123 [%s] Choose project [%s] All projects\n\n\n" 7124 (funcall fontify-key "P") 7125 (funcall fontify-key "f" ?P) 7126 (funcall fontify-key "p" ?P) 7127 (funcall fontify-key "x" ?P) 7128 (funcall fontify-key "a" ?P)) 7129 (format "[%s] Export stack [%s] Insert template\n" 7130 (funcall fontify-key "&" t) 7131 (funcall fontify-key "#" t)) 7132 (format "[%s] %s" 7133 (funcall fontify-key "q" t) 7134 (if first-key "Main menu" "Exit"))))) 7135 ;; Build prompts for both standard and expert UI. 7136 (standard-prompt (unless expertp "Export command: ")) 7137 (expert-prompt 7138 (when expertp 7139 (format 7140 "Export command (C-%s%s%s%s%s) [%s]: " 7141 (if (memq 'body options) (funcall fontify-key "b" t) "b") 7142 (if (memq 'visible options) (funcall fontify-key "v" t) "v") 7143 (if (memq 'subtree options) (funcall fontify-key "s" t) "s") 7144 (if (memq 'force options) (funcall fontify-key "f" t) "f") 7145 (if (memq 'async options) (funcall fontify-key "a" t) "a") 7146 (mapconcat (lambda (k) 7147 ;; Strip control characters. 7148 (unless (< k 27) (char-to-string k))) 7149 allowed-keys ""))))) 7150 ;; With expert UI, just read key with a fancy prompt. In standard 7151 ;; UI, display an intrusive help buffer. 7152 (if expertp 7153 (org-export--dispatch-action 7154 expert-prompt allowed-keys entries options first-key expertp) 7155 ;; At first call, create frame layout in order to display menu. 7156 (unless (get-buffer "*Org Export Dispatcher*") 7157 (delete-other-windows) 7158 (org-switch-to-buffer-other-window 7159 (get-buffer-create "*Org Export Dispatcher*")) 7160 (setq cursor-type nil) 7161 (setq header-line-format 7162 (let ((propertize-help-key 7163 (lambda (key) 7164 ;; Add `face' *and* `font-lock-face' to "work 7165 ;; reliably in any buffer", per a comment in 7166 ;; `help--key-description-fontified'. 7167 (propertize key 7168 'font-lock-face 'help-key-binding 7169 'face 'help-key-binding)))) 7170 (apply 'format 7171 (cons "Use %s, %s, %s, or %s to navigate." 7172 (mapcar propertize-help-key 7173 (list "SPC" "DEL" "C-n" "C-p")))))) 7174 ;; Make sure that invisible cursor will not highlight square 7175 ;; brackets. 7176 (set-syntax-table (copy-syntax-table)) 7177 (modify-syntax-entry ?\[ "w")) 7178 ;; At this point, the buffer containing the menu exists and is 7179 ;; visible in the current window. So, refresh it. 7180 (with-current-buffer "*Org Export Dispatcher*" 7181 ;; Refresh help. Maintain display continuity by re-visiting 7182 ;; previous window position. 7183 (let ((pt (point)) 7184 (wstart (window-start))) 7185 (erase-buffer) 7186 (insert help) 7187 (goto-char pt) 7188 (set-window-start nil wstart))) 7189 (org-fit-window-to-buffer) 7190 (org-export--dispatch-action 7191 standard-prompt allowed-keys entries options first-key expertp)))) 7192 7193 (defun org-export--dispatch-action 7194 (prompt allowed-keys entries options first-key expertp) 7195 "Read a character from command input and act accordingly. 7196 7197 PROMPT is the displayed prompt, as a string. ALLOWED-KEYS is 7198 a list of characters available at a given step in the process. 7199 ENTRIES is a list of menu entries. OPTIONS, FIRST-KEY and 7200 EXPERTP are the same as defined in `org-export--dispatch-ui', 7201 which see. 7202 7203 Toggle export options when required. Otherwise, return value is 7204 a list with action as CAR and a list of interactive export 7205 options as CDR." 7206 (let (key) 7207 ;; Scrolling: when in non-expert mode, act on motion keys (C-n, 7208 ;; C-p, SPC, DEL). 7209 (while (and (setq key (read-char-exclusive prompt)) 7210 (not expertp) 7211 ;; FIXME: Don't use C-v (22) here, as it is used as a 7212 ;; modifier key in the export dispatch. 7213 (memq key '(14 16 ?\s ?\d 134217846))) 7214 (org-scroll key t)) 7215 (cond 7216 ;; Ignore undefined associations. 7217 ((not (memq key allowed-keys)) 7218 (ding) 7219 (unless expertp (message "Invalid key") (sit-for 1)) 7220 (org-export--dispatch-ui options first-key expertp)) 7221 ;; q key at first level aborts export. At second level, cancel 7222 ;; first key instead. 7223 ((eq key ?q) (if (not first-key) (user-error "Export aborted") 7224 (org-export--dispatch-ui options nil expertp))) 7225 ;; Help key: Switch back to standard interface if expert UI was 7226 ;; active. 7227 ((eq key ??) (org-export--dispatch-ui options first-key nil)) 7228 ;; Send request for template insertion along with export scope. 7229 ((eq key ?#) (cons 'template (memq 'subtree options))) 7230 ;; Switch to asynchronous export stack. 7231 ((eq key ?&) '(stack)) 7232 ;; Toggle options: C-b (2) C-v (22) C-s (19) C-f (6) C-a (1). 7233 ((memq key '(2 22 19 6 1)) 7234 (org-export--dispatch-ui 7235 (let ((option (cl-case key (2 'body) (22 'visible) (19 'subtree) 7236 (6 'force) (1 'async)))) 7237 (if (memq option options) (remq option options) 7238 (cons option options))) 7239 first-key expertp)) 7240 ;; Action selected: Send key and options back to 7241 ;; `org-export-dispatch'. 7242 ((or first-key (functionp (nth 2 (assq key entries)))) 7243 (cons (cond 7244 ((not first-key) (nth 2 (assq key entries))) 7245 ;; Publishing actions are hard-coded. Send a special 7246 ;; signal to `org-export-dispatch'. 7247 ((eq first-key ?P) 7248 (cl-case key 7249 (?f 'publish-current-file) 7250 (?p 'publish-current-project) 7251 (?x 'publish-choose-project) 7252 (?a 'publish-all))) 7253 ;; Return first action associated to FIRST-KEY + KEY 7254 ;; path. Indeed, derived backends can share the same 7255 ;; FIRST-KEY. 7256 (t (catch 'found 7257 (dolist (entry (member (assq first-key entries) entries)) 7258 (let ((match (assq key (nth 2 entry)))) 7259 (when match (throw 'found (nth 2 match)))))))) 7260 options)) 7261 ;; Otherwise, enter sub-menu. 7262 (t (org-export--dispatch-ui options key expertp))))) 7263 7264 7265 7266 (provide 'ox) 7267 7268 ;; Local variables: 7269 ;; generated-autoload-file: "org-loaddefs.el" 7270 ;; End: 7271 7272 ;;; ox.el ends here