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