pax_global_header00006660000000000000000000000064151764406670014532gustar00rootroot0000000000000052 comment=f211167438b43795bed55e669d4a783061a07733 org-mode-9.8.4+dfsg/000077500000000000000000000000001517644066700142045ustar00rootroot00000000000000org-mode-9.8.4+dfsg/.dir-locals.el000066400000000000000000000010551517644066700166360ustar00rootroot00000000000000;;; Directory Local Variables -*- no-byte-compile: t; -*- ;;; For more information see (info "(emacs) Directory Variables") ((nil (indent-tabs-mode . t) (tab-width . 8) (fill-column . 70) (sentence-end-double-space . t)) (emacs-lisp-mode (indent-tabs-mode)) (org-mode (indent-tabs-mode) (org-adapt-indentation) (org-src-content-indentation . 0) (org-footnote-auto-adjust . t) (org-footnote-auto-label . t) (org-footnote-define-inline . nil) (org-footnote-section . "Footnotes") (org-hide-emphasis-markers . nil))) org-mode-9.8.4+dfsg/.gitignore000066400000000000000000000020631517644066700161750ustar00rootroot00000000000000# Don't bother tracking a bunch of stuff when building and installing # Org from the master git repository. # ...by ignoring everything created by 'make', 'make doc', `make info' # `make html_manual', `make release' *.aux *.bak *.cp *.cps *.diff *.dvi *.elc *.fn *.fns *.html *.info *.ky *.kys *.log *.patch *.pdf *.pg *.pgs *.ps *.toc *.tp *.vr *.vrs orgcard_letter.tex orgcard.txt org orgguide org-loaddefs.el org-version.el doc/org.texi doc/orgguide.texi doc/org-version.inc doc/org-version.tex org-*.tar* orgplus-*.tar* org-*.zip version.mk manual org_dual_license.texi ORGWEBPAGE/Changes.txt local*.mk .gitattributes mk/x11idle ChangeLog # Files generated during `make packages/org` in a clone of `elpa.git`. /org-pkg.el /org-autoloads.el /lisp/org-autoloads.el # texi2pdf --tidy doc/*.t2d # aspell word and replacement lists .aspell.org.pws .aspell.org.prepl # allow tmp and test directories that will not be tracked test t auto tmp TODO testing/.test-org-id-locations # and collateral damage from Emacs *~ .DS_Store *# .#* # # Local variables: # End: org-mode-9.8.4+dfsg/CONTRIBUTE.org000066400000000000000000000021771517644066700164020ustar00rootroot00000000000000See [[https://orgmode.org/worg/org-contribute.html][the org-contribute page on Worg]] for guidance on how to contribute effectively. We value a nice tone in our discussions: please check and respect the [[https://www.gnu.org/philosophy/kind-communication.en.html][GNU Kind Communications Guidelines]]. * Contribute as an Org user You can contribute by helping others in various channels. See [[https://orgmode.org/worg/org-contribute.html#org99b8f3e][these directions]]. * Contribute as an Emacs Lisp hacker You can contribute with bug reports and patches. See these [[https://orgmode.org/worg/org-contribute.html#org069b83a][directions]]. ** Git Hooks We provide several git hook scripts to facilitate validation of commit messages and structure. See [[https://orgmode.org/worg/org-contribute.html#git-hooks][these directions]] for how to set them up. * As an Org maintainer We encourage you to volunteer to maintain one of the Org files. Just [[mailto:emacs-orgmode@gnu.org][send an email to the list]] explaining which file and your motivations. See what is [[https://orgmode.org/worg/org-maintenance.html][the role of a maintainer]]. org-mode-9.8.4+dfsg/COPYING000066400000000000000000001045151517644066700152450ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . org-mode-9.8.4+dfsg/Makefile000066400000000000000000000076101517644066700156500ustar00rootroot00000000000000# Makefile - for the org-mode distribution # GNU make is required # # This file is not part of GNU Emacs # set up environment include mk/default.mk # defaults, customizable via "local.mk" -include local.mk # optional local customization, use default.mk as template # default target is "all" unless overridden in local.mk all:: # Describe valid make targets for org-mode. .PHONY: targets help helpall targets: help help helpall:: $(info ) $(info Getting Help) $(info ============) $(info make help - show brief help) $(info make targets - ditto) $(info make helpall - show extended help) $(info ) $(info Build and Check) $(info ===============) $(info make - build Org Elisp and all documentation) $(info make all - ditto) $(info make compile - build Org Elisp files) $(info make single - build Org Elisp files, single Emacs per source) $(info make native - build Org natively compiled Elisp files) $(info make autoloads - create org-loaddefs.el to load Org in-place) $(info make test - build Org Elisp files and run test suite) $(info make githooks - install Git hooks that automatically check for commit message conventions) $(info make vanilla - run Emacs with this Org-mode and no personal config) $(info make repro - like vanilla, but refresh compilation and enable debugging [use this to reproduce bugs]) helpall:: $(info make test-dirty - check without building first) $(info make compile-dirty - build only stale Org Elisp files) $(info ) $(info Compatibility) $(info =============) $(info make oldorg - what the old make did: compile autoloads info) $(info ) $(info Cleaning) $(info ========) $(info make clean - remove built Org Elisp files and documentation) $(info make cleangithooks - remove Git hooks) $(info make cleanall - remove everything that can be built and all remnants) $(info make clean-install - remove previous Org installation) $(info ) $(info Configuration Check) $(info ===================) help helpall:: $(info make config - check main configuration) helpall:: $(info make config-version - check Org version) $(info make config-test - check test configuration) $(info make config-exe - check executables configuration) $(info make config-cmd - check command configuration) $(info make config-all - check all configuration) $(info ) $(info Documentation) $(info =============) help helpall:: $(info make doc - build all documentation) helpall:: $(info make docs - ditto) help helpall:: $(info make info - build Info documentation) helpall:: $(info make html - build HTML documentation) $(info make pdf - build PDF documentation) $(info make card - build reference cards) $(info make refcard - ditto) help helpall:: $(info ) $(info Installation) $(info ============) $(info make install - build and install Org) helpall:: $(info make install-etc - build and install files in /etc) $(info make install-lisp - build and install Org Elisp files) $(info make install-info - build and install Info documentation) $(info ) $(info Convenience) $(info ===========) $(info make up0 - pull from upstream) $(info make up1 - pull from upstream, build and check) $(info make up2 - pull from upstream, build, check and install) $(info make update - pull from upstream and build) $(info make update2 - pull from upstream, build and install) $(info make uncompiled - combine cleanlisp and autoloads) $(info make local.mk - create new local.mk as template for adaptation) help helpall:: $(info ) $(info Full documentation on Worg) $(info ==========================) $(info https://orgmode.org/worg/dev/org-build-system.html) @echo "" include mk/targets.mk # toplevel make machinery org-mode-9.8.4+dfsg/README.org000066400000000000000000000036011517644066700156520ustar00rootroot00000000000000This is a distribution of Org Mode, a major mode for keeping notes, authoring documents, computational notebooks, literate programming, maintaining to-do lists, planning projects, and more — in a fast and effective plain text system. Check the [[https://orgmode.org][Org Mode website]] for more. * Install Org Org is part of GNU Emacs: you probably don't need to install it. To install a more recent version, please use command: =M-x list-packages=, find "org" in the list, click on it, and click "Install" in the popped up window. * Join the GNU Project Org is part of GNU Emacs and GNU Emacs is part of the GNU Operating System, developed by the GNU Project. If you are the author of an awesome program and want to join us in writing Free (libre) Software, please consider making it an official GNU program and become a GNU Maintainer. Instructions on how to do this are here http://www.gnu.org/help/evaluation. Don't have a program to contribute? Look at all the other ways to help: https://www.gnu.org/help/help.html. And to learn more about Free (libre) Software in general, please read and share this page: https://gnu.org/philosophy/free-sw.html * License Org-mode is published under the [[https://www.gnu.org/licenses/gpl-3.0.html][GNU GPLv3 license]] or any later version, the same as GNU Emacs. Org-mode is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Org mode. If not, see https://www.gnu.org/licenses/. org-mode-9.8.4+dfsg/etc/000077500000000000000000000000001517644066700147575ustar00rootroot00000000000000org-mode-9.8.4+dfsg/etc/Makefile000066400000000000000000000013411517644066700164160ustar00rootroot00000000000000ETCDIRS = styles schema csl -include local.mk # optional local customization .NOTPARALLEL: # always run this make serially .SUFFIXES: # we don't need default suffix rules ifeq ($(MAKELEVEL), 0) $(error This make needs to be started as a sub-make from the toplevel directory.) endif .PHONY: all install clean cleanall clean-install all: install: $(ETCDIRS) for dir in $? ; do \ if [ ! -d $(DESTDIR)$(datadir)/$${dir} ] ; then \ $(MKDIR) $(DESTDIR)$(datadir)/$${dir} ; \ fi ; \ $(CP) $${dir}/* $(DESTDIR)$(datadir)/$${dir} ; \ done ; clean: cleanall: clean-install: $(ETCDIRS) for dir in $? ; do \ if [ -d $(DESTDIR)$(datadir)/$${dir} ] ; then \ $(RMR) $(DESTDIR)$(datadir)/$${dir} ; \ fi ; \ done ; org-mode-9.8.4+dfsg/etc/ORG-NEWS000066400000000000000000013143451517644066700161160ustar00rootroot00000000000000ORG NEWS -- history of user-visible changes. -*- mode: org; coding: utf-8 -*- #+STARTUP: overview #+LINK: doc https://orgmode.org/worg/doc.html#%s #+LINK: msg https://list.orgmode.org/%s/ #+LINK: git https://git.savannah.nongnu.org/cgit/org-mode.git/commit/?id=%s #+macro: kbd (eval (org-texinfo-kbd-macro $1)) Copyright (C) 2012-2026 Free Software Foundation, Inc. See the end of the file for license conditions. Please send Org bug reports to mailto:emacs-orgmode@gnu.org. * Version 9.8 ** Important announcements and breaking changes # Here, we list the *most important* changes and changes that _likely_ # require user action for most Org mode users. # Sorted from most important to least important. *** You may need to update =org-protocol= bookmarklets for browsers In Firefox 133 and Firefox 128.5 ESR, the previously suggested JavaScript bookmarklets replace the current page with the bookmarklet URL text. We have updated the manual with new bookmarklets that do not have this problem. The new bookmarklets have ~void(0);~ appended at the end, so that they do not return anything. Example: #+begin_example javascript:location.href='org-protocol://store-link?url='+ encodeURIComponent(location.href);void(0); #+end_example *** =C-c C-x C-v= command toggling inline image display has been reworked Previously, =C-c C-x C-v= always toggled image display in the whole buffer (or narrowed part of the buffer). With prefix argument, it also forced displaying image links with description. Now, =C-c C-x C-v= is bound to a new command ~org-link-preview~, which uses different defaults: 1. When the region is active, images in the region are previewed 2. Otherwise, if there is an image at point, it is toggled. If there is no image at point, images in the current entry are previewed 3. With the =C-u= argument, image previews in the active region or at point are cleared instead 4. The =C-u C-u= argument unconditionally shows all images in the accessible portion of the buffer 5. The =C-u C-u C-u= argument unconditionally clears all images in the accessible portion of the buffer 6. Displaying images over links with description can be forced using numeric argument: - ~C-u 1~ for toggling all images at point/current entry - ~C-u 11~ for toggling all images in buffer (The first five of these prefix argument behaviors are the same as that of the ~org-latex-preview~ command.) In addition to images, ~org-link-preview~ can also be used to preview Org links of all types for which preview behavior is defined, see [[#link-preview][previews for arbitrary link types]]. The old ~org-toggle-inline-images~ command is obsolete but still available. You can bind it back to =C-c C-x C-v= by adding the following to your config: #+begin_src emacs-lisp (eval-after-load 'org-keys (org-defkey org-mode-map (kbd "C-c C-x C-v") #'org-toggle-inline-images)) #+end_src *** Org mode no longer treats =:results drawer= as verbatim output Previously, =:results drawer= left the code block results verbatim in some scenarios. This is no longer the case, in line with the manual and the intended purpose of this option. However, the fix may have brought subtle changes in the code block output for users who made use of the previous erroneous behavior. If you use =:results drawer= in your Org documents, please watch out for potential changes in the code evaluation. *** Diary-style timestamps are exported together with active timestamps ~org-export-with-timestamps~ and ~org-icalendar-with-timestamps~ now treat diary-style timestamps as a type of active timestamp for purposes of export. This mainly affects iCalendar export, where diary timestamps will now be included when only active timestamps are exported (the default). This should have minimal impact on non-iCalendar exporters, since ~org-export-with-timestamps~ was already ~t~ by default. However, users who manually set ~org-export-with-timestamps~ to ~active~ will now have diary timestamps included as well. To use the old behavior and export active timestamps only without diary timestamps, users can set ~org-export-with-timestamps~ and ~org-icalendar-with-timestamps~ to ~active-exclude-diary~. *** ~org-element-drawer-parser~ assigns ~:pre-blank~ property Previously, the whole contents of drawer, including blank lines at the beginning were parsed as paragraph. Now, the blank lines at the beginning are stored in ~:pre-blank~ property, just as in other greater elements. *** ~org-element-org-data-parser~ now returns syntax node with ~:pre-blank~ property Previously, parsing ~org-data~ syntax node did not record information about blank lines at the beginning of the document. Now, the number of blank lines is recorded in ~:pre-blank~ property. ~org-element-org-data-interpreter~ takes into account this information. *** Emacs 26 and Emacs 27 support has been dropped We maintain compatibility with the latest Emacs release, and two versions prior the latest. The latest is Emacs 30, so we drop everything before Emacs 28. ** New features # We list the most important features, and the features that may # require user action to be used. *** Some navigation commands can now be repeated When ~repeat-mode~ is turned on, the following navigation commands can be repeated: | Command | Key binding | Repeat key | |-----------------------------------+------------------------+--------------| | ~org-next-visible-heading~ | {{{kbd(C-c C-n)}}} | {{{kbd(n)}}} | | ~org-previous-visible-heading~ | {{{kbd(C-c C-p)}}} | {{{kbd(p)}}} | | ~org-forward-heading-same-level~ | {{{kbd(C-c C-f)}}} | {{{kbd(f)}}} | | ~org-backward-heading-same-level~ | {{{kbd(C-c C-b)}}} | {{{kbd(b)}}} | | ~org-up-heading~ | {{{kbd(C-c C-u)}}} | {{{kbd(u)}}} | | ~org-next-block~ | {{{kbd(C-c M-f)}}} | {{{kbd(f)}}} | | ~org-previous-block~ | {{{kbd(C-c M-b)}}} | {{{kbd(b)}}} | | ~org-next-link~ | {{{kbd(C-c C-x C-n)}}} | {{{kbd(n)}}} | | ~org-previous-link~ | {{{kbd(C-c C-x C-p)}}} | {{{kbd(p)}}} | The keybindings in the repeat-maps can be changed by customizing ~org-navigation-repeat-map~, ~org-link-navigation-repeat-map~, and ~org-block-navigation-repeat-map~. See the new [[info:org#Repeating commands]["Repeating commands"]] section in Org mode manual. *** New babel backend for C# code blocks Org now officially enables C# code block evaluation based on the .NET SDK. The old backend that does not use .NET SDK remains in org-contrib and will be removed in a future release. The built-in =ob-csharp.el= should be considered the official successor. *** All Org link types can be previewed :PROPERTIES: :CUSTOM_ID: link-preview :END: Org links support a new parameter =:preview= that can be used to preview arbitrary link types. The value of this parameter should be a function that is called to preview links of the corresponding type (see ~org-link-parameters~). The new preview system does not bring any brand-new link previews, but open the possibility for third-party packages to implement custom previews without having to use non-ideal hacks. On the user side, the existing image link previews should now run smoother, especially in Org buffers that have a lot of image links to preview. The new previews are less blocking, previewing link in batches, without fully blocking Emacs. See the new ~org-link-preview-batch-size~ and ~org-link-preview-delay~ options. *** New =%\*N= placeholder in ~org-capture-templates~ The new placeholder is like =%\N=, but gives access not only to the =%^{prompt}= values, but also to =%^{prompt}X= values. *** Alignment of image previews can be customized This feature was added in Org 9.7 but was not documented in the release notes. See [[https://orgmode.org/worg/org-release-notes.html#preview-align][retrospectively added news entry]]. *** ~org-open-at-point-global~ now accepts prefix argument The argument is passed through to ~org-link-open~, allowing alternative way to open links, if link ~:follow~ function supports it. *** ox-latex: Table of contents generation has been fixed and augmented The LaTeX exporter differs from other exporters in that it does not include unnumbered sections in the table of contents by default. To include an unnumbered section, set the property =:UNNUMBERED: toc= on the section. Alternatively, you can set the new custom variable ~org-latex-toc-include-unnumbered~ to include unnumbered sections by default, aligning with other exporters' behavior. In that case, to exclude a section from the table of contents, mark it as =:UNNUMBERED: notoc= in its properties. *** Tables copied from LibreOffice Calc documents can be pasted as Org tables Tables copied into the clipboard from LibreOffice Calc documents can now be pasted as an Org table using ~yank-media~. *** Ditaa code blocks can use ditaa executable, and can produce SVG output In order to use a ditaa executable instead of a JAR file, you can set ~org-ditaa-default-exec-mode~ to ~'ditaa~. The location of the executable can be configured via ~org-ditaa-exec~. SVG output can now be generated; note, however, that this requires a ditaa version of at least 0.11.0. *** New datetree capture ~:tree-type~ options :PROPERTIES: :CUSTOM_ID: 9.8-datetree-treetype :END: For datetree capture, ~:tree-type~ can now be any subset of ~(year quarter month week day)~ to construct a datetree with the specified levels. For back-compatibility, the default value of ~nil~ is an alias for ~(year month day)~, ~month~ is an alias for ~(year month)~, and ~week~ is an alias for ~(year week day)~. If ~:tree-type~ is a superset of ~(month week)~, then weeks are assigned to the month containing Thursday, to be consistent with the ISO-8601 year-week rule. If ~:tree-type~ contains ~(quarter week)~ but does not contain ~month~, then quarters are defined as 13-week periods (the final quarter of a 53-week year has 14-weeks). Otherwise, quarters are defined as 3-month periods. Additionally, ~:tree-type~ can be a function, in which case it should take the date as an argument, and generate a list of pairs for ~org-datetree-find-create-hierarchy~. This allows for creating new types of datetrees (e.g. for lunar calendars, academic calendars, retail 4-4-5 calendars, etc). *** New =shortdoc= link type You can now create links to =shortdoc= documentation groups for Emacs Lisp functions (see =M-x shortdoc-display-group=). Requires Emacs 28 or newer. *** Beamer export supports setting frame subtitles If a headline is exported as a frame, and has its =BEAMER_SUBTITLE= property set, the value is used as the subtitle. *** =:wrap= header argument can now be explicitly disabled Previously, presence of =:wrap= argument (inherited or not) in code block headers always made the block results wrapped. There was no way to disable wrapping if =:wrap= was specified in the inherited header arguments. Now, =:wrap no= or =:wrap nil= will explicitly disable wrapping. *** =ob-sqlite=: Added ability to open a database in readonly mode Added option ~:readonly~ to =ob-sqlite=. With ~:readonly yes~, the database is opened in readonly mode. For example: #+begin_example ,#+begin_src sqlite :db /tmp/rip.db :readonly yes :exports both create table rip(a,b); ,#+end_src #+end_example This results in an error such as: #+begin_example Runtime error near line 2: attempt to write a readonly database (8) [ Babel evaluation exited with code 1 ] #+end_example ** New and changed options # Changes dealing with changing default values of customizations, # adding new customizations, or changing the interpretation of the # existing customizations. *** New option ~org-edit-keep-region~ Since Org 9.7, structure editing commands do not deactivate region after editing. Now, this is configurable via the new option. *** =xelatex= can be used for LaTeX previews A new process =xelatex= is added to ~org-preview-process-alist~ to allow generating LaTeX fragment preview through =xdv= file produced by XeLaTeX, which has better support for Unicode. You can now set ~org-preview-latex-default-process~ to ~'xelatex~. *** New link preview system **** New option ~org-link-preview-batch-size~ Org link previews are generated asynchronously and a few at a time, in batches. This option controls the number of links that are previewed in each batch. **** New option ~org-link-preview-delay~ Org link previews are generated asynchronously. This option controls the minimum idle time in seconds between previews of batches of links. *** New and changed export options **** ~org-html-style-default~ now highlights =#+begin_src c= (lowercase) blocks The default value has been changed, adding ~pre.src-c:before { content: 'C'; }~ (lowercase =c=) that parallels ~pre.src-C:before { content: 'C'; }~ (uppercase =C=). **** ~org-odt-with-latex~ accepts any method from ~org-preview-latex-process-alist~ Previously, only a few conversion methods (~dvipng~, ~imagemagick~, ~dvisvgm~) could be used to render LaTeX fragments as images when exporting to ODT. Now any method in ~org-preview-latex-process-alist~ can be used. **** New environment =onlyenv= in ~org-beamer-environments-default~ The =onlyenv= environment limits showing parts of an animated Beamer slide to specific animation steps. #+begin_example ,***** Comment :PROPERTIES: :BEAMER_env: onlyenv :BEAMER_act: <2-> :END: This text will be displayed on animation step 2 and later. #+end_example **** =ox-html=: Headline self links can be enabled from an Org mode file Previously HTML export could add, to each headline, a link to itself. To enable it, you had to use the variable ~org-html-self-link-headlines~. Now, it's also possible to enable it per Org mode file by adding: : #+OPTIONS: html-self-link-headlines:t **** Allow disabling macro replacement during export New custom option ~org-export-replace-macros~ controls whether Org mode replaces macros in the buffer before export. Set it to nil to disable macro replacement. This variable has no effect on the ={{{results...}}}= macros for inline code block results. **** New option ~org-cite-bibtex-bibliography-style~ This option adds a fallback bibliography style for BibTeX when none is provided in the =#+CITE_EXPORT= options. The default style is "plain". **** New option ~org-cite-csl-bibtex-titles-to-sentence-case~ When this option is non-nil then title fields in BibTeX bibliography entries are converted to sentence-case before being formatted according to a CSL style, except for entries with a =langid= field specifying a non-English language. When nil, this conversion is limited to entries having a =langid= field specifying a variant of English. The default value is ~t~ as the CSL standard assumes that English titles are specified in sentence-case but the BibTeX bibliography format requires them to be written in title-case. **** New option ~org-latex-mathml-directory~ This option specifies the path where MathML files generated from LaTeX fragments are stored. **** New option ~org-latex-use-sans~ This option specifies the PDF should be typeset using the Sans font specified in the document class (or the user) instead of the default font (i.e. the Roman font). **** New option ~#+LATEX_CLASS_PRE~ This option prepends LaTeX code before the LaTeX preamble. **** New option ~org-odt-with-forbidden-chars~ The new export option controls how to deal with characters that are forbidden inside ODT documents during export. The ODT documents must follow XML1.0 specification and cannot contain certain Unicode characters. For example, form feed characters like ^L are disallowed. By default, =ox-odt= will strip such characters and display warning. You may return to the previous behavior by setting ~org-odt-with-forbidden-chars~ to t. Note that Emacs warnings can always be suppressed by clicking on ⛔ symbol or by customizing ~warning-suppress-types~. **** New option ~org-md-link-org-files-as-md~ This option makes it possible to disable mapping of linked org files to markdown during export to Markdown. This is analogous to how ~org-html-link-org-files-as-html~ works in export to HTML. *** New context available to save in archived headings ~org-archive-save-context-info~ can now contain ~olid~ symbol to save parent heading ID in the archived heading. *** New hook ~org-archive-finalize-hook~ Hook run after successfully archiving a subtree in final location. Unlike ~org-archive-hook~, which runs in the source Org buffer, the new hook is called with point on the subtree in the destination file. *** Headline/olp target in ~org-capture-templates~ can be a function/variable The variable ~org-capture-templates~ accepts a target specification as function or symbol for headline (~file+headline~) and olp (~file+olp~ and ~file+olp+datetree~). *** The default value of ~org-babel-latex-process-alist~ is no longer taken from ~org-preview-latex-process-alist~ The default value used to be pulled from =dvipng= process type from ~org-preview-latex-process-alist~. Now, it defaults to using =latexmk= (when available), or running =latex= multiple times, so that all the references are resolved in the generated PNG. *** ~org-tags-sort-function~ can now be a list of functions ~org-tags-sort-function~ can now be set to a list of functions. Subsequent sorting functions will be used if two tags are found to be equivalent. See docstring for more information. *** New tags sorting function ~org-tags-sort-hierarchy~ By setting ~org-tags-sort-function~ to ~org-tags-sort-hierarchy~, tags are sorted taking their hierarchy into account. See [[info:org#Tag Hierarchy][Tag Hierarchy]] for how to set up a tag hierarchy. *** New option ~org-cite-basic-complete-key-crm-separator~ This option makes ~org-cite~'s ~basic~ insert processor use ~completing-read-multiple~ instead of the default consecutive prompts. It can also be set to dynamically compute ~crm-separator~ so that the separator does not appear in completion candidates. *** ~org-yank-image-save-method~ can be a function producing directory name In previous versions, ~org-yank-image-save-method~ could be either a symbol ~attach~ or a string -- directory name. Now it can also be a function, which will be called with no arguments and its return value will be used as a directory to save the image to. *** ~org-refile-targets~ can now match all headlines in the target file(s) Candidate refile targets may now be specified with the symbol ~t~ to indicate that all headlines within the specified file are to be considered. For example, setting ~org-refile-targets~ to ~((nil . t))~ will allow one to refile to any heading within the current buffer. *** In =ob-ditaa=, the output type is now controlled consistently with other babel backends Output file type is determined as specified in Babel documentation: the suffix of =:file= is the primary determinant, and =:file-ext= secondary. Header arguments =:pdf= and =:eps= are supported for backwards compatibility. Default output type is still PNG. ** New functions and changes in function arguments # This also includes changes in function behavior from Elisp perspective. *** The deprecated =show= parameter to =org-priority= has been removed The =show= parameter for the =org-priority= function was deprecated in Org 9.2 (released in 2017). Sufficient time has passed, and it is being removed as part of refactoring for numeric priorities. *** ~org-attach-attach~ now returns a link to file stored Previously, ~org-attach-attach~ did not have any specified default value. Now, it returns a list =(LINK DESCRIPTION)= to the file stored. The link obeys non-nil ~org-attach-store-link-p~ setting. When ~org-attach-store-link-p~ is nil, an =attachment:= link is returned. *** New functions exposing link formatting done by ~org-insert-link~ New function ~org-link-get-description~ exposes handling ~:insert-description~ link parameter and ~org-link-make-description-function~. New function ~org-link-make-string-for-buffer~ exposes link and description cleanups performed by ~org-insert-link~, including cleaning up =<...>= brackets, stripping current buffer file path from the link, and adjusting =file:= links according to ~org-link-file-path-type~. *** ob-comint: New optional arguments controlling prompt handling The new argument ~prompt-handling~ in ~org-babel-comint-with-output~ and ~org-babel-comint-async-register~ allows Babel languages to specify how prompts should be handled in comint output. If equal to ~filter-prompts~, prompts are removed from output before it is passed on to language-specific processing. If equal to ~disable-prompt-filtering~, then the prompt filtering is skipped. If unset, then the default behavior is the same as ~filter-prompts~ for backwards compatibility. Prompt filtering is needed for some Babel languages, such as ob-shell, which leave extra prompts in the output as a side effect of evaluation. However, other Babel languages, like ob-python, don't leave extra prompts after evaluation, and skipping the prompt filtering can be more robust for such languages (as this avoids removing false positive prompts). *** Elisp functions for new datetree tree-types Accompanying the [[#9.8-datetree-treetype][new datetree capture ~:tree-type~ options]], on the elisp level ~org-datetree-find-create-entry~ and ~org-datetree-find-create-hierarchy~ generalize ~org-datetree-find-date-create~, ~org-datetree-find-month-create~, and ~org-datetree-find-iso-week-create~ to new datetree types. *** New function ~org-src-get-lang-mode-if-bound~ The new function is like ~org-src-get-lang-mode~, except that it ensures the returned major mode for the given language is bound, and so available to the user. If the mode is not bound, the function can optionally return a fallback mode and display a message when doing so. The function was added so that Org can fall back to Fundamental mode for source blocks where the appropriate major mode is unavailable. *** New function ~org-gnus-no-new-news-other-frame~ (to be used in ~org-link-frame-setup~) The new function is like ~org-gnus-no-new-news~, but always opens the link in other frame. *** New function ~org-string-width-invisibility-spec~ The new function constructs an invisibility spec without folds and ellipses, suitable for ~org-string-width~. This can be helpful for performance if ~org-string-width~ is called multiple times. *** New command ~org-link-preview~ to preview Org links This command replaces ~org-toggle-inline-images~, which is now obsolete. *** New command ~org-link-preview-region~ to preview Org links in a region or the buffer This command replaces ~org-display-inline-images~, which is now obsolete. *** New command ~org-link-preview-clear~ to clear Org link previews in a region or the buffer This command replaces ~org-remove-inline-images~, which is now obsolete. *** New command ~org-link-preview-refresh~ to refresh Org link previews in the buffer This command replaces ~org-redisplay-inline-images~, which is now obsolete. *** ~org-html-head~ and ~org-html-head-extra~ can now be specified as functions Previously, ~org-html-head~ and ~org-html-head-extra~ could only be specified directly as strings. Now, they can be set to functions that accept the INFO channel and return a string. This makes it possible to dynamically generate the content of the resulting ~~ tag in the resulting HTML document. *** ~org-element-create~ now ignores ~nil~​s in CHILDREN argument When CHILDREN contains ~nil~ elements, they are skipped. This way, #+begin_src emacs-lisp (let ((children nil)) (org-element-create 'section nil children)) ; => (section nil) #+end_src will yield expected results rather than assigning literal ~nil~ as a child. *** ~org-clock-get-clock-string~ now takes an optional ~max-length~ argument When a ~max-length~ is passed to ~org-clock-get-clock-string~, it will first attempt to truncate the headline and add an ellipsis in order to make the entire clock string fit under the length limit. If the length limit is too small to accommodate even a single character of the headline, after accounting for spaces and the surrounding parentheses, it will omit the headline entirely and just show as much of the clock as fits under the limit. *** ~org-string-width~ now takes an optional ~invisibility-spec~ argument For performance, if the invisibility spec has been constructed, it can be passed in as ~invisibility-spec~ instead of having it be constructed again. ** Removed or renamed functions and variables *** Obsolete functions and variables removed from ~org-datetree~ Due to the refactoring of ~org-datetree~ to support the [[#9.8-datetree-treetype][new datetree capture ~:tree-type~ options]], the internal variable ~org-datetree-base-level~ has been removed, as well as the undocumented helper function ~org-datetree-insert-line~. *** Obsolete functions ~org-let~ and ~org-let2~ are removed If any code is still using these ancient functions, it should move to ~cl-progv~. *** ~org-show-empty-lines-in-parent~ is now obsolete This function is unused in Org code and does not appear to be used in third-party code. To be removed in future releases. *** ~org-edit-src-content-indentation~ is renamed to ~org-src-content-indentation~ The new name highlights that the customization affects more than editing. ~org-src-content-indentation~ also affects detangling, printing Org syntax tree (for example, during export to Org), and indentation of src and example blocks in Org buffers. *** ~org-cycle-display-inline-images~ is renamed to ~org-cycle-display-link-previews~ Inline image previews in Org mode are now provided by the more general link previews feature. The behavior with regard to image links is unchanged. *** ~org-cycle-inline-images-display~ is renamed to ~org-cycle-link-previews-display~ The behavior is unchanged, except in that the new variable now affects previews of supported link types besides image links. *** ~org-startup-with-inline-images~ is renamed to ~org-startup-with-link-previews~ The behavior is unchanged, except in that the new variable now affects previews of supported link types besides image links. *** =ob-ditaa=: =org-babel-ditaa-java-cmd= renamed and =org-ditaa-jar-option= made obsolete To align with other customizable variable names, which do not contain the word =babel=, variable =org-babel-ditaa-java-cmd= has been renamed to =org-ditaa-java-exec=. The old variable =org-babel-ditaa-java-cmd= is still available as an obsolete alias. Variable =org-ditaa-jar-option= did not serve any sensible purpose and has been made obsolete. Its value is still used in place of default parameter -jar if the variable is defined. ** Miscellaneous *** =ob-calc.el=: Vector and matrix are now inserted as Org tables by default ~ob-calc~ now formats vector and matrix results as Org tables. This conversion can be overridden using the ~:results verbatim~ keyword on a per source block basis. To get back the old behavior, add #+begin_example (with-eval-after-load 'ob-calc (setq org-babel-header-args:calc (append '(:results . "verbatim") org-babel-header-args:calc))) #+end_example to your configuration. The new behavior follows general babel backend rules (auto-detecting result type), but may affect the existing usage. *** ~orgtbl-to-generic~ retains special rows when exporting to Org Previously, special table rows were unconditionally removed when export to Org. Now, the defaults follow what ox-org does - to retain special rows by default. See [[https://orgmode.org/worg/org-release-notes.html#ox-org-special-table-rows][previous change]]. To retain the old behavior, add ~:with-special-rows nil~ to PARAMS argument: : (orgtbl-to-generic table '(:with-special-rows nil) *** ~org-babel-lob-ingest~ no longer performs noweb expansion when ingesting blocks Previously, ~org-babel-lob-ingest~ would expand noweb references when adding source blocks to the Library of Babel. Now, blocks are stored with unexpanded noweb references. Noweb expansion is handled appropriately when blocks are actually used via ~org-babel-execute-src-block~ or ~org-babel-exp-do-export~, with the correct context (~:tangle~, ~:export~, or ~:eval~). This change is unlikely to affect most users, but code that directly accesses ~org-babel-library-of-babel~ may observe the difference. *** Trailing =-= is now allowed in plain links Previously, plain links like : https://domain/test- did not include the trailing =-= punctuation. Now, the =-= is allowed at the end, and is considered a part of the plain link. #+begin_quote These types of links will likely be encountered for sites where anchor targets are automatically generated from documentation headings which are questions. https://list.orgmode.org/orgmode/87sexh9ddv.fsf@ice9.digital/ #+end_quote *** Update of statistics cookies now respects narrowing Calling ~org-update-statistics-cookies~ with a prefix argument will now only update cookies in the accessible portion of the buffer. *** ox-man: Support specifying =#+DATE:= and ~org-export-with-date~ Previously, ox-man ignored =#+DATE:= keyword even when ~org-export-with-date~ is set to non-nil. Now, the date is exported and specified in the =footer-middle= argument of =.TH= macro (see ~man 7 man~). *** ox-man: Support specifying =:release= and =:header= in =#+MAN_CLASS_OPTIONS:= in addition to =:section-id= The newly added =:release= and =:header= options of =#+MAN_CLASS_OPTIONS= are respectively mapped to the =footer-inside= and =header-middle= arguments of the =.TH= macro (see ~man 7 groff_man~). *** ~org-capture~ target pointing to headline is now handled uniformly for =plain= entry type Previously, when using ~file+regexp~, ~file+function~ or ~function~, =plain= entries were inserted right at the point according to regexp/function, even when point is on an existing headline. Now, when target points to an existing headline, =plain= entries are inserted inside its body, honoring ~:prepend~ property. This is more consistent with how ~item~, ~checkitem~, and ~table-line~ templates are handled. *** ~org-lint~ now checks priorities Warnings are raised on headlines containing out-of-bounds, invalid (e.g., =[#-1]=, =[#AA]=), or malformed (e.g., =[#1=, =[#A=) priorities. *** In Dot code blocks, ~graphviz-dot-mode~ is used if available Previously, when editing Dot code blocks with =M-x org-edit-special=, Dot code would open in Fundamental mode, even when specialized mode is installed. The new behavior is more DWIM. *** Source blocks fall back to Fundamental mode Org now falls back to Fundamental mode for source blocks when the appropriate major mode is unavailable. *** Priority speed commands adapt to user options Previously, =1=, =2=, and =3= would insert priorities =A=, =B=, and =C=, which causes errors when using numeric priorities. These now insert ~org-priority-highest~, ~org-priority-default~, and ~org-priority-lowest~, respectively. *** ~org-store-link~ no longer asks to select store function when called noninteractively Previously, when multiple store functions are available to store link at point, ~org-store-link~ would always ask user which store function to use. Now, when ~org-store-link~ is called noninteractively (~interactive?~ argument is nil), the first matching store function is used. Interactively, the previous behavior is retained. *** Org mode may throw an error when attempting to include remote unsafe resource noninteractively Previously, when ~org-resource-download-policy~ is ~ask~ (default), and Emacs is running in batch mode, Org mode simply skipped unsafe remote resources in the =#+include:='s. Now, an error is thrown to avoid seemingly ignored =#+include= statements when publishing via batch scripts. *** HTML export wraps ~~ around all the exported src blocks HTML export always uses ~
~ tag around exported src blocks.
In addition, previously, HTML export used ~~ tag around src
blocks when ~org-html-klipsify-src~ is non-nil.

Now, both ~
~ and ~~ tags are *always* wrapped around the
export src blocks.

*** ~yank-media~ and DND handlers now honor the user option ~org-file-link-type~

When inserting file: links, ~yank-media~ and DND handlers now respect
the user option ~org-file-link-type~.

*** ~org-timer-done-hook~ is now run before the timer is stopped

Previously, ~org-timer-countdown-timer~ and ~org-timer-start-time~
were unset when the hook is run.  Now, they still hold the timer info.

*** ox-latex: LaTeX images are now stored alongside the exported =.html= file

Previously, LaTeX images (when HTML export does use images for LaTeX)
were stored alongside the original =.org= file.  Now, they are stored
alongside the =.html= file.

This change will make links to LaTeX images point to the folder
containing =.html= file, not the =.org= file.

*** Org mode no longer prevents =flyspell= from spell-checking inside =LOGBOOK= drawers

Previously, spell-checking via =flyspell= was disabled inside
=LOGBOOK= (or ~org-log-into-drawer~) drawers.  Now, it is no longer
the case.  It can be useful to see spelling mistakes inside notes
added via ~org-add-note~ command.

*** ~ob-R~ and ~ob-julia~ no longer use ESS settings for working directory

Previously, without =:dir= parameter, R and Julia code blocks could
query for working directory during evaluation.  This was because
~ess-ask-for-ess-directory~ setting was obeyed.

Now, ~ess-ask-for-ess-directory~, ~ess-directory-function~, and
~ess-directory~ are all ignored during code block evaluation (except
when session is already running).  In other words, R and Julia code
blocks now conform to the "16.4 Environment of a Code Block" section
of Org mode manual that prescribes Org buffer directory or ~:dir~
value to be used as working dir to run the code blocks.

*** ~org-cancel-repeater~ now cancels all the repeaters inside entry

Previously, ~org-cancel-repeater~ only canceled repeater in the first
active timestamp inside heading.  Now, all the repeaters are
canceled.

The function is renamed to ~org-cancel-repeaters~ accordingly (the old
name is still kept as an alias).

*** ~org-refile~ now saves current position to Org mark ring when jumping to heading

When ~org-refile~ is called with =C-u= or =C-u C-u= prefix argument
(to jump to heading or to jump to the last refiled heading), it saves
point to Org mark ring before jumping. Then, the user can return back
via ~org-mark-ring-goto~.

*** =org-attach= now considers symlinked files when searching pre-existing attach dirs

When Org buffer is opened from a symlink, Org mode looks into the
original file directory when searching if an attachment directory already exists.
This way, attachments will remain accessible when opening symlinked Org file.

When no attach dir exists, Org mode will still prefer creating it in
the "default" directory - where the symlink is located.

*** Texinfo exporter now supports links in headings

The Texinfo exporter no longer removes links from headings.  This
applies to all headings, below and above the =H= and =toc= export
=#+OPTIONS:=.

*** Texinfo exporter now considers numeric =toc= values in =#+OPTIONS:=

For example, given =H:3= and =toc:2= in =#+OPTIONS:=, all headings at
the 1st and 2nd level appear in the table of contents and those at the
3rd level do not.

*** =ob-tangle= now tangles source blocks that do not specify a =language= if an inherited property sets a tangle filename

Previously, all source blocks that did not specify a =language= where
ignored by ~org-babel-tangle-collect-blocks~. Now, if it inherits a
:tangle header argument with a value other than =no= or =yes= (that is, a
filename), a source block without =language= will get tangled to that
file.

*** BibTeX is tangled with the standard =.bib= file extension

Previously, =bibtex= source blocks located in a file named =NAME.org=
were tangled into a file named =NAME.bibtex=.  Now, they are tangled
into a file named =FILE.bib=, using the standard extension =.bib=,
matching the rest of the ecosystem, including BibTeX and LaTeX.

*** LaTeX export now respects ~org-latex-with...~ options in the PDF metadata

Previously, the LaTeX exporter handled the PDF metadata =pdfcreator=,
=pdfauthor= and =pdftitle= as defined in
~org-latex-hyperref-template~. This has changed, and these three fields
will be defined as empty and not produce any metadata if their
corresponding ~org-latex-with-author~, ~org-latex-with-title~, or
~org-latex-with-creator~ option is set to ~nil~.

*** Fancy HTML5 export uses ~
\\'" code)))) (if (and beg end) (substring code beg end) code))))))))) (defun org-html-do-format-code (code &optional lang refs retain-labels num-start wrap-lines) "Format CODE string as source code. Optional arguments LANG, REFS, RETAIN-LABELS, NUM-START, WRAP-LINES are, respectively, the language of the source code, as a string, an alist between line numbers and references (as returned by `org-export-unravel-code'), a boolean specifying if labels should appear in the source code, the number associated to the first line of code, and a boolean specifying if lines of code should be wrapped in code elements." (let* ((code-lines (split-string code "\n")) (code-length (length code-lines)) (num-fmt (and num-start (format "%%%ds: " (length (number-to-string (+ code-length num-start)))))) (code (org-html-fontify-code code lang))) (org-export-format-code code (lambda (loc line-num ref) (setq loc (concat ;; Add line number, if needed. (when num-start (format "%s" (format num-fmt line-num))) ;; Transcoded src line. (if wrap-lines (format "%s" (if num-start (format " data-ox-html-linenr=\"%s\"" line-num) "") loc) loc) ;; Add label, if needed. (when (and ref retain-labels) (format " (%s)" ref)))) ;; Mark transcoded line as an anchor, if needed. (if (not ref) loc (format "%s" ref loc))) num-start refs))) (defun org-html-format-code (element info) "Format contents of ELEMENT as source code. ELEMENT is either an example or a source block. INFO is a plist used as a communication channel." (let* ((lang (org-element-property :language element)) ;; Extract code and references. (code-info (org-export-unravel-code element)) (code (car code-info)) (refs (cdr code-info)) ;; Does the source block contain labels? (retain-labels (org-element-property :retain-labels element)) ;; Does it have line numbers? (num-start (org-export-get-loc element info)) ;; Should lines be wrapped in code elements? (wrap-lines (plist-get info :html-wrap-src-lines))) (org-html-do-format-code code lang refs retain-labels num-start wrap-lines))) ;;; Tables of Contents (defun org-html-toc (depth info &optional scope) "Build a table of contents. DEPTH is an integer specifying the depth of the table. INFO is a plist used as a communication channel. Optional argument SCOPE is an element defining the scope of the table. Return the table of contents as a string, or nil if it is empty." (let ((toc-entries (mapcar (lambda (headline) (cons (org-html--format-toc-headline headline info) (org-export-get-relative-level headline info))) (org-export-collect-headlines info depth scope)))) (when toc-entries (let* ((toc-id-counter (plist-get info :org-html--toc-counter)) (toc (concat (format "
" (if toc-id-counter (format "-%d" toc-id-counter) "")) (org-html--toc-text toc-entries scope) "
\n"))) (plist-put info :org-html--toc-counter (1+ (or toc-id-counter 0))) (if scope toc (let ((outer-tag (if (org-html--html5-fancy-p info) "nav" "div"))) (concat (format "<%s id=\"table-of-contents%s\" role=\"doc-toc\">\n" outer-tag (if toc-id-counter (format "-%d" toc-id-counter) "")) (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level (org-html--translate "Table of Contents" info) top-level)) toc (format "\n" outer-tag)))))))) (defun org-html--toc-text (toc-entries &optional scope) "Return innards of a table of contents, as a string. TOC-ENTRIES is an alist where key is an entry title, as a string, and value is its relative level, as an integer. Optional SCOPE, when non-nil, indicates a TOC for a subtree, which affects the initial nesting level." (let* ((prev-level (if scope (1- (cdar toc-entries)) 0)) (start-level prev-level)) (concat (mapconcat (lambda (entry) (let ((headline (car entry)) (level (cdr entry))) (concat (let* ((cnt (- level prev-level)) (times (if (> cnt 0) (1- cnt) (- cnt)))) (setq prev-level level) (concat (org-html--make-string times (cond ((> cnt 0) "\n
    \n
  • ") ((< cnt 0) "
  • \n
\n"))) (if (> cnt 0) "\n
    \n
  • " "
  • \n
  • "))) headline))) toc-entries "") (org-html--make-string (- prev-level start-level) "
  • \n
\n")))) (defun org-html--format-toc-headline (headline info) "Return an appropriate table of contents entry for HEADLINE. INFO is a plist used as a communication channel." (let* ((headline-number (org-export-get-headline-number headline info)) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type headline))) (priority (and (plist-get info :with-priority) (org-element-property :priority headline))) (text (org-export-data-with-backend (org-export-get-alt-title headline info) (org-export-toc-entry-backend 'html) info)) (tags (and (eq (plist-get info :with-tags) t) (org-export-get-tags headline info)))) (format "%s" ;; Label. (org-html--reference headline info) ;; Body. (concat (and (not (org-export-low-level-p headline info)) (org-export-numbered-headline-p headline info) (concat (mapconcat #'number-to-string headline-number ".") ". ")) (apply (plist-get info :html-format-headline-function) todo todo-type priority text tags :section-number nil))))) (defun org-html-list-of-listings (info) "Build a list of listings. INFO is a plist used as a communication channel. Return the list of listings as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-listings info))) (when lol-entries (concat "
\n" (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level (org-html--translate "List of Listings" info) top-level)) "
\n
    \n" (let ((count 0) (initial-fmt (format "%s" (org-html--translate "Listing %d:" info)))) (mapconcat (lambda (entry) (let ((label (org-html--reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) (org-export-get-caption entry)) info)))) (concat "
  • " (if (not label) (concat (format initial-fmt (cl-incf count)) " " title) (format "%s %s" label (format initial-fmt (cl-incf count)) title)) "
  • "))) lol-entries "\n")) "\n
\n
\n
")))) (defun org-html-list-of-tables (info) "Build a list of tables. INFO is a plist used as a communication channel. Return the list of tables as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-tables info))) (when lol-entries (concat "
\n" (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level (org-html--translate "List of Tables" info) top-level)) "
\n
    \n" (let ((count 0) (initial-fmt (format "%s" (org-html--translate "Table %d:" info)))) (mapconcat (lambda (entry) (let ((label (org-html--reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) (org-export-get-caption entry)) info)))) (concat "
  • " (if (not label) (concat (format initial-fmt (cl-incf count)) " " title) (format "%s %s" label (format initial-fmt (cl-incf count)) title)) "
  • "))) lol-entries "\n")) "\n
\n
\n
")))) ;;; Transcode Functions ;;;; Bold (defun org-html-bold (_bold contents info) "Transcode BOLD from Org to HTML. CONTENTS is the text with bold markup. INFO is a plist holding contextual information." (format (or (cdr (assq 'bold (plist-get info :html-text-markup-alist))) "%s") contents)) ;;;; Center Block (defun org-html-center-block (_center-block contents _info) "Transcode a CENTER-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (format "
\n%s
" contents)) ;;;; Clock (defun org-html-clock (clock _contents info) "Transcode a CLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (format "

%s %s%s

" org-clock-string (org-html--format-timestamp (org-element-property :value clock) info) (let ((time (org-element-property :duration clock))) (and time (format " (%s)" time))))) ;;;; Code (defun org-html-code (code _contents info) "Transcode CODE from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format (or (cdr (assq 'code (plist-get info :html-text-markup-alist))) "%s") (org-html-encode-plain-text (org-element-property :value code)))) ;;;; Drawer (defun org-html-drawer (drawer contents info) "Transcode a DRAWER element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (funcall (plist-get info :html-format-drawer-function) (org-element-property :drawer-name drawer) contents)) ;;;; Dynamic Block (defun org-html-dynamic-block (_dynamic-block contents _info) "Transcode a DYNAMIC-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information. See `org-export-data'." contents) ;;;; Entity (defun org-html-entity (entity _contents _info) "Transcode an ENTITY object from Org to HTML. CONTENTS are the definition itself. INFO is a plist holding contextual information." (org-element-property :html entity)) ;;;; Example Block (defun org-html-example-block (example-block _contents info) "Transcode a EXAMPLE-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((attributes (org-export-read-attribute :attr_html example-block))) (if (plist-get attributes :textarea) (org-html--textarea-block example-block) (if-let* ((class-val (plist-get attributes :class))) (setq attributes (plist-put attributes :class (concat "example " class-val))) (setq attributes (plist-put attributes :class "example"))) (format "\n%s
" (let* ((reference (org-html--reference example-block info)) (a (org-html--make-attribute-string (if (or (not reference) (plist-member attributes :id)) attributes (plist-put attributes :id reference))))) (if (org-string-nw-p a) (concat " " a) "")) (org-html-format-code example-block info))))) ;;;; Export Snippet (defun org-html-export-snippet (export-snippet _contents _info) "Transcode a EXPORT-SNIPPET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (when (eq (org-export-snippet-backend export-snippet) 'html) (org-element-property :value export-snippet))) ;;;; Export Block (defun org-html-export-block (export-block _contents _info) "Transcode a EXPORT-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (when (string= (org-element-property :type export-block) "HTML") (org-remove-indentation (org-element-property :value export-block)))) ;;;; Fixed Width (defun org-html-fixed-width (fixed-width _contents _info) "Transcode a FIXED-WIDTH element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "
\n%s
" (org-html-do-format-code (org-remove-indentation (org-element-property :value fixed-width))))) ;;;; Footnote Reference (defun org-html-footnote-reference (footnote-reference _contents info) "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) (when (org-element-type-p prev 'footnote-reference) (plist-get info :html-footnote-separator))) (let* ((n (org-export-get-footnote-number footnote-reference info)) (label (org-element-property :label footnote-reference)) ;; Do not assign number labels as they appear in Org mode - ;; the footnotes are re-numbered by ;; `org-export-get-footnote-number'. If the label is not a ;; number, keep it. (label (if (and (stringp label) (equal label (number-to-string (string-to-number label)))) nil label)) (id (format "fnr.%s%s" (or label n) (if (org-export-footnote-first-reference-p footnote-reference info) "" (let ((label (org-element-property :label footnote-reference))) (format ".%d" (org-export-get-ordinal footnote-reference info '(footnote-reference) `(lambda (ref _) (if ,label (equal (org-element-property :label ref) ,label) (not (org-element-property :label ref))))))))))) (format (plist-get info :html-footnote-format) (org-html--anchor id n (format " class=\"footref\" href=\"#fn.%s\" role=\"doc-backlink\"" (or label n)) info))))) ;;;; Headline (defun org-html-headline (headline contents info) "Transcode a HEADLINE element from Org to HTML. CONTENTS holds the contents of the headline. INFO is a plist holding contextual information." (unless (org-element-property :footnote-section-p headline) (let* ((numberedp (org-export-numbered-headline-p headline info)) (numbers (org-export-get-headline-number headline info)) (level (+ (org-export-get-relative-level headline info) (1- (plist-get info :html-toplevel-hlevel)))) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type headline))) (priority (and (plist-get info :with-priority) (org-element-property :priority headline))) (text (org-export-data (org-element-property :title headline) info)) (tags (and (plist-get info :with-tags) (org-export-get-tags headline info))) (full-text (funcall (plist-get info :html-format-headline-function) todo todo-type priority text tags info)) (contents (or contents "")) (id (org-html--reference headline info)) (formatted-text (if (plist-get info :html-self-link-headlines) (format "%s" id full-text) full-text))) (if (org-export-low-level-p headline info) ;; This is a deep sub-tree: export it as a list item. (let* ((html-type (if numberedp "ol" "ul"))) (concat (and (org-export-first-sibling-p headline info) (apply #'format "<%s class=\"org-%s\">\n" (make-list 2 html-type))) (org-html-format-list-item contents (if numberedp 'ordered 'unordered) nil info nil (concat (org-html--anchor id nil nil info) formatted-text)) "\n" (and (org-export-last-sibling-p headline info) (format "\n" html-type)))) ;; Standard headline. Export it as a section. (let ((extra-class (org-element-property :HTML_CONTAINER_CLASS headline)) (headline-class (org-element-property :HTML_HEADLINE_CLASS headline)) (first-content (car (org-element-contents headline)))) (format "<%s id=\"%s\" class=\"%s\">%s%s\n" (org-html--container headline info) (format "outline-container-%s" id) (concat (format "outline-%d" level) (and extra-class " ") extra-class) (format "\n%s\n" level id (if (not headline-class) "" (format " class=\"%s\"" headline-class)) (concat (and numberedp (format "%s " level (concat (mapconcat #'number-to-string numbers ".") "."))) formatted-text) level) ;; When there is no section, pretend there is an ;; empty one to get the correct
%s" lang label code))) ;;;; Inlinetask (defun org-html-inlinetask (inlinetask contents info) "Transcode an INLINETASK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (let* ((todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword inlinetask))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type inlinetask))) (priority (and (plist-get info :with-priority) (org-element-property :priority inlinetask))) (text (org-export-data (org-element-property :title inlinetask) info)) (tags (and (plist-get info :with-tags) (org-export-get-tags inlinetask info)))) (funcall (plist-get info :html-format-inlinetask-function) todo todo-type priority text tags contents info))) (defun org-html-format-inlinetask-default-function (todo todo-type priority text tags contents info) "Default format function for inlinetasks. See `org-html-format-inlinetask-function' for details and the description of TODO, TODO-TYPE, PRIORITY, TEXT, TAGS, CONTENTS, and INFO arguments." (format "
\n%s%s\n%s
" (org-html-format-headline-default-function todo todo-type priority text tags info) (org-html-close-tag "br" nil info) (or contents ""))) ;;;; Italic (defun org-html-italic (_italic contents info) "Transcode ITALIC from Org to HTML. CONTENTS is the text with italic markup. INFO is a plist holding contextual information." (format (or (cdr (assq 'italic (plist-get info :html-text-markup-alist))) "%s") contents)) ;;;; Item (defun org-html-checkbox (checkbox info) "Format CHECKBOX into HTML. INFO is a plist holding contextual information. See `org-html-checkbox-type' for customization options." (cdr (assq checkbox (cdr (assq (plist-get info :html-checkbox-type) org-html-checkbox-types))))) (defun org-html-format-list-item (contents type checkbox info &optional term-counter-id headline) "Format a list item into HTML. CONTENTS is the item contents. TYPE is one of symbols `ordered', `unordered', or `descriptive'. CHECKBOX checkbox type is nil or one of symbols `on', `off', or `trans'. INFO is the info plist." (let ((class (if checkbox (format " class=\"%s\"" (symbol-name checkbox)) "")) (checkbox (concat (org-html-checkbox checkbox info) (and checkbox " "))) (br (org-html-close-tag "br" nil info)) (extra-newline (if (and (org-string-nw-p contents) headline) "\n" ""))) (concat (pcase type (`ordered (let* ((counter term-counter-id) (extra (if counter (format " value=\"%s\"" counter) ""))) (concat (format "" class extra) (when headline (concat headline br))))) (`unordered (let* ((id term-counter-id) (extra (if id (format " id=\"%s\"" id) ""))) (concat (format "" class extra) (when headline (concat headline br))))) (`descriptive (let* ((term term-counter-id)) (setq term (or term "(no term)")) ;; Check-boxes in descriptive lists are associated to tag. (concat (format "%s" class (concat checkbox term)) "
")))) (unless (eq type 'descriptive) checkbox) extra-newline (and (org-string-nw-p contents) (org-trim contents)) extra-newline (pcase type (`ordered "") (`unordered "") (`descriptive "
"))))) (defun org-html-item (item contents info) "Transcode an ITEM element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((plain-list (org-element-parent item)) (type (org-element-property :type plain-list)) (counter (org-element-property :counter item)) (checkbox (org-element-property :checkbox item)) (tag (let ((tag (org-element-property :tag item))) (and tag (org-export-data tag info))))) (org-html-format-list-item contents type checkbox info (or tag counter)))) ;;;; Keyword (defun org-html-keyword (keyword _contents info) "Transcode a KEYWORD element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((key (org-element-property :key keyword)) (value (org-element-property :value keyword))) (cond ((string= key "HTML") value) ((string= key "TOC") (let ((case-fold-search t)) (cond ((string-match "\\" value) (let ((depth (and (string-match "\\<[0-9]+\\>" value) (string-to-number (match-string 0 value)))) (scope (cond ((string-match ":target +\\(\".+?\"\\|\\S-+\\)" value) ;link (org-export-resolve-link (org-strip-quotes (match-string 1 value)) info)) ((string-match-p "\\" value) keyword)))) ;local (org-html-toc depth info scope))) ((string= "listings" value) (org-html-list-of-listings info)) ((string= "tables" value) (org-html-list-of-tables info)))))))) ;;;; LaTeX Environment (defun org-html-format-latex (latex-frag processing-type info) "Format a LaTeX fragment LATEX-FRAG into HTML. PROCESSING-TYPE designates the tool used for conversion. It can be `mathjax', `verbatim', `html', nil, t or symbols in `org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or `imagemagick'. See `org-html-with-latex' for more information. INFO is a plist containing export properties." (let ((cache-relpath "") (cache-dir "")) (unless (or (eq processing-type 'mathjax) (eq processing-type 'html)) (let ((bfn (or (buffer-file-name) (make-temp-name (expand-file-name "latex" temporary-file-directory)))) (latex-header (let ((header (plist-get info :latex-header))) (and header (concat (mapconcat (lambda (line) (concat "#+LATEX_HEADER: " line)) (org-split-string header "\n") "\n") "\n"))))) (setq cache-relpath (concat (file-name-as-directory org-preview-latex-image-directory) (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory (or (plist-get info :output-file) bfn))) ;; Re-create LaTeX environment from original buffer in ;; temporary buffer so that dvipng/imagemagick can properly ;; turn the fragment into an image. (setq latex-frag (concat latex-header latex-frag)))) (org-export-with-buffer-copy :to-buffer (get-buffer-create " *Org HTML Export LaTeX*") :drop-visibility t :drop-narrowing t :drop-contents t (erase-buffer) (insert latex-frag) (org-format-latex cache-relpath nil nil cache-dir nil "Creating LaTeX Image..." nil processing-type) (buffer-string)))) (defun org-html--wrap-latex-environment (contents _ &optional caption label) "Wrap CONTENTS string within appropriate environment for equations. When optional arguments CAPTION and LABEL are given, use them for caption and \"id\" attribute." (format "\n\n%s%s\n
" ;; ID. (if (org-string-nw-p label) (format " id=\"%s\"" label) "") ;; Contents. (format "\n%s\n" contents) ;; Caption. (if (not (org-string-nw-p caption)) "" (format "\n\n%s\n" caption)))) (defun org-html--math-environment-p (element &optional _) "Non-nil when ELEMENT is a LaTeX math environment. Math environments match the regular expression defined in `org-latex-math-environments-re'. This function is meant to be used as a predicate for `org-export-get-ordinal' or a value to `org-html-standalone-image-predicate'." (require 'ox-latex) (defvar org-latex-math-environments-re) ; defined in ox-latex.el (string-match-p org-latex-math-environments-re (org-element-property :value element))) (defun org-html--latex-environment-numbered-p (element) "Non-nil when ELEMENT is a numbered LaTeX math environment. Starred and \"displaymath\" environments are not numbered." (not (string-match-p "\\`[ \t]*\\\\begin{\\(.*\\*\\|displaymath\\)}" (org-element-property :value element)))) (defun org-html--unlabel-latex-environment (latex-frag) "Change environment in LATEX-FRAG string to an unnumbered one. For instance, change an `equation' environment to `equation*'." (replace-regexp-in-string "\\`[ \t]*\\\\begin{\\([^*]+?\\)}" "\\1*" (replace-regexp-in-string "^[ \t]*\\\\end{\\([^*]+?\\)}[ \r\t\n]*\\'" "\\1*" latex-frag nil nil 1) nil nil 1)) (defun org-html-latex-environment (latex-environment _contents info) "Transcode a LATEX-ENVIRONMENT element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((processing-type (plist-get info :with-latex)) (latex-frag (org-remove-indentation (org-element-property :value latex-environment))) (attributes (org-export-read-attribute :attr_html latex-environment)) (label (org-html--reference latex-environment info t)) (caption (and (org-html--latex-environment-numbered-p latex-environment) (org-html--math-environment-p latex-environment) (number-to-string (org-export-get-ordinal latex-environment info nil (lambda (l _) (and (org-html--math-environment-p l) (org-html--latex-environment-numbered-p l)))))))) (cond ((memq processing-type '(t mathjax)) (org-html-format-latex (if (org-string-nw-p label) (replace-regexp-in-string "\\`.*" (format "\\&\n\\\\label{%s}" label) latex-frag) latex-frag) 'mathjax info)) ((assq processing-type org-preview-latex-process-alist) (let ((formula-link (org-html-format-latex (org-html--unlabel-latex-environment latex-frag) processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) (let ((source (org-export-file-uri (match-string 1 formula-link)))) (org-html--wrap-latex-environment (org-html--format-image source attributes info) info caption label))))) (t (org-html--wrap-latex-environment latex-frag info caption label))))) ;;;; LaTeX Fragment (defun org-html-latex-fragment (latex-fragment _contents info) "Transcode a LATEX-FRAGMENT object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((latex-frag (org-element-property :value latex-fragment)) (processing-type (plist-get info :with-latex))) (cond ;; FIXME: Duplicated value in ‘cond’: t ((memq processing-type '(t mathjax)) (org-html-format-latex latex-frag 'mathjax info)) ((memq processing-type '(t html)) (org-html-format-latex latex-frag 'html info)) ((assq processing-type org-preview-latex-process-alist) (let ((formula-link (org-html-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) (let ((source (org-export-file-uri (match-string 1 formula-link)))) (org-html--format-image source nil info))))) (t latex-frag)))) ;;;; Line Break (defun org-html-line-break (_line-break _contents info) "Transcode a LINE-BREAK object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat (org-html-close-tag "br" nil info) "\n")) ;;;; Link (defun org-html-image-link-filter (data _backend info) "Process image links that are inside descriptions. DATA is the parse tree. INFO is and info plist. See `org-export-insert-image-links' for more details." (org-export-insert-image-links data info org-html-inline-image-rules)) (defun org-html-inline-image-p (link info) "Non-nil when LINK is meant to appear as an image. INFO is a plist used as a communication channel. LINK is an inline image when it has no description and targets an image file (see `org-html-inline-image-rules' for more information), or if its description is a single link targeting an image file." (if (not (org-element-contents link)) (org-export-inline-image-p link (plist-get info :html-inline-image-rules)) (not (let ((link-count 0)) (org-element-map (org-element-contents link) (cons 'plain-text org-element-all-objects) (lambda (obj) (pcase (org-element-type obj) (`plain-text (org-string-nw-p obj)) (`link (if (= link-count 1) t (cl-incf link-count) (not (org-export-inline-image-p obj (plist-get info :html-inline-image-rules))))) (_ t))) info t))))) (defvar org-html-standalone-image-predicate) (defun org-html-standalone-image-p (element info) "Non-nil if ELEMENT is a standalone image. INFO is a plist holding contextual information. An element or object is a standalone image when - its type is `paragraph' and its sole content, save for white spaces, is a link that qualifies as an inline image; - its type is `link' and its containing paragraph has no other content save white spaces. Bind `org-html-standalone-image-predicate' to constrain paragraph further. For example, to check for only captioned standalone images, set it to: (lambda (paragraph) (org-element-property :caption paragraph))" (let ((paragraph (pcase (org-element-type element) (`paragraph element) (`link (org-element-parent element))))) (and (org-element-type-p paragraph 'paragraph) (or (not (and (boundp 'org-html-standalone-image-predicate) (fboundp org-html-standalone-image-predicate))) (funcall org-html-standalone-image-predicate paragraph)) (catch 'exit (let ((link-count 0)) (org-element-map (org-element-contents paragraph) (cons 'plain-text org-element-all-objects) (lambda (obj) (when (pcase (org-element-type obj) (`plain-text (org-string-nw-p obj)) (`link (or (> (cl-incf link-count) 1) (not (org-html-inline-image-p obj info)))) (_ t)) (throw 'exit nil))) info nil 'link) (= link-count 1)))))) (defun org-html-link (link desc info) "Transcode a LINK object from Org to HTML. DESC is the description part of the link, or the empty string. INFO is a plist holding contextual information. See `org-export-data'." (let* ((html-ext (plist-get info :html-extension)) (dot (when (> (length html-ext) 0) ".")) (link-org-files-as-html-maybe (lambda (raw-path info) ;; Treat links to `file.org' as links to `file.html', if ;; needed. See `org-html-link-org-files-as-html'. (save-match-data (cond ((and (plist-get info :html-link-org-files-as-html) (let ((case-fold-search t)) (string-match "\\(.+\\)\\.org\\(?:\\.gpg\\)?$" raw-path))) (concat (match-string 1 raw-path) dot html-ext)) (t raw-path))))) (type (org-element-property :type link)) (raw-path (org-element-property :path link)) ;; Ensure DESC really exists, or set it to nil. (desc (org-string-nw-p desc)) (path (cond ((string= "file" type) ;; During publishing, turn absolute file names belonging ;; to base directory into relative file names. Otherwise, ;; append "file" protocol to absolute file name. (setq raw-path (org-export-file-uri (org-publish-file-relative-name raw-path info))) ;; Possibly append `:html-link-home' to relative file ;; name. (let ((home (and (plist-get info :html-link-home) (org-trim (plist-get info :html-link-home))))) (when (and home (plist-get info :html-link-use-abs-url) (not (file-name-absolute-p raw-path))) (setq raw-path (concat (file-name-as-directory home) raw-path)))) ;; Maybe turn ".org" into ".html". (setq raw-path (funcall link-org-files-as-html-maybe raw-path info)) ;; Add search option, if any. A search option can be ;; relative to a custom-id, a headline title, a name or ;; a target. (let ((option (org-element-property :search-option link))) (if (not option) raw-path (let ((path (org-element-property :path link))) (concat raw-path "#" (org-publish-resolve-external-link option path t)))))) (t (url-encode-url (concat type ":" raw-path))))) (attributes-plist (org-combine-plists ;; Extract attributes from parent's paragraph. HACK: Only ;; do this for the first link in parent (inner image link ;; for inline images). This is needed as long as ;; attributes cannot be set on a per link basis. (let* ((parent (org-element-parent-element link)) (link (let ((container (org-element-parent link))) (if (and (org-element-type-p container 'link) (org-html-inline-image-p link info)) container link)))) (and (eq link (org-element-map parent 'link #'identity info t)) (org-export-read-attribute :attr_html parent))) ;; Also add attributes from link itself. Currently, those ;; need to be added programmatically before `org-html-link' ;; is invoked, for example, by backends building upon HTML ;; export. (org-export-read-attribute :attr_html link))) (attributes (let ((attr (org-html--make-attribute-string attributes-plist))) (if (org-string-nw-p attr) (concat " " attr) "")))) (cond ;; Link type is handled by a special function. ((org-export-custom-protocol-maybe link desc 'html info)) ;; Image file. ((and (plist-get info :html-inline-images) (org-export-inline-image-p link (plist-get info :html-inline-image-rules))) (org-html--format-image path attributes-plist info)) ;; Radio target: Transcode target's contents and use them as ;; link's description. ((string= type "radio") (let ((destination (org-export-resolve-radio-link link info))) (if (not destination) desc (format "%s" (org-html--reference destination info) attributes desc)))) ;; Links pointing to a headline: Find destination and build ;; appropriate referencing command. ((member type '("custom-id" "fuzzy" "id")) (let ((destination (if (string= type "fuzzy") (org-export-resolve-fuzzy-link link info) (org-export-resolve-id-link link info)))) (pcase (org-element-type destination) ;; ID link points to an external file. (`plain-text (let ((fragment (concat org-html--id-attr-prefix raw-path)) ;; Treat links to ".org" files as ".html", if needed. (path (funcall link-org-files-as-html-maybe destination info))) (format "%s" path fragment attributes (or desc destination)))) ;; Fuzzy link points nowhere. (`nil (format "%s" (or desc (org-export-data (org-element-property :raw-link link) info)))) ;; Link points to a headline. (`headline (let ((href (org-html--reference destination info)) ;; What description to use? (desc ;; Case 1: Headline is numbered and LINK has no ;; description. Display section number. (if (and (org-export-numbered-headline-p destination info) (not desc)) (mapconcat #'number-to-string (org-export-get-headline-number destination info) ".") ;; Case 2: Either the headline is un-numbered or ;; LINK has a custom description. Display LINK's ;; description or headline's title. (or desc (org-export-data (org-element-property :title destination) info))))) (format "%s" href attributes desc))) ;; Fuzzy link points to a target or an element. (_ (require 'ox-latex) (declare-function org-latex--environment-type "ox-latex" (latex-environment)) (if (and destination (memq (plist-get info :with-latex) '(mathjax t)) (org-element-type-p destination 'latex-environment) (eq 'math (org-latex--environment-type destination))) ;; Caption and labels are introduced within LaTeX ;; environment. Use "ref" or "eqref" macro, depending on user ;; preference to refer to those in the document. (format (plist-get info :html-equation-reference-format) (org-html--reference destination info)) (let* ((ref (org-html--reference destination info)) (org-html-standalone-image-predicate #'org-html--has-caption-p) (counter-predicate (if (org-element-type-p destination 'latex-environment) #'org-html--math-environment-p #'org-html--has-caption-p)) (number (cond (desc nil) ((org-html-standalone-image-p destination info) (org-export-get-ordinal (org-element-map destination 'link #'identity info t) info '(link) 'org-html-standalone-image-p)) (t (org-export-get-ordinal destination info nil counter-predicate)))) (desc (cond (desc) ((not number) "No description for this link") ((numberp number) (number-to-string number)) (t (mapconcat #'number-to-string number "."))))) (format "%s" ref attributes desc))))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") (let ((fragment (concat "coderef-" (org-html-encode-plain-text raw-path)))) (format "%s" fragment (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \ '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\"" fragment fragment) attributes (format (org-export-get-coderef-format raw-path desc) (org-export-resolve-coderef raw-path info))))) ;; External link with a description part. ((and path desc) (format "%s" (org-html-encode-plain-text path) attributes desc)) ;; External link without a description part. (path (let ((path (org-html-encode-plain-text path))) (format "%s" path attributes path))) ;; No path, only description. Try to do something useful. (t (format "%s" desc))))) ;;;; Node Property (defun org-html-node-property (node-property _contents _info) "Transcode a NODE-PROPERTY element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "%s:%s" (org-element-property :key node-property) (let ((value (org-element-property :value node-property))) (if value (concat " " value) "")))) ;;;; Paragraph (defun org-html-paragraph (paragraph contents info) "Transcode a PARAGRAPH element from Org to HTML. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." (let* ((parent (org-element-parent paragraph)) (parent-type (org-element-type parent)) (style '((footnote-definition " class=\"footpara\"") (org-data " class=\"footpara\""))) (attributes (org-html--make-attribute-string (org-export-read-attribute :attr_html paragraph))) (extra (or (cadr (assq parent-type style)) ""))) (cond ((and (eq parent-type 'item) (not (org-export-get-previous-element paragraph info)) (let ((followers (org-export-get-next-element paragraph info 2))) (and (not (cdr followers)) (org-element-type-p (car followers) '(nil plain-list))))) ;; First paragraph in an item has no tag if it is alone or ;; followed, at most, by a sub-list. contents) ((org-html-standalone-image-p paragraph info) ;; Standalone image. (let ((caption (let ((raw (org-export-data (org-export-get-caption paragraph) info)) (org-html-standalone-image-predicate #'org-html--has-caption-p)) (if (not (org-string-nw-p raw)) raw (concat "" (format (org-html--translate "Figure %d:" info) (org-export-get-ordinal (org-element-map paragraph 'link #'identity info t) info nil #'org-html-standalone-image-p)) " " raw)))) (label (org-html--reference paragraph info))) (org-html--wrap-image contents info caption label))) ;; Regular paragraph. (t (format "\n%s

" (if (org-string-nw-p attributes) (concat " " attributes) "") extra contents))))) ;;;; Plain List (defun org-html-plain-list (plain-list contents _info) "Transcode a PLAIN-LIST element from Org to HTML. CONTENTS is the contents of the list. INFO is a plist holding contextual information." (let* ((type (pcase (org-element-property :type plain-list) (`ordered "ol") (`unordered "ul") (`descriptive "dl") (other (error "Unknown HTML list type: %s" other)))) (class (format "org-%s" type)) (attributes (org-export-read-attribute :attr_html plain-list))) (format "<%s %s>\n%s" type (org-html--make-attribute-string (plist-put attributes :class (org-trim (mapconcat #'identity (list class (plist-get attributes :class)) " ")))) contents type))) ;;;; Plain Text (defun org-html-convert-special-strings (string) "Convert special characters in STRING to HTML." (dolist (a org-html-special-string-regexps string) (let ((re (car a)) (rpl (cdr a))) (setq string (replace-regexp-in-string re rpl string t))))) (defun org-html-encode-plain-text (text) "Convert plain text characters from TEXT to HTML equivalent. Possible conversions are set in `org-html-protect-char-alist'." (dolist (pair org-html-protect-char-alist text) (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))) (defun org-html-plain-text (text info) "Transcode a TEXT string from Org to HTML. TEXT is the string to transcode. INFO is a plist holding contextual information." (let ((output text)) ;; Protect following characters: <, >, &. (setq output (org-html-encode-plain-text output)) ;; Handle smart quotes. Be sure to provide original string since ;; OUTPUT may have been modified. (when (plist-get info :with-smart-quotes) (setq output (org-export-activate-smart-quotes output :html info text))) ;; Handle special strings. (when (plist-get info :with-special-strings) (setq output (org-html-convert-special-strings output))) ;; Handle break preservation if required. (when (plist-get info :preserve-breaks) (setq output (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" (concat (org-html-close-tag "br" nil info) "\n") output))) ;; Return value. output)) ;; Planning (defun org-html-planning (planning _contents info) "Transcode a PLANNING element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (format "

%s

" (org-trim (mapconcat (lambda (pair) (let ((timestamp (cdr pair))) (when timestamp (let ((string (car pair))) (format "%s \ %s " string (org-html--format-timestamp timestamp info)))))) `((,org-closed-string . ,(org-element-property :closed planning)) (,org-deadline-string . ,(org-element-property :deadline planning)) (,org-scheduled-string . ,(org-element-property :scheduled planning))) "")))) ;;;; Property Drawer (defun org-html-property-drawer (_property-drawer contents _info) "Transcode a PROPERTY-DRAWER element from Org to HTML. CONTENTS holds the contents of the drawer. INFO is a plist holding contextual information." (and (org-string-nw-p contents) (format "
\n%s
" contents))) ;;;; Quote Block (defun org-html-quote-block (quote-block contents info) "Transcode a QUOTE-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (format "\n%s" (let* ((reference (org-html--reference quote-block info t)) (attributes (org-export-read-attribute :attr_html quote-block)) (a (org-html--make-attribute-string (if (or (not reference) (plist-member attributes :id)) attributes (plist-put attributes :id reference))))) (if (org-string-nw-p a) (concat " " a) "")) contents)) ;;;; Section (defun org-html-section (section contents info) "Transcode a SECTION element from Org to HTML. CONTENTS holds the contents of the section. INFO is a plist holding contextual information." (let ((parent (org-element-lineage section 'headline))) ;; Before first headline: no container, just return CONTENTS. (if (not parent) contents ;; Get div's class and id references. (let* ((class-num (+ (org-export-get-relative-level parent info) (1- (plist-get info :html-toplevel-hlevel)))) (section-number (and (org-export-numbered-headline-p parent info) (mapconcat #'number-to-string (org-export-get-headline-number parent info) "-")))) ;; Build return value. (format "
\n%s
\n" class-num (or (org-element-property :CUSTOM_ID parent) section-number (org-export-get-reference parent info)) (or contents "")))))) ;;;; Radio Target (defun org-html-radio-target (radio-target text info) "Transcode a RADIO-TARGET object from Org to HTML. TEXT is the text of the target. INFO is a plist holding contextual information." (let ((ref (org-html--reference radio-target info))) (org-html--anchor ref text nil info))) ;;;; Special Block (defun org-html-special-block (special-block contents info) "Transcode a SPECIAL-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (let* ((block-type (org-element-property :type special-block)) (html5-fancy (and (org-html--html5-fancy-p info) (member block-type org-html-html5-elements))) (attributes (org-export-read-attribute :attr_html special-block))) (unless html5-fancy (let ((class (plist-get attributes :class))) (setq attributes (plist-put attributes :class (if class (concat class " " block-type) block-type))))) (let* ((contents (or contents "")) (reference (org-html--reference special-block info)) (a (org-html--make-attribute-string (if (or (not reference) (plist-member attributes :id)) attributes (plist-put attributes :id reference)))) (str (if (org-string-nw-p a) (concat " " a) ""))) (if html5-fancy (format "<%s%s>\n%s" block-type str contents block-type) (format "\n%s\n" str contents))))) ;;;; Src Block (defun org-html-src-block (src-block _contents info) "Transcode a SRC-BLOCK element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (if (org-export-read-attribute :attr_html src-block :textarea) (org-html--textarea-block src-block) (let* ((lang (org-element-property :language src-block)) (code (org-html-format-code src-block info)) (label (let ((lbl (org-html--reference src-block info t))) (if lbl (format " id=\"%s\"" lbl) ""))) (klipsify (and (plist-get info :html-klipsify-src) (member lang '("javascript" "js" "ruby" "scheme" "clojure" "php" "html"))))) (format "
\n%s%s\n
" ;; Build caption. (let ((caption (org-export-get-caption src-block))) (if (not caption) "" (let ((listing-number (format "%s " (format (org-html--translate "Listing %d:" info) (org-export-get-ordinal src-block info nil #'org-html--has-caption-p))))) (format "" listing-number (org-trim (org-export-data caption info)))))) ;; Contents. (if klipsify (format "
%s
" lang ; lang being nil is OK. label (if (string= lang "html") " data-editor-type=\"html\"" "") code) (format "
%s
" ;; Lang being nil is OK. lang label code)))))) ;;;; Statistics Cookie (defun org-html-statistics-cookie (statistics-cookie _contents _info) "Transcode a STATISTICS-COOKIE object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((cookie-value (org-element-property :value statistics-cookie))) (format "%s" cookie-value))) ;;;; Strike-Through (defun org-html-strike-through (_strike-through contents info) "Transcode STRIKE-THROUGH from Org to HTML. CONTENTS is the text with strike-through markup. INFO is a plist holding contextual information." (format (or (cdr (assq 'strike-through (plist-get info :html-text-markup-alist))) "%s") contents)) ;;;; Subscript (defun org-html-subscript (_subscript contents _info) "Transcode a SUBSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Superscript (defun org-html-superscript (_superscript contents _info) "Transcode a SUPERSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Table Cell (defun org-html-table-cell (table-cell contents info) "Transcode a TABLE-CELL element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (let* ((table-row (org-element-parent table-cell)) (table (org-element-lineage table-cell 'table)) (cell-attrs (if (not (plist-get info :html-table-align-individual-fields)) "" (format (if (and (boundp 'org-html-format-table-no-css) org-html-format-table-no-css) " align=\"%s\"" " class=\"org-%s\"") (org-export-table-cell-alignment table-cell info))))) (when (or (not contents) (string= "" (org-trim contents))) (setq contents " ")) (cond ((and (org-export-table-has-header-p table info) (= 1 (org-export-table-row-group table-row info))) (let ((header-tags (plist-get info :html-table-header-tags))) (concat "\n" (format (car header-tags) "col" cell-attrs) contents (cdr header-tags)))) ((and (plist-get info :html-table-use-header-tags-for-first-column) (zerop (cdr (org-export-table-cell-address table-cell info)))) (let ((header-tags (plist-get info :html-table-header-tags))) (concat "\n" (format (car header-tags) "row" cell-attrs) contents (cdr header-tags)))) (t (let ((data-tags (plist-get info :html-table-data-tags))) (concat "\n" (format (car data-tags) cell-attrs) contents (cdr data-tags))))))) ;;;; Table Row (defun org-html-table-row (table-row contents info) "Transcode a TABLE-ROW element from Org to HTML. CONTENTS is the contents of the row. INFO is a plist used as a communication channel." ;; Rules are ignored since table separators are deduced from ;; borders of the current row. (when (eq (org-element-property :type table-row) 'standard) (let* ((group (org-export-table-row-group table-row info)) (number (org-export-table-row-number table-row info)) (start-group-p (org-export-table-row-starts-rowgroup-p table-row info)) (end-group-p (org-export-table-row-ends-rowgroup-p table-row info)) (topp (and (equal start-group-p '(top)) (equal end-group-p '(below top)))) (bottomp (and (equal start-group-p '(above)) (equal end-group-p '(bottom above)))) (row-open-tag (pcase (plist-get info :html-table-row-open-tag) ((and accessor (pred functionp)) (funcall accessor number group start-group-p end-group-p topp bottomp)) (accessor accessor))) (row-close-tag (pcase (plist-get info :html-table-row-close-tag) ((and accessor (pred functionp)) (funcall accessor number group start-group-p end-group-p topp bottomp)) (accessor accessor))) (group-tags (cond ;; Row belongs to second or subsequent groups. ((not (= 1 group)) '("" . "\n")) ;; Row is from first group. Table has >=1 groups. ((org-export-table-has-header-p (org-element-lineage table-row 'table) info) '("" . "\n")) ;; Row is from first and only group. (t '("" . "\n"))))) (concat (and start-group-p (car group-tags)) (concat "\n" row-open-tag contents "\n" row-close-tag) (and end-group-p (cdr group-tags)))))) ;;;; Table (defun org-html-table-first-row-data-cells (table info) "Transcode the first row of TABLE. INFO is a plist used as a communication channel." (let ((table-row (org-element-map table 'table-row (lambda (row) (unless (eq (org-element-property :type row) 'rule) row)) info 'first-match)) (special-column-p (org-export-table-has-special-column-p table))) (if (not special-column-p) (org-element-contents table-row) (cdr (org-element-contents table-row))))) (defun org-html-table--table.el-table (table _info) "Format table.el TABLE into HTML. INFO is a plist used as a communication channel." (when (eq (org-element-property :type table) 'table.el) (let ((outbuf (with-current-buffer (get-buffer-create "*org-export-table*") (erase-buffer) (current-buffer)))) (with-temp-buffer (insert (org-element-property :value table)) (goto-char 1) (re-search-forward "^[ \t]*|[^|]" nil t) (table-generate-source 'html outbuf)) (with-current-buffer outbuf (prog1 (org-trim (buffer-string)) (kill-buffer) ))))) (defun org-html-table (table contents info) "Transcode a TABLE element from Org to HTML. CONTENTS is the contents of the table. INFO is a plist holding contextual information." (if (eq (org-element-property :type table) 'table.el) ;; "table.el" table. Convert it using appropriate tools. (org-html-table--table.el-table table info) ;; Standard table. (let* ((caption (org-export-get-caption table)) (number (org-export-get-ordinal table info nil #'org-html--has-caption-p)) (attributes (org-html--make-attribute-string (org-combine-plists (list :id (org-html--reference table info t)) (and (not (org-html-html5-p info)) (plist-get info :html-table-attributes)) (org-export-read-attribute :attr_html table)))) (alignspec (if (bound-and-true-p org-html-format-table-no-css) "align=\"%s\"" "class=\"org-%s\"")) (table-column-specs (lambda (table info) (mapconcat (lambda (table-cell) (let ((alignment (org-export-table-cell-alignment table-cell info))) (concat ;; Begin a colgroup? (when (org-export-table-cell-starts-colgroup-p table-cell info) "\n") ;; Add a column. Also specify its alignment. (format "\n%s" (org-html-close-tag "col" (concat " " (format alignspec alignment)) info)) ;; End a colgroup? (when (org-export-table-cell-ends-colgroup-p table-cell info) "\n")))) (org-html-table-first-row-data-cells table info) "\n")))) (format "\n%s\n%s\n%s" (if (equal attributes "") "" (concat " " attributes)) (if (not caption) "" (format (if (plist-get info :html-table-caption-above) "%s" "%s") (concat "" (format (org-html--translate "Table %d:" info) number) " " (org-export-data caption info)))) (funcall table-column-specs table info) contents)))) ;;;; Target (defun org-html-target (target _contents info) "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((ref (org-html--reference target info))) (org-html--anchor ref nil nil info))) ;;;; Timestamp (defun org-html-timestamp (timestamp _contents info) "Transcode a TIMESTAMP object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ( ;; Strip :post-blank ;; It will be handled as a part of generic transcoder code ;; so we should avoid double-counting post-blank. (timestamp-no-blank (org-element-put-property (org-element-copy timestamp t) :post-blank 0))) (format "%s" (org-html--format-timestamp timestamp-no-blank info)))) ;;;; Underline (defun org-html-underline (_underline contents info) "Transcode UNDERLINE from Org to HTML. CONTENTS is the text with underline markup. INFO is a plist holding contextual information." (format (or (cdr (assq 'underline (plist-get info :html-text-markup-alist))) "%s") contents)) ;;;; Verbatim (defun org-html-verbatim (verbatim _contents info) "Transcode VERBATIM from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format (or (cdr (assq 'verbatim (plist-get info :html-text-markup-alist))) "%s") (org-html-encode-plain-text (org-element-property :value verbatim)))) ;;;; Verse Block (defun org-html-verse-block (_verse-block contents info) "Transcode a VERSE-BLOCK element from Org to HTML. CONTENTS is verse block contents. INFO is a plist holding contextual information." (format "

\n%s

" ;; Replace leading white spaces with non-breaking spaces. (replace-regexp-in-string "^[ \t]+" (lambda (m) (org-html--make-string (length m) " ")) ;; Replace each newline character with line break. Also ;; remove any trailing "br" close-tag so as to avoid ;; duplicates. (let* ((br (org-html-close-tag "br" nil info)) (re (format "\\(?:%s\\)?[ \t]*\n" (regexp-quote br)))) (replace-regexp-in-string re (concat br "\n") contents))))) ;;; Filter Functions (defun org-html-final-function (contents _backend info) "Filter to indent the HTML and convert HTML entities. CONTENTS is the exported HTML code. INFO is the info plist." (with-temp-buffer (insert contents) (delay-mode-hooks (set-auto-mode t)) (when (plist-get info :html-indent) (indent-region (point-min) (point-max))) (buffer-substring-no-properties (point-min) (point-max)))) ;;; End-user functions ;;;###autoload (defun org-html-export-as-html (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to an HTML buffer. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting buffer should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\" and \"\" tags. EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Export is done in a buffer named \"*Org HTML Export*\", which will be displayed when `org-export-show-temporary-export-buffer' is non-nil." (interactive) (org-export-to-buffer 'html "*Org HTML Export*" async subtreep visible-only body-only ext-plist (lambda () (set-auto-mode t)))) ;;;###autoload (defun org-html-convert-region-to-html () "Assume the current region has Org syntax, and convert it to HTML. This can be used in any buffer. For example, you can write an itemized list in Org syntax in an HTML buffer and use this command to convert it." (interactive) (org-export-replace-region-by 'html)) (defalias 'org-export-region-to-html #'org-html-convert-region-to-html) ;;;###autoload (defun org-html-export-to-html (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to a HTML file. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\" and \"\" tags. EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Return output file's name." (interactive) (let* ((extension (concat (when (> (length org-html-extension) 0) ".") (or (plist-get ext-plist :html-extension) org-html-extension "html"))) (file (org-export-output-file-name extension subtreep)) (org-export-coding-system org-html-coding-system)) (org-export-to-file 'html file async subtreep visible-only body-only ext-plist))) ;;;###autoload (defun org-html-publish-to-html (plist filename pub-dir) "Publish an org file to HTML. FILENAME is the filename of the Org file to be published. PLIST is the property list for the given project. PUB-DIR is the publishing directory. Return output file name." (org-publish-org-to 'html filename (concat (when (> (length org-html-extension) 0) ".") (or (plist-get plist :html-extension) org-html-extension "html")) plist pub-dir)) (provide 'ox-html) ;; Local variables: ;; generated-autoload-file: "org-loaddefs.el" ;; End: ;;; ox-html.el ends here org-mode-9.8.4+dfsg/lisp/ox-icalendar.el000066400000000000000000001376661517644066700200660ustar00rootroot00000000000000;;; ox-icalendar.el --- iCalendar Backend for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2004-2026 Free Software Foundation, Inc. ;; Author: Carsten Dominik ;; Nicolas Goaziou ;; Maintainer: Jack Kamm ;; Keywords: outlines, hypermedia, calendar, text ;; URL: https://orgmode.org ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; This library implements an iCalendar backend for Org generic ;; exporter. See Org manual for more information. ;; ;; It is expected to conform to RFC 5545. ;;; Code: (require 'org-macs) (org-assert-version) (require 'cl-lib) (require 'org-agenda) (require 'ox-ascii) (declare-function org-bbdb-anniv-export-ical "ol-bbdb" nil) ;;; User-Configurable Variables (defgroup org-export-icalendar nil "Options specific for iCalendar export backend." :tag "Org Export iCalendar" :group 'org-export) (defcustom org-icalendar-combined-agenda-file "~/org.ics" "The file name for the iCalendar file covering all agenda files. This file is created with the command `\\[org-icalendar-combine-agenda-files]'. The file name should be absolute. It will be overwritten without warning." :group 'org-export-icalendar :type 'file) (defcustom org-icalendar-alarm-time 0 "Number of minutes for triggering an alarm for exported timed events. A zero value (the default) turns off the definition of an alarm trigger for timed events. If non-zero, alarms are created. - a single alarm per entry is defined - The alarm will go off N minutes before the event - only a DISPLAY action is defined." :group 'org-export-icalendar :version "24.1" :type 'integer) (defcustom org-icalendar-force-alarm nil "Non-nil means alarm will be created even if is set to zero. This overrides default behavior where zero means no alarm. With this set to non-nil and alarm set to zero, alarm will be created and will fire at the event start." :group 'org-export-icalendar :type 'boolean :package-version '(Org . "9.6") :safe #'booleanp) (defcustom org-icalendar-combined-name "OrgMode" "Calendar name for the combined iCalendar representing all agenda files." :group 'org-export-icalendar :type 'string) (defcustom org-icalendar-combined-description "" "Calendar description for the combined iCalendar (all agenda files)." :group 'org-export-icalendar :type 'string) (defcustom org-icalendar-exclude-tags nil "Tags that exclude a tree from export. This variable allows specifying different exclude tags from other backends. It can also be set with the ICALENDAR_EXCLUDE_TAGS keyword." :group 'org-export-icalendar :type '(repeat (string :tag "Tag"))) (defcustom org-icalendar-scheduled-summary-prefix "S: " "String prepended to exported scheduled headlines." :group 'org-export-icalendar :type 'string :package-version '(Org . "9.6") :safe #'stringp) (defcustom org-icalendar-deadline-summary-prefix "DL: " "String prepended to exported headlines with a deadline." :group 'org-export-icalendar :type 'string :package-version '(Org . "9.6") :safe #'stringp) (defcustom org-icalendar-use-deadline '(event-if-not-todo todo-due) "Contexts where iCalendar export should use a deadline time stamp. This is a list with possibly several symbols in it. Valid symbols are: `event-if-todo' Deadlines in TODO entries become calendar events. `event-if-todo-not-done' Deadlines in TODO entries with not-DONE state become events. `event-if-not-todo' Deadlines in non-TODO entries become calendar events. `todo-due' Use deadlines in TODO entries as due-dates." :group 'org-export-icalendar :type '(set :greedy t (const :tag "DEADLINE in non-TODO entries become events" event-if-not-todo) (const :tag "DEADLINE in TODO entries become events" event-if-todo) (const :tag "DEADLINE in TODO entries with not-DONE state become events" event-if-todo-not-done) (const :tag "DEADLINE in TODO entries become due-dates" todo-due))) (defcustom org-icalendar-use-scheduled '(todo-start) "Contexts where iCalendar export should use a scheduling time stamp. This is a list with possibly several symbols in it. Valid symbols are: `event-if-todo' Scheduling time stamps in TODO entries become an event. `event-if-todo-not-done' Scheduling time stamps in TODO entries with not-DONE state become events. `event-if-not-todo' Scheduling time stamps in non-TODO entries become an event. `todo-start' Scheduling time stamps in TODO entries become start date. (See also `org-icalendar-todo-unscheduled-start', which controls the start date for TODO entries without a scheduling time stamp)" :group 'org-export-icalendar :type '(set :greedy t (const :tag "SCHEDULED timestamps in non-TODO entries become events" event-if-not-todo) (const :tag "SCHEDULED timestamps in TODO entries become events" event-if-todo) (const :tag "SCHEDULED in TODO entries with not-DONE state become events" event-if-todo-not-done) (const :tag "SCHEDULED in TODO entries become start date" todo-start))) (defcustom org-icalendar-categories '(local-tags category) "Items that should be entered into the \"categories\" field. This is a list of symbols, the following are valid: `category' The Org mode category of the current file or tree `todo-state' The todo state, if any `local-tags' The tags, defined in the current line `all-tags' All tags, including inherited ones." :group 'org-export-icalendar :type '(repeat (choice (const :tag "The file or tree category" category) (const :tag "The TODO state" todo-state) (const :tag "Tags defined in current line" local-tags) (const :tag "All tags, including inherited ones" all-tags)))) (defcustom org-icalendar-with-timestamps 'active "Non-nil means make an event from plain time stamps. It can be set to `active', `active-exclude-diary', `inactive', t or nil, in order to make an event from, respectively, only active timestamps (with/without diary timestamps), only inactive ones, all of them or none. This variable has the same options as `org-export-with-timestamps', and takes precedence over it. However, note that this variable applies to all timestamps within an entry, whereas `org-export-with-timestamps' only applies to timestamps isolated in a paragraph containing only timestamps. It can also be set with the #+OPTIONS line, e.g. \"<:t\"." :group 'org-export-icalendar :package-version '(Org . "9.8") :type '(choice (const :tag "All timestamps" t) (const :tag "Active timestamps, including diary timestamps" active) (const :tag "Active timestamps, excluding diary timestamps" active-exclude-diary) (const :tag "Only inactive timestamps" inactive) (const :tag "No timestamp" nil)) :safe (lambda (x) (memq x '(t nil active active-exclude-diary inactive)))) (defcustom org-icalendar-include-todo nil "Non-nil means create VTODO components from TODO items. Valid values are: nil don't include any task. t include tasks that are not in DONE state. `unblocked' include all TODO items that are not blocked. `all' include both done and not done items. \\(\"TODO\" ...) include specific TODO keywords." :group 'org-export-icalendar :type '(choice (const :tag "None" nil) (const :tag "Unfinished" t) (const :tag "Unblocked" unblocked) (const :tag "All" all) (repeat :tag "Specific TODO keywords" (string :tag "Keyword")))) (defcustom org-icalendar-todo-unscheduled-start 'recurring-deadline-warning "Exported start date of unscheduled TODOs. If `org-icalendar-use-scheduled' contains `todo-start' and a task has a \"SCHEDULED\" timestamp, that is always used as the start date. Otherwise, this variable controls whether a start date is exported and what its value is. Note that the iCalendar spec RFC 5545 does not generally require tasks to have a start date, except for repeating tasks which do require a start date. However some iCalendar programs ignore the requirement for repeating tasks, and allow repeating deadlines without a matching start date. This variable has no effect when `org-icalendar-include-todo' is nil. Valid values are: `recurring-deadline-warning' If deadline repeater present, use `org-deadline-warning-days' as start. `deadline-warning' If deadline present, use `org-deadline-warning-days' as start. `current-datetime' Use the current date-time as start. nil Never add a start time for unscheduled tasks." :group 'org-export-icalendar :type '(choice (const :tag "Warning days if deadline recurring" recurring-deadline-warning) (const :tag "Warning days if deadline present" deadline-warning) (const :tag "Now" current-datetime) (const :tag "No start date" nil)) :package-version '(Org . "9.7") :safe #'symbolp) (defcustom org-icalendar-include-bbdb-anniversaries nil "Non-nil means a combined iCalendar file should include anniversaries. The anniversaries are defined in the BBDB database." :group 'org-export-icalendar :type 'boolean) (defcustom org-icalendar-include-sexps t "Non-nil means export to iCalendar files should also cover sexp entries. These are entries like in the diary, but directly in an Org file." :group 'org-export-icalendar :type 'boolean) (defcustom org-icalendar-include-body t "Amount of text below headline to be included in iCalendar export. This is a number of characters that should maximally be included. Properties, scheduling and clocking lines will always be removed. The text will be inserted into the DESCRIPTION field." :group 'org-export-icalendar :type '(choice (const :tag "Nothing" nil) (const :tag "Everything" t) (integer :tag "Max characters"))) (defcustom org-icalendar-store-UID nil "Non-nil means store any created UIDs in properties. The iCalendar standard requires that all entries have a unique identifier. Org will create these identifiers as needed. When this variable is non-nil, the created UIDs will be stored in the ID property of the entry. Then the next time this entry is exported, it will be exported with the same UID, superseding the previous form of it. This is essential for synchronization services. This variable is not turned on by default because we want to avoid creating a property drawer in every entry if people are only playing with this feature, or if they are only using it locally." :group 'org-export-icalendar :type 'boolean) (defcustom org-icalendar-timezone (getenv "TZ") "The time zone string for iCalendar export. When nil or the empty string, use output from (current-time-zone)." :group 'org-export-icalendar :type '(choice (const :tag "Unspecified" nil) (string :tag "Time zone"))) (defcustom org-icalendar-date-time-format ":%Y%m%dT%H%M%S" "Format-string for exporting icalendar DATE-TIME. See `format-time-string' for a full documentation. The only difference is that `org-icalendar-timezone' is used for %Z. Interesting value are: - \":%Y%m%dT%H%M%S\" for local time - \";TZID=%Z:%Y%m%dT%H%M%S\" for local time with explicit timezone - \":%Y%m%dT%H%M%SZ\" for time expressed in Universal Time" :group 'org-export-icalendar :version "24.1" :type '(choice (const :tag "Local time" ":%Y%m%dT%H%M%S") (const :tag "Explicit local time" ";TZID=%Z:%Y%m%dT%H%M%S") (const :tag "Universal time" ":%Y%m%dT%H%M%SZ") (string :tag "Explicit format"))) (defcustom org-icalendar-ttl nil "Time to live for the exported calendar. Subscribing clients to the exported ics file can derive the time interval to read the file again from the server. One example of such client is Nextcloud calendar, which respects the setting of X-PUBLISHED-TTL in ICS files. Setting `org-icalendar-ttl' to \"PT1H\" would advise a server to reload the file every hour. See https://icalendar.org/iCalendar-RFC-5545/3-8-2-5-duration.html for a complete description of possible specifications of this option. For example, \"PT1H\" stands for 1 hour and \"PT0H27M34S\" stands for 0 hours, 27 minutes and 34 seconds. The default value is nil, which means no such option is set in the ICS file. This option can also be set on a per-document basis with the ICAL-TTL export keyword." :group 'org-export-icalendar :type '(choice (const :tag "No refresh period" nil) (const :tag "One hour" "PT1H") (const :tag "One day" "PT1D") (const :tag "One week" "PT7D") (string :tag "Other")) :package-version '(Org . "9.7")) (defvar org-icalendar-after-save-hook nil "Hook run after an iCalendar file has been saved. This hook is run with the name of the file as argument. A good way to use this is to tell a desktop calendar application to re-read the iCalendar file.") ;;; Define Backend (org-export-define-derived-backend 'icalendar 'ascii :translate-alist '((clock . nil) (footnote-definition . nil) (footnote-reference . nil) (headline . org-icalendar-entry) (inner-template . org-icalendar-inner-template) (inlinetask . nil) (planning . nil) (section . nil) (template . org-icalendar-template)) :options-alist '((:exclude-tags "ICALENDAR_EXCLUDE_TAGS" nil org-icalendar-exclude-tags split) (:with-timestamps nil "<" org-icalendar-with-timestamps) ;; Other variables. (:icalendar-alarm-time nil nil org-icalendar-alarm-time) (:icalendar-categories nil nil org-icalendar-categories) (:icalendar-date-time-format nil nil org-icalendar-date-time-format) (:icalendar-include-bbdb-anniversaries nil nil org-icalendar-include-bbdb-anniversaries) (:icalendar-include-body nil nil org-icalendar-include-body) (:icalendar-include-sexps nil nil org-icalendar-include-sexps) (:icalendar-include-todo nil nil org-icalendar-include-todo) (:icalendar-store-UID nil nil org-icalendar-store-UID) (:icalendar-timezone nil nil org-icalendar-timezone) (:icalendar-use-deadline nil nil org-icalendar-use-deadline) (:icalendar-use-scheduled nil nil org-icalendar-use-scheduled) (:icalendar-scheduled-summary-prefix nil nil org-icalendar-scheduled-summary-prefix) (:icalendar-deadline-summary-prefix nil nil org-icalendar-deadline-summary-prefix) (:icalendar-ttl "ICAL-TTL" nil org-icalendar-ttl)) :filters-alist '((:filter-headline . org-icalendar-clear-blank-lines)) :menu-entry '(?c "Export to iCalendar" ((?f "Current file" org-icalendar-export-to-ics) (?a "All agenda files" (lambda (a s v b) (org-icalendar-export-agenda-files a))) (?c "Combine all agenda files" (lambda (a s v b) (org-icalendar-combine-agenda-files a)))))) ;;; Internal Functions (defun org-icalendar-create-uid (file &optional bell) "Set ID property on headlines missing it in FILE. When optional argument BELL is non-nil, inform the user with a message if the file was modified." (let (modified-flag) (org-map-entries (lambda () (let ((entry (org-element-at-point))) (unless (org-element-property :ID entry) (org-id-get-create) (setq modified-flag t) (forward-line)))) nil nil 'comment) (when (and bell modified-flag) (message "ID properties created in file \"%s\"" file) (sit-for 2)))) (defun org-icalendar-blocked-headline-p (headline info) "Non-nil when HEADLINE is considered to be blocked. INFO is a plist used as a communication channel. A headline is blocked when either - it has children which are not all in a completed state; - it has a parent with the property :ORDERED:, and there are siblings prior to it with incomplete status; - its parent is blocked because it has siblings that should be done first or is a child of a blocked grandparent entry." (or ;; Check if any child is not done. (org-element-map (org-element-contents headline) 'headline (lambda (hl) (eq (org-element-property :todo-type hl) 'todo)) info 'first-match) ;; Check :ORDERED: node property. (catch 'blockedp (let ((current headline)) (dolist (parent (org-element-lineage headline)) (cond ((not (org-element-property :todo-keyword parent)) (throw 'blockedp nil)) ((org-not-nil (org-element-property :ORDERED parent)) (let ((sibling current)) (while (setq sibling (org-export-get-previous-element sibling info)) (when (eq (org-element-property :todo-type sibling) 'todo) (throw 'blockedp t))))) (t (setq current parent)))))))) (defun org-icalendar-use-UTC-date-time-p () "Non-nil when `org-icalendar-date-time-format' requires UTC time." (char-equal (elt org-icalendar-date-time-format (1- (length org-icalendar-date-time-format))) ?Z)) (defun org-icalendar-convert-timestamp (timestamp keyword &optional end tz) "Convert TIMESTAMP to iCalendar format. TIMESTAMP is a timestamp object. KEYWORD is added in front of it, in order to make a complete line (e.g. \"DTSTART\"). When optional argument END is non-nil, use end of time range. Also increase the hour by two (if time string contains a time), or the day by one (if it does not contain a time) when no explicit ending time is specified. When optional argument TZ is non-nil, timezone data time will be added to the timestamp. It can be the string \"UTC\", to use UTC time, or a string in the IANA TZ database format (e.g. \"Europe/London\"). In either case, the value of `org-icalendar-date-time-format' will be ignored." (let* ((year-start (org-element-property :year-start timestamp)) (year-end (org-element-property :year-end timestamp)) (month-start (org-element-property :month-start timestamp)) (month-end (org-element-property :month-end timestamp)) (day-start (org-element-property :day-start timestamp)) (day-end (org-element-property :day-end timestamp)) (hour-start (org-element-property :hour-start timestamp)) (hour-end (org-element-property :hour-end timestamp)) (minute-start (org-element-property :minute-start timestamp)) (minute-end (org-element-property :minute-end timestamp)) (with-time-p minute-start) (equal-bounds-p (equal (list year-start month-start day-start hour-start minute-start) (list year-end month-end day-end hour-end minute-end))) (mi (cond ((not with-time-p) 0) ((not end) minute-start) ((and org-agenda-default-appointment-duration equal-bounds-p) (+ minute-end org-agenda-default-appointment-duration)) (t minute-end))) (h (cond ((not with-time-p) 0) ((not end) hour-start) ((or (not equal-bounds-p) org-agenda-default-appointment-duration) hour-end) (t (+ hour-end 2)))) (d (cond ((not end) day-start) ((not with-time-p) (1+ day-end)) (t day-end))) (m (if end month-end month-start)) (y (if end year-end year-start))) (concat keyword (format-time-string (cond ((string-equal tz "UTC") ":%Y%m%dT%H%M%SZ") ((not with-time-p) ";VALUE=DATE:%Y%m%d") ((stringp tz) (concat ";TZID=" tz ":%Y%m%dT%H%M%S")) (t (replace-regexp-in-string "%Z" org-icalendar-timezone org-icalendar-date-time-format t))) ;; Convert timestamp into internal time in order to use ;; `format-time-string' and fix any mistake (i.e. MI >= 60). (org-encode-time 0 mi h d m y) (and (or (string-equal tz "UTC") (and (null tz) with-time-p (org-icalendar-use-UTC-date-time-p))) t))))) (defun org-icalendar-dtstamp () "Return DTSTAMP property, as a string." (format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t)) (defun org-icalendar-get-categories (entry info) "Return categories according to `org-icalendar-categories'. ENTRY is a headline or an inlinetask element. INFO is a plist used as a communication channel." (mapconcat #'identity (org-uniquify (let (categories) (dolist (type org-icalendar-categories (nreverse categories)) (cl-case type (category (push (org-export-get-category entry info) categories)) (todo-state (let ((todo (org-element-property :todo-keyword entry))) (and todo (push todo categories)))) (local-tags (setq categories (append (nreverse (org-export-get-tags entry info)) categories))) (all-tags (setq categories (append (nreverse (org-export-get-tags entry info nil t)) categories))))))) ",")) (defun org-icalendar-transcode-diary-sexp (sexp uid summary) "Transcode a diary sexp into iCalendar format. SEXP is the diary sexp being transcoded, as a string. UID is the unique identifier for the entry. SUMMARY defines a short summary or subject for the event." (when (require 'icalendar nil t) (org-element-normalize-string (with-temp-buffer (let ((sexp (if (not (string-match "\\`<%%" sexp)) sexp (concat (substring sexp 1 -1) " " summary)))) (put-text-property 0 1 'uid uid sexp) (insert sexp "\n")) (org-diary-to-ical-string (current-buffer)))))) (defun org-icalendar-cleanup-string (s) "Cleanup string S according to RFC 5545." (when s ;; Protect "\", "," and ";" characters. and replace newline ;; characters with literal \n. (replace-regexp-in-string "[ \t]*\n" "\\n" (replace-regexp-in-string "[\\,;]" "\\\\\\&" s) nil t))) (defun org-icalendar-fold-string (s) "Fold string S according to RFC 5545." (org-element-normalize-string (mapconcat (lambda (line) ;; Limit each line to a maximum of 75 characters. If it is ;; longer, fold it by using "\r\n " as a continuation marker. (let ((len (length line))) (if (<= len 75) line (let ((folded-line (substring line 0 75)) (chunk-start 75) chunk-end) ;; Since continuation marker takes up one character on the ;; line, real contents must be split at 74 chars. (while (< (setq chunk-end (+ chunk-start 74)) len) (setq folded-line (concat folded-line "\n " (substring line chunk-start chunk-end)) chunk-start chunk-end)) (concat folded-line "\n " (substring line chunk-start)))))) (org-split-string s "\n") "\n"))) (defun org-icalendar--post-process-file (file) "Post-process the exported iCalendar FILE. Converts line endings to dos-style CRLF as per RFC 5545, then runs `org-icalendar-after-save-hook'." (with-temp-buffer (insert-file-contents file) (let ((coding-system-for-write (coding-system-change-eol-conversion last-coding-system-used 'dos))) (write-region nil nil file))) (run-hook-with-args 'org-icalendar-after-save-hook file) nil) ;;; Filters (defun org-icalendar-clear-blank-lines (headline _backend _info) "Remove blank lines in HEADLINE export. HEADLINE is a string representing a transcoded headline. BACKEND and INFO are ignored." (replace-regexp-in-string "^\\(?:[ \t]*\n\\)+" "" headline)) ;;; Transcode Functions ;;;; Headline and Inlinetasks ;; The main function is `org-icalendar-entry', which extracts ;; information from a headline or an inlinetask (summary, ;; description...) and then delegates code generation to ;; `org-icalendar--vtodo' and `org-icalendar--vevent', depending ;; on the component needed. ;; Obviously, `org-icalendar--valarm' handles alarms, which can ;; happen within a VTODO component. (defun org-icalendar-entry (entry contents info) "Transcode ENTRY element into iCalendar format. ENTRY is either a headline or an inlinetask. CONTENTS is ignored. INFO is a plist used as a communication channel. This function is called on every headline, the section below it (minus inlinetasks) being its contents. It tries to create VEVENT and VTODO components out of scheduled date, deadline date, plain timestamps, diary sexps. It also calls itself on every inlinetask within the section." (unless (org-element-property :footnote-section-p entry) (let* ((type (org-element-type entry)) ;; Determine contents really associated to the entry. For ;; a headline, limit them to section, if any. For an ;; inlinetask, this is every element within the task. (inside (if (eq type 'inlinetask) (cons 'org-data (cons nil (org-element-contents entry))) (let ((first (car (org-element-contents entry)))) (and (org-element-type-p first 'section) (cons 'org-data (cons nil (org-element-contents first)))))))) (concat (let ((todo-type (org-element-property :todo-type entry)) (uid (or (org-element-property :ID entry) (org-id-new))) (summary (org-icalendar-cleanup-string (or (let ((org-property-separators '(("SUMMARY" . "\n")))) (org-entry-get entry "SUMMARY" 'selective)) (org-export-data (org-element-property :title entry) info)))) (loc (let ((org-property-separators '(("LOCATION" . "\n")))) (org-icalendar-cleanup-string (org-entry-get entry "LOCATION" 'selective)))) (class (org-icalendar-cleanup-string (org-export-get-node-property :CLASS entry (org-property-inherit-p "CLASS")))) ;; Build description of the entry from associated section ;; (headline) or contents (inlinetask). (desc (org-icalendar-cleanup-string (or (let ((org-property-separators '(("DESCRIPTION" . "\n")))) (org-entry-get entry "DESCRIPTION" 'selective)) (let ((contents (org-export-data inside info))) (cond ((not (org-string-nw-p contents)) nil) ((wholenump org-icalendar-include-body) (let ((contents (org-trim contents))) (substring contents 0 (min (length contents) org-icalendar-include-body)))) (org-icalendar-include-body (org-trim contents))))))) (cat (org-icalendar-get-categories entry info)) (tz (org-export-get-node-property :TIMEZONE entry (org-property-inherit-p "TIMEZONE")))) (concat ;; Events: Delegate to `org-icalendar--vevent' to generate ;; "VEVENT" component from scheduled, deadline, or any ;; timestamp in the entry. (let ((deadline (org-element-property :deadline entry)) (use-deadline (plist-get info :icalendar-use-deadline)) (deadline-summary-prefix (org-icalendar-cleanup-string (plist-get info :icalendar-deadline-summary-prefix)))) (and deadline (pcase todo-type (`todo (or (memq 'event-if-todo-not-done use-deadline) (memq 'event-if-todo use-deadline))) (`done (memq 'event-if-todo use-deadline)) (_ (memq 'event-if-not-todo use-deadline))) (org-icalendar--vevent entry deadline (concat "DL-" uid) (concat deadline-summary-prefix summary) loc desc cat tz class))) (let ((scheduled (org-element-property :scheduled entry)) (use-scheduled (plist-get info :icalendar-use-scheduled)) (scheduled-summary-prefix (org-icalendar-cleanup-string (plist-get info :icalendar-scheduled-summary-prefix)))) (and scheduled (pcase todo-type (`todo (or (memq 'event-if-todo-not-done use-scheduled) (memq 'event-if-todo use-scheduled))) (`done (memq 'event-if-todo use-scheduled)) (_ (memq 'event-if-not-todo use-scheduled))) (org-icalendar--vevent entry scheduled (concat "SC-" uid) (concat scheduled-summary-prefix summary) loc desc cat tz class))) ;; When collecting plain timestamps from a headline and its ;; title, skip inlinetasks since collection will happen once ;; ENTRY is one of them. (let ((counter 0)) (mapconcat #'identity (org-element-map (cons (org-element-property :title entry) (org-element-contents inside)) 'timestamp (lambda (ts) (unless (org-export--skip-timestamp-p (plist-get info :with-timestamps) (org-element-property :type ts)) (let ((uid (format "TS%d-%s" (cl-incf counter) uid))) (org-icalendar--vevent entry ts uid summary loc desc cat tz class)))) info nil (and (eq type 'headline) 'inlinetask)) "")) ;; Task: First check if it is appropriate to export it. If ;; so, call `org-icalendar--vtodo' to transcode it into ;; a "VTODO" component. (when (and todo-type (pcase (plist-get info :icalendar-include-todo) (`all t) (`unblocked (and (eq type 'headline) (not (org-icalendar-blocked-headline-p entry info)))) ;; unfinished (`t (eq todo-type 'todo)) ((and (pred listp) kwd-list) (member (org-element-property :todo-keyword entry) kwd-list)))) (org-icalendar--vtodo entry uid summary loc desc cat tz class)) ;; Diary-sexp: Collect every diary-sexp element within ENTRY ;; and its title, and transcode them. If ENTRY is ;; a headline, skip inlinetasks: they will be handled ;; separately. (when org-icalendar-include-sexps (let ((counter 0)) (mapconcat #'identity (org-element-map (cons (org-element-property :title entry) (org-element-contents inside)) 'diary-sexp (lambda (sexp) (org-icalendar-transcode-diary-sexp (org-element-property :value sexp) (format "DS%d-%s" (cl-incf counter) uid) summary)) info nil (and (eq type 'headline) 'inlinetask)) ""))))) ;; If ENTRY is a headline, call current function on every ;; inlinetask within it. In agenda export, this is independent ;; from the mark (or lack thereof) on the entry. (when (eq type 'headline) (mapconcat #'identity (org-element-map inside 'inlinetask (lambda (task) (org-icalendar-entry task nil info)) info) "")) ;; Don't forget components from inner entries. contents)))) (defun org-icalendar--rrule (unit value) "Format RRULE icalendar entry for UNIT frequency and VALUE interval. UNIT is a symbol `hour', `day', `week', `month', or `year'." (format "RRULE:FREQ=%s;INTERVAL=%d" (cl-case unit (hour "HOURLY") (day "DAILY") (week "WEEKLY") (month "MONTHLY") (year "YEARLY")) value)) (defun org-icalendar--vevent (entry timestamp uid summary location description categories timezone class) "Create a VEVENT component. ENTRY is either a headline or an inlinetask element. TIMESTAMP is a timestamp object defining the date-time of the event. UID is the unique identifier for the event. SUMMARY defines a short summary or subject for the event. LOCATION defines the intended venue for the event. DESCRIPTION provides the complete description of the event. CATEGORIES defines the categories the event belongs to. TIMEZONE specifies a time zone for this event only. CLASS contains the visibility attribute. Three of them \\(\"PUBLIC\", \"CONFIDENTIAL\", and \"PRIVATE\") are predefined, others should be treated as \"PRIVATE\" if they are unknown to the iCalendar server. Return VEVENT component as a string." (if (eq (org-element-property :type timestamp) 'diary) (org-icalendar-transcode-diary-sexp (org-element-property :raw-value timestamp) uid summary) (concat "BEGIN:VEVENT\n" (org-icalendar-dtstamp) "\n" "UID:" uid "\n" (org-icalendar-convert-timestamp timestamp "DTSTART" nil timezone) "\n" (org-icalendar-convert-timestamp timestamp "DTEND" t timezone) "\n" ;; RRULE. (when (org-element-property :repeater-type timestamp) (concat (org-icalendar--rrule (org-element-property :repeater-unit timestamp) (org-element-property :repeater-value timestamp)) "\n")) "SUMMARY:" summary "\n" (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) (and (org-string-nw-p class) (format "CLASS:%s\n" class)) (and (org-string-nw-p description) (format "DESCRIPTION:%s\n" description)) "CATEGORIES:" categories "\n" ;; VALARM. (org-icalendar--valarm entry timestamp summary) "END:VEVENT\n"))) (defun org-icalendar--repeater-type (elem) "Return ELEM's repeater-type if supported, else warn and return nil." (let ((repeater-value (org-element-property :repeater-value elem)) (repeater-type (org-element-property :repeater-type elem))) (cond ((not (and repeater-type repeater-value (> repeater-value 0))) nil) ;; TODO Add catch-up to supported repeaters (use EXDATE to implement) ((not (memq repeater-type '(cumulate))) (org-display-warning (format "Repeater-type %s not currently supported by iCalendar export" (symbol-name repeater-type))) nil) (repeater-type)))) (defun org-icalendar--vtodo (entry uid summary location description categories timezone class) "Create a VTODO component. ENTRY is either a headline or an inlinetask element. UID is the unique identifier for the task. SUMMARY defines a short summary or subject for the task. LOCATION defines the intended venue for the task. CLASS sets the task class (e.g. confidential). DESCRIPTION provides the complete description of the task. CATEGORIES defines the categories the task belongs to. TIMEZONE specifies a time zone for this TODO only. Return VTODO component as a string." (let* ((sc (and (memq 'todo-start org-icalendar-use-scheduled) (org-element-property :scheduled entry))) (dl (and (memq 'todo-due org-icalendar-use-deadline) (org-element-property :deadline entry))) (sc-repeat-p (org-icalendar--repeater-type sc)) (dl-repeat-p (org-icalendar--repeater-type dl)) (repeat-value (or (org-element-property :repeater-value sc) (org-element-property :repeater-value dl))) (repeat-unit (or (org-element-property :repeater-unit sc) (org-element-property :repeater-unit dl))) (repeat-until (and sc-repeat-p (not dl-repeat-p) dl)) (start (cond (sc) ((eq org-icalendar-todo-unscheduled-start 'current-datetime) (let ((now (decode-time))) (list 'timestamp (list :type 'active :minute-start (nth 1 now) :hour-start (nth 2 now) :day-start (nth 3 now) :month-start (nth 4 now) :year-start (nth 5 now))))) ((or (and (eq org-icalendar-todo-unscheduled-start 'deadline-warning) dl) (and (eq org-icalendar-todo-unscheduled-start 'recurring-deadline-warning) dl-repeat-p)) (let ((dl-raw (org-element-property :raw-value dl))) (with-temp-buffer (insert dl-raw) (goto-char (point-min)) (org-timestamp-down-day (org-get-wdays dl-raw)) (org-element-timestamp-parser))))))) (concat "BEGIN:VTODO\n" "UID:TODO-" uid "\n" (org-icalendar-dtstamp) "\n" (when start (concat (org-icalendar-convert-timestamp start "DTSTART" nil timezone) "\n")) (when (and dl (not repeat-until)) (concat (org-icalendar-convert-timestamp dl "DUE" nil timezone) "\n")) ;; RRULE (cond ;; SCHEDULED, DEADLINE have different repeaters ((and dl-repeat-p (not (and (eq repeat-value (org-element-property :repeater-value dl)) (eq repeat-unit (org-element-property :repeater-unit dl))))) ;; TODO Implement via RDATE with changing DURATION (org-display-warning "Not yet implemented: \ different repeaters on SCHEDULED and DEADLINE. Skipping.") nil) ;; DEADLINE has repeater but SCHEDULED doesn't ((and dl-repeat-p (and sc (not sc-repeat-p))) ;; TODO SCHEDULED should only apply to first instance; ;; use RDATE with custom DURATION to implement that (org-display-warning "Not yet implemented: \ repeater on DEADLINE but not SCHEDULED. Skipping.") nil) ((or sc-repeat-p dl-repeat-p) (concat (org-icalendar--rrule repeat-unit repeat-value) ;; add UNTIL part to RRULE (when repeat-until (let* ((start-time (org-element-property :minute-start start)) ;; RFC5545 requires UTC iff DTSTART is not local time (local-time-p (and (not timezone) (equal org-icalendar-date-time-format ":%Y%m%dT%H%M%S"))) (encoded (org-encode-time 0 (or (org-element-property :minute-start repeat-until) 0) (or (org-element-property :hour-start repeat-until) 0) (org-element-property :day-start repeat-until) (org-element-property :month-start repeat-until) (org-element-property :year-start repeat-until)))) (concat ";UNTIL=" (cond ((not start-time) (format-time-string "%Y%m%d" encoded)) (local-time-p (format-time-string "%Y%m%dT%H%M%S" encoded)) ((format-time-string "%Y%m%dT%H%M%SZ" encoded t)))))) "\n"))) "SUMMARY:" summary "\n" (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) (and (org-string-nw-p class) (format "CLASS:%s\n" class)) (and (org-string-nw-p description) (format "DESCRIPTION:%s\n" description)) "CATEGORIES:" categories "\n" "SEQUENCE:1\n" (format "PRIORITY:%d\n" (let ((pri (or (org-element-property :priority entry) org-priority-default))) (floor (- 9 (* 8. (/ (float (- org-priority-lowest pri)) (- org-priority-lowest org-priority-highest))))))) (format "STATUS:%s\n" (if (eq (org-element-property :todo-type entry) 'todo) "NEEDS-ACTION" "COMPLETED")) "END:VTODO\n"))) (defun org-icalendar--valarm (entry timestamp summary) "Create a VALARM component. ENTRY is the calendar entry triggering the alarm. TIMESTAMP is the start date-time of the entry. SUMMARY defines a short summary or subject for the task. Return VALARM component as a string, or nil if it isn't allowed." ;; Create a VALARM entry if the entry is timed. This is not very ;; general in that: ;; (a) only one alarm per entry is defined, ;; (b) only minutes are allowed for the trigger period ahead of the ;; start time, ;; (c) only a DISPLAY action is defined. [ESF] (let ((alarm-time (let ((warntime (org-element-property :APPT_WARNTIME entry))) (if warntime (string-to-number warntime) nil)))) (and (or (and alarm-time (> alarm-time 0)) (> org-icalendar-alarm-time 0) org-icalendar-force-alarm) (org-element-property :hour-start timestamp) (format "BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:%s TRIGGER:-P0DT0H%dM0S END:VALARM\n" summary (cond ((and alarm-time org-icalendar-force-alarm) alarm-time) ((and alarm-time (not (zerop alarm-time))) alarm-time) (t org-icalendar-alarm-time)))))) ;;;; Template (defun org-icalendar-inner-template (contents _) "Return document body string after iCalendar conversion. CONTENTS is the transcoded contents string." contents) (defun org-icalendar-template (contents info) "Return complete document string after iCalendar conversion. CONTENTS is the transcoded contents string. INFO is a plist used as a communication channel." (org-icalendar--vcalendar ;; Name. (if (not (plist-get info :input-file)) (buffer-name (buffer-base-buffer)) (file-name-nondirectory (file-name-sans-extension (plist-get info :input-file)))) ;; Owner. (if (not (plist-get info :with-author)) "" (org-export-data (plist-get info :author) info)) ;; Timezone. (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z")) ;; Description. (org-export-data (plist-get info :title) info) ;; TTL (plist-get info :icalendar-ttl) contents)) (defun org-icalendar--vcalendar (name owner tz description ttl contents) "Create a VCALENDAR component. NAME, OWNER, TZ, DESCRIPTION, TTL and CONTENTS are all strings giving, respectively, the name of the calendar, its owner, the timezone used, a short description, time to live (refresh period) and the other components included." (org-icalendar-fold-string (concat (format "BEGIN:VCALENDAR VERSION:2.0 X-WR-CALNAME:%s PRODID:-//%s//Emacs with Org mode//EN X-WR-TIMEZONE:%s X-WR-CALDESC:%s\n" (org-icalendar-cleanup-string name) (org-icalendar-cleanup-string owner) (org-icalendar-cleanup-string tz) (org-icalendar-cleanup-string description)) (when ttl (format "X-PUBLISHED-TTL:%s\n" (org-icalendar-cleanup-string ttl))) "CALSCALE:GREGORIAN\n" contents "END:VCALENDAR\n"))) ;;; Interactive Functions ;;;###autoload (defun org-icalendar-export-to-ics (&optional async subtreep visible-only body-only) "Export current buffer to an iCalendar file. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"BEGIN:VCALENDAR\" and \"END:VCALENDAR\". Return ICS file name." (interactive) (let ((file (buffer-file-name (buffer-base-buffer)))) (when (and file org-icalendar-store-UID) (org-icalendar-create-uid file 'warn-user))) ;; Export part. Since this backend is backed up by `ascii', ensure ;; links will not be collected at the end of sections. (let ((outfile (org-export-output-file-name ".ics" subtreep))) (org-export-to-file 'icalendar outfile async subtreep visible-only body-only '(:ascii-charset utf-8 :ascii-links-to-notes nil) #'org-icalendar--post-process-file))) ;;;###autoload (defun org-icalendar-export-agenda-files (&optional async) "Export all agenda files to iCalendar files. When optional argument ASYNC is non-nil, export happens in an external process." (interactive) (if async ;; Asynchronous export is not interactive, so we will not call ;; `org-check-agenda-file'. Instead we remove any non-existent ;; agenda file from the list. (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t)))) (org-export-async-start (lambda (results) (dolist (f results) (org-export-add-to-stack f 'icalendar))) `(let (output-files) (dolist (file ',files outputfiles) (with-current-buffer (org-get-agenda-file-buffer file) (push (expand-file-name (org-icalendar-export-to-ics)) output-files)))))) (let ((files (org-agenda-files t))) (org-agenda-prepare-buffers files) (unwind-protect (dolist (file files) (catch 'nextfile (org-check-agenda-file file) (with-current-buffer (org-get-agenda-file-buffer file) (condition-case err (org-icalendar-export-to-ics) (error (warn "Exporting %s to icalendar failed: %s" file (error-message-string err)) (signal (car err) (cdr err))))))) (org-release-buffers org-agenda-new-buffers))))) ;;;###autoload (defun org-icalendar-combine-agenda-files (&optional async) "Combine all agenda files into a single iCalendar file. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. The file is stored under the name chosen in `org-icalendar-combined-agenda-file'." (interactive) (if async (let ((files (cl-remove-if-not #'file-exists-p (org-agenda-files t)))) (org-export-async-start (lambda (_) (org-export-add-to-stack (expand-file-name org-icalendar-combined-agenda-file) 'icalendar)) `(apply #'org-icalendar--combine-files ',files))) (apply #'org-icalendar--combine-files (org-agenda-files t)))) (defun org-icalendar-export-current-agenda (file) "Export current agenda view to an iCalendar FILE. This function assumes major mode for current buffer is `org-agenda-mode'." (let* ((org-export-use-babel) ;don't evaluate Babel blocks (contents (org-export-string-as (with-output-to-string (save-excursion (let ((p (point-min)) (seen nil)) ;prevent duplicates (while (setq p (next-single-property-change p 'org-hd-marker)) (let ((m (get-text-property p 'org-hd-marker))) (when (and m (not (member m seen))) (push m seen) (with-current-buffer (marker-buffer m) (org-with-wide-buffer (goto-char (marker-position m)) (princ (org-element-normalize-string (buffer-substring (point) (org-entry-end-position)))))))) (forward-line))))) 'icalendar t '(:ascii-charset utf-8 :ascii-links-to-notes nil :icalendar-include-todo all)))) (with-temp-file file (insert (org-icalendar--vcalendar org-icalendar-combined-name user-full-name (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z")) org-icalendar-combined-description org-icalendar-ttl contents))) (org-icalendar--post-process-file file))) (defun org-icalendar--combine-files (&rest files) "Combine entries from multiple files into an iCalendar file. FILES is a list of files to build the calendar from." ;; At the end of the process, all buffers related to FILES are going ;; to be killed. Make sure to only kill the ones opened in the ;; process. (let ((org-agenda-new-buffers nil)) (unwind-protect (progn (with-temp-file org-icalendar-combined-agenda-file (insert (org-icalendar--vcalendar ;; Name. org-icalendar-combined-name ;; Owner. user-full-name ;; Timezone. (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z")) ;; Description. org-icalendar-combined-description ;; TTL (Refresh period) org-icalendar-ttl ;; Contents. (concat ;; Agenda contents. (mapconcat (lambda (file) (catch 'nextfile (org-check-agenda-file file) (with-current-buffer (org-get-agenda-file-buffer file) ;; Create ID if necessary. (when org-icalendar-store-UID (org-icalendar-create-uid file t)) (org-export-as 'icalendar nil nil t '(:ascii-charset utf-8 :ascii-links-to-notes nil))))) files "") ;; BBDB anniversaries. (when (and org-icalendar-include-bbdb-anniversaries (require 'ol-bbdb nil t)) (with-output-to-string (org-bbdb-anniv-export-ical))))))) (org-icalendar--post-process-file org-icalendar-combined-agenda-file)) (org-release-buffers org-agenda-new-buffers)))) (provide 'ox-icalendar) ;; Local variables: ;; generated-autoload-file: "org-loaddefs.el" ;; End: ;;; ox-icalendar.el ends here org-mode-9.8.4+dfsg/lisp/ox-koma-letter.el000066400000000000000000001171631517644066700203560ustar00rootroot00000000000000;;; ox-koma-letter.el --- KOMA Scrlttr2 Backend for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2007-2026 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Alan Schmitt ;; Viktor Rosenfeld ;; Rasmus Pank Roulund ;; Keywords: org, text, tex ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; This library implements a KOMA Scrlttr2 backend, derived from the ;; LaTeX one. ;; ;; Depending on the desired output format, three commands are provided ;; for export: `org-koma-letter-export-as-latex' (temporary buffer), ;; `org-koma-letter-export-to-latex' ("tex" file) and ;; `org-koma-letter-export-to-pdf' ("pdf" file). ;; ;; On top of buffer keywords supported by `latex' backend (see ;; `org-latex-packages-alist'), this backend introduces the following ;; keywords: ;; - CLOSING: see `org-koma-letter-closing', ;; - FROM_ADDRESS: see `org-koma-letter-from-address', ;; - LCO: see `org-koma-letter-class-option-file', ;; - OPENING: see `org-koma-letter-opening', ;; - PHONE_NUMBER: see `org-koma-letter-phone-number', ;; - URL: see `org-koma-letter-url', ;; - FROM_LOGO: see `org-koma-letter-from-logo', ;; - SIGNATURE: see `org-koma-letter-signature', ;; - PLACE: see `org-koma-letter-place', ;; - LOCATION: see `org-koma-letter-location', ;; - TO_ADDRESS: If unspecified this is set to "\mbox{}". ;; ;; TO_ADDRESS, FROM_ADDRESS, LOCATION, CLOSING, and SIGNATURE can also ;; be specified using "special headings" with the special tags ;; specified in `org-koma-letter-special-tags-in-letter'. LaTeX line ;; breaks are not necessary for TO_ADDRESS, FROM_ADDRESS and LOCATION. ;; If both a headline and a keyword specify a to or from address the ;; value is determined in accordance with ;; `org-koma-letter-prefer-special-headings'. ;; ;; A number of OPTIONS settings can be set to change which contents is ;; exported. ;; - backaddress (see `org-koma-letter-use-backaddress') ;; - foldmarks (see `org-koma-letter-use-foldmarks') ;; - phone (see `org-koma-letter-use-phone') ;; - url (see `org-koma-letter-use-url') ;; - from-logo (see `org-koma-letter-use-from-logo') ;; - email (see `org-koma-letter-use-email') ;; - place (see `org-koma-letter-use-place') ;; - location (see `org-koma-letter-location') ;; - subject, a list of format options ;; (see `org-koma-letter-subject-format') ;; - after-closing-order, a list of the ordering of headings with ;; special tags after closing (see ;; `org-koma-letter-special-tags-after-closing') ;; - after-letter-order, as above, but after the end of the letter ;; (see `org-koma-letter-special-tags-after-letter'). ;; ;; The following variables works differently from the main LaTeX class ;; - AUTHOR: Default to user-full-name but may be disabled. ;; (See also `org-koma-letter-author'.) ;; - EMAIL: Same as AUTHOR. (See also `org-koma-letter-email'.) ;; ;; FROM_LOGO uses LaTeX markup. FROM_LOGO provides the ;; "includegraphics" command to tell LaTeX where to find the logo. ;; This command needs to know the logo's directory and file name. The ;; directory can either be relative or absolute, just as you would ;; expect. LaTeX can use three file types for the logo: PDF, JPEG, or ;; PNG. The logo can either include or exclude its extension, which ;; might surprise you. When you exclude its extension, LaTeX will ;; search the directory for the "best" quality graphics format. For ;; example if it finds both logo.pdf and logo.png then it will ;; identify the PDF as "better", and include "logo.pdf". This can be ;; useful, for example, when you are mocking up a logo in the PNG ;; raster format and then switch over to the higher quality PDF vector ;; format. When you include the file extension then LaTeX will ;; include it without searching for higher quality file types. ;; Whatever file type you choose, it will probably require a few ;; design iterations to get the best looking logo size for your ;; letter. Finally, the directory and file name are specified ;; *without* quotes. Here are some examples with commentary, in the ;; location of your letter, with a logo named "logo", to get you ;; started: ;; ;; Logo in the same directory: \includegraphics{logo} ;; or a sub-directory: \includegraphics{logos/production/logo} ;; ;; Logos specified using absolute paths on Linux or Windows: ;; ;; \includegraphics{~/correspondence/logo} ;; \includegraphics{~/correspondence/logos/production/logo} ;; \includegraphics{c:/you/correspondence/logo} ;; \includegraphics{c:/you/correspondence/logos/production/logo} ;; ;; Logos in the same directory where the "better" quality PDF will ;; be chosen over the JPG: ;; ;; \includegraphics{logo.pdf} ;; \includegraphics{logo.png} ;; ;; Headlines are in general ignored. However, headlines with special ;; tags can be used for specified contents like postscript (ps), ;; carbon copy (cc), enclosures (encl) and code to be inserted after ;; \end{letter} (after_letter). Specials tags are defined in ;; `org-koma-letter-special-tags-after-closing' and ;; `org-koma-letter-special-tags-after-letter'. Currently members of ;; `org-koma-letter-special-tags-after-closing' used as macros and the ;; content of the headline is the argument. ;; ;; Headlines with to and from may also be used rather than the keyword ;; approach described above. If both a keyword and a headline with ;; information is present precedence is determined by ;; `org-koma-letter-prefer-special-headings'. ;; ;; You need an appropriate association in `org-latex-classes' in order ;; to use the KOMA Scrlttr2 class. By default, a sparse scrlttr2 ;; class is provided: "default-koma-letter". You can also add you own ;; letter class. For instance: ;; ;; (add-to-list 'org-latex-classes ;; '("my-letter" ;; "\\documentclass\[% ;; DIV=14, ;; fontsize=12pt, ;; parskip=half, ;; subject=titled, ;; backaddress=false, ;; fromalign=left, ;; fromemail=true, ;; fromphone=true\]\{scrlttr2\} ;; \[DEFAULT-PACKAGES] ;; \[PACKAGES] ;; \[EXTRA]")) ;; ;; Then, in your Org document, be sure to require the proper class ;; with: ;; ;; #+LATEX_CLASS: my-letter ;; ;; Or by setting `org-koma-letter-default-class'. ;; ;; You may have to load (LaTeX) Babel as well, e.g., by adding ;; it to `org-latex-packages-alist', ;; ;; (add-to-list 'org-latex-packages-alist '("AUTO" "babel" nil)) ;;; Code: (require 'org-macs) (org-assert-version) (require 'cl-lib) (require 'ox-latex) ;; Install a default letter class. (unless (assoc "default-koma-letter" org-latex-classes) (add-to-list 'org-latex-classes '("default-koma-letter" "\\documentclass[11pt]{scrlttr2}"))) ;;; User-Configurable Variables (defgroup org-export-koma-letter nil "Options for exporting to KOMA scrlttr2 class in LaTeX export." :tag "Org Koma-Letter" :group 'org-export) (defcustom org-koma-letter-class-option-file "NF" "Letter Class Option File. This option can also be set with the LCO keyword." :type 'string) (defcustom org-koma-letter-author 'user-full-name "Sender's name. This variable defaults to calling the function `user-full-name' which just returns the current function `user-full-name'. Alternatively a string, nil or a function may be given. Functions must return a string. This option can also be set with the AUTHOR keyword." :type '(radio (function-item user-full-name) (string) (function) (const :tag "Do not export author" nil))) (defcustom org-koma-letter-email 'org-koma-letter-email "Sender's email address. This variable defaults to the value `org-koma-letter-email' which returns `user-mail-address'. Alternatively a string, nil or a function may be given. Functions must return a string. This option can also be set with the EMAIL keyword." :type '(radio (function-item org-koma-letter-email) (string) (function) (const :tag "Do not export email" nil))) (defcustom org-koma-letter-from-address "" "Sender's address, as a string. This option can also be set with one or more FROM_ADDRESS keywords." :type 'string) (defcustom org-koma-letter-phone-number "" "Sender's phone number, as a string. This option can also be set with the PHONE_NUMBER keyword." :type 'string) (defcustom org-koma-letter-url "" "Sender's URL, e. g., the URL of her homepage. This option can also be set with the URL keyword." :type 'string :safe #'stringp) (defcustom org-koma-letter-from-logo "" "Commands for inserting the sender's logo, e. g., \\includegraphics{logo}. This option can also be set with the FROM_LOGO keyword." :type 'string :safe #'stringp) (defcustom org-koma-letter-place "" "Place from which the letter is sent, as a string. This option can also be set with the PLACE keyword." :type 'string) (defcustom org-koma-letter-location "" "Sender's extension field, as a string. This option can also be set with the LOCATION keyword. Moreover, when: (1) Either `org-koma-letter-prefer-special-headings' is non-nil or there is no LOCATION keyword or the LOCATION keyword is empty; (2) the letter contains a headline with the special tag \"location\"; then the location will be set as the content of the location special heading. The location field is typically printed right of the address field (See Figure 4.9. in the English manual of 2015-10-03)." :type 'string) (defcustom org-koma-letter-opening "" "Letter's opening, as a string. This option can also be set with the OPENING keyword. Moreover, when: (1) Either `org-koma-letter-prefer-special-headings' is non-nil or the CLOSING keyword is empty (2) `org-koma-letter-headline-is-opening-maybe' is non-nil; (3) the letter contains a headline without a special tag (e.g. \"to\" or \"ps\"); then the opening will be implicitly set as the untagged headline title." :type 'string) (defcustom org-koma-letter-closing "" "Letter's closing, as a string. This option can also be set with the CLOSING keyword. Moreover, when: (1) Either `org-koma-letter-prefer-special-headings' is non-nil or the CLOSING keyword is empty; (2) `org-koma-letter-headline-is-opening-maybe' is non-nil; (3) the letter contains a headline with the special tag \"closing\"; then the opening will be set as the title of the closing special heading title." :type 'string) (defcustom org-koma-letter-signature "" "Signature, as a string. This option can also be set with the SIGNATURE keyword. Moreover, when: (1) Either `org-koma-letter-prefer-special-headings' is non-nil or there is no CLOSING keyword or the CLOSING keyword is empty; (2) `org-koma-letter-headline-is-opening-maybe' is non-nil; (3) the letter contains a headline with the special tag \"closing\"; then the signature will be set as the content of the closing special heading. Note if the content is empty the signature will not be set." :type 'string) (defcustom org-koma-letter-prefer-special-headings nil "Non-nil means prefer headlines over keywords for TO and FROM. This option can also be set with the OPTIONS keyword, e.g.: \"special-headings:t\"." :type 'boolean) (defcustom org-koma-letter-subject-format t "Non-nil means include the subject. Support formatting options. When t, insert a subject using default options. When nil, do not insert a subject at all. It can also be a list of symbols among the following ones: `afteropening' Subject after opening `beforeopening' Subject before opening `centered' Subject centered `left' Subject left-justified `right' Subject right-justified `titled' Add title/description to subject `underlined' Set subject underlined `untitled' Do not add title/description to subject Please refer to the KOMA-script manual (Table 4.16. in the English manual of 2012-07-22). This option can also be set with the OPTIONS keyword, e.g.: \"subject:(underlined centered)\"." :type '(choice (const :tag "No export" nil) (const :tag "Default options" t) (set :tag "Configure options" (const :tag "Subject after opening" afteropening) (const :tag "Subject before opening" beforeopening) (const :tag "Subject centered" centered) (const :tag "Subject left-justified" left) (const :tag "Subject right-justified" right) (const :tag "Add title or description to subject" underlined) (const :tag "Set subject underlined" titled) (const :tag "Do not add title or description to subject" untitled)))) (defcustom org-koma-letter-use-backaddress nil "Non-nil prints return address in line above to address. This option can also be set with the OPTIONS keyword, e.g.: \"backaddress:t\"." :type 'boolean) (defcustom org-koma-letter-use-foldmarks t "Configure appearance of folding marks. When t, activate default folding marks. When nil, do not insert folding marks at all. It can also be a list of symbols among the following ones: `B' Activate upper horizontal mark on left paper edge `b' Deactivate upper horizontal mark on left paper edge `H' Activate all horizontal marks on left paper edge `h' Deactivate all horizontal marks on left paper edge `L' Activate left vertical mark on upper paper edge `l' Deactivate left vertical mark on upper paper edge `M' Activate middle horizontal mark on left paper edge `m' Deactivate middle horizontal mark on left paper edge `P' Activate punch or center mark on left paper edge `p' Deactivate punch or center mark on left paper edge `T' Activate lower horizontal mark on left paper edge t Deactivate lower horizontal mark on left paper edge `V' Activate all vertical marks on upper paper edge `v' Deactivate all vertical marks on upper paper edge This option can also be set with the OPTIONS keyword, e.g.: \"foldmarks:(b l m t)\"." :type '(choice (const :tag "Activate default folding marks" t) (const :tag "Deactivate folding marks" nil) (set :tag "Configure folding marks" (const :tag "Activate upper horizontal mark on left paper edge" B) (const :tag "Deactivate upper horizontal mark on left paper edge" b) (const :tag "Activate all horizontal marks on left paper edge" H) (const :tag "Deactivate all horizontal marks on left paper edge" h) (const :tag "Activate left vertical mark on upper paper edge" L) (const :tag "Deactivate left vertical mark on upper paper edge" l) (const :tag "Activate middle horizontal mark on left paper edge" M) (const :tag "Deactivate middle horizontal mark on left paper edge" m) (const :tag "Activate punch or center mark on left paper edge" P) (const :tag "Deactivate punch or center mark on left paper edge" p) (const :tag "Activate lower horizontal mark on left paper edge" T) (const :tag "Deactivate lower horizontal mark on left paper edge" t) (const :tag "Activate all vertical marks on upper paper edge" V) (const :tag "Deactivate all vertical marks on upper paper edge" v)))) (defcustom org-koma-letter-use-phone nil "Non-nil prints sender's phone number. This option can also be set with the OPTIONS keyword, e.g.: \"phone:t\"." :type 'boolean) (defcustom org-koma-letter-use-url nil "Non-nil prints sender's URL. This option can also be set with the OPTIONS keyword, e.g.: \"url:t\"." :type 'boolean :safe #'booleanp) (defcustom org-koma-letter-use-from-logo nil "Non-nil prints sender's FROM_LOGO. This option can also be set with the OPTIONS keyword, e.g.: \"from-logo:t\"." :type 'boolean :safe #'booleanp) (defcustom org-koma-letter-use-email nil "Non-nil prints sender's email address. This option can also be set with the OPTIONS keyword, e.g.: \"email:t\"." :type 'boolean) (defcustom org-koma-letter-use-place t "Non-nil prints the letter's place next to the date. This option can also be set with the OPTIONS keyword, e.g.: \"place:nil\"." :type 'boolean) (defcustom org-koma-letter-default-class "default-koma-letter" "Default class for `org-koma-letter'. The value must be a member of `org-latex-classes'." :type 'string) (defcustom org-koma-letter-headline-is-opening-maybe t "Non-nil means a headline may be used as an opening and closing. See also `org-koma-letter-opening' and `org-koma-letter-closing'." :type 'boolean) (defcustom org-koma-letter-prefer-subject nil "Non-nil means title should be interpreted as subject if subject is missing. This option can also be set with the OPTIONS keyword, e.g. \"title-subject:t\"." :type 'boolean) (defconst org-koma-letter-special-tags-in-letter '(to from closing location) "Header tags related to the letter itself.") (defconst org-koma-letter-special-tags-after-closing '(after_closing ps encl cc) "Header tags to be inserted in the letter after closing.") (defconst org-koma-letter-special-tags-as-macro '(ps encl cc) "Header tags to be inserted as macros.") (defconst org-koma-letter-special-tags-after-letter '(after_letter) "Header tags to be inserted after the letter.") (defvar org-koma-letter-special-contents nil "Holds special content temporarily.") ;;; Define Backend (org-export-define-derived-backend 'koma-letter 'latex :options-alist '((:latex-class "LATEX_CLASS" nil org-koma-letter-default-class t) (:lco "LCO" nil org-koma-letter-class-option-file) (:author "AUTHOR" nil (org-koma-letter--get-value org-koma-letter-author) parse) (:author-changed-in-buffer-p "AUTHOR" nil nil t) (:from-address "FROM_ADDRESS" nil org-koma-letter-from-address newline) (:phone-number "PHONE_NUMBER" nil org-koma-letter-phone-number) (:url "URL" nil org-koma-letter-url) (:from-logo "FROM_LOGO" nil org-koma-letter-from-logo) (:email "EMAIL" nil (org-koma-letter--get-value org-koma-letter-email) t) (:to-address "TO_ADDRESS" nil nil newline) (:place "PLACE" nil org-koma-letter-place) (:location "LOCATION" nil org-koma-letter-location) (:subject "SUBJECT" nil nil parse) (:opening "OPENING" nil org-koma-letter-opening parse) (:closing "CLOSING" nil org-koma-letter-closing parse) (:signature "SIGNATURE" nil org-koma-letter-signature newline) (:special-headings nil "special-headings" org-koma-letter-prefer-special-headings) (:special-tags-as-macro nil nil org-koma-letter-special-tags-as-macro) (:special-tags-in-letter nil nil org-koma-letter-special-tags-in-letter) (:special-tags-after-closing nil "after-closing-order" org-koma-letter-special-tags-after-closing) (:special-tags-after-letter nil "after-letter-order" org-koma-letter-special-tags-after-letter) (:with-backaddress nil "backaddress" org-koma-letter-use-backaddress) (:with-email nil "email" org-koma-letter-use-email) (:with-foldmarks nil "foldmarks" org-koma-letter-use-foldmarks) (:with-phone nil "phone" org-koma-letter-use-phone) (:with-url nil "url" org-koma-letter-use-url) (:with-from-logo nil "from-logo" org-koma-letter-use-from-logo) (:with-place nil "place" org-koma-letter-use-place) (:with-subject nil "subject" org-koma-letter-subject-format) (:with-title-as-subject nil "title-subject" org-koma-letter-prefer-subject) (:with-headline-opening nil nil org-koma-letter-headline-is-opening-maybe) ;; Special properties non-nil when a setting happened in buffer. ;; They are used to prioritize in-buffer settings over "lco" ;; files. See `org-koma-letter-template'. (:inbuffer-author "AUTHOR" nil 'koma-letter:empty) (:inbuffer-from "FROM" nil 'koma-letter:empty) (:inbuffer-email "EMAIL" nil 'koma-letter:empty) (:inbuffer-phone-number "PHONE_NUMBER" nil 'koma-letter:empty) (:inbuffer-url "URL" nil 'koma-letter:empty) (:inbuffer-from-logo "FROM_LOGO" nil 'koma-letter:empty) (:inbuffer-place "PLACE" nil 'koma-letter:empty) (:inbuffer-location "LOCATION" nil 'koma-letter:empty) (:inbuffer-signature "SIGNATURE" nil 'koma-letter:empty) (:inbuffer-with-backaddress nil "backaddress" 'koma-letter:empty) (:inbuffer-with-email nil "email" 'koma-letter:empty) (:inbuffer-with-foldmarks nil "foldmarks" 'koma-letter:empty) (:inbuffer-with-phone nil "phone" 'koma-letter:empty) (:inbuffer-with-url nil "url" 'koma-letter:empty) (:inbuffer-with-from-logo nil "from-logo" 'koma-letter:empty) (:inbuffer-with-place nil "place" 'koma-letter:empty)) :translate-alist '((export-block . org-koma-letter-export-block) (export-snippet . org-koma-letter-export-snippet) (headline . org-koma-letter-headline) (keyword . org-koma-letter-keyword) (template . org-koma-letter-template)) :menu-entry '(?k "Export with KOMA Scrlttr2" ((?L "As LaTeX buffer" org-koma-letter-export-as-latex) (?l "As LaTeX file" org-koma-letter-export-to-latex) (?p "As PDF file" org-koma-letter-export-to-pdf) (?o "As PDF file and open" (lambda (a s v b) (if a (org-koma-letter-export-to-pdf t s v b) (org-open-file (org-koma-letter-export-to-pdf nil s v b)))))))) ;;; Helper functions (defun org-koma-letter-email () "Return the current `user-mail-address'." user-mail-address) ;; The following is taken from/inspired by ox-grof.el ;; Thanks, Luis! (defun org-koma-letter--get-tagged-contents (key) "Get contents from a headline tagged with KEY. The contents is stored in `org-koma-letter-special-contents'." (let ((value (cdr (assoc-string (org-koma-letter--get-value key) org-koma-letter-special-contents)))) (when value (org-string-nw-p (org-trim value))))) (defun org-koma-letter--get-value (value) "Turn value into a string whenever possible. Determines if VALUE is nil, a string, a function or a symbol and return a string or nil." (when value (cond ((stringp value) value) ((functionp value) (funcall value)) ((symbolp value) (symbol-name value)) (t value)))) (defun org-koma-letter--special-contents-inline (keywords info) "Process KEYWORDS members of `org-koma-letter-special-contents'. KEYWORDS is a list of symbols. Return them as a string to be formatted. INFO is the information plist possibly holding :special-tags-as-macro property. See `org-koma-letter-special-tags-as-macro'. The function is used for inserting content of special headings such as the one tagged with PS." (mapconcat (lambda (keyword) (let* ((name (org-koma-letter--get-value keyword)) (value (org-koma-letter--get-tagged-contents name)) (macrop (memq keyword (plist-get info :special-tags-as-macro)))) (cond ((not value) nil) (macrop (format "\\%s{%s}\n" name value)) (t value)))) keywords "\n")) (defun org-koma-letter--add-latex-newlines (string) "Replace regular newlines with LaTeX newlines (i.e. `\\\\') in STRING. Return a new string." (let ((str (org-trim string))) (when (org-string-nw-p str) (replace-regexp-in-string "\n" "\\\\\\\\\n" str)))) ;;; Transcode Functions ;;;; Export Block (defun org-koma-letter-export-block (export-block _contents _info) "Transcode an EXPORT-BLOCK element into KOMA Scrlttr2 code. CONTENTS is nil. INFO is a plist used as a communication channel." (when (member (org-element-property :type export-block) '("KOMA-LETTER" "LATEX")) (org-remove-indentation (org-element-property :value export-block)))) ;;;; Export Snippet (defun org-koma-letter-export-snippet (export-snippet _contents _info) "Transcode an EXPORT-SNIPPET object into KOMA Scrlttr2 code. CONTENTS is nil. INFO is a plist used as a communication channel." (when (memq (org-export-snippet-backend export-snippet) '(latex koma-letter)) (org-element-property :value export-snippet))) ;;;; Keyword (defun org-koma-letter-keyword (keyword contents info) "Transcode a KEYWORD element into KOMA Scrlttr2 code. CONTENTS is nil. INFO is a plist used as a communication channel." (let ((key (org-element-property :key keyword)) (value (org-element-property :value keyword))) ;; Handle specifically KOMA-LETTER keywords. Otherwise, fallback ;; to `latex' backend. (if (equal key "KOMA-LETTER") value (org-export-with-backend 'latex keyword contents info)))) ;; Headline (defun org-koma-letter-headline (headline contents info) "Transcode a HEADLINE element from Org to LaTeX. CONTENTS holds the contents of the headline. INFO is a plist holding contextual information. Note that if a headline is tagged with a tag from `org-koma-letter-special-tags' it will not be exported, but stored in `org-koma-letter-special-contents' and included at the appropriate place." (let ((special-tag (org-koma-letter--special-tag headline info))) (if (not special-tag) contents (push (cons special-tag contents) org-koma-letter-special-contents) ""))) (defun org-koma-letter--special-tag (headline info) "Non-nil if HEADLINE is a special headline. INFO is a plist holding contextual information. Return first special tag headline." (let ((special-tags (append (plist-get info :special-tags-in-letter) (plist-get info :special-tags-after-closing) (plist-get info :special-tags-after-letter)))) (cl-some (lambda (tag) (and (assoc-string tag special-tags) tag)) (org-export-get-tags headline info)))) (defun org-koma-letter--keyword-or-headline (plist-key pred info) "Return the correct version of opening or closing. PLIST-KEY should be a key in info, typically :opening or :closing. PRED is a predicate run on headline to determine which title to use which takes two arguments, a headline element and an info plist. INFO is a plist holding contextual information. Return the preferred candidate for the exported of PLIST-KEY." (let* ((keyword-candidate (plist-get info plist-key)) (headline-candidate (when (and (plist-get info :with-headline-opening) (or (plist-get info :special-headings) (not keyword-candidate))) (org-element-map (plist-get info :parse-tree) 'headline (lambda (h) (and (funcall pred h info) (org-element-property :title h))) info t)))) (org-export-data (or headline-candidate keyword-candidate "") info))) ;;;; Template (defun org-koma-letter-template (contents info) "Return complete document string after KOMA Scrlttr2 conversion. CONTENTS is the transcoded contents string. INFO is a plist holding export options." (concat ;; Timestamp. (and (plist-get info :time-stamp-file) (format-time-string "%% Created %Y-%m-%d %a %H:%M\n")) ;; LaTeX compiler (org-latex--insert-compiler info) ;; Document class and packages. (org-latex-make-preamble info) ;; Settings. They can come from three locations, in increasing ;; order of precedence: global variables, LCO files and in-buffer ;; settings. Thus, we first insert settings coming from global ;; variables, then we insert LCO files, and, eventually, we insert ;; settings coming from buffer keywords. (org-koma-letter--build-settings 'global info) (mapconcat (lambda (file) (format "\\LoadLetterOption{%s}\n" file)) (split-string (or (plist-get info :lco) "")) "") (org-koma-letter--build-settings 'buffer info) ;; Date. (format "\\date{%s}\n" (org-export-data (org-export-get-date info) info)) ;; Hyperref, document start, and subject and title. (let* ((with-subject (plist-get info :with-subject)) (with-title (plist-get info :with-title)) (title-as-subject (and with-subject (plist-get info :with-title-as-subject))) (subject* (org-string-nw-p (org-export-data (plist-get info :subject) info))) (title* (and with-title (org-string-nw-p (org-export-data (plist-get info :title) info)))) (subject (cond ((not with-subject) nil) (title-as-subject (or subject* title*)) (t subject*))) (title (cond ((not with-title) nil) (title-as-subject (and subject* title*)) (t title*))) (hyperref-template (plist-get info :latex-hyperref-template)) (spec (append (list (cons ?t (or title subject ""))) (org-latex--format-spec info)))) (concat (when (and with-subject (not (eq with-subject t))) (format "\\KOMAoption{subject}{%s}\n" (if (symbolp with-subject) with-subject (mapconcat #'symbol-name with-subject ",")))) ;; Hyperref. (and (stringp hyperref-template) (format-spec hyperref-template spec)) ;; Document start. "\\begin{document}\n\n" ;; Subject and title. (when subject (format "\\setkomavar{subject}{%s}\n" subject)) (when title (format "\\setkomavar{title}{%s}\n" title)) (when (or (org-string-nw-p title) (org-string-nw-p subject)) "\n"))) ;; Letter start. (let ((keyword-val (plist-get info :to-address)) (heading-val (org-koma-letter--get-tagged-contents 'to))) (format "\\begin{letter}{%%\n%s}\n\n" (org-koma-letter--add-latex-newlines (or (if (plist-get info :special-headings) (or heading-val keyword-val) (or keyword-val heading-val)) "\\mbox{}")))) ;; Opening. (format "\\opening{%s}\n\n" (org-koma-letter--keyword-or-headline :opening (lambda (h i) (not (org-koma-letter--special-tag h i))) info)) ;; Letter body. contents ;; Closing. (format "\\closing{%s}\n" (org-koma-letter--keyword-or-headline :closing (lambda (h i) (let ((special-tag (org-koma-letter--special-tag h i))) (and special-tag (string= "closing" special-tag)))) info)) (org-koma-letter--special-contents-inline (plist-get info :special-tags-after-closing) info) ;; Letter end. "\n\\end{letter}\n" (org-koma-letter--special-contents-inline (plist-get info :special-tags-after-letter) info) ;; Document end. "\n\\end{document}")) (defun org-koma-letter--build-settings (scope info) "Build settings string according to type. SCOPE is either `global' or `buffer'. INFO is a plist used as a communication channel." (let* ((check-scope ;; Non-nil value when SETTING was defined in SCOPE. (lambda (setting) (let ((property (intern (format ":inbuffer-%s" setting)))) (if (eq scope 'global) (eq (plist-get info property) 'koma-letter:empty) (not (eq (plist-get info property) 'koma-letter:empty)))))) (heading-or-key-value (lambda (heading key &optional scoped) (let* ((heading-val (org-koma-letter--get-tagged-contents heading)) (key-val (org-string-nw-p (plist-get info key))) (scopedp (funcall check-scope (or scoped heading)))) (and (or (and key-val scopedp) heading-val) (not (and (eq scope 'global) heading-val)) (if scopedp key-val heading-val)))))) (concat ;; Name. (let ((author (plist-get info :author))) (and author (funcall check-scope 'author) (format "\\setkomavar{fromname}{%s}\n" (org-export-data author info)))) ;; From. (let ((from (funcall heading-or-key-value 'from :from-address))) (and from (format "\\setkomavar{fromaddress}{%s}\n" (org-koma-letter--add-latex-newlines from)))) ;; Email. (let ((email (plist-get info :email))) (and email (funcall check-scope 'email) (format "\\setkomavar{fromemail}{%s}\n" email))) (and (funcall check-scope 'with-email) (format "\\KOMAoption{fromemail}{%s}\n" (if (plist-get info :with-email) "true" "false"))) ;; Phone number. (let ((phone-number (plist-get info :phone-number))) (and (org-string-nw-p phone-number) (funcall check-scope 'phone-number) (format "\\setkomavar{fromphone}{%s}\n" phone-number))) (and (funcall check-scope 'with-phone) (format "\\KOMAoption{fromphone}{%s}\n" (if (plist-get info :with-phone) "true" "false"))) ;; URL (let ((url (plist-get info :url))) (and (org-string-nw-p url) (funcall check-scope 'url) (format "\\setkomavar{fromurl}{%s}\n" url))) (and (funcall check-scope 'with-url) (format "\\KOMAoption{fromurl}{%s}\n" (if (plist-get info :with-url) "true" "false"))) ;; From Logo (let ((from-logo (plist-get info :from-logo))) (and (org-string-nw-p from-logo) (funcall check-scope 'from-logo) (format "\\setkomavar{fromlogo}{%s}\n" from-logo))) (and (funcall check-scope 'with-from-logo) (format "\\KOMAoption{fromlogo}{%s}\n" (if (plist-get info :with-from-logo) "true" "false"))) ;; Signature. (let* ((heading-val (and (plist-get info :with-headline-opening) (pcase (org-koma-letter--get-tagged-contents 'closing) ((and (pred org-string-nw-p) closing) (org-trim closing)) (_ nil)))) (signature (org-string-nw-p (plist-get info :signature))) (signature-scope (funcall check-scope 'signature))) (and (or (and signature signature-scope) heading-val) (not (and (eq scope 'global) heading-val)) (format "\\setkomavar{signature}{%s}\n" (if signature-scope signature heading-val)))) ;; Back address. (and (funcall check-scope 'with-backaddress) (format "\\KOMAoption{backaddress}{%s}\n" (if (plist-get info :with-backaddress) "true" "false"))) ;; Place. (let ((with-place-set (funcall check-scope 'with-place)) (place-set (funcall check-scope 'place))) (and (or (and with-place-set place-set) (and (eq scope 'buffer) (or with-place-set place-set))) (format "\\setkomavar{place}{%s}\n" (if (plist-get info :with-place) (plist-get info :place) "")))) ;; Location. (let ((location (funcall heading-or-key-value 'location :location))) (and location (format "\\setkomavar{location}{%s}\n" location))) ;; Folding marks. (and (funcall check-scope 'with-foldmarks) (let ((foldmarks (plist-get info :with-foldmarks))) (cond ((consp foldmarks) (format "\\KOMAoptions{foldmarks=true,foldmarks=%s}\n" (mapconcat #'symbol-name foldmarks ""))) (foldmarks "\\KOMAoptions{foldmarks=true}\n") (t "\\KOMAoptions{foldmarks=false}\n"))))))) ;;; Commands ;;;###autoload (defun org-koma-letter-export-as-latex (&optional async subtreep visible-only body-only ext-plist) "Export current buffer as a KOMA Scrlttr2 letter. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting buffer should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\\begin{letter}\" and \"\\end{letter}\". EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Export is done in a buffer named \"*Org KOMA-LETTER Export*\". It will be displayed if `org-export-show-temporary-export-buffer' is non-nil." (interactive) (let (org-koma-letter-special-contents) (org-export-to-buffer 'koma-letter "*Org KOMA-LETTER Export*" async subtreep visible-only body-only ext-plist (if (fboundp 'major-mode-remap) (major-mode-remap 'latex-mode) #'LaTeX-mode)))) ;;;###autoload (defun org-koma-letter-export-to-latex (&optional async subtreep visible-only body-only ext-plist) "Export current buffer as a KOMA Scrlttr2 letter (tex). If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\\begin{letter}\" and \"\\end{letter}\". EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. When optional argument PUB-DIR is set, use it as the publishing directory. Return output file's name." (interactive) (let ((outfile (org-export-output-file-name ".tex" subtreep)) (org-koma-letter-special-contents)) (org-export-to-file 'koma-letter outfile async subtreep visible-only body-only ext-plist))) ;;;###autoload (defun org-koma-letter-export-to-pdf (&optional async subtreep visible-only body-only ext-plist) "Export current buffer as a KOMA Scrlttr2 letter (pdf). If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\\begin{letter}\" and \"\\end{letter}\". EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Return PDF file's name." (interactive) (let ((file (org-export-output-file-name ".tex" subtreep)) (org-koma-letter-special-contents)) (org-export-to-file 'koma-letter file async subtreep visible-only body-only ext-plist #'org-latex-compile))) (provide 'ox-koma-letter) ;;; ox-koma-letter.el ends here org-mode-9.8.4+dfsg/lisp/ox-latex.el000066400000000000000000005552631517644066700172560ustar00rootroot00000000000000;;; ox-latex.el --- LaTeX Backend for Org Export Engine -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2026 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Maintainer: Daniel Fleischer ;; Keywords: outlines, hypermedia, calendar, text ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; See Org manual for details. ;;; Code: (require 'org-macs) (org-assert-version) (require 'cl-lib) (require 'ox) (require 'ox-publish) ;;; Function Declarations (defvar org-latex-default-packages-alist) (defvar org-latex-packages-alist) (defvar orgtbl-exp-regexp) (declare-function engrave-faces-latex-gen-preamble "ext:engrave-faces-latex") (declare-function engrave-faces-latex-buffer "ext:engrave-faces-latex") (declare-function engrave-faces-latex-gen-preamble-line "ext:engrave-faces-latex") (declare-function engrave-faces-get-theme "ext:engrave-faces") (defvar engrave-faces-latex-output-style) (defvar engrave-faces-current-preset-style) (defvar engrave-faces-latex-mathescape) ;;; Define Backend (org-export-define-backend 'latex '((bold . org-latex-bold) (center-block . org-latex-center-block) (clock . org-latex-clock) (code . org-latex-code) (drawer . org-latex-drawer) (dynamic-block . org-latex-dynamic-block) (entity . org-latex-entity) (example-block . org-latex-example-block) (export-block . org-latex-export-block) (export-snippet . org-latex-export-snippet) (fixed-width . org-latex-fixed-width) (footnote-definition . org-latex-footnote-definition) (footnote-reference . org-latex-footnote-reference) (headline . org-latex-headline) (horizontal-rule . org-latex-horizontal-rule) (inline-src-block . org-latex-inline-src-block) (inlinetask . org-latex-inlinetask) (italic . org-latex-italic) (item . org-latex-item) (keyword . org-latex-keyword) (latex-environment . org-latex-latex-environment) (latex-fragment . org-latex-latex-fragment) (line-break . org-latex-line-break) (link . org-latex-link) (node-property . org-latex-node-property) (paragraph . org-latex-paragraph) (plain-list . org-latex-plain-list) (plain-text . org-latex-plain-text) (planning . org-latex-planning) (property-drawer . org-latex-property-drawer) (quote-block . org-latex-quote-block) (radio-target . org-latex-radio-target) (section . org-latex-section) (special-block . org-latex-special-block) (src-block . org-latex-src-block) (statistics-cookie . org-latex-statistics-cookie) (strike-through . org-latex-strike-through) (subscript . org-latex-subscript) (superscript . org-latex-superscript) (table . org-latex-table) (table-cell . org-latex-table-cell) (table-row . org-latex-table-row) (target . org-latex-target) (template . org-latex-template) (timestamp . org-latex-timestamp) (underline . org-latex-underline) (verbatim . org-latex-verbatim) (verse-block . org-latex-verse-block) ;; Pseudo objects and elements. (latex-math-block . org-latex-math-block) (latex-matrices . org-latex-matrices)) :menu-entry '(?l "Export to LaTeX" ((?L "As LaTeX buffer" org-latex-export-as-latex) (?l "As LaTeX file" org-latex-export-to-latex) (?p "As PDF file" org-latex-export-to-pdf) (?o "As PDF file and open" (lambda (a s v b) (if a (org-latex-export-to-pdf t s v b) (org-open-file (org-latex-export-to-pdf nil s v b))))))) :filters-alist '((:filter-options . org-latex-math-block-options-filter) (:filter-paragraph . org-latex-clean-invalid-line-breaks) (:filter-parse-tree org-latex-math-block-tree-filter org-latex-matrices-tree-filter org-latex-image-link-filter) (:filter-verse-block . org-latex-clean-invalid-line-breaks)) :options-alist '((:latex-class "LATEX_CLASS" nil org-latex-default-class t) (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t) (:latex-header "LATEX_HEADER" nil nil newline) (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline) (:latex-class-pre "LATEX_CLASS_PRE" nil nil newline) (:description "DESCRIPTION" nil nil parse) (:keywords "KEYWORDS" nil nil parse) (:subtitle "SUBTITLE" nil nil parse) ;; Other variables. (:latex-active-timestamp-format nil nil org-latex-active-timestamp-format) (:latex-caption-above nil nil org-latex-caption-above) (:latex-classes nil nil org-latex-classes) (:latex-default-figure-position nil nil org-latex-default-figure-position) (:latex-default-table-environment nil nil org-latex-default-table-environment) (:latex-default-quote-environment nil nil org-latex-default-quote-environment) (:latex-default-table-mode nil nil org-latex-default-table-mode) (:latex-default-footnote-command "LATEX_FOOTNOTE_COMMAND" nil org-latex-default-footnote-command) (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format) (:latex-engraved-options nil nil org-latex-engraved-options) (:latex-engraved-preamble nil nil org-latex-engraved-preamble) (:latex-engraved-theme "LATEX_ENGRAVED_THEME" nil org-latex-engraved-theme) (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format) (:latex-footnote-separator nil nil org-latex-footnote-separator) (:latex-format-drawer-function nil nil org-latex-format-drawer-function) (:latex-format-headline-function nil nil org-latex-format-headline-function) (:latex-format-inlinetask-function nil nil org-latex-format-inlinetask-function) (:latex-hyperref-template nil nil org-latex-hyperref-template t) (:latex-image-default-scale nil nil org-latex-image-default-scale) (:latex-image-default-height nil nil org-latex-image-default-height) (:latex-image-default-option nil nil org-latex-image-default-option) (:latex-image-default-width nil nil org-latex-image-default-width) (:latex-images-centered nil nil org-latex-images-centered) (:latex-inactive-timestamp-format nil nil org-latex-inactive-timestamp-format) (:latex-inline-image-rules nil nil org-latex-inline-image-rules) (:latex-link-with-unknown-path-format nil nil org-latex-link-with-unknown-path-format) (:latex-src-block-backend nil nil org-latex-src-block-backend) (:latex-listings-langs nil nil org-latex-listings-langs) (:latex-listings-options nil nil org-latex-listings-options) (:latex-listings-src-omit-language nil nil org-latex-listings-src-omit-language) (:latex-minted-langs nil nil org-latex-minted-langs) (:latex-minted-options nil nil org-latex-minted-options) (:latex-prefer-user-labels nil nil org-latex-prefer-user-labels) (:latex-subtitle-format nil nil org-latex-subtitle-format) (:latex-subtitle-separate nil nil org-latex-subtitle-separate) (:latex-table-scientific-notation nil nil org-latex-table-scientific-notation) (:latex-tables-booktabs nil nil org-latex-tables-booktabs) (:latex-tables-centered nil nil org-latex-tables-centered) (:latex-text-markup-alist nil nil org-latex-text-markup-alist) (:latex-title-command nil nil org-latex-title-command) (:latex-toc-command nil nil org-latex-toc-command) (:latex-compiler "LATEX_COMPILER" nil org-latex-compiler) (:latex-use-sans nil "latex-use-sans" org-latex-use-sans) ;; Redefine regular options. (:date "DATE" nil "\\today" parse))) ;;; Internal Variables (defconst org-latex-language-alist (let ((de-default-plist '(:babel "ngerman" :babel-ini-alt "german" :polyglossia "german" :polyglossia-variant "german" :lang-name "German" :script "latin" :script-tag "latn")) (zh-default-plist '(:babel-ini-only "chinese" :polyglossia "chinese" :polyglossia-variant "simplified" :lang-name "Chinese Simplified" :script "hans" :script-tag "hans"))) `(("af" :babel "afrikaans" :polyglossia "afrikaans" :lang-name "Afrikaans" :script "latin" :script-tag "latn") ("am" :babel-ini-only "amharic" :polyglossia "amharic" :lang-name "Amharic" :script "ethiopic" :script-tag "ethi") ("ar" :babel-ini-only "arabic" :polyglossia "arabic" :lang-name "Arabic" :script "arabic" :script-tag "arab") ("ast" :babel-ini-only "asturian" :polyglossia "asturian" :lang-name "Asturian" :script "latin" :script-tag "latn") ("bg" :babel "bulgarian" :polyglossia "bulgarian" :lang-name "Bulgarian" :script "cyrillic" :script-tag "cyrl") ("bn" :babel-ini-only "bengali" :polyglossia "bengali" :lang-name "Bengali" :script "bengali" :script-tag: "beng") ("bo" :babel-ini-only "tibetan" :polyglossia "tibetan" :lang-name "Tibetan" :script "tibetan" :script-tag "tib") ("br" :babel "breton" :polyglossia "breton" :lang-name "Breton" :script "latin" :script-tag "latn") ("ca" :babel "catalan" :polyglossia "catalan" :lang-name "Catalan" :script "latin" :script-tag "latn") ("cop" :babel-ini-only "coptic" :polyglossia "coptic" :lang-name "Coptic" :script "coptic" :script-tag "copt") ("cs" :babel "czech" :polyglossia "czech" :lang-name "Czech" :script "latin" :script-tag "latn") ("cy" :babel "welsh" :polyglossia "welsh" :lang-name "Welsh" :script "latin" :script-tag "latn") ("da" :babel "danish" :polyglossia "danish" :lang-name "Danish" :script "latin" :script-tag "latn") ("de" ,@de-default-plist) ("de-de" ,@de-default-plist) ("de-at" :babel "naustrian" :babel-ini-alt "german-austria" :polyglossia "german" :polyglossia-variant "austrian" :lang-name "German" :script "latin" :script-tag "latn") ("dsb" :babel "lowersorbian" :babel-ini-alt "lsorbian" :polyglossia "sorbian" :polyglossia-variant "lower" :lang-name "Lower Sorbian" :script "latin" :script-tag "latn") ("dv" :polyglossia "divehi" :lang-name "Dhivehi" :script "latin" :script-tag "latn") ("el" :babel "greek" :polyglossia "greek" :lang-name "Greek" :script "greek" :script-tag "grek") ("el-polyton" :babel "polutonikogreek" :babel-ini-alt "polytonicgreek" :polyglossia "greek" :polyglossia-variant "polytonic" :lang-name "Polytonic Greek" :script "greek" :script-tag "grek") ("grc" :babel "greek.ancient" :babel-ini-alt "ancientgreek" :polyglossia "greek" :polyglossia-variant "ancient" :lang-name "Ancient Greek" :script "greek" :script-tag "grek") ("en" :babel "english" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English" :script "latin" :script-tag "latn") ("en-au" :babel "australian" :polyglossia "english" :polyglossia-variant "australian" :lang-name "English" :script "latin" :script-tag "latn") ("en-ca" :babel "canadian" :polyglossia "english" :polyglossia-variant "canadian" :lang-name "English" :script "latin" :script-tag "latn") ("en-gb" :babel "british" :polyglossia "english" :polyglossia-variant "uk" :lang-name "English" :script "latin" :script-tag "latn") ("en-nz" :babel "newzealand" :polyglossia "english" :polyglossia-variant "newzealand" :lang-name "English" :script "latin" :script-tag "latn") ("en-us" :babel "american" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English" :script "latin" :script-tag "latn") ("eo" :babel "esperanto" :polyglossia "esperanto" :lang-name "Esperanto" :script "latin" :script-tag "latn") ("es" :babel "spanish" :polyglossia "spanish" :lang-name "Spanish" :script "latin" :script-tag "latn") ("es-mx" :babel "spanishmx" :polyglossia "spanish" :polyglossia-variant "mexican" :lang-name "Spanish" :script "latin" :script-tag "latn") ("et" :babel "estonian" :polyglossia "estonian" :lang-name "Estonian" :script "latin" :script-tag "latn") ("eu" :babel "basque" :polyglossia "basque" :lang-name "Basque" :script "latin" :script-tag "latn") ("fa" :babel "persian" :polyglossia "persian" :lang-name "Persian" :script "arabic" :script-tag "arab") ("fi" :babel "finnish" :polyglossia "finnish" :lang-name "Finnish" :script "latin" :script-tag "latn") ("fr" :babel "french" :polyglossia "french" :lang-name "French" :script "latin" :script-tag "latn") ("fr-ca" :babel "canadien" :babel-ini-alt "canadian" :polyglossia "french" :polyglossia-variant "canadian" :lang-name "French" :script "latin" :script-tag "latn") ("fur" :babel "friulian" :polyglossia "friulian" :lang-name "Friulian" :script "latin" :script-tag "latn") ("ga" :babel "irish" :polyglossia "gaelic" :polyglossia-variant "irish" :lang-name "Irish Gaelic" :script "latin" :script-tag "latn") ("gd" :babel "scottish" :polyglossia "gaelic" :polyglossia-variant "scottish" :lang-name "Scottish Gaelic" :script "latin" :script-tag "latn") ("gl" :babel "galician" :polyglossia "galician" :lang-name "Galician" :script "latin" :script-tag "latn") ("he" :babel "hebrew" :polyglossia "hebrew" :lang-name "Hebrew" :script "hebrew" :script-tag "hebr") ("hi" :babel "hindi" :polyglossia "hindi" :lang-name "Hindi" :script "devanagari" :script-tag "deva") ("hr" :babel "croatian" :polyglossia "croatian" :lang-name "Croatian" :script "latin" :script-tag "latn") ("hsb" :babel "uppersorbian" :polyglossia "sorbian" :polyglossia-variant "upper" :lang-name "Upper Sorbian" :script "latin" :script-tag "latn") ("hu" :babel "magyar" :polyglossia "magyar" :lang-name "Magyar" :script "latin" :script-tag "latn") ("hy" :babel-ini-only "armenian" :polyglossia "armenian" :lang-name "Armenian" :script "armenian" :script-tag "armn") ("ia" :babel "interlingua" :polyglossia "interlingua" :lang-name "Interlingua" :script "latin" :script-tag "latn") ("id" :babel "indonesian" :polyglossia "malay" :polyglossia-variant "indonesian" :lang-name "Indonesian" :script "latin" :script-tag "latn") ("is" :babel "icelandic" :polyglossia "icelandic" :lang-name "Icelandic" :script "latin" :script-tag "latn") ("it" :babel "italian" :polyglossia "italian" :lang-name "Italian" :script "latin" :script-tag "latn") ("kn" :babel-ini-only "kannada" :polyglossia "kannada" :lang-name "Kannada" :script "kannada" :script-tag "knda") ("la" :babel "latin" :polyglossia "latin" :lang-name "Latin" :script "latin" :script-tag "latn") ("la-classic" :babel "classiclatin" :polyglossia "latin" :polyglossia-variant "classic" :lang-name "Classic Latin" :script "latin" :script-tag "latn") ("la-medieval" :babel "medievallatin" :polyglossia "latin" :polyglossia-variant "medieval" :lang-name "Medieval Latin" :script "latin" :script-tag "latn") ("la-ecclesiastic" :babel "ecclesiasticlatin" :polyglossia "latin" :polyglossia-variant "ecclesiastic" :lang-name "Ecclesiastic Latin" :script "latin" :script-tag "latn") ("lo" :babel-ini-only "lao" :polyglossia "lao" :lang-name "Lao" :script "lao" :script-tag "lao") ("lt" :babel "lithuanian" :polyglossia "lithuanian" :lang-name "Lithuanian" :script "latin" :script-tag "latn") ("lv" :babel "latvian" :polyglossia "latvian" :lang-name "Latvian" :script "latin" :script-tag "latn") ("ml" :babel-ini-only "malayalam" :polyglossia "malayalam" :lang-name "Malayalam" :script "malayalam" :script-tag "mlym") ("mr" :babel-ini-only "marathi" :polyglossia "marathi" :lang-name "Marathi" :script "devanagari" :script-tag "deva") ("ms" :babel "malay" :polyglossia "malay" :polyglossia-variant "malaysian" :lang-name "Malay" :script "latin" :script-tag "latn") ("nb" :babel "norsk" :polyglossia "norwegian" :polyglossia-variant "bokmal" :lang-name "Norwegian Bokmål" :script "latin" :script-tag "latn") ("nl" :babel "dutch" :polyglossia "dutch" :lang-name "Dutch" :script "latin" :script-tag "latn") ("nn" :babel "nynorsk" :polyglossia "norwegian" :polyglossia-variant "nynorsk" :lang-name "Norwegian Nynorsk" :script "latin" :script-tag "latn") ("no" :babel "norsk" :polyglossia "norsk" :lang-name "Norwegian" :script "latin" :script-tag "latn") ("oc" :babel "occitan" :polyglossia "occitan" :lang-name "Occitan" :script "latin" :script-tag "latn") ("pl" :babel "polish" :polyglossia "polish" :lang-name "Polish" :script "latin" :script-tag "latn") ("pms" :babel "piedmontese" :polyglossia "piedmontese" :lang-name "Piedmontese" :script "latin" :script-tag "latn") ("pt" :babel "portuges" :polyglossia "portuges" :lang-name "Portuges" :script "latin" :script-tag "latn") ("pt-br" :babel "brazilian" :polyglossia "brazilian" :lang-name "Portuges" :script "latin" :script-tag "latn") ("rm" :babel-ini-only "romansh" :polyglossia "romansh" :lang-name "Romansh" :script "latin" :script-tag "latn") ("ro" :babel "romanian" :polyglossia "romanian" :lang-name "Romanian" :script "latin" :script-tag "latn") ("ru" :babel "russian" :polyglossia "russian" :lang-name "Russian" :script "cyrillic" :script-tag "cyrl") ("sa" :babel-ini-only "sanskrit" :polyglossia "sanskrit" :lang-name "Sanskrit" :script "devanagari" :script-tag "deva") ("sk" :babel "slovak" :polyglossia "slovak" :lang-name "Slovak" :script "latin" :script-tag "latn") ("sl" :babel "slovene" :polyglossia "slovene" :lang-name "Slovene" :script "latin" :script-tag "latn") ("sq" :babel "albanian" :polyglossia "albanian" :lang-name "Albanian" :script "latin" :script-tag "latn") ("sr" :babel "serbian" :polyglossia "serbian" :lang-name "Serbian" :script "latin" :script-tag "latn") ("sr-cyrl" :babel-ini-only "serbian-cyrl" :polyglossia "serbian" :lang-name "Serbian" :script "cyrillic" :script-tag "cyrl") ("sr-latn" :babel-ini-only "serbian-latin" :polyglossia "serbian" :lang-name "Serbian" :script "latin" :script-tag "latn") ("sv" :babel "swedish" :polyglossia "swedish" :lang-name "Swedish" :script "latin" :script-tag "latn") ("syr" :babel-ini-only "syriac" :polyglossia "syriac" :lang-name "Syriac" :script "syriac" :script-tag "syrc") ("ta" :babel-ini-only "tamil" :polyglossia "tamil" :lang-name "Tamil" :script "tamil" :script-tag "taml") ("te" :babel-ini-only "telugu" :polyglossia "telugu" :lang-name "Telugu" :script "telugu" :script-tag "telu") ("th" :babel "thai" :polyglossia "thai" :lang-name "Thai" :script "thai" :script-tag "thai") ("tk" :babel "turkmen" :polyglossia "turkmen" :lang-name "Turkmen" :script "latin" :script-tag "latn") ("tr" :babel "turkish" :polyglossia "turkish" :lang-name "Turkish" :script "latin" :script-tag "latn") ("uk" :babel "ukrainian" :polyglossia "ukrainian" :lang-name "Ukrainian" :script "cyrillic" :script-tag "cyrl") ("ur" :babel-ini-only "urdu" :polyglossia "urdu" :lang-name "Urdu" :script "arabic" :script-tag "arab") ("vi" :babel "vietnamese" :polyglossia "vietnamese" :lang-name "Vietnamese" :script "latin" :script-tag "latn") ("zh" ,@zh-default-plist) ("zh-cn" ,@zh-default-plist) ("zh-tw" :babel-ini-only "chinese-traditional" :polyglossia "chinese" :polyglossia-variant "traditional" :lang-name "Chinese Traditional" :script "hant" :script-tag "hant"))) "Alist between language code and its properties for LaTeX export. In each element of the list car is always the language code and cdr is a property list. Valid keywords for this list can be: - `:babel' the name of the language loaded by the Babel LaTeX package - `:polyglossia' the name of the language loaded by the Polyglossia LaTeX package - `:babel-ini-only' the name of the language loaded by Babel exclusively through the new ini files method. See `http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf' - `:babel-ini-alt' an alternative language name when it is loaded using ini files - `:polyglossia-variant' the language variant loaded by Polyglossia - `:lang-name' the actual name of the language - `:script' the script name - `:script-tag' the script otf tag.") (defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr") ("qbordermatrix" . "\\cr") ("kbordermatrix" . "\\\\")) "Alist between matrix macros and their row ending.") (defconst org-latex-math-environments-re (format "\\`[ \t]*\\\\begin{%s\\*?}" (regexp-opt '("equation" "eqnarray" "math" "displaymath" "align" "gather" "multline" "flalign" "alignat" "xalignat" "xxalignat" "subequations" ;; breqn "dmath" "dseries" "dgroup" "darray" ;; empheq "empheq"))) "Regexp of LaTeX math environments.") ;;; User Configurable Variables (defgroup org-export-latex nil "Options for exporting Org mode files to LaTeX." :tag "Org Export LaTeX" :group 'org-export) ;;;; Generic (defcustom org-latex-caption-above '(table) "When non-nil, place caption string at the beginning of elements. Otherwise, place it near the end. When value is a list of symbols, put caption above selected elements only. Allowed symbols are: `image', `table', `src-block' and `special-block'." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :type '(choice (const :tag "For all elements" t) (const :tag "For no element" nil) (set :tag "For the following elements only" :greedy t (const :tag "Images" image) (const :tag "Tables" table) (const :tag "Source code" src-block) (const :tag "Special blocks" special-block)))) (defcustom org-latex-prefer-user-labels nil "Use user-provided labels instead of internal ones when non-nil. When this variable is non-nil, Org will use the value of CUSTOM_ID property, NAME keyword or Org target as the key for the \\label commands generated. By default, Org generates its own internal labels during LaTeX export. This process ensures that the \\label keys are unique and valid, but it means the keys are not available in advance of the export process. Setting this variable gives you control over how Org generates labels during LaTeX export, so that you may know their keys in advance. One reason to do this is that it allows you to refer to various elements using a single label both in Org's link syntax and in embedded LaTeX code. For example, when this variable is non-nil, a headline like this: ** Some section :PROPERTIES: :CUSTOM_ID: sec:foo :END: This is section [[#sec:foo]]. #+BEGIN_EXPORT latex And this is still section \\ref{sec:foo}. #+END_EXPORT will be exported to LaTeX as: \\subsection{Some section} \\label{sec:foo} This is section \\ref{sec:foo}. And this is still section \\ref{sec:foo}. A non-default value of `org-latex-reference-command' will change the command (\\ref by default) used to create label references. Note, however, that setting this variable introduces a limitation on the possible values for CUSTOM_ID and NAME. When this variable is non-nil, Org passes their value to \\label unchanged. You are responsible for ensuring that the value is a valid LaTeX \\label key, and that no other \\label commands with the same key appear elsewhere in your document. (Keys may contain letters, numbers, and the following punctuation: `_' `.' `-' `:'.) There are no such limitations on CUSTOM_ID and NAME when this variable is nil. For headlines that do not define the CUSTOM_ID property or elements without a NAME, Org will continue to use its default labeling scheme to generate labels and resolve links into proper references." :group 'org-export-latex :type 'boolean :version "26.1" :package-version '(Org . "8.3") :safe #'booleanp) (defcustom org-latex-reference-command "\\ref{%s}" "Format string that takes a reference to produce a LaTeX reference command. The reference is a label such as sec:intro. A format string of \"\\ref{%s}\" produces numbered references and will always work. It may be desirable to make use of a package such as hyperref or cleveref and then change the format string to \"\\autoref{%s}\" or \"\\cref{%s}\" for example." :group 'org-export-latex :type 'string :package-version '(Org . "9.5")) ;;;; Preamble (defcustom org-latex-default-class "article" "The default LaTeX class." :group 'org-export-latex :type '(string :tag "LaTeX class")) (defcustom org-latex-classes '(("article" "\\documentclass[11pt]{article}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ("report" "\\documentclass[11pt]{report}" ("\\part{%s}" . "\\part*{%s}") ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) ("book" "\\documentclass[11pt]{book}" ("\\part{%s}" . "\\part*{%s}") ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) "Alist of LaTeX classes and associated header and structure. If #+LATEX_CLASS is set in the buffer, use its value and the associated information. Here is the structure of each cell: (class-name header-string (numbered-section . unnumbered-section) ...) The header string ----------------- The HEADER-STRING is the header that will be inserted into the LaTeX file. It should contain the \\documentclass macro, and anything else that is needed for this setup. To this header, the following commands will be added: - Calls to \\usepackage for all packages mentioned in the variables `org-latex-default-packages-alist' and `org-latex-packages-alist'. Thus, your header definitions should avoid to also request these packages. - Lines specified via \"#+LATEX_HEADER:\" and \"#+LATEX_HEADER_EXTRA:\" keywords. If you need more control about the sequence in which the header is built up, or if you want to exclude one of these building blocks for a particular class, you can use the following macro-like placeholders. [DEFAULT-PACKAGES] \\usepackage statements for default packages [NO-DEFAULT-PACKAGES] do not include any of the default packages [PACKAGES] \\usepackage statements for packages [NO-PACKAGES] do not include the packages [EXTRA] the stuff from #+LATEX_HEADER(_EXTRA) [NO-EXTRA] do not include #+LATEX_HEADER(_EXTRA) stuff So a header like \\documentclass{article} [NO-DEFAULT-PACKAGES] [EXTRA] \\providecommand{\\alert}[1]{\\textbf{#1}} [PACKAGES] will omit the default packages, and will include the #+LATEX_HEADER and #+LATEX_HEADER_EXTRA lines, then have a call to \\providecommand, and then place \\usepackage commands based on the content of `org-latex-packages-alist'. If your header, `org-latex-default-packages-alist' or `org-latex-packages-alist' inserts \"\\usepackage[AUTO]{inputenc}\", AUTO will automatically be replaced with a coding system derived from `buffer-file-coding-system'. See also the variable `org-latex-inputenc-alist' for a way to influence this mechanism. Likewise, if your header contains \"\\usepackage[AUTO]{babel}\" or \"\\usepackage[AUTO]{polyglossia}\", AUTO will be replaced with the language related to the language code specified by `org-export-default-language'. Note that constructions such as \"\\usepackage[french,AUTO,english]{babel}\" are permitted. For Polyglossia the language will be set via the macros \"\\setmainlanguage\" and \"\\setotherlanguage\". See also `org-latex-guess-babel-language' and `org-latex-guess-polyglossia-language'. The sectioning structure ------------------------ The sectioning structure of the class is given by the elements following the header string. For each sectioning level, a number of strings is specified. A %s formatter is mandatory in each section string and will be replaced by the title of the section. Instead of a cons cell (numbered . unnumbered), you can also provide a list of 2 or 4 elements, (numbered-open numbered-close) or (numbered-open numbered-close unnumbered-open unnumbered-close) providing opening and closing strings for a LaTeX environment that should represent the document section. The opening clause should have a %s to represent the section title. Instead of a list of sectioning commands, you can also specify a function name. That function will be called with two parameters, the (reduced) level of the headline, and a predicate non-nil when the headline should be numbered. It must return a format string in which the section title will be added." :group 'org-export-latex :type '(repeat (list (string :tag "LaTeX class") (string :tag "LaTeX header") (repeat :tag "Levels" :inline t (choice (cons :tag "Heading" (string :tag " numbered") (string :tag "unnumbered")) (list :tag "Environment" (string :tag "Opening (numbered)") (string :tag "Closing (numbered)") (string :tag "Opening (unnumbered)") (string :tag "Closing (unnumbered)")) (function :tag "Hook computing sectioning")))))) (defcustom org-latex-inputenc-alist nil "Alist of inputenc coding system names, and what should really be used. For example, adding an entry (\"utf8\" . \"utf8x\") will cause \\usepackage[utf8x]{inputenc} to be used for buffers that are written as utf8 files." :group 'org-export-latex :type '(repeat (cons (string :tag "Derived from buffer") (string :tag "Use this instead")))) (defcustom org-latex-title-command "\\maketitle" "The command used to insert the title just after \\begin{document}. This format string may contain these elements: %a for AUTHOR keyword %t for TITLE keyword %s for SUBTITLE keyword %k for KEYWORDS line %d for DESCRIPTION line %c for CREATOR line %l for Language keyword %L for capitalized language keyword %D for DATE keyword If you need to use a \"%\" character, you need to escape it like that: \"%%\". Setting :latex-title-command in publishing projects will take precedence over this variable." :group 'org-export-latex :safe #'stringp :type '(string :tag "Format string")) (defcustom org-latex-subtitle-format "\\\\\\medskip\n\\large %s" "Format string used for transcoded subtitle. The format string should have at most one \"%s\"-expression, which is replaced with the subtitle." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :safe #'stringp :type '(string :tag "Format string")) (defcustom org-latex-subtitle-separate nil "Non-nil means the subtitle is not typeset as part of title." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :safe #'booleanp :type 'boolean) (defcustom org-latex-toc-command "\\tableofcontents\n\n" "LaTeX command to set the table of contents, list of figures, etc. This command only applies to the table of contents generated with the toc:t, toc:1, toc:2, toc:3, ... options, not to those generated with the #+TOC keyword." :group 'org-export-latex :type 'string) (defcustom org-latex-hyperref-template "\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k}, pdfsubject={%d},\n pdfcreator={%c},\n pdflang={%L}}\n" "Template for hyperref package options. This format string may contain these elements: %a for AUTHOR keyword %t for TITLE keyword %s for SUBTITLE keyword %k for KEYWORDS line %d for DESCRIPTION line %c for CREATOR line %l for Language keyword %L for capitalized language keyword %D for DATE keyword If you need to use a \"%\" character, you need to escape it like that: \"%%\". As a special case, a nil value prevents template from being inserted. Setting :latex-hyperref-template in publishing projects will take precedence over this variable." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :type '(choice (const :tag "No template" nil) (string :tag "Format string")) :safe #'string-or-null-p) ;;;; Headline (defcustom org-latex-format-headline-function 'org-latex-format-headline-default-function "Function for formatting the headline's text. This function will be called with six arguments: TODO the todo keyword (string or nil) TODO-TYPE the type of todo (symbol: `todo', `done', nil) PRIORITY the priority of the headline (integer or nil) TEXT the main headline text (string) TAGS the tags (list of strings or nil) INFO the export options (plist) The function result will be used in the section format string." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'function) ;;;; Footnotes (defcustom org-latex-default-footnote-command "\\footnote{%s%s}" "Default command used to insert footnotes. Customize this command if the LaTeX class provides a different command like \"\\sidenote{%s%s}\" that you want to use. The value will be passed as an argument to `format' as the following (format org-latex-default-footnote-command footnote-description footnote-label)" :group 'org-export-latex :package-version '(Org . "9.7") :type 'string) (defcustom org-latex-footnote-separator "\\textsuperscript{,}\\," "Text used to separate footnotes." :group 'org-export-latex :type 'string) (defcustom org-latex-footnote-defined-format "\\textsuperscript{\\ref{%s}}" "Format string used to format reference to footnote already defined. %s will be replaced by the label of the referred footnote." :group 'org-export-latex :type '(choice (const :tag "Use plain superscript (default)" "\\textsuperscript{\\ref{%s}}") (const :tag "Use Memoir/KOMA-Script footref" "\\footref{%s}") (string :tag "Other format string")) :version "26.1" :package-version '(Org . "9.0")) ;;;; Timestamps (defcustom org-latex-active-timestamp-format "\\textit{%s}" "A `format' string to be applied to active timestamps." :group 'org-export-latex :type 'string) (defcustom org-latex-inactive-timestamp-format "\\textit{%s}" "A `format' string to be applied to inactive timestamps." :group 'org-export-latex :type 'string) (defcustom org-latex-diary-timestamp-format "\\textit{%s}" "A `format' string to be applied to diary timestamps." :group 'org-export-latex :type 'string) ;;;; Links (defcustom org-latex-images-centered t "When non-nil, images are centered." :group 'org-export-latex :version "26.1" :package-version '(Org . "9.0") :type 'boolean :safe #'booleanp) (defcustom org-latex-image-default-option "" "Default option for images." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'string) (defcustom org-latex-image-default-width ".9\\linewidth" "Default width for images. This value will not be used if a height is provided." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'string) (defcustom org-latex-image-default-scale "" "Default scale for images. This value will not be used if a width or a scale is provided, or if the image is wrapped within a \"wrapfigure\" environment. Scale overrides width and height." :group 'org-export-latex :package-version '(Org . "9.3") :type 'string) (defcustom org-latex-image-default-height "" "Default height for images. This value will not be used if a width is provided, or if the image is wrapped within a \"figure\" or \"wrapfigure\" environment." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'string) (defcustom org-latex-default-figure-position "htbp" "Default position for LaTeX figures." :group 'org-export-latex :type 'string :version "26.1" :package-version '(Org . "9.0")) (defcustom org-latex-inline-image-rules `(("file" . ,(rx "." (or "pdf" "jpeg" "jpg" "png" "ps" "eps" "tikz" "pgf" "svg") eos)) ("https" . ,(rx "." (or "jpeg" "jpg" "png" "ps" "eps" "tikz" "pgf" "svg") eos))) "Rules characterizing image files that can be inlined into LaTeX. A rule consists in an association whose key is the type of link to consider, and value is a regexp that will be matched against link's path. Note that, by default, the image extension *actually* allowed depend on the way the LaTeX file is processed. When used with pdflatex, pdf, jpg and png images are OK. When processing through dvi to Postscript, only ps and eps are allowed. The default we use here encompasses both." :group 'org-export-latex :package-version '(Org . "9.6") :type '(alist :key-type (string :tag "Type") :value-type (regexp :tag "Path"))) (defcustom org-latex-link-with-unknown-path-format "\\texttt{%s}" "Format string for links with unknown path type." :group 'org-export-latex :type 'string) ;;;; Tables (defcustom org-latex-default-table-environment "tabular" "Default environment used to build tables." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'string) (defcustom org-latex-default-quote-environment "quote" "Default environment used to `quote' blocks." :group 'org-export-latex :package-version '(Org . "9.5") :type 'string) (defcustom org-latex-default-table-mode 'table "Default mode for tables. Value can be a symbol among: `table' Regular LaTeX table. `math' In this mode, every cell is considered as being in math mode and the complete table will be wrapped within a math environment. It is particularly useful to write matrices. `inline-math' This mode is almost the same as `math', but the math environment will be inlined. `verbatim' The table is exported as it appears in the Org buffer, within a verbatim environment. This value can be overridden locally with, i.e. \":mode math\" in LaTeX attributes. When modifying this variable, it may be useful to change `org-latex-default-table-environment' accordingly." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type '(choice (const :tag "Table" table) (const :tag "Matrix" math) (const :tag "Inline matrix" inline-math) (const :tag "Verbatim" verbatim)) :safe (lambda (s) (memq s '(table math inline-math verbatim)))) (defcustom org-latex-tables-centered t "When non-nil, tables are exported in a center environment." :group 'org-export-latex :type 'boolean :safe #'booleanp) (defcustom org-latex-tables-booktabs nil "When non-nil, display tables in a formal \"booktabs\" style. This option assumes that the \"booktabs\" package is properly loaded in the header of the document. This value can be ignored locally with \":booktabs t\" and \":booktabs nil\" LaTeX attributes." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type 'boolean :safe #'booleanp) (defcustom org-latex-table-scientific-notation nil "Format string to display numbers in scientific notation. The format should have \"%s\" twice, for mantissa and exponent \(i.e., \"%s\\\\times10^{%s}\"). When nil, no transformation is made." :group 'org-export-latex :version "24.4" :package-version '(Org . "8.0") :type '(choice (string :tag "Format string") (const :tag "No formatting" nil))) ;;;; Text markup (defcustom org-latex-text-markup-alist '((bold . "\\textbf{%s}") (code . protectedtexttt) (italic . "\\emph{%s}") (strike-through . "\\sout{%s}") (underline . "\\uline{%s}") (verbatim . protectedtexttt)) "Alist of LaTeX expressions to convert text markup. The key must be a symbol among `bold', `code', `italic', `strike-through', `underline' and `verbatim'. The value is a formatting string to wrap fontified text with. Value can also be set to the following symbols: `verb' and `protectedtexttt'. For the former, Org will use \"\\verb\" to create a format string and select a delimiter character that isn't in the string. For the latter, Org will use \"\\texttt\" to typeset and try to protect special characters. If no association can be found for a given markup, text will be returned as-is." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :type 'alist :options '(bold code italic strike-through underline verbatim)) ;;;; Drawers (defcustom org-latex-format-drawer-function (lambda (_ contents) contents) "Function called to format a drawer in LaTeX code. The function must accept two parameters: NAME the drawer name, like \"LOGBOOK\" CONTENTS the contents of the drawer. The function should return the string to be exported. The default function simply returns the value of CONTENTS." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :type 'function) ;;;; Inlinetasks (defcustom org-latex-format-inlinetask-function 'org-latex-format-inlinetask-default-function "Function called to format an inlinetask in LaTeX code. The function must accept seven parameters: TODO the todo keyword (string or nil) TODO-TYPE the todo type (symbol: `todo', `done', nil) PRIORITY the inlinetask priority (integer or nil) NAME the inlinetask name (string) TAGS the inlinetask tags (list of strings or nil) CONTENTS the contents of the inlinetask (string or nil) INFO the export options (plist) The function should return the string to be exported." :group 'org-export-latex :type 'function :version "26.1" :package-version '(Org . "8.3")) ;; Src blocks (defcustom org-latex-src-block-backend 'verbatim "Backend used to generate source code listings. This sets the behavior for fontifying source code, possibly even with color. There are four implementations of this functionality you may choose from (ordered from least to most capable): 1. Verbatim 2. Listings 3. Minted 4. Engraved The first two options provide basic syntax highlighting (listings), or none at all (verbatim). When using listings, you also need to make use of LaTeX package \"listings\". The \"xcolor\" LaTeX package is also needed for color management. These can simply be added to `org-latex-packages-alist', using customize or something like: (require \\='ox-latex) (add-to-list \\='org-latex-packages-alist \\='(\"\" \"listings\")) (add-to-list \\='org-latex-packages-alist \\='(\"\" \"xcolor\")) There are two further options for more comprehensive fontification. The first can be set with, (setq org-latex-src-block-backend \\='minted) which causes source code to be exported using the LaTeX package minted as opposed to listings. If you want to use minted, you need to add the minted package to `org-latex-packages-alist', for example using customize, or with (require \\='ox-latex) (add-to-list \\='org-latex-packages-alist \\='(\"newfloat\" \"minted\")) In addition, it is necessary to install pygments \(URL `https://pygments.org>'), and to configure the variable `org-latex-pdf-process' so that the -shell-escape option is passed to pdflatex. The minted choice has possible repercussions on the preview of latex fragments (see `org-latex-preview'). If you run into previewing problems, please consult URL `https://orgmode.org/worg/org-tutorials/org-latex-preview.html'. The most comprehensive option can be set with, (setq org-latex-src-block-backend \\='engraved) which causes source code to be run through `engrave-faces-latex-buffer', which generates colorings using Emacs's font-lock information. This requires the Emacs package engrave-faces (available from GNU ELPA), and the LaTeX package fvextra be installed. The styling of the engraved result can be customized with `org-latex-engraved-preamble' and `org-latex-engraved-options'. The default preamble also uses the LaTeX package tcolorbox in addition to fvextra." :group 'org-export-latex :package-version '(Org . "9.6") :type '(choice (const :tag "Use listings" listings) (const :tag "Use minted" minted) (const :tag "Use engrave-faces-latex" engraved) (const :tag "Export verbatim" verbatim)) :safe (lambda (s) (memq s '(listings minted engraved verbatim)))) (defcustom org-latex-listings-langs '((emacs-lisp "Lisp") (lisp "Lisp") (clojure "Lisp") (c "C") (cc "C++") (fortran "fortran") (perl "Perl") (cperl "Perl") (python "Python") (ruby "Ruby") (html "HTML") (xml "XML") (tex "TeX") (latex "[LaTeX]TeX") (shell-script "bash") (gnuplot "Gnuplot") (ocaml "[Objective]Caml") (caml "Caml") (sql "SQL") (sqlite "sql") (makefile "make") (R "r")) "Alist mapping languages to their listing language counterpart. The key is a symbol, the major mode symbol without the \"-mode\". The value is the string that should be inserted as the language parameter for the listings package. If the mode name and the listings name are the same, the language does not need an entry in this list - but it does not hurt if it is present." :group 'org-export-latex :version "26.1" :package-version '(Org . "8.3") :type '(repeat (list (symbol :tag "Major mode ") (string :tag "Listings language")))) (defcustom org-latex-listings-src-omit-language nil "Discard src block language parameter in listings. Set this option to t to omit the \"language=\" in the parameters to \"lstlisting\" environments when exporting an src block. This is necessary, for example, when the \"fancyvrb\" package is used instead of \"listings\": #+LATEX_HEADER: \\RequirePackage{fancyvrb} #+LATEX_HEADER: \\DefineVerbatimEnvironment{verbatim}{Verbatim}{...} #+LATEX_HEADER: \\DefineVerbatimEnvironment{lstlisting}{Verbatim}{...}" :group 'org-export-latex :package-version '(Org . "9.7") :type 'boolean :safe #'booleanp) (defcustom org-latex-listings-options nil "Association list of options for the latex listings package. These options are supplied as a comma-separated list to the \\lstlisting command. Each element of the association list should be a list or cons cell containing two strings: the name of the option, and the value. For example, (setq org-latex-listings-options \\='((\"basicstyle\" \"\\\\small\") (\"keywordstyle\" \"\\\\color{black}\\\\bfseries\\\\underbar\"))) ; or (setq org-latex-listings-options \\='((\"basicstyle\" . \"\\\\small\") (\"keywordstyle\" . \"\\\\color{black}\\\\bfseries\\\\underbar\"))) will typeset the code in a small size font with underlined, bold black keywords. Note that the same options will be applied to blocks of all languages. If you need block-specific options, you may use the following syntax: #+ATTR_LATEX: :options key1=value1,key2=value2 #+BEGIN_SRC ... #+END_SRC" :group 'org-export-latex :type '(repeat (list (string :tag "Listings option name ") (string :tag "Listings option value")))) (defcustom org-latex-minted-langs '((emacs-lisp "common-lisp") (cc "c++") (cperl "perl") (shell-script "bash") (caml "ocaml")) "Alist mapping languages to their minted language counterpart. The key is a symbol, the major mode symbol without the \"-mode\". The value is the string that should be inserted as the language parameter for the minted package. If the mode name and the listings name are the same, the language does not need an entry in this list - but it does not hurt if it is present. Note that minted uses all lower case for language identifiers, and that the full list of language identifiers can be obtained with: pygmentize -L lexers" :group 'org-export-latex :type '(repeat (list (symbol :tag "Major mode ") (string :tag "Minted language")))) (defcustom org-latex-minted-options nil "Association list of options for the latex minted package. These options are supplied within square brackets in \\begin{minted} environments. Each element of the alist should be a list or cons cell containing two strings: the name of the option, and the value. For example, (setq org-latex-minted-options \\='((\"bgcolor\" \"bg\") (\"frame\" \"lines\"))) ; or (setq org-latex-minted-options \\='((\"bgcolor\" . \"bg\") (\"frame\" . \"lines\"))) will result in source blocks being exported with \\begin{minted}[bgcolor=bg,frame=lines]{} as the start of the minted environment. Note that the same options will be applied to blocks of all languages. If you need block-specific options, you may use the following syntax: #+ATTR_LATEX: :options key1=value1,key2=value2 #+BEGIN_SRC ... #+END_SRC" :group 'org-export-latex :type '(repeat (list (string :tag "Minted option name ") (string :tag "Minted option value")))) (defcustom org-latex-custom-lang-environments nil "Alist mapping languages to language-specific LaTeX environments. It is used during export of source blocks by the listings and minted LaTeX packages. The environment may be a simple string, composed of only letters and numbers. In this case, the string is directly the name of the LaTeX environment to use. The environment may also be a format string. In this case the format string will be directly exported. This format string may contain these elements: %s for the formatted source %c for the caption %f for the float attribute %l for an appropriate label %o for the LaTeX attributes For example, (setq org-latex-custom-lang-environments \\='((python \"pythoncode\") (ocaml \"\\\\begin{listing} \\\\begin{minted}[%o]{ocaml} %s\\\\end{minted} \\\\caption{%c} \\\\label{%l}\"))) would have the effect that if Org encounters a Python source block during LaTeX export it will produce \\begin{pythoncode} \\end{pythoncode} and if Org encounters an Ocaml source block during LaTeX export it will produce \\begin{listing} \\begin{minted}[]{ocaml} \\end{minted} \\caption{} \\label{