* multipage html output @ 2024-07-03 9:44 Orm Finnendahl 2024-07-03 10:33 ` Dr. Arne Babenhauserheide ` (2 more replies) 0 siblings, 3 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-03 9:44 UTC (permalink / raw) To: emacs-orgmode Hi, after my clunky publishing chain from org to gitbook with multipage page output broke down recently I finally decided to tackle adding an export backend for multipage html output to org-export. It is done now and mainly working. The backend uses all the funcionality of the ox html exporter, only slightly modifying the code in places where it is necessary for multipage output. In addition I tried to make it as general, as possible to enable adding other multipage backends (like for md output) easily. Before sharing it I thought it might be a good idea to think about integrating it properly/officially into org. I would be willing to provide the code, docs, patches, etc. There are a couple of decisions to make (should it be integrated as an option into the html output backend or should it be a separate backend altogether? What options concerning footnotes, toc, etc. should be provided? etc...) and this mail is basically asking about how to proceed. My questions: - Is there widespread interest to fully integrate it into org mode? - If so, whom should I contact, or is it expected that I just go ahead and supply merge requests? I'm a bit hesitant putting in the extra work of fully integrating it without approval by the maintainers to go ahead. In case someone wants to take a peek at the current state of the code you can check out my github repository here: https://github.com/ormf/ox-html-multipage Be aware and warned that the code is in constant flux, not finalized and there still are some open questions for me what would be the best way to integrate the code into the old export engine, like whether adding optional args to the transcoding functions or using properties in the info channel, etc... Once it is finalized, the current single page html export will work exactly as before (it already does, but while checking it out I am modifying the html templates for the multipage navigation, toc, etc.) Hope to hear from you, especially if the maintainers are reading this. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 9:44 multipage html output Orm Finnendahl @ 2024-07-03 10:33 ` Dr. Arne Babenhauserheide 2024-07-03 10:58 ` Christian Moe 2024-07-03 21:11 ` Rudolf Adamkovič 2 siblings, 0 replies; 72+ messages in thread From: Dr. Arne Babenhauserheide @ 2024-07-03 10:33 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 440 bytes --] Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > https://github.com/ormf/ox-html-multipage Do I understand it right, that this exports a single org file into multiple HTML files in the html subfolder? In the interest of making it possible to build upon the code, can you make the license GPL v2.0 *or later*? Best wishes, Arne -- Unpolitisch sein heißt politisch sein, ohne es zu merken. draketo.de [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 1125 bytes --] ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 9:44 multipage html output Orm Finnendahl 2024-07-03 10:33 ` Dr. Arne Babenhauserheide @ 2024-07-03 10:58 ` Christian Moe 2024-07-03 11:05 ` Ihor Radchenko 2024-07-03 21:11 ` Rudolf Adamkovič 2 siblings, 1 reply; 72+ messages in thread From: Christian Moe @ 2024-07-03 10:58 UTC (permalink / raw) To: emacs-orgmode Orm Finnendahl writes: > Hi, > > after my clunky publishing chain from org to gitbook with multipage > page output broke down recently I finally decided to tackle adding an > export backend for multipage html output to org-export. > > (... snip ...) > > - Is there widespread interest to fully integrate it into org mode? It would be nice to have. Conceptually, I'd see it as fitting into org-publish, perhaps, rather than as an exporter? With org-publish-project-alist as a convenient place to set up various options? Yours, Christian ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 10:58 ` Christian Moe @ 2024-07-03 11:05 ` Ihor Radchenko 2024-07-03 14:34 ` Christian Moe 2024-07-04 9:50 ` Orm Finnendahl 0 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-03 11:05 UTC (permalink / raw) To: Christian Moe; +Cc: emacs-orgmode Christian Moe <mail@christianmoe.com> writes: >> after my clunky publishing chain from org to gitbook with multipage >> page output broke down recently I finally decided to tackle adding an >> export backend for multipage html output to org-export. >> >> (... snip ...) >> >> - Is there widespread interest to fully integrate it into org mode? > > It would be nice to have. > > Conceptually, I'd see it as fitting into org-publish, perhaps, rather > than as an exporter? With org-publish-project-alist as a convenient > place to set up various options? Not really. ox-publish is more about exporting multiple input .org/non-.org files into outputs. I'd rather see this kind of feature being a part of ox.el - an option to export one .org to many smaller files. Currently, we only have an option to export one .org (or part of it) to a single string/file. (And then, ox-odt has to try various kludges to make things work as expected with .odt, which consist of multiple files under the hood). -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 11:05 ` Ihor Radchenko @ 2024-07-03 14:34 ` Christian Moe 2024-07-04 9:50 ` Orm Finnendahl 1 sibling, 0 replies; 72+ messages in thread From: Christian Moe @ 2024-07-03 14:34 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Ihor Radchenko writes: > Christian Moe <mail@christianmoe.com> writes: > >>> after my clunky publishing chain from org to gitbook with multipage >>> page output broke down recently I finally decided to tackle adding an >>> export backend for multipage html output to org-export. >>> >>> (... snip ...) >>> >>> - Is there widespread interest to fully integrate it into org mode? >> >> It would be nice to have. >> >> Conceptually, I'd see it as fitting into org-publish, perhaps, rather >> than as an exporter? With org-publish-project-alist as a convenient >> place to set up various options? > > Not really. ox-publish is more about exporting multiple input > .org/non-.org files into outputs. I was thinking in terms of purpose: organizing export of multiple outputs to be published together. It does that with multiple inputs because, as you say, one-to-one export is the option we currently have. > I'd rather see this kind of feature being a part of ox.el - an option to > export one .org to many smaller files. Currently, we only have an option > to export one .org (or part of it) to a single string/file. (And then, > ox-odt has to try various kludges to make things work as expected with > .odt, which consist of multiple files under the hood). Yes, I suppose the code for multipage export belongs on the ox.el level. And then one would want to be able to use it out of the box without necessarily having to configure a publishing project, just relying on sensible defaults. So I take that back. (There might be some considerations for ox-publish when using multipage/chunked export *inside* a publishing project, e.g. regarding which levels of output to include in a sitemap, but that's for another day.) Yours, Christian ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 11:05 ` Ihor Radchenko 2024-07-03 14:34 ` Christian Moe @ 2024-07-04 9:50 ` Orm Finnendahl 2024-07-04 11:41 ` Ihor Radchenko 1 sibling, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-04 9:50 UTC (permalink / raw) To: emacs-orgmode Hi, Am Mittwoch, den 03. Juli 2024 um 11:05:39 Uhr (+0000) schrieb Ihor Radchenko: > > Not really. ox-publish is more about exporting multiple input > .org/non-.org files into outputs. > > I'd rather see this kind of feature being a part of ox.el - an option to > export one .org to many smaller files. Currently, we only have an option > to export one .org (or part of it) to a single string/file. (And then, > ox-odt has to try various kludges to make things work as expected with > .odt, which consist of multiple files under the hood). that is/was my intention: Basically there was only a very small change to ox.el necessary to make it work (it's mentioned in the comment on top of ox-multipage-html in my github repository): Currently `org-export-as' combines parsing the org document into a global parse tree with all additional options applied and serializing that into the final output target format. My code simply splits the code sections of these tasks into two separate functions, which are called by org-export-as, `org-export--collect-tree-info' and `org-export--transcode-headline'. The advantage of this approach is that it is fully compatible with the prior code, but gives the necessary flexibility to the backend export code to split up the global parse tree before serializing. The multipage html backend (ox-html-multipage.el) takes care of generating the global parse tree with org-export--headline, divides that tree into the subtrees of the individual pages, then calls the serializing function for each of the subtrees and writes the results to file. Is that along the lines of what you meant? In the meantime I thought about the proposed backend. Maybe it's a good idea to integrate the single page *and* the multipage backend into one backend altogether: The Backend *always* produces multipage output, but you can define the level at which the pages are split with an #+OPTION: in the org file. Setting the default level to 0 if the option is not set will generate the exact same output as the old backend without breaking anything for anybody. I'm quite sure it'll work and as I said it's mainly done and wouldn't require a lot of work. What do you think? -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-04 9:50 ` Orm Finnendahl @ 2024-07-04 11:41 ` Ihor Radchenko 2024-07-04 13:33 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-04 11:41 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> I'd rather see this kind of feature being a part of ox.el - an option to >> export one .org to many smaller files. Currently, we only have an option >> to export one .org (or part of it) to a single string/file. (And then, >> ox-odt has to try various kludges to make things work as expected with >> .odt, which consist of multiple files under the hood). > > that is/was my intention: Basically there was only a very small > change to ox.el necessary to make it work (it's mentioned in the > comment on top of ox-multipage-html in my github repository): > > Currently `org-export-as' combines parsing the org document into a > global parse tree with all additional options applied and serializing > that into the final output target format. My code simply splits the > code sections of these tasks into two separate functions, which are > called by org-export-as, `org-export--collect-tree-info' and > `org-export--transcode-headline'. The advantage of this approach is > that it is fully compatible with the prior code, but gives the > necessary flexibility to the backend export code to split up the > global parse tree before serializing. This makes sense. Although, multipage export may imply two different things: 1. An ability to produce multiple pages from parts of the original Org file. 2. An ability to produce multiple pages from a single part of Org file. For example, consider an Org document with images exported to ODT. The images should be stored alongside XML content file and referenced from there. So, export produces multiple files from the same document/subtree. Your approach only addresses (1), but not (2). That said, even having (1) is a welcome improvement. > The multipage html backend (ox-html-multipage.el) takes care of > generating the global parse tree with org-export--headline, divides > that tree into the subtrees of the individual pages, then calls the > serializing function for each of the subtrees and writes the results > to file. Is that along the lines of what you meant? Yes, but we also need to carefully discuss the rules how the full parse tree is separated into subtrees. Your proof of concept code hard-codes these rules. > In the meantime I thought about the proposed backend. Maybe it's a > good idea to integrate the single page *and* the multipage backend > into one backend altogether: The Backend *always* produces multipage > output, but you can define the level at which the pages are split with > an #+OPTION: in the org file. Setting the default level to 0 if the > option is not set will generate the exact same output as the old > backend without breaking anything for anybody. I'm quite sure it'll > work and as I said it's mainly done and wouldn't require a lot of > work. 1. Most of the existing backends are written to produce a single page. So, our design of ox.el part should be able to handle those. What you proposed (calling the same backend on pre-split parse tree) sounds good in this context. 2. Some backends, as you proposed, may target multipage export from the very beginning. So, we need to provide some way for the backend (in org-export-define*-backend) to specify that it wants to split the original parse tree. I imagine some kind of option with default values configured via backend, but optionally overwritten by user settings/in-buffer keywords. 3. Your suggestion to add a new export option for splitting based on headline level is one idea. Another idea is to split out subtrees with :EXPORT_FILE_NAME: property. 4. One possible extra feature might be exporting only a part of the original Org file to separate pages. Say, only pages with specific tag. The whole original Org file is also exported, replacing the split-out parts with, for example, links. This will generalize "index" pages from ox-publish. 5. We need to consider the rules used to generate export file names. Currently, we choose between :EXPORT_FILE_NAME: property, #+EXPORT_FILE_NAME: keyword, and the original file name. As I see in your code, you also introduced deriving file name from the headline title. 6. I can see people flipping between exporting the whole document and multipage document. We probably need some kind of easy switch in M-x org-export-dispatch to choose how to export. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-04 11:41 ` Ihor Radchenko @ 2024-07-04 13:33 ` Orm Finnendahl 2024-07-04 16:20 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-04 13:33 UTC (permalink / raw) To: emacs-orgmode Hi Ihor, thanks for your time to study the code and your very valuable input, much appreciated! Am Donnerstag, den 04. Juli 2024 um 11:41:35 Uhr (+0000) schrieb Ihor Radchenko: > > 2. An ability to produce multiple pages from a single part of Org file. > For example, consider an Org document with images exported to > ODT. The images should be stored alongside XML content file and > referenced from there. So, export produces multiple files from the > same document/subtree. > > Your approach only addresses (1), but not (2). Sure. I'm not at all familiar with the peculiarities of other output backends, but see your point. If you can give any hints or have any ideas *how* we could find general rules for separating the subtrees, which cover foreseeable use cases, or devise a flexible mechanism for doing so, I'd be glad to help setting them up and implementing them. I definitely agree, the code should be as general as possible while providing complete backward compatibility. > 1. Most of the existing backends are written to produce a single > page. So, our design of ox.el part should be able to handle > those. What you proposed (calling the same backend on pre-split parse > tree) sounds good in this context. Ok. > 2. Some backends, as you proposed, may target multipage export from the > very beginning. So, we need to provide some way for the backend (in > org-export-define*-backend) to specify that it wants to split the > original parse tree. I imagine some kind of option with default > values configured via backend, but optionally overwritten by user > settings/in-buffer keywords. I'll look into that and maybe I can come up with something. I was hesitant to propose anything as I tried to stay as limited as possible and not get too deep into changing things. If you have suggestions, please let me know. > 3. Your suggestion to add a new export option for splitting based on > headline level is one idea. > > Another idea is to split out subtrees with :EXPORT_FILE_NAME: > property. I'm not sure I fully understand what you mean: Do you mean specifying different :EXPORT_FILE_NAME: properties throughout the same document and then export accordingly? > 4. One possible extra feature might be exporting only a part of the > original Org file to separate pages. Say, only pages with specific > tag. The whole original Org file is also exported, replacing the > split-out parts with, for example, links. This will generalize > "index" pages from ox-publish. Very nice idea! MAybe along these lines is that I thought about "Master" org files which combine different documentations by linking to them in some sort of top menu which is included on every page of all these documentations and then being able to generate a single documentation without having to recompile everything. But for now I'd prefer to first get it working and then think about such extensions (I have more ideas for different extensions and "plugins" which could be useful). It shouldn't be too hard to implement at a later point and probably also wouldn't need a complete rewrite. > 5. We need to consider the rules used to generate export file names. > Currently, we choose between :EXPORT_FILE_NAME: property, > #+EXPORT_FILE_NAME: keyword, and the original file name. > > As I see in your code, you also introduced deriving file name from > the headline title. Exactly. I wanted to make sure, the file names are sorted correctly, are unique and the title is relatable to the section it names on the directory level. I also thought about making it user-configurable, but first wanted to implement a working solution. > 6. I can see people flipping between exporting the whole document and > multipage document. We probably need some kind of easy switch in M-x > org-export-dispatch to choose how to export. Sure, that is the disadvantage of my proposal to make everything a "multipage" document. Another disadvantage is that when the user chooses to open the final document or display it in a buffer the user can't choose whether to only open/display one page or every exported page. In most circumstances it should be advisable to just open/display the first page. We can also just add a switch between single-page and multipage, with multipage always just exporting to file, but that also has disadvantages. As the code I proposed is encapsulated in the html backend and not spreading all over the place, I will now first go ahead to finalize the existing code to a fully working setup. ASFAICT adapting that to other needs shouldn't require a complete rewrite. And I might be around for a while ;-) -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-04 13:33 ` Orm Finnendahl @ 2024-07-04 16:20 ` Ihor Radchenko 2024-07-07 19:33 ` Orm Finnendahl 2024-07-07 20:50 ` Orm Finnendahl 0 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-04 16:20 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > Sure. I'm not at all familiar with the peculiarities of other output > backends, but see your point. If you can give any hints or have any > ideas *how* we could find general rules for separating the subtrees, > which cover foreseeable use cases, or devise a flexible mechanism for > doing so, I'd be glad to help setting them up and implementing them. I > definitely agree, the code should be as general as possible while > providing complete backward compatibility. I think that the easiest would be adding a new option to `org-export-options-alist' - it is already extendable for individual backends and allows users to tweak things via in-buffer keywords, properties, variables, and export options. The most generic rule would be some kind of function that takes AST node as input and returns whether that node should be going to a separate file or not, and if yes, tell (1) which export backend to use to export that subtree to a file (may as well allow exporting to different formats, while we are at it); (2) what are the export parameters to be used for that export, (possibly) including the file path. Then, in addition to the most generic (and most flexible) "rule being an Elisp function", we can allow some simplified semantics to define rules. The semantics should probably give a couple of toggles to customize: (1) which subtrees are selected for export; (2) which export backend is used (3) how their file names are generated; (4) (optional) how they are represented when exporting the whole original file; e.g. whether to put links to exported files in place of their subtrees; (5) (optional) how the original file is represented in the exported subtrees; e.g. whether to put backlink to parent file The subtree selection may boil down to the usual TAGS matcher (or function), as described in "11.3.3 Matching tags and properties" section of the manual. This will cover the previously discussed separation based on headline level, a tag, or a property. The export backend selection may be realized by allowing multiple rules with each rule defining selection/backend/file name/.... In terms of the value semantics in Elisp, I am thinking about something re-using backend definition format: (setq org-export-pages '(:selector "LEVEL=2+blog+TODO=DONE" :backend html ;; completely remove the exported subtree is original document ;; is being exported. :page-transcoder nil ;; or :page-transcoder #'org-export-page-as-heading-with-link :export-file-name "%{TITLE}-%{page-number}" ;; or some other kind of template syntax ) '(:selector a-function-accepting-ast-node :source-backend any :backend (:parent html ;; `org-export-define-derived-backend'-like semantics :options-alist ;; Do not export private headings in HTML pages. ((:exclude-tags "EXCLUDE_TAGS" nil (cons "private" org-export-exclude-tags) split)))) '(:selector "+export_ascii_page" :source-backend html ; only use this rule when exporting to html :backend (:parent ascii ((template . (lambda (contents info) (format "Paged out from %s\n%s" (plist-get ;; INFO channel for parent document (plist-get info :page-source) :title) (org-ascii-template contents info))))))))) >> 2. Some backends, as you proposed, may target multipage export from the >> very beginning. So, we need to provide some way for the backend (in >> org-export-define*-backend) to specify that it wants to split the >> original parse tree. I imagine some kind of option with default >> values configured via backend, but optionally overwritten by user >> settings/in-buffer keywords. > > I'll look into that and maybe I can come up with something. I was > hesitant to propose anything as I tried to stay as limited as possible > and not get too deep into changing things. If you have suggestions, > please let me know. One way could be simply adding an option like :selector above to the backend definition. Then, it will be used as default selector: (setq org-export-pages (:selector default :backend html) ; export pages to html with default selector ) or even (setq org-export-pages (:backend html) ; export pages to html with default selector ) or just ;; export using the same target backend as selected in the export menu (setq org-export-pages t) ;; (setq org-export-pages nil) - existing single page export ;; (setq org-export-pages 'only-pages) - only export pages, ignore original file >> 3. Your suggestion to add a new export option for splitting based on >> headline level is one idea. >> >> Another idea is to split out subtrees with :EXPORT_FILE_NAME: >> property. > > I'm not sure I fully understand what you mean: Do you mean specifying > different :EXPORT_FILE_NAME: properties throughout the same document > and then export accordingly? Yes. It is re-using the existing idea with subtree export 13.2 Export Settings ‘EXPORT_FILE_NAME’ The name of the output file to be generated. Otherwise, Org generates the file name based on the buffer name and the extension based on the backend format. If a subtree has that property set, it is used as output file name. Since there is usually no reason to set this property unless you also want to export subtree to individual file, it makes sense to use this as selector for what to export as pages. Example: #+TITLE: Index document * Emacs notes ** Emacs blog post #1 :PROPERTIES: :EXPORT_FILE_NAME: my-first-post :END: ... ** Fleeting note at [2024-06-20 Thu 22:16] Some notes, no need to export them. * Personal notes ** Personal blog post #1 :PROPERTIES: :EXPORT_FILE_NAME: private/personal-post-trial :END: ... >> 6. I can see people flipping between exporting the whole document and >> multipage document. We probably need some kind of easy switch in M-x >> org-export-dispatch to choose how to export. > > Sure, that is the disadvantage of my proposal to make everything a > "multipage" document. Another disadvantage is that when the user > chooses to open the final document or display it in a buffer the user > can't choose whether to only open/display one page or every exported > page. In most circumstances it should be advisable to just > open/display the first page. We can also just add a switch between > single-page and multipage, with multipage always just exporting to > file, but that also has disadvantages. What to open is a minor detail, really. It can be worked out any moment we need to. The most sensible default, IMHO, it to open dired with the containing directory with all the exported pages. > As the code I proposed is encapsulated in the html backend and not > spreading all over the place, I will now first go ahead to finalize > the existing code to a fully working setup. ASFAICT adapting that to > other needs shouldn't require a complete rewrite. And I might be > around for a while ;-) I advice against doing this. While reading your code, I saw that you used some html-specific functions for modifications in ox.el. If you start by modifying ox.el in Org git repo directly, simply doing "make compile" will warn about instances of using functions not defined in ox.el. Another advantage of editing the ox.el and using Org repository is that you can run "make test" any time and see if you managed to break Org :) -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-04 16:20 ` Ihor Radchenko @ 2024-07-07 19:33 ` Orm Finnendahl 2024-07-08 15:29 ` Ihor Radchenko 2024-07-07 20:50 ` Orm Finnendahl 1 sibling, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-07 19:33 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Hi, this is a report of my current state with the html multipage export backend: I finished most of the heavy lifting and am currently trying to integrate it with the old backend into a single file. For now I plan to use a custom menu-entry ('m') in the export dialog rather than doing it with an option in the file. The main reason is that I like to be able to switch between output formats easily without having to change the document. But that's debatable. I could also implement it with an option in the document and I'm open for opinions. For the backend I'm planning to realize the following options (implemented as custom variables, which can be overwritten in the document): - org-html-multipage-export-directory The directory for the exported files (relative or absolute). - org-html-multipage-head (similar to HTML_HEAD but will be used instead of the HTML_HEAD for custom css/js) - org-html-multipage-front-matter A list to specify pages in front of the headlines of the document. Possible values are 'title, 'title-toc and 'toc. title-toc is a combined page containing the title and the toc. Multiple entries are possible. - org-html-multipage-join-first-subsection Boolean: Non-nil means that the first subsection of a section without a body will be joined on the section page (recursively). See my generated example pages linked below (Chapters 4, 5 and 7 for a recursive example) - org-html-multipage-split How to split the document. Possible values are 'toc for generating a page for each toc entry. 'export-filename for splitting into pages along :EXPORT_FILENAME: properties. The autogenerated filename mechanism for the other options will be overwritten in this case. A number for the depth to split (similar to the value for h: or toc:) I haven't tested all options yet but will see whether/how it works. - org-html-multipage-open Whether and where to open the first page of the document after export. Possible values are 'browser 'buffer or nil. (As Ihor mentioned this is a minor issue). This is fairly straightforward for me to realize (it's mostly done already). The suggestions of Ihor are excellent, but IIUC they implement a larger and more general context, which of course is desirable. I have to study the ideas more thoroughly to see, how difficult/time consuming it will be to implement. It might be that it is better to do it in two steps to keep it manageable for me. I'm pretty sure that the current approach can be adapted to the larger context easily so the work is not in vain. In addition I have a question about the html output layout structure. Here is an example of a file generated with the current code with some preliminary layout. It might give an idea about my use case: https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch/01_00_00_vorwort.html#orge24571b Regardless of the colours, the file has a slightly different hierarchy than the single page html template of ORGMODE and is more oriented towards the layout of documentation nowadays with a (hideable) toc at the side on every page rather than the texinfo oriented layout used by the orgmode manual. If my code gets accepted/merged to org what should be the default layout shipped with multipage output? FYI: The visibility of the toc entries is managed by the css and the whole toc is included on each page (and its visibility could be managed with js as well). Should I rather go for the classic texinfo view? And now just a short answer to Ihor's remarks. Am Donnerstag, den 04. Juli 2024 um 16:20:29 Uhr (+0000) schrieb Ihor Radchenko: > While reading your code, I saw that you used some html-specific > functions for modifications in ox.el. If you start by modifying ox.el in > Org git repo directly, simply doing "make compile" will warn about > instances of using functions not defined in ox.el. > Another advantage of editing the ox.el and using Org repository is that > you can run "make test" any time and see if you managed to break Org :) Of course. I never intended to corrupt ox.el with html specific stuff, that was just preliminary while getting acquainted with the code. Currently I'm in the process of separating everything and reducing it to the minimal requirements for change. I'll let you know when it's done. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-07 19:33 ` Orm Finnendahl @ 2024-07-08 15:29 ` Ihor Radchenko 2024-07-08 19:12 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-08 15:29 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > For the backend I'm planning to realize the following options > (implemented as custom variables, which can be overwritten in the > document): > > - org-html-multipage-export-directory > > The directory for the exported files (relative or absolute). I am wondering about the reasoning behind not re-using #+EXPORT_FILE_NAME: here (its directory part) and simply defaulting to `default-directory'. Is there any situation when you need to export the full document vs. multipage to different places? > - org-html-multipage-head > > (similar to HTML_HEAD but will be used instead of the HTML_HEAD for > custom css/js) Again, why not directly using #+HTML_HEAD? > - org-html-multipage-front-matter > > A list to specify pages in front of the headlines of the > document. Possible values are 'title, 'title-toc and 'toc. title-toc > is a combined page containing the title and the toc. Multiple > entries are possible. This sounds orthogonal to multipage export. May you please illustrate what you want to achieve by introducing this option? Maybe there is an existing feature that can be re-used instead of creating something new? > - org-html-multipage-join-first-subsection > > Boolean: Non-nil means that the first subsection of a section > without a body will be joined on the section page (recursively). See > my generated example pages linked below (Chapters 4, 5 and 7 for a > recursive example) Sorry, but I cannot understand anything from there. May you explain in words? > - org-html-multipage-split > > How to split the document. Possible values are > > 'toc for generating a page for each toc entry. May I guess that the previous option may have something do with situation when #+TOC: keyword is in the middle of a text? > In addition I have a question about the html output layout > structure. Here is an example of a file generated with the current > code with some preliminary layout. It might give an idea about my use > case: > > https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch/01_00_00_vorwort.html#orge24571b > > Regardless of the colours, the file has a slightly different hierarchy > than the single page html template of ORGMODE and is more oriented > towards the layout of documentation nowadays with a (hideable) toc at > the side on every page rather than the texinfo oriented layout used by > the orgmode manual. If my code gets accepted/merged to org what should > be the default layout shipped with multipage output? FYI: The > visibility of the toc entries is managed by the css and the whole toc > is included on each page (and its visibility could be managed with js > as well). Should I rather go for the classic texinfo view? Do I understand correctly that your alternative layout is simply a question of custom #+HTML_HEADER? Or is there something more to it? -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 15:29 ` Ihor Radchenko @ 2024-07-08 19:12 ` Orm Finnendahl 2024-07-09 17:55 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-08 19:12 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Am Montag, den 08. Juli 2024 um 15:29:47 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > For the backend I'm planning to realize the following options > > (implemented as custom variables, which can be overwritten in the > > document): > > > > - org-html-multipage-export-directory > > > > The directory for the exported files (relative or absolute). > > I am wondering about the reasoning behind not re-using > #+EXPORT_FILE_NAME: here (its directory part) and simply defaulting to > `default-directory'. > > Is there any situation when you need to export the full document > vs. multipage to different places? Actually that is what I'm currently doing (and what I need for my publishing chain): The single-page document is not in the html folder used for the multipage document. Both files happen to have the same name so it wouldn't work out, if I want to generate single-page along the multipage version, without having to change the document. > > - org-html-multipage-head > > > > (similar to HTML_HEAD but will be used instead of the HTML_HEAD for > > custom css/js) > > Again, why not directly using #+HTML_HEAD? Same as above: My multipage has a completely different css and js and I think this is unavoidable. All this is just for being able to do both exports without interfering. > > - org-html-multipage-front-matter > > > > A list to specify pages in front of the headlines of the > > document. Possible values are 'title, 'title-toc and 'toc. title-toc > > is a combined page containing the title and the toc. Multiple > > entries are possible. > > This sounds orthogonal to multipage export. May you please illustrate > what you want to achieve by introducing this option? Maybe there is an > existing feature that can be re-used instead of creating something new? Could be: The toc as a first page is needed, when you don't want a toc on the side of each html page, e.g. when using the classical info layout. And it might be necessary to be able to distinguish between a separate title page with author and the toc on the next page (or a combined page with title and toc or no front matter at all because the title appears on every page). If this is possible with already existing options, even better. I just think that it might be necessary to be able to distinguish between the needs for html output format vs. the needs for LaTex or single-page output without having to edit the document (I need that as my publishing chain is going to export info, html multipage, pdf output and html single-page output using the same org file). > > - org-html-multipage-join-first-subsection > > > > Boolean: Non-nil means that the first subsection of a section > > without a body will be joined on the section page > > (recursively). See my generated example pages linked below > > (Chapters 4, 5 and 7 for a recursive example) > > Sorry, but I cannot understand anything from there. May you explain in > words? Consider a case like this: * Headline 1 ** Headline 2 *** Headline 3 Text for Headline 3 Without the above option, Headline 1, Headline 2 and Headline 3 would be on separate pages with Headline 1 and Headline 2 being empty pages with just the Headline. The option puts all three Headlines and the Contents of Headline 3 on the same page. See here: https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch Chapters 4, 4.8, 5, 5.4 and 6 (two Headline levels combined) and Chapter 7 (three Headline levels combined) are examples of joined headlines and the other (sub)chapters are examples, how Chapters containing body text are handled. It's mainly a matter of style but in some situations it doesn't make much sense to me to add content below a headline just to avoid an empty page in multipage html output. > > - org-html-multipage-split > > > > How to split the document. Possible values are > > > > 'toc for generating a page for each toc entry. > > May I guess that the previous option may have something do with > situation when #+TOC: keyword is in the middle of a text? No: In the online document of the link above the page splitting follows the toc (with the exception of the page joining explained above), meaning that each visible toc entry will generate one page. Be aware that this is not obvious on the online page as subfolders are folded automatically using the css (folded elements have the class "toc-hidden"). If you look at the html page source you can see that every page contains the full toc to enable other css or js based styling decisions. > Do I understand correctly that your alternative layout is simply a > question of custom #+HTML_HEADER? Or is there something more to it? In my layout the main difference is that the nav left and nav right elements are part of the page-main-body rather than part of <content>. I'm not positive this is elegantly manageable with css, when the navigation is outside the page-main-body. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 19:12 ` Orm Finnendahl @ 2024-07-09 17:55 ` Ihor Radchenko 2024-07-10 18:03 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-09 17:55 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> Is there any situation when you need to export the full document >> vs. multipage to different places? > > Actually that is what I'm currently doing (and what I need for my > publishing chain): The single-page document is not in the html folder > used for the multipage document. Both files happen to have the same > name so it wouldn't work out, if I want to generate single-page along > the multipage version, without having to change the document. If this is the case, users may potentially need similar diverging settings for single- vs. multi- page documents for almost any given export option, not just the ones you mentioned. To address such situations, we may, for example, allow an alternative "multi" version of each export keyword to act specially when multipage export is used. Consider that there is an export option #+SAMPLEOPTION. If the document has only "#+SAMPLEOPTION: value", exporter will use it for both normal and multipage export. However, we may allow an alternative #+SAMPLEOPTION[multipage]: multipage value that will be used instead when defined. In addition to defining alternative variants of in-buffer settings, we also need to provide the equivalent feature for custom variables defining the export options. We can do it by treating the value of such export-related variables specially - we may allow special values like [org-export-variants :default default-value :multipage multipage-value] and provide helper functions like (org-export-set-option option-name value) ; :default (org-export-set-option option-name :multipage value) ; for multipage export only (org-export-set-option option-name :singlepage value) ; just for singlepage export (Or can be some other consistent way to define alternatives; feel free to brainstorm) >> > - org-html-multipage-front-matter >> > >> > A list to specify pages in front of the headlines of the >> > document. Possible values are 'title, 'title-toc and 'toc. title-toc >> > is a combined page containing the title and the toc. Multiple >> > entries are possible. >> >> This sounds orthogonal to multipage export. May you please illustrate >> what you want to achieve by introducing this option? Maybe there is an >> existing feature that can be re-used instead of creating something new? > > Could be: The toc as a first page is needed, when you don't want a toc > on the side of each html page, e.g. when using the classical info > layout. And it might be necessary to be able to distinguish between a > separate title page with author and the toc on the next page (or a > combined page with title and toc or no front matter at all because the > title appears on every page). If this is possible with already > existing options, even better. I just think that it might be necessary > to be able to distinguish between the needs for html output format > vs. the needs for LaTex or single-page output without having to edit > the document (I need that as my publishing chain is going to export > info, html multipage, pdf output and html single-page output using the > same org file). Sorry, but I still do not quite understand. May you please illustrate a bit more with some kind of simple example? >> > - org-html-multipage-join-first-subsection >> > >> > Boolean: Non-nil means that the first subsection of a section >> > without a body will be joined on the section page >> > (recursively). See my generated example pages linked below >> > (Chapters 4, 5 and 7 for a recursive example) >> >> Sorry, but I cannot understand anything from there. May you explain in >> words? > > Consider a case like this: > > * Headline 1 > ** Headline 2 > *** Headline 3 > Text for Headline 3 > > Without the above option, Headline 1, Headline 2 and Headline 3 would > be on separate pages with Headline 1 and Headline 2 being empty pages > with just the Headline. The option puts all three Headlines and the > Contents of Headline 3 on the same page. See here: I see. It sounds useful given that your strategy to split the document into pages is "on each headline on each level". Conceptually, I see this as one of possible customizations for paging strategies. Your `org-html-multipage-join-first-subsection' simply tells to split off pages only when there is non-empty contents inside the containing headings. This also reveals that we may sometimes want more than just to tell how to split the document. After splitting, we may want to rearrange the pages differently (maybe even re-order?). In other words, multipage export may need to: 1. Take document AST 2. Split it into multiple parts 3. Filter the obtained part list (post-process) 4. Perform actual per-page export ... >> > - org-html-multipage-split >> > >> > How to split the document. Possible values are >> > >> > 'toc for generating a page for each toc entry. >> >> May I guess that the previous option may have something do with >> situation when #+TOC: keyword is in the middle of a text? > > No: In the online document of the link above the page splitting > follows the toc (with the exception of the page joining explained > above), meaning that each visible toc entry will generate one page. Be > aware that this is not obvious on the online page as subfolders are > folded automatically using the css (folded elements have the class > "toc-hidden"). If you look at the html page source you can see that > every page contains the full toc to enable other css or js based > styling decisions. Sounds reasonable. I guess that the docstring can be improved :) >> Do I understand correctly that your alternative layout is simply a >> question of custom #+HTML_HEADER? Or is there something more to it? > > In my layout the main difference is that the nav left and nav right > elements are part of the page-main-body rather than part of > <content>. I'm not positive this is elegantly manageable with css, > when the navigation is outside the page-main-body. Sorry, but I am lost. What do you mean by "content" and what do you mean by "page-main-body"? -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-09 17:55 ` Ihor Radchenko @ 2024-07-10 18:03 ` Orm Finnendahl 2024-07-10 18:53 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-10 18:03 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Am Dienstag, den 09. Juli 2024 um 17:55:51 Uhr (+0000) schrieb Ihor Radchenko: > > To address such situations, we may, for example, allow an alternative > "multi" version of each export keyword to act specially when multipage > export is used. Consider that there is an export option #+SAMPLEOPTION. > If the document has only "#+SAMPLEOPTION: value", exporter will use it > for both normal and multipage export. However, we may allow an > alternative #+SAMPLEOPTION[multipage]: multipage value that will be used > instead when defined. > > In addition to defining alternative variants of in-buffer settings, we > also need to provide the equivalent feature for custom variables > defining the export options. We can do it by treating the value of such > export-related variables specially - we may allow special values like > [org-export-variants :default default-value :multipage multipage-value] > and provide helper functions like > > (org-export-set-option option-name value) ; :default > (org-export-set-option option-name :multipage value) ; for multipage export only > (org-export-set-option option-name :singlepage value) ; just for singlepage export > > (Or can be some other consistent way to define alternatives; feel free > to brainstorm) Yes. Currently I' more concerned with the architecural layout. Everything else is a matter of taste and easily configured (and hopefully agreed upon) once the structure is done. I'm very relaxed and unopinionated about how to handle options as long as they don't involve changing the org document for each export backend. > >> > - org-html-multipage-front-matter > >> > > >> > A list to specify pages in front of the headlines of the > >> > document. Possible values are 'title, 'title-toc and 'toc. title-toc > >> > is a combined page containing the title and the toc. Multiple > >> > entries are possible. > >> > >> This sounds orthogonal to multipage export. May you please illustrate > >> what you want to achieve by introducing this option? Maybe there is an > >> existing feature that can be re-used instead of creating something new? > > > > Could be: The toc as a first page is needed, when you don't want a toc > > on the side of each html page, e.g. when using the classical info > > layout. And it might be necessary to be able to distinguish between a > > separate title page with author and the toc on the next page (or a > > combined page with title and toc or no front matter at all because the > > title appears on every page). If this is possible with already > > existing options, even better. I just think that it might be necessary > > to be able to distinguish between the needs for html output format > > vs. the needs for LaTex or single-page output without having to edit > > the document (I need that as my publishing chain is going to export > > info, html multipage, pdf output and html single-page output using the > > same org file). > > Sorry, but I still do not quite understand. May you please illustrate a > bit more with some kind of simple example? Consider a doucument like this: ** Headline 1 ** Headline 2 *** Subheadline 2.1 In the multipage export you want a front page with booktitle, author, date, etc. (maybe even an image...) and as a second page after the front page you want to have a full toc. Both pages should be reachable by the side toc but shouldn't get numbered so the toc on the side would appear like this: My Booktitle Contents 1 Headline 1 2 Headline 1 2.1 Subheadline 1 On the other hand you might always print the booktitle on every page and as the toc is always at the side you might not need titlepage and toc as seperate pages. Or you like the layout of the info mode with just navigation buttons and no side toc. In these documents, the toc is normally on the first "home" page. This would also imply a seperate html page with a toc and possibly the title on it. As there are always different preferences for this I thought to introduce a list which specifies, what king of documents should appear at the front of the document which aren't counted in the toc. All these are -in my opinion- legitimate decisions not at all unusual in publication situations so I thought I accomodate for that. Is my explanation somewhat clearer? > > >> > - org-html-multipage-join-first-subsection > >> > > >> > Boolean: Non-nil means that the first subsection of a section > >> > without a body will be joined on the section page > >> > (recursively). See my generated example pages linked below > >> > (Chapters 4, 5 and 7 for a recursive example) > >> > >> Sorry, but I cannot understand anything from there. May you explain in > >> words? > > > > Consider a case like this: > > > > * Headline 1 > > ** Headline 2 > > *** Headline 3 > > Text for Headline 3 > > > > Without the above option, Headline 1, Headline 2 and Headline 3 would > > be on separate pages with Headline 1 and Headline 2 being empty pages > > with just the Headline. The option puts all three Headlines and the > > Contents of Headline 3 on the same page. See here: > > I see. It sounds useful given that your strategy to split the document > into pages is "on each headline on each level". > > Conceptually, I see this as one of possible customizations for paging > strategies. Your `org-html-multipage-join-first-subsection' simply tells > to split off pages only when there is non-empty contents inside the > containing headings. > > This also reveals that we may sometimes want more than just to tell how > to split the document. After splitting, we may want to rearrange the > pages differently (maybe even re-order?). In other words, multipage > export may need to: > > 1. Take document AST > 2. Split it into multiple parts > 3. Filter the obtained part list (post-process) > 4. Perform actual per-page export > ... yes. we can build a complete machinery around all that, but currently I fear that this gets a bit out of control for me: I really have to get going with other things and currently I'd prefer to realize something that works with the architecture built in way that it is easlily extendable in the future without having to redo everything again. > > >> > - org-html-multipage-split > >> > > >> > How to split the document. Possible values are > >> > > >> > 'toc for generating a page for each toc entry. > >> > >> May I guess that the previous option may have something do with > >> situation when #+TOC: keyword is in the middle of a text? > > > > No: In the online document of the link above the page splitting > > follows the toc (with the exception of the page joining explained > > above), meaning that each visible toc entry will generate one page. Be > > aware that this is not obvious on the online page as subfolders are > > folded automatically using the css (folded elements have the class > > "toc-hidden"). If you look at the html page source you can see that > > every page contains the full toc to enable other css or js based > > styling decisions. > > Sounds reasonable. I guess that the docstring can be improved :) > :-) > >> Do I understand correctly that your alternative layout is simply a > >> question of custom #+HTML_HEADER? Or is there something more to it? > > > > In my layout the main difference is that the nav left and nav right > > elements are part of the page-main-body rather than part of > > <content>. I'm not positive this is elegantly manageable with css, > > when the navigation is outside the page-main-body. > > Sorry, but I am lost. What do you mean by "content" and what do you mean > by "page-main-body"? Look at the tags and ids of the html code on these pages. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-10 18:03 ` Orm Finnendahl @ 2024-07-10 18:53 ` Ihor Radchenko 0 siblings, 0 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-10 18:53 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> >> > - org-html-multipage-front-matter >> >> > >> >> > A list to specify pages in front of the headlines of the >> >> > document. Possible values are 'title, 'title-toc and 'toc. title-toc >> >> > is a combined page containing the title and the toc. Multiple >> >> > entries are possible. > ... > Consider a doucument like this: > > ** Headline 1 > ** Headline 2 > *** Subheadline 2.1 > > In the multipage export you want a front page with booktitle, author, > date, etc. (maybe even an image...) and as a second page after the > front page you want to have a full toc. Both pages should be reachable > by the side toc but shouldn't get numbered so the toc on the side > would appear like this: > > My Booktitle > Contents > 1 Headline 1 > 2 Headline 1 > 2.1 Subheadline 1 > ...Is my explanation somewhat clearer? Yup. Clear now. In the nutshell, you want 1. Special export settings for certain pages (inline toc vs. side toc) 2. Extend TOC generation rules to be more automatic than they are now (insert TOC inline automatically for certain headings vs side TOC for the rest) Looks doable using the available means + previously discussed multipage setting ideas. >> 1. Take document AST >> 2. Split it into multiple parts >> 3. Filter the obtained part list (post-process) >> 4. Perform actual per-page export >> ... > > yes. we can build a complete machinery around all that, but currently > I fear that this gets a bit out of control for me: I really have to > get going with other things and currently I'd prefer to realize > something that works with the architecture built in way that it is > easlily extendable in the future without having to redo everything > again. Sure. Feel free to do things that work better for you. Just keep in mind the ideas we discuss - we will eventually need to get them going and the preliminary implementation should not cause hard blockers. I am looking forward to your future contributions. (And, BTW, feel free to check out https://orgmode.org/worg/org-contribute.html - we provide some important information about our patch conventions. Please pay attention to https://orgmode.org/worg/org-contribute.html#copyright) > ... >> Sorry, but I am lost. What do you mean by "content" and what do you mean >> by "page-main-body"? > > Look at the tags and ids of the html code on these pages. Ok. More clear now. What you have is <body> <nav ...> {TOC element aligned left} </nav> {TITLE} <div contents> {document body aligned right} <div> </body> Now, I think I can answer your original question: > In addition I have a question about the html output layout > structure. Here is an example of a file generated with the current > code with some preliminary layout. It might give an idea about my use > case: > > https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch/01_00_00_vorwort.html#orge24571b > > Regardless of the colours, the file has a slightly different hierarchy > than the single page html template of ORGMODE and is more oriented > towards the layout of documentation nowadays with a (hideable) toc at > the side on every page rather than the texinfo oriented layout used by > the orgmode manual. If my code gets accepted/merged to org what should > be the default layout shipped with multipage output? FYI: The > visibility of the toc entries is managed by the css and the whole toc > is included on each page (and its visibility could be managed with js > as well). Should I rather go for the classic texinfo view? For context, the vanilla exported HTML body is (see `org-html-template', `org-html-inner-template', `org-html-toc') <body> {LINK UP} {PREAMBLE} <div content> {TITLE} {TOC} {exported CONTENTS} {Footnotes} </div> {POSTAMBLE} {JS scripts} </body> I see no major problem customizing TOC position in the HTML template. In fact, it would be rather desirable to provide a set of less bare-bones defaults (as long as they do not get too complex). -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-04 16:20 ` Ihor Radchenko 2024-07-07 19:33 ` Orm Finnendahl @ 2024-07-07 20:50 ` Orm Finnendahl 2024-07-08 15:05 ` Ihor Radchenko 1 sibling, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-07 20:50 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Hi Ihor, I'm trying to grasp what you are proposing and have some questions to make sure I've understood (please correct me if I'm wrong): - Your idea is to add an option to the backend definition called org-export-pages which is a plist containing information about the way to export the document in case some "multipage" option is chosen in the export dialog. - Am I right that you suggest that all these org-export-pages properties can be overwritten in the header of the org file? - If that is correct I assume multipage export should then be a generic option common to different export backends (if defined) (something like "export-as-multipage") and the question is how to specify that when exporting. Should this option just be listed in the export dialog for every export backend which supports it (like in my current approach for html) and when choosing it the rules of the current definition of org-export-pages in the current context are used? - This implies that the code handling this is done in ox.el like this: The export-pages function in ox.el 1. generates the parse-tree 2. extracts the subtrees according to the rules 3. calls org-export-to-file on the backends for each of them. 4. optionally also exports the whole document, maybe stripped from its exported sections (replaced by links, etc.) If this is the way you suggest it, it doesn't sound too complicated as most of it is done already. My only concern is that in this case org-export-pages is not really backend specific and therefore the place for it semantically shouldn't be in the definition of the backend, but separate from it. The backend should just define a general function for exporting a subtree to a file for the multipage case as this might differ from the definition for single file output of the complete parse-tree (with the name of this general multipage export function being the same in all backends which support multipage output). This would also imply a mechanism to define different org-export-pages plists and select from them before exporting by calling a generic backend-agnostic org-export-to-pages function in ox.el. This is very elegant but also somewhat different from the current layout of org-export which is single-page single-backend centered. Hmm... -- Orm Am Donnerstag, den 04. Juli 2024 um 16:20:29 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > Sure. I'm not at all familiar with the peculiarities of other output > > backends, but see your point. If you can give any hints or have any > > ideas *how* we could find general rules for separating the subtrees, > > which cover foreseeable use cases, or devise a flexible mechanism for > > doing so, I'd be glad to help setting them up and implementing them. I > > definitely agree, the code should be as general as possible while > > providing complete backward compatibility. > > I think that the easiest would be adding a new option to > `org-export-options-alist' - it is already extendable for individual > backends and allows users to tweak things via in-buffer keywords, > properties, variables, and export options. > > The most generic rule would be some kind of function that takes AST > node as input and returns whether that node should be going to a separate > file or not, and if yes, tell (1) which export backend to use to export > that subtree to a file (may as well allow exporting to different > formats, while we are at it); (2) what are the export parameters to be > used for that export, (possibly) including the file path. > > Then, in addition to the most generic (and most flexible) "rule being an > Elisp function", we can allow some simplified semantics to define rules. > > The semantics should probably give a couple of toggles to customize: > (1) which subtrees are selected for export; (2) which export backend is > used (3) how their file names are generated; (4) (optional) how they are > represented when exporting the whole original file; e.g. whether to put > links to exported files in place of their subtrees; (5) (optional) how > the original file is represented in the exported subtrees; e.g. whether > to put backlink to parent file > > The subtree selection may boil down to the usual TAGS matcher (or > function), as described in "11.3.3 Matching tags and properties" section > of the manual. This will cover the previously discussed separation based > on headline level, a tag, or a property. > > The export backend selection may be realized by allowing multiple rules > with each rule defining selection/backend/file name/.... > > In terms of the value semantics in Elisp, I am thinking about something > re-using backend definition format: > > (setq org-export-pages > '(:selector "LEVEL=2+blog+TODO=DONE" > :backend html > ;; completely remove the exported subtree is original document > ;; is being exported. > :page-transcoder nil > ;; or :page-transcoder #'org-export-page-as-heading-with-link > :export-file-name "%{TITLE}-%{page-number}" ;; or some other kind of template syntax > ) > > '(:selector a-function-accepting-ast-node > :source-backend any > :backend > (:parent html ;; `org-export-define-derived-backend'-like semantics > :options-alist > ;; Do not export private headings in HTML pages. > ((:exclude-tags "EXCLUDE_TAGS" nil (cons "private" org-export-exclude-tags) split)))) > > '(:selector "+export_ascii_page" > :source-backend html ; only use this rule when exporting to html > :backend > (:parent ascii > ((template . > (lambda (contents info) > (format "Paged out from %s\n%s" > (plist-get > ;; INFO channel for parent document > (plist-get info :page-source) > :title) > (org-ascii-template contents info))))))))) > > >> 2. Some backends, as you proposed, may target multipage export from the > >> very beginning. So, we need to provide some way for the backend (in > >> org-export-define*-backend) to specify that it wants to split the > >> original parse tree. I imagine some kind of option with default > >> values configured via backend, but optionally overwritten by user > >> settings/in-buffer keywords. > > > > I'll look into that and maybe I can come up with something. I was > > hesitant to propose anything as I tried to stay as limited as possible > > and not get too deep into changing things. If you have suggestions, > > please let me know. > > One way could be simply adding an option like :selector above to the > backend definition. Then, it will be used as default selector: > > (setq org-export-pages > (:selector default :backend html) ; export pages to html with default selector > ) > > or even > > (setq org-export-pages > (:backend html) ; export pages to html with default selector > ) > > or just > > ;; export using the same target backend as selected in the export menu > (setq org-export-pages t) > ;; (setq org-export-pages nil) - existing single page export > ;; (setq org-export-pages 'only-pages) - only export pages, ignore original file > > >> 3. Your suggestion to add a new export option for splitting based on > >> headline level is one idea. > >> > >> Another idea is to split out subtrees with :EXPORT_FILE_NAME: > >> property. > > > > I'm not sure I fully understand what you mean: Do you mean specifying > > different :EXPORT_FILE_NAME: properties throughout the same document > > and then export accordingly? > > Yes. It is re-using the existing idea with subtree export > > 13.2 Export Settings > > ‘EXPORT_FILE_NAME’ > The name of the output file to be generated. Otherwise, Org > generates the file name based on the buffer name and the extension > based on the backend format. > > If a subtree has that property set, it is used as output file name. > Since there is usually no reason to set this property unless you also > want to export subtree to individual file, it makes sense to use this as > selector for what to export as pages. > > Example: > > #+TITLE: Index document > > * Emacs notes > ** Emacs blog post #1 > :PROPERTIES: > :EXPORT_FILE_NAME: my-first-post > :END: > ... > ** Fleeting note at [2024-06-20 Thu 22:16] > Some notes, no need to export them. > > * Personal notes > ** Personal blog post #1 > :PROPERTIES: > :EXPORT_FILE_NAME: private/personal-post-trial > :END: > ... > > >> 6. I can see people flipping between exporting the whole document and > >> multipage document. We probably need some kind of easy switch in M-x > >> org-export-dispatch to choose how to export. > > > > Sure, that is the disadvantage of my proposal to make everything a > > "multipage" document. Another disadvantage is that when the user > > chooses to open the final document or display it in a buffer the user > > can't choose whether to only open/display one page or every exported > > page. In most circumstances it should be advisable to just > > open/display the first page. We can also just add a switch between > > single-page and multipage, with multipage always just exporting to > > file, but that also has disadvantages. > > What to open is a minor detail, really. It can be worked out any moment > we need to. The most sensible default, IMHO, it to open dired with the > containing directory with all the exported pages. > > > As the code I proposed is encapsulated in the html backend and not > > spreading all over the place, I will now first go ahead to finalize > > the existing code to a fully working setup. ASFAICT adapting that to > > other needs shouldn't require a complete rewrite. And I might be > > around for a while ;-) > > I advice against doing this. > While reading your code, I saw that you used some html-specific > functions for modifications in ox.el. If you start by modifying ox.el in > Org git repo directly, simply doing "make compile" will warn about > instances of using functions not defined in ox.el. > Another advantage of editing the ox.el and using Org repository is that > you can run "make test" any time and see if you managed to break Org :) > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> > ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-07 20:50 ` Orm Finnendahl @ 2024-07-08 15:05 ` Ihor Radchenko 2024-07-08 15:41 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-08 15:05 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > I'm trying to grasp what you are proposing and have some questions to > make sure I've understood (please correct me if I'm wrong): (Just for some context, do not take my ideas as something you must follow 100% accurately. I am largely brainstorming here. So, feel free to disagree, propose anything alternative, etc; My main focus in this discussion is that multipage export should be backend-agnostic if possible) > - Your idea is to add an option to the backend definition called > org-export-pages which is a plist containing information about the > way to export the document in case some "multipage" option is chosen > in the export dialog. Yup. Not an "option" in a sense of variable, but a proper export option that can be set via (1) variable; (2) backend option plist (in other words, overridden by backends); (3) in-buffer keyword, locally. > - Am I right that you suggest that all these org-export-pages > properties can be overwritten in the header of the org file? Yes. But that may be controlled by the backends, as with any other export option. To illustrate, there is CREATOR option that ox-html re-defines like the following: ;; Original global definition in ox.el (:creator "CREATOR" nil org-export-creator-string) ;; Override inside ox.el. In this example, it uses a backend-specific ;; customization instead of `org-export-creator-string', but anything ;; at all can be overridden. (:creator "CREATOR" nil org-html-creator-string) In both cases, the :creator export option can be set in buffer via, #+CREATOR: name > - If that is correct I assume multipage export should then be a > generic option common to different export backends (if defined) > (something like "export-as-multipage") and the question is how to > specify that when exporting. Should this option just be listed in > the export dialog for every export backend which supports it (like > in my current approach for html) and when choosing it the rules of > the current definition of org-export-pages in the current context > are used? Yes. Something similar to `org-export-visible-only', `org-export-body-only', etc. These customizations can be toggled interactively, from `org-export-dispatch'. A question for future is whether we want more than just "t" or "nil" toggle, but it should not be too hard to generalize if we simply start from just t/nil. We might also consider adding MULTIPAGE as an additional argument to the API function (just like BODY-ONLY, VISIBLE-ONLY, SUBTREEP that we already use), but that's probably an implementation idea we may or may not need to use. > - This implies that the code handling this is done in ox.el like this: > > The export-pages function in ox.el > > 1. generates the parse-tree > > 2. extracts the subtrees according to the rules > > 3. calls org-export-to-file on the backends for each of them. > > 4. optionally also exports the whole document, maybe stripped from > its exported sections (replaced by links, etc.) > > If this is the way you suggest it, it doesn't sound too complicated as > most of it is done already. Yes, roughly like this. Ideally, we should simply modify `org-export-as', but handling output file name may be a bit tricky - it is somewhat awkwardly placed in the current ox.el API (see the discussion in https://list.orgmode.org/orgmode/25393.61240.135445.401251@gargle.gargle.HOWL/T/#u). > My only concern is that in this case org-export-pages is not really > backend specific and therefore the place for it semantically shouldn't > be in the definition of the backend, but separate from it. I guess that backends may provide some defaults that make more sense for those backends only. But otherwise splitting the full AST before individual page export might be simply handled in ox.el. > The backend should just define a general function for exporting a > subtree to a file for the multipage case as this might differ from the > definition for single file output of the complete parse-tree (with the > name of this general multipage export function being the same in all > backends which support multipage output). All the built-in backends already have such function. For example, (defun org-html-export-to-html (&optional async subtreep visible-only body-only ext-plist) ^^^^^^^^ If subtree export is good enough to handle multi-page export, we may not even need to do much. (Although, deriving the file names is currently hard-coded for subtrees and is not very customizable; see the link I shared above) > This would also imply a mechanism to define different org-export-pages > plists and select from them before exporting by calling a generic > backend-agnostic org-export-to-pages function in ox.el. This is very > elegant but also somewhat different from the current layout of > org-export which is single-page single-backend centered. Hmm... I do not think that we need to go too deep into this rabbit hole for now. A simple toggle based on `org-export-dispatch' might be good enough. It can be easily extended to something like multi-state switch (t/nil vs. t -> option A -> option B -> nil -> t -> ...). -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 15:05 ` Ihor Radchenko @ 2024-07-08 15:41 ` Orm Finnendahl 2024-07-08 15:56 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-08 15:41 UTC (permalink / raw) To: emacs-orgmode Hi, Am Montag, den 08. Juli 2024 um 15:05:58 Uhr (+0000) schrieb Ihor Radchenko: > > We might also consider adding MULTIPAGE as an additional argument to the > API function (just like BODY-ONLY, VISIBLE-ONLY, SUBTREEP that we > already use), but that's probably an implementation idea we may or may > not need to use. Currently I set the :multipage property in info, but that's a detail that can be sorted out later. > Yes, roughly like this. Ideally, we should simply modify > `org-export-as', but handling output file name may be a bit tricky - > it is somewhat awkwardly placed in the current ox.el API (see the > discussion in > https://list.orgmode.org/orgmode/25393.61240.135445.401251@gargle.gargle.HOWL/T/#u). Today I had a look at ox.el when upgrading my code to 9.8-pre. Unfortunately the code (and behaviour of org-element, etc.) has changed quite a bit and I had to fix many things. Especially in org-export-as the parsing of the tree is now done in the lexical context of a copy of the buffer which makes implementing a multipage backend even more awkward. IMHO the code is just the wrong way around: org-export-to-file calls org-export-as which combines the parsing with generating the output string. The multipage code has to split that part and that doesn't get easier when both parts have to be evaluated in the context of org-export-with-buffer-copy. I'd rather have that turned inside out: Instead of org-export-as being a part of org-export-to-file/buffer/etc., its functionality could be at the top-level and then call org-export-to... appropriately (either for multipage output, single-page output, buffer-output...). I will handle it by splitting org-export-as just before the org-export-with-buffer-copy, but consider it a bit ugly. > I do not think that we need to go too deep into this rabbit hole for > now. A simple toggle based on `org-export-dispatch' might be good > enough. It can be easily extended to something like multi-state switch > (t/nil vs. t -> option A -> option B -> nil -> t -> ...). There is something else: A lot of my energy in the multipage backend went into getting links and footnotes correct. Footnotes aren't a big deal, but I have no idea how to handle cross document links if different backends are present (e.g. linking from html to a pdf document and vice versa ;-) I think this requires quite a bit more thinking and maybe is unrealistic altogether, but at least the framework could be changed to be able to tackle that in the distant future... -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 15:41 ` Orm Finnendahl @ 2024-07-08 15:56 ` Ihor Radchenko 2024-07-08 19:18 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-08 15:56 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> Yes, roughly like this. Ideally, we should simply modify >> `org-export-as', but handling output file name may be a bit tricky - >> it is somewhat awkwardly placed in the current ox.el API (see the >> discussion in >> https://list.orgmode.org/orgmode/25393.61240.135445.401251@gargle.gargle.HOWL/T/#u). > > Today I had a look at ox.el when upgrading my code to > 9.8-pre. Unfortunately the code (and behaviour of org-element, etc.) > has changed quite a bit and I had to fix many things. > > Especially in org-export-as the parsing of the tree is now done in the > lexical context of a copy of the buffer which makes implementing a > multipage backend even more awkward. > > IMHO the code is just the wrong way around: org-export-to-file calls > org-export-as which combines the parsing with generating the output > string. The multipage code has to split that part and that doesn't get > easier when both parts have to be evaluated in the context of > org-export-with-buffer-copy. I'd rather have that turned inside out: > Instead of org-export-as being a part of > org-export-to-file/buffer/etc., its functionality could be at the > top-level and then call org-export-to... appropriately (either for > multipage output, single-page output, buffer-output...). I will handle > it by splitting org-export-as just before the > org-export-with-buffer-copy, but consider it a bit ugly. Or we can make `org-export-as' retain INFO channel when returning the output. Then, we can make `org-export-to-file' make use of the INFO channel to decide the file name. This way, there will be no need to decide the file name before running the parsing. > There is something else: A lot of my energy in the multipage backend > went into getting links and footnotes correct. Footnotes aren't a big > deal, but I have no idea how to handle cross document links if > different backends are present (e.g. linking from html to a pdf > document and vice versa ;-) I think this requires quite a bit more > thinking and maybe is unrealistic altogether, but at least the > framework could be changed to be able to tackle that in the distant > future... Yes, it is an important feature we would need to implement - turning internal links into external when they no longer point inside the same document. Somewhat relevant code: `org-export--update-included-link' and ox-publish. For links to external pdfs and co, we have discussed what can be done in https://list.orgmode.org/orgmode/87a5rpoi4c.fsf@localhost/ TL;DR: In latex, \href{file.pdf#anchor} works; In web, anchors should also work with pdfjs. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 15:56 ` Ihor Radchenko @ 2024-07-08 19:18 ` Orm Finnendahl 2024-07-09 18:08 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-08 19:18 UTC (permalink / raw) To: emacs-orgmode Hi Ihor, Am Montag, den 08. Juli 2024 um 15:56:48 Uhr (+0000) schrieb Ihor Radchenko: > > Or we can make `org-export-as' retain INFO channel when returning the > output. Then, we can make `org-export-to-file' make use of the INFO > channel to decide the file name. This way, there will be no need to > decide the file name before running the parsing. Are you sure that works? org-export-as currently returns a string. It could in addition return the parse-tree in info, plus the smaller parts which need to be exported, but we should not forget, that org-export-as is an inferior function called from org-export-to-file or org-export-to-buffer. But maybe I misunderstand what you mean. Here is what is needed from my perspective: 1. parse the tree of the whole document 2. split the tree up. 3. call the export backend on each of the split parts to generate the string and save it to disk or do whatever is appropriate. For me the most natural way would be that a central function (export-according-to-org-property-list) does the parsing and then call the different backend functions to export according to their rules (the trees being converted in the central function or in backend code). If toplevel functions like org-export-to-file use org-export-as, than org-export-as should only be concerned with generating the string but not with reparsing. Alternatively we can do the conversion to a string in the central function as now with org-export-as, but there still needs to be a mechanism to generate the different files for multipage output and call the export backend on them to save them or whatever. Or what did you have in mind? > For links to external pdfs and co, we have discussed what can be done in > https://list.orgmode.org/orgmode/87a5rpoi4c.fsf@localhost/ > TL;DR: In latex, \href{file.pdf#anchor} works; In web, anchors should > also work with pdfjs. Thanks, I'll check that out. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-08 19:18 ` Orm Finnendahl @ 2024-07-09 18:08 ` Ihor Radchenko 2024-07-10 19:37 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-09 18:08 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> Or we can make `org-export-as' retain INFO channel when returning the >> output. Then, we can make `org-export-to-file' make use of the INFO >> channel to decide the file name. This way, there will be no need to >> decide the file name before running the parsing. > > Are you sure that works? org-export-as currently returns a string. It > could in addition return the parse-tree in info, plus the smaller > parts which need to be exported, but we should not forget, that > org-export-as is an inferior function called from org-export-to-file > or org-export-to-buffer. But maybe I misunderstand what you mean. That's exactly what I mean. > Here is what is needed from my perspective: > > 1. parse the tree of the whole document > > 2. split the tree up. > > 3. call the export backend on each of the split parts to generate the > string and save it to disk or do whatever is appropriate. > > For me the most natural way would be that a central function > (export-according-to-org-property-list) does the parsing and then call > the different backend functions to export according to their rules > (the trees being converted in the central function or in backend > code). > > If toplevel functions like org-export-to-file use org-export-as, than > org-export-as should only be concerned with generating the string but > not with reparsing. Sorry, but I do not understand your concern. > Alternatively we can do the conversion to a string in the central > function as now with org-export-as, but there still needs to be a > mechanism to generate the different files for multipage output and > call the export backend on them to save them or whatever. Or what did > you have in mind? What I have in mind is that `org-export-as' will return a list of strings + INFO. INFO will contain data about which files to use for saving the strings. Then, the caller does the saving and whatever is necessary. If we write to files from `org-export-as' it will be a massive breaking change in the expected behavior. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-09 18:08 ` Ihor Radchenko @ 2024-07-10 19:37 ` Orm Finnendahl 2024-07-11 12:35 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-10 19:37 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Am Dienstag, den 09. Juli 2024 um 18:08:10 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > If toplevel functions like org-export-to-file use org-export-as, than > > org-export-as should only be concerned with generating the string but > > not with reparsing. > > Sorry, but I do not understand your concern. If org-export-as returns just one string, then it will reparse the parse tree each time it needs to generate an output string. But as you say below, you rather think org-export-as returns a list of strings for the multipage case. > > Alternatively we can do the conversion to a string in the central > > function as now with org-export-as, but there still needs to be a > > mechanism to generate the different files for multipage output and > > call the export backend on them to save them or whatever. Or what did > > you have in mind? > > What I have in mind is that `org-export-as' will return a list of > strings + INFO. INFO will contain data about which files to use for > saving the strings. Then, the caller does the saving and whatever is > necessary. If we write to files from `org-export-as' it will be a > massive breaking change in the expected behavior. ok, that's what you mean. I can do this, but don't you think it'd be more consistent with the general layout of ox, if org-export-as uses a callback function to call on each generated string with the filename as argument nad we agree on names for multipage file output which have to get implemented by multipage backends? Whatever, both ways will do what's needed, just let me know what you prefer and I will provide a suggestion, ok? I try to find time on the weekend, otherwise I'll have time after the end of next week. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-10 19:37 ` Orm Finnendahl @ 2024-07-11 12:35 ` Ihor Radchenko 2024-07-13 7:44 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-11 12:35 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > If org-export-as returns just one string, then it will reparse the > parse tree each time it needs to generate an output string. But as you > say below, you rather think org-export-as returns a list of strings > for the multipage case. Got it now. >> What I have in mind is that `org-export-as' will return a list of >> strings + INFO. INFO will contain data about which files to use for >> saving the strings. Then, the caller does the saving and whatever is >> necessary. If we write to files from `org-export-as' it will be a >> massive breaking change in the expected behavior. > > ok, that's what you mean. I can do this, but don't you think it'd be > more consistent with the general layout of ox, if org-export-as uses a > callback function to call on each generated string with the filename > as argument nad we agree on names for multipage file output which have > to get implemented by multipage backends? This sounds like some kind of extension to :filter-final-output. I think it should also be an ok option. > Whatever, both ways will do what's needed, just let me know what you > prefer and I will provide a suggestion, ok? I try to find time on the > weekend, otherwise I'll have time after the end of next week. I am ok with what you propose. So, please go ahead. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-11 12:35 ` Ihor Radchenko @ 2024-07-13 7:44 ` Orm Finnendahl 2024-07-13 10:13 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-13 7:44 UTC (permalink / raw) To: emacs-orgmode Hi, Am Donnerstag, den 11. Juli 2024 um 12:35:21 Uhr (+0000) schrieb Ihor Radchenko: > > ok, that's what you mean. I can do this, but don't you think it'd be > > more consistent with the general layout of ox, if org-export-as uses a > > callback function to call on each generated string with the filename > > as argument and we agree on names for multipage file output which have > > to get implemented by multipage backends? > > This sounds like some kind of extension to :filter-final-output. > I think it should also be an ok option. :filter-final-output functions could be used, but the name is a bit misleading. Therefore I'd suggest to extend the org-export-filters-alist with :export-final-output which only gets called if non-nil. Otherwise org-export-as will return a single string as before, so we don't break anything. In the multipage case we still need a hook to split the parse tree before transcoding. The place for this should probably be in org-export--annotate-info. I don't see any mechanism/alist function to use so I would suggest to add an option :multipage-process-hook to org-export-filters-alist. In addition the backend will set a :multipage option at the beginning of the export, when exporting to multipage. I will go ahead and implement a proposal. Let me know if something sounds bad/unreasonable. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-13 7:44 ` Orm Finnendahl @ 2024-07-13 10:13 ` Ihor Radchenko 2024-07-13 11:01 ` Orm Finnendahl 2024-07-23 8:56 ` Orm Finnendahl 0 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-13 10:13 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> This sounds like some kind of extension to :filter-final-output. >> I think it should also be an ok option. > > :filter-final-output functions could be used, but the name is a bit > misleading. Therefore I'd suggest to extend the > org-export-filters-alist with :export-final-output which only gets > called if non-nil. Otherwise org-export-as will return a single string > as before, so we don't break anything. It is not very clear for me from the name how :export-final-output would differ from :filter-final-output. Maybe :finalize-export-functions? > In the multipage case we still need a hook to split the parse tree > before transcoding. The place for this should probably be in > org-export--annotate-info. I don't see any mechanism/alist function to > use so I would suggest to add an option :multipage-process-hook to > org-export-filters-alist. We should better use a new option, yes. Many existing options can be modified by users by accident, and we do not want that. > In addition the backend will set a :multipage option at the beginning > of the export, when exporting to multipage. It will be more in-line with the existing design to set :export-options. See `org-export--get-export-attributes'. > I will go ahead and implement a proposal. Let me know if something > sounds bad/unreasonable. As you see, nothing major. We can work out the details after you get a prototype to work with. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-13 10:13 ` Ihor Radchenko @ 2024-07-13 11:01 ` Orm Finnendahl 2024-07-23 8:56 ` Orm Finnendahl 1 sibling, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-13 11:01 UTC (permalink / raw) To: emacs-orgmode Hi, while doing it, I found out it only needs one function call in org-export-as for splitting, transcoding and writing the file. Currently it's called :process-multipage, but we can change that later. I'll take your advice and use an :export-option for multipage. -- Orm Am Samstag, den 13. Juli 2024 um 10:13:56 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > >> This sounds like some kind of extension to :filter-final-output. > >> I think it should also be an ok option. > > > > :filter-final-output functions could be used, but the name is a bit > > misleading. Therefore I'd suggest to extend the > > org-export-filters-alist with :export-final-output which only gets > > called if non-nil. Otherwise org-export-as will return a single string > > as before, so we don't break anything. > > It is not very clear for me from the name how :export-final-output would > differ from :filter-final-output. Maybe :finalize-export-functions? > > > In the multipage case we still need a hook to split the parse tree > > before transcoding. The place for this should probably be in > > org-export--annotate-info. I don't see any mechanism/alist function to > > use so I would suggest to add an option :multipage-process-hook to > > org-export-filters-alist. > > We should better use a new option, yes. Many existing options can be > modified by users by accident, and we do not want that. > > > In addition the backend will set a :multipage option at the beginning > > of the export, when exporting to multipage. > > It will be more in-line with the existing design to set > :export-options. See `org-export--get-export-attributes'. > > > I will go ahead and implement a proposal. Let me know if something > > sounds bad/unreasonable. > > As you see, nothing major. We can work out the details after you get a > prototype to work with. > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-13 10:13 ` Ihor Radchenko 2024-07-13 11:01 ` Orm Finnendahl @ 2024-07-23 8:56 ` Orm Finnendahl 2024-07-23 10:24 ` Ihor Radchenko 1 sibling, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 8:56 UTC (permalink / raw) To: emacs-orgmode Hi, I managed to get the proposal for the multipage output done. Please review it and let me know what you think/would prefer to change. I'm pretty open about it. You can find it here: https://github.com/ormf/ox-html-multipage The code is intended to replace ox.el and ox-html.el. The repository contains a pretty exhaustive CHANGELOG.txt to show what I did. I also found a way to tackle the problem with the correct output template by integrating both approaches into one template with the option of customizing it simply with css. Here are the two layouts, the first being just the plain output with a css styling similar to the plain singlepage output, the second with the navigation elements integrated into the main-text-body: 1. Plain https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch-plain/ 2. Inline navigation https://www.selma.hfmdk-frankfurt.de/finnendahl/klangsynthesebuch/ My code proposal shouldn't break anything in the single-page export for any backend and produce the exact same output as before with one exception: There now is an option :html-numbered-link-format which applies to numbered links to Chapters, Sections or Images. If the link doesn't have a label, in previous versions of ox-html the link label just consisted of a number. With the chenge, the link label will be replaced by a customizable string for the three cases. The default setting now is "Chapter %s", "Section %s" and "Fig. %s", which will get translated using the org-export-dictionary (I added those entries in ox.el). The customizable strings can be set to "%s" if the previous behaviour is preferred, but I consider it an enhancement and assume, the new behaviour is preferred by most users. In addition I found a minor bug regarding infojs and implemented a more general way to determine footnote numbers (which is not a bug in single-page output, but in my opinion a more concise method aligning with the way footnote numbers are created in the first place). The new multipage output will get triggered with 'C-c C-e h m'. Whether the first page opens in a buffer, browser or the output just get written to file can be controlled with the :html-multipage-open option in the file (or as a customized variable). In addition these customizable options are implemented: - :html-multipage-head-include-default-style default css style for multipage documents. - :html-multipage-join-empty-bodies / org-html-multipage-join-empty-bodies Whether to join subheadlines on the same page in case a headline has no body text (I tried to clarify that in the doc string of the defcustom). - :html-multipage-export-directory / org-html-multipage-export-direcotry The directory for the multipage output (relative or absolute). - :html-multipage-nav-format / org-multipage-nav-format Html snippets for the top navigation elements. - :html-multipage-split / org-multipage-split Where to split the document. Possible values are 'toc to split at the toc entries or a number indicating the headline level. - :html-multipage-toc-to-top / org-html-multipage-toc-to-top link destination from toc (either directly to the headline, or to the top of the page, more convenient in the standard case with the navigation on top). I did *not* implement: - Front matter options as I think the standard tools for org mode cover most cases I thought of very elegantly and it seemed somewhat clunky to me. - Page split at section-filenames. The main reason for this is that it needs a longer discussion, how this should get implemented correctly to cover all use cases. In principle it is not very complicated, especially with my better understanding of the underlying principles of ox. But if I understand Ihor's ideas correctly, it is a separate issue altogether which won't be handled properly in the html backend but rather in a general multipage backend which is backend agnostic. I'm perfectly willing to tackle this and to contribute, but currently I think it is better to make the proposed code with applied improvements available, as it is useful and pretty complete for the use case of publishing an org document to multiple html pages. If the code gets reviewed and accepted I have some questions regarding final submittal: 1. How do I provide the code? Is there a mechanism like issuing a merge-request or how is it normally done? 2. How do I add documentation to the org manual? 3. Should there be test functions for the code added and are there recommendations how to do that? I'm glad that I finally got it done. Hope you like it and please let me know what you think. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 8:56 ` Orm Finnendahl @ 2024-07-23 10:24 ` Ihor Radchenko 2024-07-23 11:35 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 10:24 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > I managed to get the proposal for the multipage output done. Please > review it and let me know what you think/would prefer to change. I'm > pretty open about it. > > You can find it here: > > https://github.com/ormf/ox-html-multipage > > The code is intended to replace ox.el and ox-html.el. The repository > contains a pretty exhaustive CHANGELOG.txt to show what I did. Thanks! I will first focus on reviewing changes to ox.el. > ox.el > > - added `org-export-collect-tree-info', and And it is not used anywhere... What is the purpose? > org-export-transcode-headline, extracted from `org-export-as' How does it have anything to do with "headline"? Maybe `org-export-transcode-page'? > - added :multipage case to `org-export-as', calling :process-multipage > callback submitted in info. In the multipage case, org-export-as > returns nil relying on :process-multipage to do the exporting, while > in the single page case it returns the transcoded string to the > caller from the backend. Does it mean that you do not want page splitting to be controlled globally, in ox.el, as we discussed? > - changed `org-export-collect-footnote-definitions' to get its > numbering using `org-export-get-footnote-number' rather than always > counting from 1 as before. This should always work for single-page > and multipage export. This looks reasonable. Maybe even as a separate patch we can merge earlier. > - changed that `org-export-numbered-headline-p' always returns t for > headlines in the multipage case to ensure headline numbering is > collected. > NOTE: The single-page case will be handled like before, but it might > be a better idea to change the behaviour and do it the same way as > in the multipage case: Always collect the headline-numbering and > only decide at the transcoding stage whether the headline should be > numbered in the output. Why? What if one wants headlines to be not numbered? > If the code gets reviewed and accepted I have some questions regarding > final submittal: > > 1. How do I provide the code? Is there a mechanism like issuing a > merge-request or how is it normally done? https://orgmode.org/worg/org-contribute.html#orge044121 You need to clone Org mode repository and modify it on a public branch. Then, just share it. Also, please make sure that you track the latest main branch. Your version of ox.el already diverged from the latest main. > 2. How do I add documentation to the org manual? Edit doc/org-manual.org in the Org repository. > 3. Should there be test functions for the code added and are there > recommendations how to do that? Yes, ideally. See testing/README, testing/lisp/test-ox.el, and testing/lisp/text-ox-html.el files in the Org repo. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 10:24 ` Ihor Radchenko @ 2024-07-23 11:35 ` Orm Finnendahl 2024-07-23 12:52 ` Ihor Radchenko ` (2 more replies) 0 siblings, 3 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 11:35 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Hi, thanks for the quick response! Am Dienstag, den 23. Juli 2024 um 10:24:54 Uhr (+0000) schrieb Ihor Radchenko: > I will first focus on reviewing changes to ox.el. > > > ox.el > > > > - added `org-export-collect-tree-info', and > > And it is not used anywhere... What is the purpose? That was not cleaned up from a previous stage. Removed, thanks! > > > org-export-transcode-headline, extracted from `org-export-as' > > How does it have anything to do with "headline"? Maybe `org-export-transcode-page'? changed. > > > - added :multipage case to `org-export-as', calling :process-multipage > > callback submitted in info. In the multipage case, org-export-as > > returns nil relying on :process-multipage to do the exporting, while > > in the single page case it returns the transcoded string to the > > caller from the backend. > > Does it mean that you do not want page splitting to be controlled > globally, in ox.el, as we discussed? Not for now (I mention that later in the mail when I talk about section-filenames and future generalizations, where this definitely has to be done). In the html multipage export are many peculiarities which don't apply to other backends, so ox.el wouldn't be the place for it, so we will need some callback mechanism anyway. Right now this gets accomplished with a small branch in org-export-as in order to change as little as possible. It'll be easy to change if we find a good way to get this done using a more general approach. But I'm open for suggestions, if you have an idea how to already do it now. > This looks reasonable. Maybe even as a separate patch we can merge > earlier. Sure. > > > - changed that `org-export-numbered-headline-p' always returns t for > > headlines in the multipage case to ensure headline numbering is > > collected. > > > NOTE: The single-page case will be handled like before, but it might > > be a better idea to change the behaviour and do it the same way as > > in the multipage case: Always collect the headline-numbering and > > only decide at the transcoding stage whether the headline should be > > numbered in the output. > > Why? What if one wants headlines to be not numbered? Just set num:nil in the options. As mentioned, I think printing headline numbers should get handled in the transcoding stage of the backend and not before. Multipage export behind the scenes is completely dependant on headline numbering, even if headlines aren't displayed, so the code in ox.el first proceeds, as if headline numbering is turned on and moves the check for headline numbering to the transcoding stage. I didn't change the behaviour in the single-page html situation. Although I think that it might make sense that headline-numbering in general only gets checked at the transcoding stage that would affect all backends, so I didn't change anything. Thanks also for the info regarding how to contribute. It'd be nice if you could gibe me a go in case you approve the proposal. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 11:35 ` Orm Finnendahl @ 2024-07-23 12:52 ` Ihor Radchenko 2024-07-23 14:56 ` Orm Finnendahl [not found] ` <Zp_EhDDxxYRWKFPL@orm-t14s> 2024-07-23 14:13 ` Ihor Radchenko 2024-07-23 14:19 ` Ihor Radchenko 2 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 12:52 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > Thanks also for the info regarding how to contribute. It'd be nice if > you could gibe me a go in case you approve the proposal. May you please elaborate? All you need to do is cloning/forking Org mode repository, making edits there, and sharing the link to your branch. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 12:52 ` Ihor Radchenko @ 2024-07-23 14:56 ` Orm Finnendahl [not found] ` <Zp_EhDDxxYRWKFPL@orm-t14s> 1 sibling, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 14:56 UTC (permalink / raw) To: emacs-orgmode Am Dienstag, den 23. Juli 2024 um 12:52:51 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > Thanks also for the info regarding how to contribute. It'd be nice if > > you could gibe me a go in case you approve the proposal. > > May you please elaborate? Writing documentation and test functions doesn't make a lot of sense if the code doesn't get integrated into an org release and in addition I'd like to start working on the doc after finalizing the design and names, therefore I'm asking (I don't need the documentation for myself and wouldn't write it if it didn't get published ;-) > All you need to do is cloning/forking Org mode repository, making edits > there, and sharing the link to your branch. ok, I will do that. Best, Orm ---------------------------------------------------------------------- Prof. Orm Finnendahl Komposition Hochschule für Musik und Darstellende Kunst Eschersheimer Landstr. 29-39 60322 Frankfurt am Main https://www.youtube.com/watch?v=2rWha1HTfFE&list=PLiGfneJSWmNw6dTUvcTHbTkCYOOTiB_N6 ^ permalink raw reply [flat|nested] 72+ messages in thread
[parent not found: <Zp_EhDDxxYRWKFPL@orm-t14s>]
[parent not found: <874j8g2lvq.fsf@localhost>]
* Re: multipage html output [not found] ` <874j8g2lvq.fsf@localhost> @ 2024-07-23 15:36 ` Orm Finnendahl 0 siblings, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 15:36 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Am Dienstag, den 23. Juli 2024 um 15:01:13 Uhr (+0000) schrieb Ihor Radchenko: > > Multipage export is something I want to see as a part of Org mode. > I thought that you were aiming for upstream from the very beginning. I > never opposed that. Ok, thanks. You're right, I was aiming at that from the very beginning, but it was unclear to me how integration of code is handled in org development and whether my code is considered acceptable or aligns with design guidelines. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 11:35 ` Orm Finnendahl 2024-07-23 12:52 ` Ihor Radchenko @ 2024-07-23 14:13 ` Ihor Radchenko [not found] ` <Zp_b2lL2SzDswa-w@orm-t14s> 2024-07-23 14:19 ` Ihor Radchenko 2 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 14:13 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> > - added :multipage case to `org-export-as', calling :process-multipage >> > callback submitted in info. In the multipage case, org-export-as >> > returns nil relying on :process-multipage to do the exporting, while >> > in the single page case it returns the transcoded string to the >> > caller from the backend. >> >> Does it mean that you do not want page splitting to be controlled >> globally, in ox.el, as we discussed? > > Not for now (I mention that later in the mail when I talk about > section-filenames and future generalizations, where this definitely > has to be done). In the html multipage export are many peculiarities > which don't apply to other backends, so ox.el wouldn't be the place > for it, so we will need some callback mechanism anyway. > > Right now this gets accomplished with a small branch in org-export-as > in order to change as little as possible. It'll be easy to change if > we find a good way to get this done using a more general approach. But > I'm open for suggestions, if you have an idea how to already do it > now. Then, a more natural way to achieve custom document-wide transcoder will be introducing "org-data" transcoder into `org-export-transcoder': (defun org-export-transcoder (blob info) "Return appropriate transcoder for BLOB. INFO is a plist containing export directives." (let ((type (org-element-type blob))) ;; Return contents only for complete parse trees. (if (eq type 'org-data) (lambda (_datum contents _info) contents) ; <=------------------ (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) (and (functionp transcoder) transcoder))))) For now, we have a hard-coded identity CONTENTS -> CONTENTS transcoder when exporting the whole document, followed by applying inner/outer templates. We may instead allow the export backends to introduce "org-data" transcoder as a part of exporter definition. When non-nil, it will be used instead of what you extracted into `org-export-transcode-page'. And `org-export-transcode-page' will be used as the fallback. WDYT? >> > - changed that `org-export-numbered-headline-p' always returns t for >> > headlines in the multipage case to ensure headline numbering is >> > collected. >> >> > NOTE: The single-page case will be handled like before, but it might >> > be a better idea to change the behaviour and do it the same way as >> > in the multipage case: Always collect the headline-numbering and >> > only decide at the transcoding stage whether the headline should be >> > numbered in the output. >> >> Why? What if one wants headlines to be not numbered? > > Just set num:nil in the options. But your code ignores num:nil, does it not? (defun org-export-numbered-headline-p (headline info) "Return a non-nil value if HEADLINE element should be numbered. INFO is a plist used as a communication channel." (unless (org-not-nil (org-export-get-node-property :UNNUMBERED headline t)) (let ((sec-num (or (plist-get info :section-numbers) (plist-get info :multipage))) ; <-- overrides num:nil (level (org-export-get-relative-level headline info))) (if (wholenump sec-num) (<= level sec-num) sec-num)))) -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
[parent not found: <Zp_b2lL2SzDswa-w@orm-t14s>]
* Re: multipage html output [not found] ` <Zp_b2lL2SzDswa-w@orm-t14s> @ 2024-07-23 17:10 ` Ihor Radchenko 2024-07-23 20:35 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 17:10 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode [ Adding the mailing list back to CC ] Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > Let me recapitulate to make sure I understand you completely: > > 1. Replace the call to org-export-transcode-page at the end of > ord-export-as by a call to org-export-data Yes. > 2. If a transcoder for org-data is defined, call that and return nil > from org-export-date. > > Otherwise return the transcoded string. > 3. In case a string is returned, process it as it is done in > org-export-transcode-page (only that the output string will be > supplied in place of the headline and we will find a better name for > org-export-transcode-page as it is called *after* the transcoding. No. If a transcoder for org-data is defined, call it and return whatever it returns. Otherwise, call `org-export-transcode-page' (adjusted to follow transcoder arguments). > 1. org-export-data has to be modified to catch the case of > org-export-transcoder being called on org-data in the > multipage-case (after ;; Element/Object with contents.). This seems > a bit complicated as there is memoization going on in > :exported-data of info further down in org-export-data which > probably should get circumvented in the multipage case (e.g. by > checking the value of results). I do not fully understand the problem you are describing here, but hope that my clarification above resolved it. > 2. The code has to define/provide a transcoding function in the > multipage case but should *not* provide such a function in the > single page case, which means (in the multipage case) to modify the > alist of the backend on-the-fly before calling org-export-as. I propose to allow custom org-data transcoder for single page case as well. If there is no need to have custom transcoder for single page, the custom transcoder can check :multipage property and fall back to calling `org-export-transcode-page' if it is nil. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 17:10 ` Ihor Radchenko @ 2024-07-23 20:35 ` Orm Finnendahl 2024-07-24 10:20 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 20:35 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Am Dienstag, den 23. Juli 2024 um 17:10:17 Uhr (+0000) schrieb Ihor Radchenko: > > 2. If a transcoder for org-data is defined, call that and return nil > > from org-export-date. > > > > Otherwise return the transcoded string. > > > 3. In case a string is returned, process it as it is done in > > org-export-transcode-page (only that the output string will be > > supplied in place of the headline and we will find a better name for > > org-export-transcode-page as it is called *after* the transcoding. > > No. > > If a transcoder for org-data is defined, call it and return whatever it > returns. Otherwise, call `org-export-transcode-page' (adjusted to follow > transcoder arguments). Sorry, this is still quite obscure to me: Why should a transcoder for org-data return anything in the multipage case and who should handle the return value(s)? The transcoder could return a list of strings which can get returned by org-export-as and then handled in the function which called org-export-as. If that's what you mean I can implement it, although I'm admittedly not really convinced, especially as there are hairy details to solve, when we really want to use org-export-data to generate multiple return values: - what should 'results in org-export-data be when calling the transcoding function for multipage? A list of strings returned by the transcoding of the individual pages? Shall each string be memoized? How? How to deal with assigning a file-name to each string, should we rather return a (filename . transcoded-string) alist? To recapitulate: In my code, org-export-as calls process-multipage in the backend. This function: - collects and adds information necessary for org-multipage to do its job, splitting the document into different parts, etc. and - then calls org-export-data on the subtrees and exports each returned string to an individual file. - It finally issues a done string and executes a browser open/visit file or simply exits nil. For me this is rather clean and it seems unnecessary to go through all the hassle of dealing with a multipage transcoder within org-export-data. Anyway, I will try to follow your recommendation once I fully understand what you're up to, although I fear this will open a can of worms... > > > 1. org-export-data has to be modified to catch the case of > > org-export-transcoder being called on org-data in the > > multipage-case (after ;; Element/Object with contents.). This seems > > a bit complicated as there is memoization going on in > > :exported-data of info further down in org-export-data which > > probably should get circumvented in the multipage case (e.g. by > > checking the value of results). > > I do not fully understand the problem you are describing here, but hope > that my clarification above resolved it. > Unfortunately not :-( Sorry that I can't really make sense of your explanations. Somehow we seem to think from quite different perspectives and it is really hard for me to get your point (although it is also fascinating and I'm not willing to give up ;-) > > 2. The code has to define/provide a transcoding function in the > > multipage case but should *not* provide such a function in the > > single page case, which means (in the multipage case) to modify the > > alist of the backend on-the-fly before calling org-export-as. > > I propose to allow custom org-data transcoder for single page case as well. > If there is no need to have custom transcoder for single page, the > custom transcoder can check :multipage property and fall back to > calling `org-export-transcode-page' if it is nil. ok, that much is clear. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 20:35 ` Orm Finnendahl @ 2024-07-24 10:20 ` Ihor Radchenko 2024-07-24 11:24 ` Orm Finnendahl ` (3 more replies) 0 siblings, 4 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-24 10:20 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list [-- Attachment #1: Type: text/plain, Size: 3467 bytes --] Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > To recapitulate: In my code, org-export-as calls process-multipage in > the backend. This function: > > - collects and adds information necessary for org-multipage to do its > job, splitting the document into different parts, etc. and > > - then calls org-export-data on the subtrees and exports each returned > string to an individual file. > > - It finally issues a done string and executes a browser open/visit > file or simply exits nil. Currently, org-export-as does the following: 1. Compute global export attributes, according to the selected export backend 2. Copy original buffer into working copy 3. Process and parse the copy, generating AST 4. Do the actual export You plugged your multipage processing into (4), but what it actually does involves (3), (4), and also a new kind of post-processing. I do not think that it is a good design from the point of view of ox.el. I prefer to reuse or extend the existing mechanisms if at all possible - this makes new features less confusing for users and backend developers. > - collects and adds information necessary for org-multipage to do its > job, splitting the document into different parts, etc. and What you describe here is more or less what :filter-parse-tree filters do - they can rearrange the parse tree before passing it to the transcoders. Why not reusing it for multipage export? > - then calls org-export-data on the subtrees and exports each returned > string to an individual file. And you simply call `org-export-transcode-page' for this, followed by writing the returned string to file. The first part can fit within `org-export-as', but writing to file is going a step beyond, duplicating what `org-export-to-file' does. > - It finally issues a done string and executes a browser open/visit > file or simply exits nil. ... which again steps beyond `org-export-as' scope - post-processing is currently done as a part of `org-export-to-file'/`org-export-to-buffer'. ---- Let me propose the following changes to ox.el: 1. org-data will be transcoded using `org-export-transcode-org-data', which can be overridden by setting org-data transcoders in the individual backends. 2. org-export-as will understand transcoded output to be a list of strings and will transfer INFO plist as text property in the return values 3. org-export-to-file will make use of the text properties to retrieve the file name to write. This way, export backend itself can assign the file names where each exporter string should go. I believe that my changes should allow you to implement multipage export in the following way: 1. You can use :filter-parse-tree in ox-html backend to replace the original (org-data ...) AST with a list of ((org-page ...) (org-page ...) ...) pseudo-elements and populate INFO channel with auxiliary information you now compute in `org-html-process-multipage' 2. You can define org-page transcoder to render individual pages as needed 3. You can assign :output-file text property to the returned org-page strings and use org-export-to-file to generate the multipage output on disk 4. You can handle opening exported files by augmenting POST-PROCESS argument in `org-html-export-to-multipage-html' and calling `org-export-file' instead of `org-export-as'. The tentative patches (against Org mode main branch) implementing my changes are attached. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-ox-Factor-out-org-data-transcoding-into-dedicated-ov.patch --] [-- Type: text/x-patch, Size: 4398 bytes --] From 540c8ef21c26df79cf48f58afb4e88130985e2f7 Mon Sep 17 00:00:00 2001 Message-ID: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> From: Ihor Radchenko <yantar92@posteo.net> Date: Wed, 24 Jul 2024 11:40:57 +0200 Subject: [PATCH 1/3] ox: Factor out org-data transcoding into dedicated overrideable transcoder * lisp/ox.el (org-export-transcode-org-data): New function serving as the default transcoder for org-data export. (org-export-transcoder): Use `org-export-transcode-org-data' when no org-data transcoder is defined. (org-export-as): Rely upon org-data transcoder to do its job. --- lisp/ox.el | 55 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index fbd9bb0df..bdee71082 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -1883,9 +1883,11 @@ (defun org-export-transcoder (blob info) INFO is a plist containing export directives." (let ((type (org-element-type blob))) ;; Return contents only for complete parse trees. - (if (eq type 'org-data) (lambda (_datum contents _info) contents) - (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) - (and (functionp transcoder) transcoder))))) + (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) + (cond + ((functionp transcoder) transcoder) + ;; Use default org-data transcoder unless specified. + ((eq type 'org-data) #'org-export-transcode-org-data))))) (defun org-export--keep-spaces (data info) "Non-nil, when post-blank spaces after removing DATA should be preserved. @@ -3004,31 +3006,34 @@ (defun org-export-as backend info subtreep visible-only ext-plist)) ;; Eventually transcode TREE. Wrap the resulting string into ;; a template. - (let* ((body (org-element-normalize-string - (or (org-export-data (plist-get info :parse-tree) info) - ""))) - (inner-template (cdr (assq 'inner-template - (plist-get info :translate-alist)))) - (full-body (org-export-filter-apply-functions - (plist-get info :filter-body) - (if (not (functionp inner-template)) body - (funcall inner-template body info)) - info)) - (template (cdr (assq 'template - (plist-get info :translate-alist)))) - (output - (if (or (not (functionp template)) body-only) full-body - (funcall template full-body info)))) + (let ((output + (or (org-export-data (plist-get info :parse-tree) info) + ""))) ;; Call citation export finalizer. (when (plist-get info :with-cite-processors) (setq output (org-cite-finalize-export output info))) - ;; Remove all text properties since they cannot be - ;; retrieved from an external process. Finally call - ;; final-output filter and return result. - (org-no-properties - (org-export-filter-apply-functions - (plist-get info :filter-final-output) - output info))))))))) + (let ((filters (plist-get info :filter-final-output))) + ;; Remove all text properties since they cannot be + ;; retrieved from an external process. Finally call + ;; final-output filter and return result. + (org-no-properties + (org-export-filter-apply-functions filters output info)))))))))) + +(defun org-export-transcode-org-data (_ body info) + "Transcode `org-data' node with BODY. Return transcoded string. +INFO is the communication channel plist." + (let* ((inner-template (cdr (assq 'inner-template + (plist-get info :translate-alist)))) + (full-body (org-export-filter-apply-functions + (plist-get info :filter-body) + (if (not (functionp inner-template)) body + (funcall inner-template body info)) + info)) + (template (cdr (assq 'template + (plist-get info :translate-alist)))) + (body-only (memq 'body-only (plist-get info :export-options)))) + (if (or (not (functionp template)) body-only) full-body + (funcall template full-body info)))) (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) "Annotate the INFO plist according to the BACKEND. -- 2.45.2 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: 0002-org-export-as-Allow-the-return-value-to-be-a-list-of.patch --] [-- Type: text/x-patch, Size: 3375 bytes --] From 1b0b331f92abc1ca7e04f71fe7ff60da57c719b8 Mon Sep 17 00:00:00 2001 Message-ID: <1b0b331f92abc1ca7e04f71fe7ff60da57c719b8.1721815865.git.yantar92@posteo.net> In-Reply-To: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> References: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> From: Ihor Radchenko <yantar92@posteo.net> Date: Wed, 24 Jul 2024 11:51:21 +0200 Subject: [PATCH 2/3] org-export-as: Allow the return value to be a list of strings; add INFO * lisp/ox.el (org-export-as): Allow the transcoders to return list of strings and return it. When returning a string, put INFO plist as text property. Do not remove text properties assigned by the transcoders. (org-export-data): Document that list of strings may be returned. --- lisp/ox.el | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index bdee71082..a76b3b353 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -1930,7 +1930,7 @@ (defun org-export-data (data info) The `:filter-parse-tree' filters are not applied. -Return a string." +Return a string or a list of strings." (or (gethash data (plist-get info :exported-data)) ;; Handle broken links according to ;; `org-export-with-broken-links'. @@ -2969,7 +2969,9 @@ (defun org-export-as with external parameters overriding Org default settings, but still inferior to file-local settings. -Return code as a string." +Return code as a string or a list of strings. +The returned strings will have their `org-export-info' property set to +export information channel." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (org-export-barf-if-invalid-backend backend) (org-fold-core-ignore-modifications @@ -3009,15 +3011,25 @@ (defun org-export-as (let ((output (or (org-export-data (plist-get info :parse-tree) info) ""))) + (setq output (ensure-list output)) ;; Call citation export finalizer. (when (plist-get info :with-cite-processors) - (setq output (org-cite-finalize-export output info))) + (setq output + (mapcar + (lambda (o) (org-cite-finalize-export o info)) + output))) (let ((filters (plist-get info :filter-final-output))) - ;; Remove all text properties since they cannot be - ;; retrieved from an external process. Finally call - ;; final-output filter and return result. - (org-no-properties - (org-export-filter-apply-functions filters output info)))))))))) + ;; Call final-output filter and return result. + (setq output + (mapcar + (lambda (o) (org-export-filter-apply-functions filters o info)) + output))) + ;; Apply org-export-info property. + (setq output + (mapcar + (lambda (o) (org-add-props o nil 'org-export-info info)) + output)) + (if (length= output 1) (car output) output)))))))) (defun org-export-transcode-org-data (_ body info) "Transcode `org-data' node with BODY. Return transcoded string. -- 2.45.2 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #4: 0003-org-export-to-file-Derive-file-name-to-write-from-ex.patch --] [-- Type: text/x-patch, Size: 4627 bytes --] From 6fa2efadd229a667fba1b18aecc9d1ead5f284ac Mon Sep 17 00:00:00 2001 Message-ID: <6fa2efadd229a667fba1b18aecc9d1ead5f284ac.1721815865.git.yantar92@posteo.net> In-Reply-To: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> References: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> From: Ihor Radchenko <yantar92@posteo.net> Date: Wed, 24 Jul 2024 12:09:36 +0200 Subject: [PATCH 3/3] org-export-to-file: Derive file name to write from export output * lisp/ox.el (org-export--write-output): New helper function performing writing an export output or a list of outputs to file. It derives the file name from :output-file property in the output string or INFO plist stored in the output string. (org-export-to-file): Handle export output being a list of strings. Use `org-export--write-output'. --- lisp/ox.el | 61 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index a76b3b353..d78c04998 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -6830,6 +6830,31 @@ (defun org-latex-export-as-latex (switch-to-buffer-other-window buffer)) buffer))) +(defun org-export--write-output (output encoding) + "Write OUTPUT to file with ENCODING. +OUTPUT may be a string or a list of strings. +The target file is retrieved from :output-file OUTPUT property or +:output-file property in plist stored in `org-export-info' property of +each string. + +Return the file name or a list of file names." + (if (listp output) (mapcar #'org-export--write-output output) + (let ((file (or + (get-text-property 0 :output-file output) + (plist-get + (get-text-property 0 'org-export-info output) + :output-file)))) + (with-temp-buffer + (insert output) + ;; Ensure final newline. This is what was done + ;; historically, when we used `write-file'. + ;; Note that adding a newline is only safe for + ;; non-binary data. + (unless (bolp) (insert "\n")) + (let ((coding-system-for-write encoding)) + (write-region nil nil file)) + file)))) + ;;;###autoload (defun org-export-to-file (backend file &optional async subtreep visible-only body-only ext-plist @@ -6878,33 +6903,23 @@ (defun org-latex-export-to-latex `(let ((output (org-export-as ',backend ,subtreep ,visible-only ,body-only - ',ext-plist))) - (with-temp-buffer - (insert output) - ;; Ensure final newline. This is what was done - ;; historically, when we used `write-file'. - ;; Note that adding a newline is only safe for - ;; non-binary data. - (unless (bolp) (insert "\n")) - (let ((coding-system-for-write ',encoding)) - (write-region nil nil ,file))) - (or (ignore-errors (funcall ',post-process ,file)) ,file))) + ',ext-plist)) + file) + (setq file (org-export--write-output output ',encoding)) + (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f)))) + (if (listp file) (mapcar post file) (funcall post file))))) (let ((output (org-export-as - backend subtreep visible-only body-only ext-plist))) - (with-temp-buffer - (insert output) - ;; Ensure final newline. This is what was done - ;; historically, when we used `write-file'. - ;; Note that adding a newline is only safe for - ;; non-binary data. - (unless (bolp) (insert "\n")) - (let ((coding-system-for-write encoding)) - (write-region nil nil file))) + backend subtreep visible-only body-only ext-plist)) + file) + (setq file (org-export--write-output output encoding)) (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) (org-kill-new output)) ;; Get proper return value. - (or (and (functionp post-process) (funcall post-process file)) - file)))))) + (let ((post (lambda (f) + (or (and (functionp post-process) + (funcall post-process f)) + f)))) + (if (listp file) (mapcar post file) (funcall post file)))))))) (defun org-export-output-file-name (extension &optional subtreep pub-dir) "Return output file's name according to buffer specifications. -- 2.45.2 [-- Attachment #5: Type: text/plain, Size: 224 bytes --] -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-24 10:20 ` Ihor Radchenko @ 2024-07-24 11:24 ` Orm Finnendahl 2024-07-25 9:49 ` Orm Finnendahl ` (2 subsequent siblings) 3 siblings, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-24 11:24 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi Ihor, thanks a lot for the patches and explanations. Your assessment makes sense and I agree that we should stick to the current design as much as possible. I will go ahead and adapt my ox-html.el code the way you propose and use your patched ox.el for this. It shouldn't take too much effort and I will get back as soon as I have results (or questions ;-). -- Orm Am Mittwoch, den 24. Juli 2024 um 10:20:16 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > To recapitulate: In my code, org-export-as calls process-multipage in > > the backend. This function: > > > > - collects and adds information necessary for org-multipage to do its > > job, splitting the document into different parts, etc. and > > > > - then calls org-export-data on the subtrees and exports each returned > > string to an individual file. > > > > - It finally issues a done string and executes a browser open/visit > > file or simply exits nil. > > Currently, org-export-as does the following: > > 1. Compute global export attributes, according to the selected export backend > 2. Copy original buffer into working copy > 3. Process and parse the copy, generating AST > 4. Do the actual export > > You plugged your multipage processing into (4), but what it actually > does involves (3), (4), and also a new kind of post-processing. > I do not think that it is a good design from the point of view of ox.el. > I prefer to reuse or extend the existing mechanisms if at all possible - > this makes new features less confusing for users and backend developers. > > > - collects and adds information necessary for org-multipage to do its > > job, splitting the document into different parts, etc. and > > What you describe here is more or less what :filter-parse-tree filters > do - they can rearrange the parse tree before passing it to the > transcoders. Why not reusing it for multipage export? > > > - then calls org-export-data on the subtrees and exports each returned > > string to an individual file. > > And you simply call `org-export-transcode-page' for this, followed by > writing the returned string to file. > > The first part can fit within `org-export-as', but writing to file is > going a step beyond, duplicating what `org-export-to-file' does. > > > - It finally issues a done string and executes a browser open/visit > > file or simply exits nil. > > ... which again steps beyond `org-export-as' scope - post-processing is > currently done as a part of `org-export-to-file'/`org-export-to-buffer'. > > ---- > > Let me propose the following changes to ox.el: > > 1. org-data will be transcoded using `org-export-transcode-org-data', > which can be overridden by setting org-data transcoders in the > individual backends. > > 2. org-export-as will understand transcoded output to be a list of > strings and will transfer INFO plist as text property in the return > values > > 3. org-export-to-file will make use of the text properties to retrieve > the file name to write. This way, export backend itself can assign > the file names where each exporter string should go. > > I believe that my changes should allow you to implement multipage export > in the following way: > > 1. You can use :filter-parse-tree in ox-html backend to replace the > original (org-data ...) AST with a list of > ((org-page ...) (org-page ...) ...) pseudo-elements and populate INFO > channel with auxiliary information you now compute in `org-html-process-multipage' > > 2. You can define org-page transcoder to render individual pages as > needed > > 3. You can assign :output-file text property to the returned org-page > strings and use org-export-to-file to generate the multipage output > on disk > > 4. You can handle opening exported files by augmenting POST-PROCESS > argument in `org-html-export-to-multipage-html' and calling > `org-export-file' instead of `org-export-as'. > > The tentative patches (against Org mode main branch) implementing my > changes are attached. > > From 540c8ef21c26df79cf48f58afb4e88130985e2f7 Mon Sep 17 00:00:00 2001 > Message-ID: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> > From: Ihor Radchenko <yantar92@posteo.net> > Date: Wed, 24 Jul 2024 11:40:57 +0200 > Subject: [PATCH 1/3] ox: Factor out org-data transcoding into dedicated > overrideable transcoder > > * lisp/ox.el (org-export-transcode-org-data): New function serving as > the default transcoder for org-data export. > (org-export-transcoder): Use `org-export-transcode-org-data' when no > org-data transcoder is defined. > (org-export-as): Rely upon org-data transcoder to do its job. > --- > lisp/ox.el | 55 +++++++++++++++++++++++++++++------------------------- > 1 file changed, 30 insertions(+), 25 deletions(-) > > diff --git a/lisp/ox.el b/lisp/ox.el > index fbd9bb0df..bdee71082 100644 > --- a/lisp/ox.el > +++ b/lisp/ox.el > @@ -1883,9 +1883,11 @@ (defun org-export-transcoder (blob info) > INFO is a plist containing export directives." > (let ((type (org-element-type blob))) > ;; Return contents only for complete parse trees. > - (if (eq type 'org-data) (lambda (_datum contents _info) contents) > - (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) > - (and (functionp transcoder) transcoder))))) > + (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) > + (cond > + ((functionp transcoder) transcoder) > + ;; Use default org-data transcoder unless specified. > + ((eq type 'org-data) #'org-export-transcode-org-data))))) > > (defun org-export--keep-spaces (data info) > "Non-nil, when post-blank spaces after removing DATA should be preserved. > @@ -3004,31 +3006,34 @@ (defun org-export-as > backend info subtreep visible-only ext-plist)) > ;; Eventually transcode TREE. Wrap the resulting string into > ;; a template. > - (let* ((body (org-element-normalize-string > - (or (org-export-data (plist-get info :parse-tree) info) > - ""))) > - (inner-template (cdr (assq 'inner-template > - (plist-get info :translate-alist)))) > - (full-body (org-export-filter-apply-functions > - (plist-get info :filter-body) > - (if (not (functionp inner-template)) body > - (funcall inner-template body info)) > - info)) > - (template (cdr (assq 'template > - (plist-get info :translate-alist)))) > - (output > - (if (or (not (functionp template)) body-only) full-body > - (funcall template full-body info)))) > + (let ((output > + (or (org-export-data (plist-get info :parse-tree) info) > + ""))) > ;; Call citation export finalizer. > (when (plist-get info :with-cite-processors) > (setq output (org-cite-finalize-export output info))) > - ;; Remove all text properties since they cannot be > - ;; retrieved from an external process. Finally call > - ;; final-output filter and return result. > - (org-no-properties > - (org-export-filter-apply-functions > - (plist-get info :filter-final-output) > - output info))))))))) > + (let ((filters (plist-get info :filter-final-output))) > + ;; Remove all text properties since they cannot be > + ;; retrieved from an external process. Finally call > + ;; final-output filter and return result. > + (org-no-properties > + (org-export-filter-apply-functions filters output info)))))))))) > + > +(defun org-export-transcode-org-data (_ body info) > + "Transcode `org-data' node with BODY. Return transcoded string. > +INFO is the communication channel plist." > + (let* ((inner-template (cdr (assq 'inner-template > + (plist-get info :translate-alist)))) > + (full-body (org-export-filter-apply-functions > + (plist-get info :filter-body) > + (if (not (functionp inner-template)) body > + (funcall inner-template body info)) > + info)) > + (template (cdr (assq 'template > + (plist-get info :translate-alist)))) > + (body-only (memq 'body-only (plist-get info :export-options)))) > + (if (or (not (functionp template)) body-only) full-body > + (funcall template full-body info)))) > > (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) > "Annotate the INFO plist according to the BACKEND. > -- > 2.45.2 > > From 1b0b331f92abc1ca7e04f71fe7ff60da57c719b8 Mon Sep 17 00:00:00 2001 > Message-ID: <1b0b331f92abc1ca7e04f71fe7ff60da57c719b8.1721815865.git.yantar92@posteo.net> > In-Reply-To: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> > References: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> > From: Ihor Radchenko <yantar92@posteo.net> > Date: Wed, 24 Jul 2024 11:51:21 +0200 > Subject: [PATCH 2/3] org-export-as: Allow the return value to be a list of > strings; add INFO > > * lisp/ox.el (org-export-as): Allow the transcoders to return list of > strings and return it. When returning a string, put INFO plist as > text property. Do not remove text properties assigned by the > transcoders. > (org-export-data): Document that list of strings may be returned. > --- > lisp/ox.el | 28 ++++++++++++++++++++-------- > 1 file changed, 20 insertions(+), 8 deletions(-) > > diff --git a/lisp/ox.el b/lisp/ox.el > index bdee71082..a76b3b353 100644 > --- a/lisp/ox.el > +++ b/lisp/ox.el > @@ -1930,7 +1930,7 @@ (defun org-export-data (data info) > > The `:filter-parse-tree' filters are not applied. > > -Return a string." > +Return a string or a list of strings." > (or (gethash data (plist-get info :exported-data)) > ;; Handle broken links according to > ;; `org-export-with-broken-links'. > @@ -2969,7 +2969,9 @@ (defun org-export-as > with external parameters overriding Org default settings, but > still inferior to file-local settings. > > -Return code as a string." > +Return code as a string or a list of strings. > +The returned strings will have their `org-export-info' property set to > +export information channel." > (when (symbolp backend) (setq backend (org-export-get-backend backend))) > (org-export-barf-if-invalid-backend backend) > (org-fold-core-ignore-modifications > @@ -3009,15 +3011,25 @@ (defun org-export-as > (let ((output > (or (org-export-data (plist-get info :parse-tree) info) > ""))) > + (setq output (ensure-list output)) > ;; Call citation export finalizer. > (when (plist-get info :with-cite-processors) > - (setq output (org-cite-finalize-export output info))) > + (setq output > + (mapcar > + (lambda (o) (org-cite-finalize-export o info)) > + output))) > (let ((filters (plist-get info :filter-final-output))) > - ;; Remove all text properties since they cannot be > - ;; retrieved from an external process. Finally call > - ;; final-output filter and return result. > - (org-no-properties > - (org-export-filter-apply-functions filters output info)))))))))) > + ;; Call final-output filter and return result. > + (setq output > + (mapcar > + (lambda (o) (org-export-filter-apply-functions filters o info)) > + output))) > + ;; Apply org-export-info property. > + (setq output > + (mapcar > + (lambda (o) (org-add-props o nil 'org-export-info info)) > + output)) > + (if (length= output 1) (car output) output)))))))) > > (defun org-export-transcode-org-data (_ body info) > "Transcode `org-data' node with BODY. Return transcoded string. > -- > 2.45.2 > > From 6fa2efadd229a667fba1b18aecc9d1ead5f284ac Mon Sep 17 00:00:00 2001 > Message-ID: <6fa2efadd229a667fba1b18aecc9d1ead5f284ac.1721815865.git.yantar92@posteo.net> > In-Reply-To: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> > References: <540c8ef21c26df79cf48f58afb4e88130985e2f7.1721815865.git.yantar92@posteo.net> > From: Ihor Radchenko <yantar92@posteo.net> > Date: Wed, 24 Jul 2024 12:09:36 +0200 > Subject: [PATCH 3/3] org-export-to-file: Derive file name to write from export > output > > * lisp/ox.el (org-export--write-output): New helper function > performing writing an export output or a list of outputs to file. It > derives the file name from :output-file property in the output string > or INFO plist stored in the output string. > (org-export-to-file): Handle export output being a list of strings. > Use `org-export--write-output'. > --- > lisp/ox.el | 61 ++++++++++++++++++++++++++++++++++-------------------- > 1 file changed, 38 insertions(+), 23 deletions(-) > > diff --git a/lisp/ox.el b/lisp/ox.el > index a76b3b353..d78c04998 100644 > --- a/lisp/ox.el > +++ b/lisp/ox.el > @@ -6830,6 +6830,31 @@ (defun org-latex-export-as-latex > (switch-to-buffer-other-window buffer)) > buffer))) > > +(defun org-export--write-output (output encoding) > + "Write OUTPUT to file with ENCODING. > +OUTPUT may be a string or a list of strings. > +The target file is retrieved from :output-file OUTPUT property or > +:output-file property in plist stored in `org-export-info' property of > +each string. > + > +Return the file name or a list of file names." > + (if (listp output) (mapcar #'org-export--write-output output) > + (let ((file (or > + (get-text-property 0 :output-file output) > + (plist-get > + (get-text-property 0 'org-export-info output) > + :output-file)))) > + (with-temp-buffer > + (insert output) > + ;; Ensure final newline. This is what was done > + ;; historically, when we used `write-file'. > + ;; Note that adding a newline is only safe for > + ;; non-binary data. > + (unless (bolp) (insert "\n")) > + (let ((coding-system-for-write encoding)) > + (write-region nil nil file)) > + file)))) > + > ;;;###autoload > (defun org-export-to-file > (backend file &optional async subtreep visible-only body-only ext-plist > @@ -6878,33 +6903,23 @@ (defun org-latex-export-to-latex > `(let ((output > (org-export-as > ',backend ,subtreep ,visible-only ,body-only > - ',ext-plist))) > - (with-temp-buffer > - (insert output) > - ;; Ensure final newline. This is what was done > - ;; historically, when we used `write-file'. > - ;; Note that adding a newline is only safe for > - ;; non-binary data. > - (unless (bolp) (insert "\n")) > - (let ((coding-system-for-write ',encoding)) > - (write-region nil nil ,file))) > - (or (ignore-errors (funcall ',post-process ,file)) ,file))) > + ',ext-plist)) > + file) > + (setq file (org-export--write-output output ',encoding)) > + (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f)))) > + (if (listp file) (mapcar post file) (funcall post file))))) > (let ((output (org-export-as > - backend subtreep visible-only body-only ext-plist))) > - (with-temp-buffer > - (insert output) > - ;; Ensure final newline. This is what was done > - ;; historically, when we used `write-file'. > - ;; Note that adding a newline is only safe for > - ;; non-binary data. > - (unless (bolp) (insert "\n")) > - (let ((coding-system-for-write encoding)) > - (write-region nil nil file))) > + backend subtreep visible-only body-only ext-plist)) > + file) > + (setq file (org-export--write-output output encoding)) > (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) > (org-kill-new output)) > ;; Get proper return value. > - (or (and (functionp post-process) (funcall post-process file)) > - file)))))) > + (let ((post (lambda (f) > + (or (and (functionp post-process) > + (funcall post-process f)) > + f)))) > + (if (listp file) (mapcar post file) (funcall post file)))))))) > > (defun org-export-output-file-name (extension &optional subtreep pub-dir) > "Return output file's name according to buffer specifications. > -- > 2.45.2 > > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-24 10:20 ` Ihor Radchenko 2024-07-24 11:24 ` Orm Finnendahl @ 2024-07-25 9:49 ` Orm Finnendahl 2024-07-25 9:57 ` Ihor Radchenko 2024-07-25 9:57 ` Orm Finnendahl 2024-07-26 8:22 ` Orm Finnendahl 3 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-25 9:49 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi Ihor, I studied your proposal and changes in ox.el. It is pretty clear now and I agree that this is the right way to do it with regards to the architecture of ox. Thanks for putting in your time. Am Mittwoch, den 24. Juli 2024 um 10:20:16 Uhr (+0000) schrieb Ihor Radchenko: > > 1. org-data will be transcoded using `org-export-transcode-org-data', > which can be overridden by setting org-data transcoders in the > individual backends. Just for clarification: In the html backend there would be a definition for an org-data transcoder, which checks for the multipage case and either returns a list of output strings with additional information or just calls `org-export-transcode-org-data' for the single-page case, right? I can't do it today but will try to get it done in the next days. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-25 9:49 ` Orm Finnendahl @ 2024-07-25 9:57 ` Ihor Radchenko 0 siblings, 0 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-25 9:57 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > Am Mittwoch, den 24. Juli 2024 um 10:20:16 Uhr (+0000) schrieb Ihor Radchenko: >> >> 1. org-data will be transcoded using `org-export-transcode-org-data', >> which can be overridden by setting org-data transcoders in the >> individual backends. > > Just for clarification: In the html backend there would be a > definition for an org-data transcoder, which checks for the multipage > case and either returns a list of output strings with additional > information or just calls `org-export-transcode-org-data' for the > single-page case, right? Yes. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-24 10:20 ` Ihor Radchenko 2024-07-24 11:24 ` Orm Finnendahl 2024-07-25 9:49 ` Orm Finnendahl @ 2024-07-25 9:57 ` Orm Finnendahl 2024-07-25 10:04 ` Ihor Radchenko 2024-07-26 8:22 ` Orm Finnendahl 3 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-25 9:57 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi Ihor, another thing: org-export--write-ouput inserts the output string into a temp-buffer before writing it to file. When exporting to multipage I found out that this imposes a pretty significant performance hit. That's why I write the output string directly to file in my own code. Is it sensitive to set an optional argument to circumvent the buffer insert (or circumvent it altogether)? -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-25 9:57 ` Orm Finnendahl @ 2024-07-25 10:04 ` Ihor Radchenko 2024-07-25 14:59 ` Orm Finnendahl 2024-07-27 19:24 ` Orm Finnendahl 0 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-07-25 10:04 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > org-export--write-ouput inserts the output string into a temp-buffer > before writing it to file. When exporting to multipage I found out > that this imposes a pretty significant performance hit. That's why I > write the output string directly to file in my own code. > > Is it sensitive to set an optional argument to circumvent the buffer > insert (or circumvent it altogether)? There is no particular reason why we use temporary buffer to write to file. However, I am surprised that it produces performance hit - `with-temp-buffer' should disable all kinds of hooks, except in distributions like Doom that abuse advices and hook into buffer creation unconditionally. Do you know the source of the performance problem? Are you sure that it is creating the buffer and is not related to the packages you have installed? -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-25 10:04 ` Ihor Radchenko @ 2024-07-25 14:59 ` Orm Finnendahl 2024-07-27 19:24 ` Orm Finnendahl 1 sibling, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-25 14:59 UTC (permalink / raw) To: Org mailing list Hi, Am Donnerstag, den 25. Juli 2024 um 10:04:21 Uhr (+0000) schrieb Ihor Radchenko: > > Do you know the source of the performance problem? When I last checked it was 4.5 Seconds vs 2.2 Seconds and I assume it was due to the gc kicking in, but whatever the reason I checked back and forth between using the temp-buffer and writing directly to file and the difference was consistent. > Are you sure that it is creating the buffer and is not related to > the packages you have installed? I will doublecheck once it is finished. If the difference remains I'll report back. I tweaked some settings after seeing your lecture from last year on EmacsConf and it improved considerably. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-25 10:04 ` Ihor Radchenko 2024-07-25 14:59 ` Orm Finnendahl @ 2024-07-27 19:24 ` Orm Finnendahl 2024-07-27 19:39 ` Ihor Radchenko 1 sibling, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-27 19:24 UTC (permalink / raw) To: Org mailing list Hi, html multipage output is fully working now in the org-export compliant way sketched by Ihor. There is a small issue with org-export-as from ox.el: On my machine applying the :filter-final-output functions to the final output strings delete their :output-file Text Property. Below is a commented somewhat ugly fix just to show what was necessary to make it work. Maybe you have a better idea about how to change it. (let* ((output (or (org-export-data (plist-get info :parse-tree) info) ""))) (setq output (ensure-list output)) ;; we need to capture the :output-file properties as they ;; might get erased in the following filter stages. (let ((output-files (mapcar (lambda (o) (get-text-property 0 :output-file o)) output))) ;; Call citation export finalizer. (when (plist-get info :with-cite-processors) (setq output (mapcar (lambda (o) (org-cite-finalize-export o info)) output))) (let ((filters (plist-get info :filter-final-output))) ;; Call final-output filter and return result. (setq output (mapcar (lambda (o) (org-export-filter-apply-functions filters o info)) output))) ;; Apply org-export-info property and add back the ;; :output-file property. (setq output (cl-mapcar (lambda (o file) (org-add-props o nil :output-file file 'org-export-info info)) output output-files)) (if (length= output 1) (car output) output))) I will now review the code and test thoroughly before issuing merge requests and adding documentation but it looks good :-) -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-27 19:24 ` Orm Finnendahl @ 2024-07-27 19:39 ` Ihor Radchenko 2024-08-05 16:52 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-27 19:39 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > html multipage output is fully working now in the org-export > compliant way sketched by Ihor. Great! > There is a small issue with org-export-as from ox.el: On my machine > applying the :filter-final-output functions to the final output > strings delete their :output-file Text Property. Below is a commented > somewhat ugly fix just to show what was necessary to make it > work. Maybe you have a better idea about how to change it. `org-html-final-function' strips the text properties. You can modify it. Or, better, you can add an additional filter to ox-html that will apply the necessary text properties (to make sure that user filters that do no care about text properties never interfere). -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-27 19:39 ` Ihor Radchenko @ 2024-08-05 16:52 ` Orm Finnendahl 2024-08-05 18:22 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-08-05 16:52 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 1730 bytes --] Hi, attached are the patches for the multipage html export proposal. The tgz file contains all commits after branching from the main branch to the org-html-multipage branch (see: https://github.com/ormf/org-mode/tree/org-html-multipage) There are also diffs for the only changed files, ox.el, ox-html.el and org-manual.org between 2a4fdffac163e91f6ed2055ec34cbcadf8b95dec of the main branch and my last commit to my org-html-multipage branch. Let me know if there are problems or you need anything. I tried to be conformant to Org in general and hope I succeeded. Let me know what you think. -- Orm Am Samstag, den 27. Juli 2024 um 19:39:36 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > html multipage output is fully working now in the org-export > > compliant way sketched by Ihor. > > Great! > > > There is a small issue with org-export-as from ox.el: On my machine > > applying the :filter-final-output functions to the final output > > strings delete their :output-file Text Property. Below is a commented > > somewhat ugly fix just to show what was necessary to make it > > work. Maybe you have a better idea about how to change it. > > `org-html-final-function' strips the text properties. You can modify > it. Or, better, you can add an additional filter to ox-html that will > apply the necessary text properties (to make sure that user filters that > do no care about text properties never interfere). > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> > [-- Attachment #2: ox-html-multipage-patches.tgz --] [-- Type: application/gzip, Size: 51795 bytes --] [-- Attachment #3: ox.el.patch --] [-- Type: text/plain, Size: 17371 bytes --] *** org-mode/lisp/ox.el 2024-08-05 17:15:57.631928954 +0200 --- org-mode-multipage/lisp/ox.el 2024-08-03 12:57:24.346459632 +0200 *************** *** 215,220 **** --- 215,221 ---- (:filter-latex-fragment . org-export-filter-latex-fragment-functions) (:filter-line-break . org-export-filter-line-break-functions) (:filter-link . org-export-filter-link-functions) + (:multipage-split . org-export-multipage-split-functions) (:filter-node-property . org-export-filter-node-property-functions) (:filter-options . org-export-filter-options-functions) (:filter-paragraph . org-export-filter-paragraph-functions) *************** *** 1883,1891 **** INFO is a plist containing export directives." (let ((type (org-element-type blob))) ;; Return contents only for complete parse trees. ! (if (eq type 'org-data) (lambda (_datum contents _info) contents) ! (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) ! (and (functionp transcoder) transcoder))))) (defun org-export--keep-spaces (data info) "Non-nil, when post-blank spaces after removing DATA should be preserved. --- 1884,1894 ---- INFO is a plist containing export directives." (let ((type (org-element-type blob))) ;; Return contents only for complete parse trees. ! (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) ! (cond ! ((functionp transcoder) transcoder) ! ;; Use default org-data transcoder unless specified. ! ((eq type 'org-data) #'org-export-transcode-org-data))))) (defun org-export--keep-spaces (data info) "Non-nil, when post-blank spaces after removing DATA should be preserved. *************** *** 1928,1934 **** The `:filter-parse-tree' filters are not applied. ! Return a string." (or (gethash data (plist-get info :exported-data)) ;; Handle broken links according to ;; `org-export-with-broken-links'. --- 1931,1937 ---- The `:filter-parse-tree' filters are not applied. ! Return a string or a list of strings." (or (gethash data (plist-get info :exported-data)) ;; Handle broken links according to ;; `org-export-with-broken-links'. *************** *** 2194,2199 **** --- 2197,2205 ---- as a plist. It must return a string that will be used as the final export output.") + (defvar org-export-multipage-split-functions nil + "List of functions applied when multipage output has to be split.") + ;;;; Elements Filters *************** *** 2537,2542 **** --- 2543,2549 ---- (let (plist) ;; Install user-defined filters with `org-export-filters-alist' ;; and filters already in INFO (through ext-plist mechanism). + (setq tmp-info info) (dolist (p org-export-filters-alist) (let* ((prop (car p)) (info-value (plist-get info prop)) *************** *** 2548,2553 **** --- 2555,2561 ---- (append (if (listp info-value) info-value (list info-value)) default-value))))) + (setq global-prop org-export-filters-alist) ;; Prepend backend specific filters to that list. (dolist (p (org-export-get-all-filters (plist-get info :back-end))) ;; Single values get consed, lists are appended. *************** *** 2967,2973 **** with external parameters overriding Org default settings, but still inferior to file-local settings. ! Return code as a string." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (org-export-barf-if-invalid-backend backend) (org-fold-core-ignore-modifications --- 2975,2983 ---- with external parameters overriding Org default settings, but still inferior to file-local settings. ! Return code as a string or a list of strings. ! The returned strings will have their `org-export-info' property set to ! export information channel." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (org-export-barf-if-invalid-backend backend) (org-fold-core-ignore-modifications *************** *** 3004,3034 **** backend info subtreep visible-only ext-plist)) ;; Eventually transcode TREE. Wrap the resulting string into ;; a template. ! (let* ((body (org-element-normalize-string ! (or (org-export-data (plist-get info :parse-tree) info) ! ""))) ! (inner-template (cdr (assq 'inner-template ! (plist-get info :translate-alist)))) ! (full-body (org-export-filter-apply-functions ! (plist-get info :filter-body) ! (if (not (functionp inner-template)) body ! (funcall inner-template body info)) ! info)) ! (template (cdr (assq 'template ! (plist-get info :translate-alist)))) ! (output ! (if (or (not (functionp template)) body-only) full-body ! (funcall template full-body info)))) ;; Call citation export finalizer. (when (plist-get info :with-cite-processors) ! (setq output (org-cite-finalize-export output info))) ! ;; Remove all text properties since they cannot be ! ;; retrieved from an external process. Finally call ! ;; final-output filter and return result. ! (org-no-properties ! (org-export-filter-apply-functions ! (plist-get info :filter-final-output) ! output info))))))))) (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) "Annotate the INFO plist according to the BACKEND. --- 3014,3059 ---- backend info subtreep visible-only ext-plist)) ;; Eventually transcode TREE. Wrap the resulting string into ;; a template. ! (let ((output ! (or (org-export-data (plist-get info :parse-tree) info) ! ""))) ! (setq output (ensure-list output)) ;; Call citation export finalizer. (when (plist-get info :with-cite-processors) ! (setq output ! (mapcar ! (lambda (o) (org-cite-finalize-export o info)) ! output))) ! (let ((filters (plist-get info :filter-final-output))) ! ;; Call final-output filter and return result. ! (setq output ! (mapcar ! (lambda (o) (org-export-filter-apply-functions filters o info)) ! output))) ! ;; Apply org-export-info property. ! (setq output ! (mapcar ! (lambda (o) (org-add-props o nil ! :output-file (get-text-property 0 :output-file o) ! 'org-export-info info)) ! output)) ! (if (length= output 1) (car output) output)))))))) ! ! (defun org-export-transcode-org-data (_ body info) ! "Transcode `org-data' node with BODY. Return transcoded string. ! INFO is the communication channel plist." ! (let* ((inner-template (cdr (assq 'inner-template ! (plist-get info :translate-alist)))) ! (full-body (org-export-filter-apply-functions ! (plist-get info :filter-body) ! (if (not (functionp inner-template)) body ! (funcall inner-template body info)) ! info)) ! (template (cdr (assq 'template ! (plist-get info :translate-alist)))) ! (body-only (memq 'body-only (plist-get info :export-options)))) ! (if (or (not (functionp template)) body-only) full-body ! (funcall template full-body info)))) (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) "Annotate the INFO plist according to the BACKEND. *************** *** 3107,3120 **** (_ nil))) ;; Install user's and developer's filters. (setq info (org-export-install-filters info)) ;; Call options filters and update export options. We do not ;; use `org-export-filter-apply-functions' here since the ;; arity of such filters is different. (let ((backend-name (org-export-backend-name backend))) (dolist (filter (plist-get info :filter-options)) ! (let ((result (funcall filter info backend-name))) ! (when result (setq info result))))) ;; Parse buffer. (setq tree (org-element-parse-buffer nil visible-only 'defer)) ;; Prune tree from non-exported elements and transform ;; uninterpreted elements or objects in both parse tree and --- 3132,3147 ---- (_ nil))) ;; Install user's and developer's filters. (setq info (org-export-install-filters info)) + ;; Call options filters and update export options. We do not ;; use `org-export-filter-apply-functions' here since the ;; arity of such filters is different. (let ((backend-name (org-export-backend-name backend))) (dolist (filter (plist-get info :filter-options)) ! (let ((result (funcall filter info backend-name))) ! (when result (setq info result))))) ;; Parse buffer. + (setq tree (org-element-parse-buffer nil visible-only 'defer)) ;; Prune tree from non-exported elements and transform ;; uninterpreted elements or objects in both parse tree and *************** *** 3131,3136 **** --- 3158,3166 ---- ;; to communication channel. This is responsible for setting ;; :parse-tree to TREE. (setq info (org-export--collect-tree-properties tree info)) + (when (plist-get info :multipage) + (setq tree (org-export-filter-apply-functions + (plist-get info :multipage-split) tree info))) ;; Process citations and bibliography. Replace each citation ;; and "print_bibliography" keyword in the parse tree with ;; the output of the selected citation export processor. *************** *** 6140,6145 **** --- 6170,6195 ---- ("uk" :html "Автор" :utf-8 "Автор") ("zh-CN" :html "作者" :utf-8 "作者") ("zh-TW" :html "作者" :utf-8 "作者")) + ("Chapter %s" + ("ar" :default "الفصل %s") + ("cs" :default "kapitola %s") + ("da" :default "kapitel %s") + ("de" :default "Kapitel %s") + ("es" :ascii "capitulo %s" :html "capítulo %s" :default "capítulo %s") + ("et" :html "peatükk %s" :utf-8 "peatükk %s") + ("fa" :default "فصل %s") + ("fr" :default "chapitre %s") + ("it" :default "capitolo %s") + ("ja" :default "章 %s") + ("nl" :default "hoofdstuk %s" + :html "hoofdstuk %s" :latex "hoofdstuk~%s") + ("pt_BR" :ascii "capitulo %s" :html "capítulo %s" :default "capítulo %s") + ("ro" :default "capitol %s") + ("ru" :html "глава %s" + :utf-8 "глава %s") + ("sl" :default "odsek %s") + ("tr" :html "bölüm" :default "bölüm %s") + ("zh-CN" :html "章节" :utf-8 "章节 %s")) ("Continued from previous page" ("ar" :default "تتمة الصفحة السابقة") ("cs" :default "Pokračování z předchozí strany") *************** *** 6269,6274 **** --- 6319,6326 ---- ("sv" :default "Illustration") ("tr" :default "Şekil") ("zh-CN" :html "图" :utf-8 "图")) + ("Fig. %s" + ("de" :default "Abb. %s")) ("Figure %d:" ("ar" :default "شكل %d:") ("cs" :default "Obrázek %d:") *************** *** 6436,6441 **** --- 6488,6515 ---- ("sl" :default "Reference") ("sv" :default "Referenser") ("tr" :default "Referanslar")) + ("Section %s" + ("ar" :default "انظر قسم %s") + ("cs" :default "sekce %s") + ("da" :default "afsnit %s") + ("de" :default "Abschnitt %s") + ("es" :ascii "seccion %s" :html "sección %s" :default "sección %s") + ("et" :html "peatükki %s" :utf-8 "peatükki %s") + ;; ("fa" :default "نمایش بخش %s") + ("fr" :default "section %s") + ("it" :default "sezione %s") + ;; ("ja" :default "セクション %s を参照") + ("nl" :default "sectie %s" + :html "sectie %s" :latex "sectie~%s") + ("pt_BR" :html "seção %s" :default "seção %s" + :ascii "secao %s") + ("ro" :default "secțiunea %s") + ("ru" :html "&раздел %s" + :utf-8 "раздел %s") + ("sl" :default "poglavje %d") + ("tr" :default "bölüm %s") + ;; ("zh-CN" :html "参见第%s节" :utf-8 "参见第%s节") + ) ("See figure %s" ("cs" :default "Viz obrázek %s") ("et" :default "Vaata joonist %s") *************** *** 6813,6818 **** --- 6887,6918 ---- (switch-to-buffer-other-window buffer)) buffer))) + (defun org-export--write-output (output encoding) + "Write OUTPUT to file with ENCODING. + OUTPUT may be a string or a list of strings. + The target file is retrieved from :output-file OUTPUT property or + :output-file property in plist stored in `org-export-info' property of + each string. + + Return the file name or a list of file names." + (if (listp output) (mapcar #'org-export--write-output output) + (setq tmp-debug output) + (let ((file (or + (get-text-property 0 :output-file output) + (plist-get + (get-text-property 0 'org-export-info output) + :output-file)))) + (with-temp-buffer + (insert output) + ;; Ensure final newline. This is what was done + ;; historically, when we used `write-file'. + ;; Note that adding a newline is only safe for + ;; non-binary data. + (unless (bolp) (insert "\n")) + (let ((coding-system-for-write encoding)) + (write-region nil nil file)) + file)))) + ;;;###autoload (defun org-export-to-file (backend file &optional async subtreep visible-only body-only ext-plist *************** *** 6861,6893 **** `(let ((output (org-export-as ',backend ,subtreep ,visible-only ,body-only ! ',ext-plist))) ! (with-temp-buffer ! (insert output) ! ;; Ensure final newline. This is what was done ! ;; historically, when we used `write-file'. ! ;; Note that adding a newline is only safe for ! ;; non-binary data. ! (unless (bolp) (insert "\n")) ! (let ((coding-system-for-write ',encoding)) ! (write-region nil nil ,file))) ! (or (ignore-errors (funcall ',post-process ,file)) ,file))) (let ((output (org-export-as ! backend subtreep visible-only body-only ext-plist))) ! (with-temp-buffer ! (insert output) ! ;; Ensure final newline. This is what was done ! ;; historically, when we used `write-file'. ! ;; Note that adding a newline is only safe for ! ;; non-binary data. ! (unless (bolp) (insert "\n")) ! (let ((coding-system-for-write encoding)) ! (write-region nil nil file))) (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) (org-kill-new output)) ;; Get proper return value. ! (or (and (functionp post-process) (funcall post-process file)) ! file)))))) (defun org-export-output-file-name (extension &optional subtreep pub-dir) "Return output file's name according to buffer specifications. --- 6961,6983 ---- `(let ((output (org-export-as ',backend ,subtreep ,visible-only ,body-only ! ',ext-plist)) ! file) ! (setq file (org-export--write-output output ',encoding)) ! (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f)))) ! (if (listp file) (mapcar post file) (funcall post file))))) (let ((output (org-export-as ! backend subtreep visible-only body-only ext-plist)) ! file) ! (setq file (org-export--write-output output encoding)) (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) (org-kill-new output)) ;; Get proper return value. ! (let ((post (lambda (f) ! (or (and (functionp post-process) ! (funcall post-process f)) ! f)))) ! (if (listp file) (mapcar post file) (funcall post file)))))))) (defun org-export-output-file-name (extension &optional subtreep pub-dir) "Return output file's name according to buffer specifications. [-- Attachment #4: ox-html.el.patch --] [-- Type: text/plain, Size: 85342 bytes --] *** org-mode/lisp/ox-html.el 2024-08-05 17:15:57.628595589 +0200 --- org-mode-multipage/lisp/ox-html.el 2024-08-05 17:11:54.979585435 +0200 *************** *** 4,9 **** --- 4,11 ---- ;; Author: Carsten Dominik <carsten.dominik@gmail.com> ;; Jambunathan K <kjambunathan at gmail dot com> + ;; multipage export by Orm Finnendahl + ;; <orm dot finnendahl at selma dot hfmdk-frankfurt dot de> ;; Maintainer: TEC <orgmode@tec.tecosaur.net> ;; Keywords: outlines, hypermedia, calendar, text *************** *** 82,88 **** --- 84,94 ---- (latex-fragment . org-html-latex-fragment) (line-break . org-html-line-break) (link . org-html-link) + (multipage-inner-template . org-html-multipage-inner-template) + (multipage-template . org-html-multipage-template) (node-property . org-html-node-property) + (org-data . org-html-transcode-org-data) + ;;; (org-page . org-html-transcode-org-page) (paragraph . org-html-paragraph) (plain-list . org-html-plain-list) (plain-text . org-html-plain-text) *************** *** 108,118 **** --- 114,126 ---- (verse-block . org-html-verse-block)) :filters-alist '((:filter-options . org-html-infojs-install-script) (:filter-parse-tree . org-html-image-link-filter) + (:multipage-split . org-html-multipage-split) (:filter-final-output . org-html-final-function)) :menu-entry '(?h "Export to HTML" ((?H "As HTML buffer" org-html-export-as-html) (?h "As HTML file" org-html-export-to-html) + (?m "As HTML Multipage files" org-html-export-to-multipage) (?o "As HTML file and open" (lambda (a s v b) (if a (org-html-export-to-html t s v b) *************** *** 134,141 **** (:html-head "HTML_HEAD" nil org-html-head newline) (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) (:subtitle "SUBTITLE" nil nil parse) ! (:html-head-include-default-style ! nil "html-style" org-html-head-include-default-style) (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts) (:html-allow-name-attribute-in-anchors nil nil org-html-allow-name-attribute-in-anchors) --- 142,148 ---- (:html-head "HTML_HEAD" nil org-html-head newline) (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) (:subtitle "SUBTITLE" nil nil parse) ! (:html-head-include-default-style nil "html-style" org-html-head-include-default-style) (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts) (:html-allow-name-attribute-in-anchors nil nil org-html-allow-name-attribute-in-anchors) *************** *** 158,163 **** --- 165,190 ---- (:html-mathjax-options nil nil org-html-mathjax-options) (:html-mathjax-template nil nil org-html-mathjax-template) (:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format) + (:html-multipage-clear-export-directory nil "html-multipage-clear-export-directory" + org-html-multipage-clear-export-directory) + (:html-multipage-export-directory + nil "html-multipage-export-directory" org-html-multipage-export-directory) + (:html-multipage-head-include-default-style + nil "html-multipage-include-default-style" org-html-multipage-head-include-default-style) + (:html-multipage-join-empty-bodies + nil "html-multipage-join-empty-bodies" org-html-multipage-join-empty-bodies) + (:html-multipage-nav-format nil nil org-html-multipage-nav-format) + (:html-multipage-numbered-filenames nil "html-multipage-numbered-filenames" + org-html-multipage-numbered-filenames) + (:html-multipage-open nil "html-multipage-open" org-html-multipage-open) + (:html-multipage-postamble-position + nil "html-multipage-postamble-position" org-html-multipage-postamble-position) + (:html-multipage-preamble-position + nil "html-multipage-preamble-position" org-html-multipage-preamble-position) + (:html-multipage-split-hooks nil nil org-html-multipage-split-hooks) + (:html-multipage-split-level nil "html-multipage-split-level" org-html-multipage-split-level) + (:html-multipage-toc-to-top nil "html-multipage-toc-to-top" org-html-multipage-toc-to-top) + (:html-numbered-link-format nil nil org-html-numbered-link-format) (:html-postamble-format nil nil org-html-postamble-format) (:html-preamble-format nil nil org-html-preamble-format) (:html-prefer-user-labels nil nil org-html-prefer-user-labels) *************** *** 171,179 **** nil nil org-html-table-use-header-tags-for-first-column) (:html-tag-class-prefix nil nil org-html-tag-class-prefix) (:html-text-markup-alist nil nil org-html-text-markup-alist) (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix) (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel) ! (:html-use-infojs nil nil org-html-use-infojs) (:html-validation-link nil nil org-html-validation-link) (:html-viewport nil nil org-html-viewport) (:html-inline-images nil nil org-html-inline-images) --- 198,207 ---- nil nil org-html-table-use-header-tags-for-first-column) (:html-tag-class-prefix nil nil org-html-tag-class-prefix) (:html-text-markup-alist nil nil org-html-text-markup-alist) + (:html-toc-title nil "html-toc-title" org-html-toc-title) (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix) (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel) ! (:html-use-infojs nil nil org-export-html-use-infojs) (:html-validation-link nil nil org-html-validation-link) (:html-viewport nil nil org-html-viewport) (:html-inline-images nil nil org-html-inline-images) *************** *** 186,191 **** --- 214,221 ---- (:html-klipse-css nil nil org-html-klipse-css) (:html-klipse-js nil nil org-html-klipse-js) (:html-klipse-selection-script nil nil org-html-klipse-selection-script) + ;;; (:multipage-split nil nil org-html-multipage-split) + ;;; (:multipage nil nil org-html-multipage) (:infojs-opt "INFOJS_OPT" nil nil) ;; Redefine regular options. (:creator "CREATOR" nil org-html-creator-string) *************** *** 462,467 **** --- 492,720 ---- :package-version '(Org . "9.5") :type 'string) + (defcustom org-html-multipage-style-default + "<style type=\"text/css\"> + #content { margin: auto; + display: grid; + position: absolute; + padding-top: 1em; + grid-template-rows: 4em 1fr; + grid-template-columns: 27em 1fr; + grid-template-areas: \"toc title\" + \"toc content\"; + } + + header { + grid-area: title; + } + + #table-of-contents { + grid-area: toc; + height: 100%; + } + + #page-main-body { + grid-area: content; + height: 100%; + overflow: auto; + padding: 4em; + } + + #page-text-body { + height: 100%; + width: 100%; + overflow: auto; + } + + .title { text-align: center; + margin-bottom: .2em; } + .subtitle { text-align: center; + font-size: medium; + font-weight: bold; + margin-top:0; } + .todo { font-family: monospace; color: red; } + .done { font-family: monospace; color: green; } + .priority { font-family: monospace; color: orange; } + .tag { background-color: #eee; font-family: monospace; + padding: 2px; font-size: 80%; font-weight: normal; } + .timestamp { color: #bebebe; } + .timestamp-kwd { color: #5f9ea0; } + .org-right { margin-left: auto; margin-right: 0px; text-align: right; } + .org-left { margin-left: 0px; margin-right: auto; text-align: left; } + .org-center { margin-left: auto; margin-right: auto; text-align: center; } + .underline { text-decoration: underline; } + #postamble p, #preamble p { font-size: 90%; margin: .2em; } + p.verse { margin-left: 3%; } + pre { + border: 1px solid #e6e6e6; + border-radius: 3px; + background-color: #f2f2f2; + padding: 8pt; + font-family: monospace; + overflow: auto; + margin: 1.2em; + } + pre.src { + position: relative; + overflow: auto; + } + pre.src:before { + display: none; + position: absolute; + top: -8px; + right: 12px; + padding: 3px; + color: #555; + background-color: #f2f2f299; + } + pre.src:hover:before { display: inline; margin-top: 14px;} + /* Languages per Org manual */ + pre.src-asymptote:before { content: 'Asymptote'; } + pre.src-awk:before { content: 'Awk'; } + pre.src-authinfo::before { content: 'Authinfo'; } + pre.src-C:before { content: 'C'; } + /* pre.src-C++ doesn't work in CSS */ + pre.src-clojure:before { content: 'Clojure'; } + pre.src-css:before { content: 'CSS'; } + pre.src-D:before { content: 'D'; } + pre.src-ditaa:before { content: 'ditaa'; } + pre.src-dot:before { content: 'Graphviz'; } + pre.src-calc:before { content: 'Emacs Calc'; } + pre.src-emacs-lisp:before { content: 'Emacs Lisp'; } + pre.src-fortran:before { content: 'Fortran'; } + pre.src-gnuplot:before { content: 'gnuplot'; } + pre.src-haskell:before { content: 'Haskell'; } + pre.src-hledger:before { content: 'hledger'; } + pre.src-java:before { content: 'Java'; } + pre.src-js:before { content: 'Javascript'; } + pre.src-latex:before { content: 'LaTeX'; } + pre.src-ledger:before { content: 'Ledger'; } + pre.src-lisp:before { content: 'Lisp'; } + pre.src-lilypond:before { content: 'Lilypond'; } + pre.src-lua:before { content: 'Lua'; } + pre.src-matlab:before { content: 'MATLAB'; } + pre.src-mscgen:before { content: 'Mscgen'; } + pre.src-ocaml:before { content: 'Objective Caml'; } + pre.src-octave:before { content: 'Octave'; } + pre.src-org:before { content: 'Org mode'; } + pre.src-oz:before { content: 'OZ'; } + pre.src-plantuml:before { content: 'Plantuml'; } + pre.src-processing:before { content: 'Processing.js'; } + pre.src-python:before { content: 'Python'; } + pre.src-R:before { content: 'R'; } + pre.src-ruby:before { content: 'Ruby'; } + pre.src-sass:before { content: 'Sass'; } + pre.src-scheme:before { content: 'Scheme'; } + pre.src-screen:before { content: 'Gnu Screen'; } + pre.src-sed:before { content: 'Sed'; } + pre.src-sh:before { content: 'shell'; } + pre.src-sql:before { content: 'SQL'; } + pre.src-sqlite:before { content: 'SQLite'; } + /* additional languages in org.el's org-babel-load-languages alist */ + pre.src-forth:before { content: 'Forth'; } + pre.src-io:before { content: 'IO'; } + pre.src-J:before { content: 'J'; } + pre.src-makefile:before { content: 'Makefile'; } + pre.src-maxima:before { content: 'Maxima'; } + pre.src-perl:before { content: 'Perl'; } + pre.src-picolisp:before { content: 'Pico Lisp'; } + pre.src-scala:before { content: 'Scala'; } + pre.src-shell:before { content: 'Shell Script'; } + pre.src-ebnf2ps:before { content: 'ebfn2ps'; } + /* additional language identifiers per \"defun org-babel-execute\" + in ob-*.el */ + pre.src-cpp:before { content: 'C++'; } + pre.src-abc:before { content: 'ABC'; } + pre.src-coq:before { content: 'Coq'; } + pre.src-groovy:before { content: 'Groovy'; } + /* additional language identifiers from org-babel-shell-names in + ob-shell.el: ob-shell is the only babel language using a lambda to put + the execution function name together. */ + pre.src-bash:before { content: 'bash'; } + pre.src-csh:before { content: 'csh'; } + pre.src-ash:before { content: 'ash'; } + pre.src-dash:before { content: 'dash'; } + pre.src-ksh:before { content: 'ksh'; } + pre.src-mksh:before { content: 'mksh'; } + pre.src-posh:before { content: 'posh'; } + /* Additional Emacs modes also supported by the LaTeX listings package */ + pre.src-ada:before { content: 'Ada'; } + pre.src-asm:before { content: 'Assembler'; } + pre.src-caml:before { content: 'Caml'; } + pre.src-delphi:before { content: 'Delphi'; } + pre.src-html:before { content: 'HTML'; } + pre.src-idl:before { content: 'IDL'; } + pre.src-mercury:before { content: 'Mercury'; } + pre.src-metapost:before { content: 'MetaPost'; } + pre.src-modula-2:before { content: 'Modula-2'; } + pre.src-pascal:before { content: 'Pascal'; } + pre.src-ps:before { content: 'PostScript'; } + pre.src-prolog:before { content: 'Prolog'; } + pre.src-simula:before { content: 'Simula'; } + pre.src-tcl:before { content: 'tcl'; } + pre.src-tex:before { content: 'TeX'; } + pre.src-plain-tex:before { content: 'Plain TeX'; } + pre.src-verilog:before { content: 'Verilog'; } + pre.src-vhdl:before { content: 'VHDL'; } + pre.src-xml:before { content: 'XML'; } + pre.src-nxml:before { content: 'XML'; } + /* add a generic configuration mode; LaTeX export needs an additional + (add-to-list 'org-latex-listings-langs '(conf \" \")) in .emacs */ + pre.src-conf:before { content: 'Configuration File'; } + + table { border-collapse:collapse; } + caption.t-above { caption-side: top; } + caption.t-bottom { caption-side: bottom; } + td, th { vertical-align:top; } + th.org-right { text-align: center; } + th.org-left { text-align: center; } + th.org-center { text-align: center; } + td.org-right { text-align: right; } + td.org-left { text-align: left; } + td.org-center { text-align: center; } + dt { font-weight: bold; } + .footpara { display: inline; } + .footdef { margin-bottom: 1em; } + .figure { padding: 1em; } + .figure p { text-align: center; } + .equation-container { + display: table; + text-align: center; + width: 100%; + } + .equation { + vertical-align: middle; + } + .equation-label { + display: table-cell; + text-align: right; + vertical-align: middle; + } + .inlinetask { + padding: 10px; + border: 2px solid gray; + margin: 10px; + background: #ffffcc; + } + #org-div-home-and-up + { text-align: right; font-size: 70%; white-space: nowrap; } + textarea { overflow-x: auto; } + .linenr { font-size: smaller } + .code-highlighted { background-color: #ffff00; } + .org-info-js_info-navigation { border-style: none; } + #org-info-js_console-label + { font-size: 10px; font-weight: bold; white-space: nowrap; } + .org-info-js_search-highlight + { background-color: #ffff00; color: #000000; font-weight: bold; } + .org-svg { } + </style>" + "The default style specification for exported HTML files. + You can use `org-html-head' and `org-html-head-extra' to add to + this style. If you don't want to include this default style, + customize `org-html-head-include-default-style'." + :group 'org-export-html + :package-version '(Org . "9.8") + :type 'string) \f ;;; User Configuration Variables *************** *** 486,492 **** (home LINK_HOME :html-link-home)) "JavaScript options, long form for script, default values.") ! (defcustom org-html-use-infojs 'when-configured "Non-nil when Sebastian Rose's Java Script org-info.js should be active. This option can be nil or t to never or always use the script. It can also be the symbol `when-configured', meaning that the --- 739,745 ---- (home LINK_HOME :html-link-home)) "JavaScript options, long form for script, default values.") ! (defcustom org-export-html-use-infojs 'when-configured "Non-nil when Sebastian Rose's Java Script org-info.js should be active. This option can be nil or t to never or always use the script. It can also be the symbol `when-configured', meaning that the *************** *** 501,506 **** --- 754,766 ---- (const :tag "When configured in buffer" when-configured) (const :tag "Always" t))) + ;; (defcustom org-html-multipage nil + ;; "Boolean indicating multipage export." + ;; :group 'org-export-html + ;; :version "29.4" + ;; :package-version '(Org . "9.8") + ;; :type 'boolean) + (defcustom org-html-infojs-options (mapcar (lambda (x) (cons (car x) (nth 2 x))) org-html-infojs-opts-table) "Options settings for the INFOJS JavaScript. *************** *** 849,854 **** --- 1109,1129 ---- :group 'org-export-html :type 'boolean) + (defcustom org-html-numbered-link-format + '("Chapter %s" + "Section %s" + "Fig. %s") + "Format for the labels of numbered links. + + The first string is used for links to Chapters, the second for + links to Sections and the third for links to Figures. %s will be + replaced by the number of the reference. The strings get + translated using org-html--translate." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + ;;;; Links :: Inline images (defcustom org-html-inline-images t *************** *** 1384,1389 **** --- 1659,1673 ---- (list (string :tag "Language") (string :tag "Format string")))) + (defcustom org-html-toc-title "Table of Contents" + "The string tp be used for the title of the table of contents. It + will be passed to org-html-translate." + :group 'org-export-html + :package-version '(Org . "9.8") + :version "29.4" + :type 'string + :safe #'stringp) + (defcustom org-html-validation-link "<a href=\"https://validator.w3.org/check?uri=referer\">Validate</a>" "Link to HTML validation service." *************** *** 1522,1529 **** --- 1806,1954 ---- :version "24.4" :package-version '(Org . "8.0") :type 'boolean) + + (defcustom org-html-multipage-clear-export-directory t + "Boolean. If non-nil remove all .html files from the export + directory before exporting." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-export-directory "html" + "The default directory for exported HTML files." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'string) + + (defcustom org-html-multipage-head-include-default-style t + "Non-nil means include the default style in exported HTML files. + The actual style is defined in `org-html-style-default' and + should not be modified. Use `org-html-head' to use your own + style information." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-join-empty-bodies t + "Recursively join subheadlines, if a headline doesn't contain any + text before its Subheadline. + + Example: + + * Headline 1 + ** Subheadline 1.1 + *** Subsubheadline 1.1.1 + Text of Subsubheadline 1.1.1 + + will be put on the same HTML page if this option is set, + otherwise Headline 1 And Subheadline 1.1 will be put on a + separate HTML page with empty content. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-nav-format + '("<div id=\"org-div-nav-menu\">%s</div>" + "Next: <a accesskey=\"n\" href=\"%s\"> %s </a>, " + "Previous: <a accesskey=\"p\" href=\"%s\"> %s </a>, " + "Up: <a accesskey=\"u\" href=\"%s\"> %s </a>, " + "Home: <a accesskey=\"h\" href=\"%s\"> %s </a>") + "Snippets used to insert the NEXT, PREV, HOME and UP links in + multipage output. The list contains format strings for the HTML + div and the navigation elements. The %s in the HTML div will + receive a concatenated string of the navigation elements. The + first %s in the navigation elements will receive the link, + the second the title" + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + + (defcustom org-html-multipage-numbered-filenames t + "Boolean indicating whether filenames in multipage export should + get their headline-numbering prepended. Note: This option is + independent of the num: option and the backend guarantees that + filenames are unique in any case." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-open 'nil + "If and where to open the top page of the multipage html after + export." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const browser) (const buffer) (const nil))) + + (defcustom org-html-multipage-postamble-position 'bottom + "The position of the postamble in the html output. + + bottom - at the bottom of the page, directly before </body> + + text-content - at the bottom of the text-content. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const bottom) (const text-content))) + + (defcustom org-html-multipage-preamble-position 'top + "If and where to open the top page of the multipage html after + export. + + top - at the top of the page, directly after <body> + + text-content - at the top of the text-content. + + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const top) (const text-content))) + + (defcustom org-html-multipage-split-hooks nil + "list of additional custom functions to be called during the + export after multipage splitting has taken place and before + transcoding with info as input. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + + (defcustom org-html-multipage-split-level 'toc + "How to split the ORG file into multiple HTML pages. + + toc - split each entry of the toc into a separate page. + + number - a number indicating the maximum headline-level for + splitting. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const toc) (number :tag "Headline Level" 3))) + + (defcustom org-html-multipage-toc-to-top t + "If t links in the TOC will always point to the top of the page, + otherwise it will link directly to the referenced headline + element." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + ;;;###autoload (put 'org-html-head-include-default-style 'safe-local-variable 'booleanp) + (put 'org-html-multipage-head-include-default-style 'safe-local-variable 'booleanp) + (put 'org-html-multipage-join-empty-bodies 'safe-local-variable 'booleanp) (defcustom org-html-head "" "Org-wide head definitions for exported HTML files. *************** *** 1873,1890 **** (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." ! (pcase (org-export-collect-footnote-definitions info) (`nil nil) (definitions - (format - (plist-get info :html-footnotes-section) - (org-html--translate "Footnotes" info) (format ! "\n%s\n" ! (mapconcat ! (lambda (definition) ! (pcase definition ! (`(,n ,label ,def) ;; 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 --- 2298,2315 ---- (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." ! (pcase (org-export-collect-footnote-definitions info (plist-get info :tl-headline)) (`nil nil) (definitions (format ! (plist-get info :html-footnotes-section) ! (org-html--translate "Footnotes" info) ! (format ! "\n%s\n" ! (mapconcat ! (lambda (definition) ! (pcase definition ! (`(,n ,label ,def) ;; 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 *************** *** 1911,1918 **** (if (not inline?) contents (format "<p class=\"footpara\">%s</p>" contents)))))))) ! definitions ! "\n")))))) \f ;;; Template --- 2336,2343 ---- (if (not inline?) contents (format "<p class=\"footpara\">%s</p>" contents)))))))) ! definitions ! "\n")))))) \f ;;; Template *************** *** 2018,2025 **** INFO is a plist used as a communication channel." (org-element-normalize-string (concat ! (when (plist-get info :html-head-include-default-style) ! (org-element-normalize-string org-html-style-default)) (org-html-normalize-string-or-function (plist-get info :html-head) info) (org-html-normalize-string-or-function (plist-get info :html-head-extra) info) --- 2443,2453 ---- INFO is a plist used as a communication channel." (org-element-normalize-string (concat ! (if (plist-get info :multipage) ! (when (plist-get info :html-multipage-head-include-default-style) ! (org-element-normalize-string org-html-multipage-style-default)) ! (when (plist-get info :html-head-include-default-style) ! (org-element-normalize-string org-html-style-default))) (org-html-normalize-string-or-function (plist-get info :html-head) info) (org-html-normalize-string-or-function (plist-get info :html-head-extra) info) *************** *** 2206,2212 **** holding export options." (concat ;; Table of contents. ! (let ((depth (plist-get info :with-toc))) (when depth (org-html-toc depth info))) ;; Document contents. contents --- 2634,2644 ---- holding export options." (concat ;; Table of contents. ! (let* ((with-toc (plist-get info :with-toc)) ! (depth (if with-toc ! (if (numberp with-toc) ! with-toc ! (plist-get info :headline-levels))))) (when depth (org-html-toc depth info))) ;; Document contents. contents *************** *** 2477,2484 **** 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)) --- 2909,2918 ---- of contents as a string, or nil if it is empty." (let ((toc-entries (mapcar (lambda (headline) ! (cl-list* ! (org-html--format-toc-headline headline info) ! nil ;;; no hidden attribute ! (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)) *************** *** 2497,2503 **** (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "<h%d>%s</h%d>\n" top-level ! (org-html--translate "Table of Contents" info) top-level)) toc (format "</%s>\n" outer-tag)))))))) --- 2931,2940 ---- (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "<h%d>%s</h%d>\n" top-level ! (org-html--translate ! (or (plist-get info :html-toc-title) ! org-html-toc-title) ! info) top-level)) toc (format "</%s>\n" outer-tag)))))))) *************** *** 2505,2527 **** (defun org-html--toc-text (toc-entries) "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." ! (let* ((prev-level (1- (cdar toc-entries))) (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<ul>\n<li>") ! ((< cnt 0) "</li>\n</ul>\n"))) ! (if (> cnt 0) "\n<ul>\n<li>" "</li>\n<li>"))) headline))) toc-entries "") (org-html--make-string (- prev-level start-level) "</li>\n</ul>\n")))) --- 2942,2974 ---- (defun org-html--toc-text (toc-entries) "Return innards of a table of contents, as a string. TOC-ENTRIES is an alist where key is an entry title, as a string, ! second element a flag whether the entry gets a ! class=\"toc-hidden\" attribute and the third element is its ! relative level, as an integer." ! (let* ((prev-level (1- (cddar toc-entries))) (start-level prev-level)) (concat (mapconcat (lambda (entry) (let ((headline (car entry)) ! (hidden (cadr entry)) ! (level (cddr entry))) (concat ! (format ! (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) (format "\n<ul class=\"ul-toc-level-%d\">\n<li>" level)) ! ((< cnt 0) "</li>\n</ul>\n"))) ! (if (> cnt 0) ! (concat "\n<ul" ! (format " class=\"ul-toc-level-%d\"" level) ! ">\n<li%s>") ! "</li>\n<li%s>"))) ! (if hidden (format " class=\"toc-hidden toc-level-%d\"" level) ! (format " class=\"toc-level-%d\"" level))) headline))) toc-entries "") (org-html--make-string (- prev-level start-level) "</li>\n</ul>\n")))) *************** *** 2572,2578 **** (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) --- 3019,3025 ---- (org-html--translate "Listing %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--full-reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) *************** *** 2610,2616 **** (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) --- 3057,3063 ---- (org-html--translate "Table %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--full-reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) *************** *** 2759,2765 **** (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 --- 3206,3215 ---- (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 ! (if (plist-get info :multipage) ! (org-html-get-multipage-tl-headline 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 *************** *** 2795,2801 **** 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)))) --- 3245,3253 ---- CONTENTS holds the contents of the headline. INFO is a plist holding contextual information." (unless (org-element-property :footnote-section-p headline) ! (let* ((numberedp (if (plist-get info :multipage) ! (plist-get info :section-numbers) ! (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)))) *************** *** 3023,3028 **** --- 3475,3481 ---- ((string= key "HTML") value) ((string= key "TOC") (let ((case-fold-search t)) + (setq global-key keyword) (cond ((string-match "\\<headlines\\>" value) (let ((depth (and (string-match "\\<[0-9]+\\>" value) *************** *** 3033,3039 **** (org-export-resolve-link (org-strip-quotes (match-string 1 value)) info)) ((string-match-p "\\<local\\>" 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)))))))) --- 3486,3496 ---- (org-export-resolve-link (org-strip-quotes (match-string 1 value)) info)) ((string-match-p "\\<local\\>" value) keyword)))) ;local ! (if (plist-get info :multipage) ! (progn ! (setq global-key keyword) ! (org-html-multipage-toc depth (cl-list* :full-toc t info) scope)) ! (org-html-toc depth info scope)))) ((string= "listings" value) (org-html-list-of-listings info)) ((string= "tables" value) (org-html-list-of-tables info)))))))) *************** *** 3187,3193 **** (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)) --- 3644,3650 ---- (defun org-html-image-link-filter (data _backend info) "Process image links that are inside descriptions. ! DATA is the parse tree. INFO is an info plist. See `org-export-insert-image-links' for more details." (org-export-insert-image-links data info org-html-inline-image-rules)) *************** *** 3367,3389 **** (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 "<a href=\"#%s\"%s>%s</a>" href attributes desc))) ;; Fuzzy link points to a target or an element. (_ (if (and destination --- 3824,3860 ---- (org-element-property :raw-link link) info)))) ;; Link points to a headline. (`headline ! (let ((href ! (org-html--full-reference ! (if (plist-get info :multipage) ! (alist-get destination ! (plist-get info :stripped-hl-to-parse-tree-hl)) ! 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)) ! (let ((headline-number (org-export-get-headline-number ! destination info))) ! (if (> (length headline-number) 1) ! (format ! (org-html--translate (nth 1 org-html-numbered-link-format) info) ! (mapconcat #'number-to-string ! headline-number ".")) ! (format ! (org-html--translate (nth 0 org-html-numbered-link-format) info) ! (mapconcat #'number-to-string ! headline-number ".")))) ;; 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 "<a href=\"%s\"%s>%s</a>" href attributes desc))) ;; Fuzzy link points to a target or an element. (_ (if (and destination *************** *** 3394,3422 **** ;; 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 "<a href=\"#%s\"%s>%s</a>" ref attributes desc))))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") --- 3865,3895 ---- ;; 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--full-reference destination info)) ! (let* ((ref (org-html--full-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)) ! (numbered-ref (cond (desc nil) ((org-html-standalone-image-p destination info) ! (format (org-html--translate (nth 2 org-html-numbered-link-format) 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 numbered-ref) "No description for this link") ! ((numberp numbered-ref) (number-to-string number)) ! ((stringp numbered-ref) numbered-ref) (t (mapconcat #'number-to-string number "."))))) ! (format "<a href=\"%s\"%s>%s</a>" ref attributes desc))))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") *************** *** 3924,3930 **** "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 --- 4397,4403 ---- "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." ! (let ((ref (org-html--full-reference target info))) (org-html--anchor ref nil nil info))) ;;;; Timestamp *************** *** 3984,3990 **** (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)))) \f ;;; End-user functions --- 4457,4470 ---- (delay-mode-hooks (set-auto-mode t)) (when (plist-get info :html-indent) (indent-region (point-min) (point-max))) ! (if (plist-get info :multipage) ! (let ((output-file (get-text-property ! 0 :output-file ! (buffer-substring (point-min) (point-max))))) ! (put-text-property ! 0 1 :output-file output-file ! (buffer-substring-no-properties (point-min) (point-max)))) ! (buffer-substring-no-properties (point-min) (point-max))))) \f ;;; End-user functions *************** *** 4092,4097 **** --- 4572,5482 ---- "html")) plist pub-dir)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;; + ;;; Code specific to the multipage backend + ;;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (defun org-html-reverse-assoc-list (assoc-list) + (mapcar (lambda (entry) (cons (cdr entry) (car entry))) assoc-list)) + + (defun org-html-element-title (element) + (org-element-property :raw-value element)) + + (defun org-html-increment-string-idx (string) + (if (string-match "\\([0-9]+\\)$" string) + (replace-match (format "%s" (1+ (read (match-string 0 string)))) nil nil string) + (format "%s-1" string))) + + (defun org-html-unique-filename (string filenames) + "return a unique filename by appending -<num> to the string with + <num> starting from 1 and incrementing until the string is + unique in filenames." + (if (member string filenames) + (org-html-unique-filename + (org-html-increment-string-idx string) filenames) + string)) + + (defun org-html-replace-chars-with-dash (chars string) + (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "-" accum)) + chars + :initial-value string)) + + (defun org-html-remove-chars (chars string) + (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "" accum)) + chars + :initial-value string)) + + (defun org-html-string-to-filename (string) + (replace-regexp-in-string + "-+" "-" + (org-html-remove-chars + '("(" ")" "*" "," ";" "{" "}" "'" "\\" "?") + (org-html-replace-chars-with-dash + '(" " "_" ":" "/") + (replace-regexp-in-string + "\\\\ast{}" "*" + (downcase (string-trim string))))))) + + (defun org-html-string-prepend-section-numbering (string levels maxlevel) + "Prepend the chapter outline numbers given in levels to + string. Truncate levels to maxlevel or pad with zeroes if + required." + (cl-loop + for i from (1- maxlevel) downto 0 + with result = string + do (setq result (format "%02d_%s" (or (nth i levels) 0) result)) + finally (return result))) + + (defun org-html--get-multipage-page-url (element info) + "Return the url of the page containing ELEMENT." + (alist-get + (org-html-get-multipage-tl-headline element info) + (plist-get info :tl-url-lookup))) + + (defun org-html--full-reference (destination info &optional page-only) + "Return an appropriate reference for DESTINATION. Like + org-html--reference, but generating an extended cross-page + reference for multipage. + + DESTINATION is an element or a `target' type object. INFO is the + current export state, as a plist. + + When PAGE-ONLY is non-nil just return the page reference." + (if (plist-get info :multipage) + (concat (org-html--get-multipage-page-url destination info) + (if page-only "" + (format "#%s" (org-export-get-reference destination info)))) + (format "#%s" (org-export-get-reference destination info)))) + + (defun org-html-multipage-toc (depth info &optional scope) + "Build a table of contents for a page in multipage + export. `:tl-headline-number' and `:tl-headline' refer to the + current page and have to be supplied in INFO. + + 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* ((tl-headline-number (plist-get info :tl-headline-number)) + (tl-headline (unless (plist-get info :full-toc) (plist-get info :tl-headline))) + (curr-number-ref tl-headline-number) + (toc-entries + (cl-loop + for (entry . props) in (plist-get info :multipage-toc-lookup) + if (<= (length (plist-get props :toc-hl-number)) depth) + collect (let* ((tl-hl (plist-get props :tl-hl)) + (page-headline-number (plist-get props :page-hl-number))) + (if (eq tl-hl tl-headline) + (setf curr-number-ref page-headline-number)) + (cl-list* + (org-html--format-mp-toc-headline + (plist-get props :href) + (plist-get props :toc-body) + (equal (plist-get props :tl-hl) tl-headline) + (plist-get info :full-toc)) + (unless (plist-get info :full-toc) + (org-html--hidden-in-toc? page-headline-number + curr-number-ref)) + (plist-get props :relative-level)))))) + (when toc-entries + (let ((toc (concat "<div id=\"text-table-of-contents\" role=\"doc-toc\">" + (org-html--toc-text toc-entries) + "</div>\n"))) + (if scope toc + (let ((outer-tag (if (org-html--html5-fancy-p info) + "nav" + "div"))) + (concat (format "<%s id=\"table-of-contents\" role=\"doc-toc\">\n" outer-tag) + (let ((top-level (plist-get info :html-toplevel-hlevel))) + (format "<h%d>%s</h%d>\n" + top-level + (org-html--translate + (or (plist-get info :html-toc-title) + org-html-toc-title) + info) + top-level)) + toc + (format "</%s>\n" outer-tag)))))))) + + (defun org-html--get-toc-body (headline info) + "Return the body of the toc entry of HEADLINE. INFO is a plist + used as a communication channel." + (let* ((headline-number (org-html-get-multipage-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)))) + ;; Body. + (concat + (and (not (org-export-low-level-p headline info)) + (plist-get info :section-numbers) + (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--format-mp-toc-headline (href body active full-toc) + "Return a table of contents entry for multipage output." + (format "<a %s>%s</a>" + ;; Target + (format "href=\"%s\"%s" + href + (concat + "class=\"" + (if full-toc "inline-toc-entry" + "toc-entry") + (if active + " toc-active" "") + "\"")) + + ;; Body. + body)) + + (defun org-html-multipage-ensure-export-dir (dir) + "get the full pathname of dir and ensure it exists." + (when (symbolp dir) (setq dir (format "%s" dir))) + (unless (= (aref dir 0) 47) + (setq dir (concat (file-name-directory (buffer-file-name)) dir))) + (unless (file-directory-p dir) + (make-directory dir :parents)) + dir) + + (defun org-html-multipage-split-tree (info) + (let ((split-ref (plist-get info :html-multipage-split-level)) + (headline-numbering (plist-get info :headline-numbering))) + (cond + ((eq split-ref 'toc) + (let ((maxdepth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)))) + (plist-put info :export-depth maxdepth) + (org-html-page-headlines + (cl-remove-if (lambda (hl-num) (> (length hl-num) maxdepth)) + headline-numbering :key 'cdr) + info))) + ((numberp split-ref) + (plist-put info :export-depth split-ref) + (org-html-page-headlines + (cl-remove-if (lambda (hl-num) (> (length hl-num) split-ref)) + headline-numbering :key 'cdr) + info))))) + + (defun org-html-transcode-multipage (info &optional body-only) + "Central routine transcoding to multipage output called by + `org-html-transcode-org-data' called from `org-export-as'. + + The pages to be exported are in the :multipage-org-pages property + of info as a list of org-page pseudo elements. This function + transcodes the org-pages and returns a list of the transcoded + output strings with their filename as :output-file Text Property + to be further processed by the function calling `org-export-as'. + + INFO is the communication channel. + " + (let ((async (plist-get info :async)) + (post-process (plist-get info :post-process))) + (declare (indent 2)) + (setq global-output + (cl-loop + for org-page in (plist-get info :multipage-org-pages) + collect (let ((file (org-element-property :output-file org-page))) + (message "transcoding: %s" file) + (let ((output (org-html-transcode-org-page org-page info))) + (put-text-property 0 1 :output-file file output) + output)))))) + + (defun org-html-multipage-split (data _backend info) + "Filter routine to collect all properties relevant to multipage + output. It is called in the context of calling all + :filter-parse-tree alist functions in `org-export-annotate-info' + after the parse-tree is completed and its properties + collected. The function takes care of splitting the parse-tree + into the subtrees for each page, creating org-page pseudo + elements, adding them in a list in the :multipage-org-pages + property of info. In addition lookup alists for the stripped + pages, for the page-urls, the navigation elements, the toc, + etc. are added to info, which are needed by the html transcoders. + + DATA is the completed parse-tree of the document. + + INFO is the communication channel. + " + (if (plist-get info :multipage) + (let ((dir (plist-get info :verified-export-directory)) + (async (plist-get info :async)) + (post-process (plist-get info :post-process))) + (declare (indent 2)) + (plist-put info :headline-numbering + (org-export--collect-headline-numbering + (plist-get info :parse-tree) + (cl-list* :section-numbers t info))) + (if (not (file-writable-p dir)) (error "Output dir not writable") + (let* ((encoding (or org-export-coding-system buffer-file-coding-system)) + (headline-numbering (plist-get info :headline-numbering)) + ;; each entry in exported-headline-numbering will become a + ;; single page in multipage output. + (exported-headline-numbering + (let ((tmp (org-html-multipage-split-tree info))) + (plist-put info :exported-headline-numbering tmp) + tmp)) + (max-toc-depth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels))) + ;; section-trees is a list of all sections which get + ;; exported to a single page + (section-trees + (cl-loop + for section-entry in exported-headline-numbering + for keep-first-subhls = (plist-get info :keep-first-subhls) then (cdr keep-first-subhls) + collect + (let* ((section-number (cdr section-entry))) + (if (< (length section-number) max-toc-depth) + (org-html-element-remove-subheadlines + (car section-entry) + (car keep-first-subhls) + max-toc-depth) + (org-html-element-copy-element (car section-entry)))))) + ;; stripped-section-headline-numbering is the equivalent of + ;; headline-numbering but replacing the car of its elements + ;; with the stripped version of the headlines. + (stripped-section-headline-numbering + (cl-mapcar 'cons + (cl-loop for section in section-trees + ;; collect all subheadlines to match + ;; headline-numbering: + append (org-element-map section 'headline + 'identity)) + (mapcar 'cdr headline-numbering))) + ;; lookup from all toc headline-numbers to the tl-headline. + ) + ;; add stripped-section-headline-numbering to + ;; :headline-numbering, to make their headline-numbering + ;; accessible when generating the body of the individual + ;; pages. + (plist-put info :headline-numbering + (append + headline-numbering + stripped-section-headline-numbering)) + (plist-put info :section-trees section-trees) + (plist-put info :stripped-section-headline-numbering + stripped-section-headline-numbering) + ;; tl-url-lookup associates the stripped section headlines + ;; with the names of the joined pages to export. + (plist-put info :tl-url-lookup (org-html--generate-tl-url-lookup info)) + ;; lookup for the navigation elements of each page. + (plist-put info :section-nav-lookup + (org-html--make-section-nav-lookup info)) + (let ((section-filenames + (mapcar + (lambda (hl) (alist-get hl (plist-get info :tl-url-lookup))) + section-trees))) + (plist-put info :section-filenames section-filenames) + ;; bidirectional lookup tables to map between the + ;; stripped-section headlines and their global + ;; parse-tree equvialent. + (plist-put + info :stripped-hl-to-parse-tree-hl + (append + (cl-mapcar 'cons + (mapcar 'car stripped-section-headline-numbering) + (mapcar 'car headline-numbering)) + (cl-mapcar 'cons + (mapcar 'car headline-numbering) + (mapcar 'car stripped-section-headline-numbering)))) + ;; collect the toc information to avoid repeated + ;; recalculation in the toc transcoder for the + ;; individual pages. + (plist-put info :multipage-toc-lookup + (org-html--make-multipage-toc-lookup info)) + ;; The url for the "top" link on each page. + (plist-put info :html-top-url + (alist-get + (car (plist-get info :section-trees)) + (plist-get info :tl-url-lookup))) + ;; The title for the "top" link on each page. + (plist-put info :html-top-title + (org-html-element-title + (car (plist-get info :section-trees)))) + ;; collect all org-pages to be exported. + (plist-put info :multipage-org-pages + (cl-loop + for file in section-filenames + for tl-headline in section-trees + collect + (list 'org-page + (list :output-file (format "%s/%s" dir file) + :tl-headline tl-headline + :tl-headline-number + (alist-get + tl-headline + stripped-section-headline-numbering)) + nil)))))))) + data) + + (defun org-html--generate-tl-url-lookup (info) + "Return an assoc list for all headlines appearing in the toc + and the url names of the page they're on." + (let ((extension (plist-get info :html-extension)) + (stripped-section-headline-numbering + (plist-get info :stripped-section-headline-numbering)) + filenames) + (mapcar + (lambda (entry) + (let* ((tl-elem (org-html-element-get-top-level entry)) + (title (org-html-element-title tl-elem))) + (cons + entry + (format "%s.%s" + (car (push + (org-html-unique-filename + (if (plist-get info :html-multipage-numbered-filenames) + (org-html-string-prepend-section-numbering + (org-html-string-to-filename title) + (cdr (assoc + tl-elem + stripped-section-headline-numbering)) + org-export-headline-levels) + (org-html-string-to-filename title)) + filenames) + filenames)) + extension)))) + (plist-get info :section-trees)))) + + (defun org-html--make-section-nav-lookup (info) + "Return an assoc-list for the headlines of all + exported pages with a plist containing titles and urls for the + section and its navigation." + (let* ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering)) + ;;; first collect navigation-info once for each page only + (nav (mapcar (lambda (hl) + (let* ((hl-number (alist-get hl stripped-section-headline-numbering)) + (up (car (rassoc (butlast hl-number) stripped-section-headline-numbering)))) + (list hl + (org-html-element-title hl) + (org-html--full-reference hl info t) + (org-html-element-title up) + (and up (org-html--full-reference up info t))))) + (plist-get info :section-trees)))) + ;;; collect the info for prev, curr, next and up navigation for + ;;; each page by cdr-ing over nav. + (cl-labels ((inner (prev-entry curr-entry) + (let ((prev (car prev-entry)) + (curr (car curr-entry)) + (next (cadr curr-entry))) + (if curr + (cons (list (car curr) + :prev-title (nth 1 prev) + :curr-title (nth 1 curr) + :next-title (nth 1 next) + :up-title (nth 3 curr) + :prev-url (nth 2 prev) + :curr-url (nth 2 curr) + :next-url (nth 2 next) + :up-url (nth 4 curr)) + (inner (cdr prev-entry) (cdr curr-entry))))))) + (inner (cons nil nav) nav)))) + + (defun org-html--make-multipage-toc-lookup (info) + "Return an assoc-list containing info for the headlines of all toc entries." + (mapcar + (lambda (hl) + (let* ((tl-hl (org-html-element-get-top-level hl))) + (list hl + :href (org-html--full-reference hl info (plist-get info :html-multipage-toc-to-top)) + :tl-hl tl-hl + :relative-level (org-export-get-relative-level hl info) + :toc-body (org-html--get-toc-body hl info) + :toc-hl-number (alist-get hl (plist-get info :headline-numbering)) + :page-hl-number (org-html-get-multipage-headline-number hl info)))) + (org-html-collect-local-headlines info nil))) + + (defun org-html-get-multipage-tl-headline (element info) + "return the headline of the page containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (let* ((elem element) + (parent (org-element-property :parent elem))) + (while parent + (setf elem parent) + (setf parent (org-element-property :parent elem))) + elem)) + + (defun org-html-get-multipage-headline-numbering (element info) + "return the headline of the section containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (let* ((elem element) + (parent (org-element-property :parent elem)) + (hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering)))) + (while (not hl-numbering) + (setf elem parent) + (setf parent (org-element-property :parent elem)) + (setf hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering)))) + hl-numbering)) + + (defun org-html-get-multipage-headline-number (element info) + "return the headline-number of the section containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (cdr (org-html-get-multipage-headline-numbering element info))) + + (defun org-html-element-get-top-level (element) + "Return the top-level element of ELEMENT by traversing the parse + tree upwards until the parent of element is nil." + (let ((elem element) + (parent (org-element-property :parent element))) + (while parent + (setq elem parent) + (setq parent (org-element-property :parent elem))) + elem)) + + (defun org-html-element-copy-element (org-node &optional keep-parent) + "copy ORG-NODE to a new org-node with elements not copied, + but referenced." + (let* (headline + (props (copy-sequence (nth 1 org-node))) + (new (list (car org-node) props))) + (unless keep-parent (setf (org-element-property :parent new) nil)) + (apply 'org-element-adopt-elements new (org-element-contents org-node)))) + + (defun org-html-element-remove-subheadlines (org-node &optional + keep-first-subheadlines max-toc-depth keep-parent) + "remove all elements starting with and including the first headline + in the children of ORG-NODE if JOIN_EMPTY_BODIES is nil. Returns a + new ast with all elements starting at START-CHILD-IDX copied into + it with the :parent property optionally removed in the top node." + (let* ((num-subheadlines 0) + contents-end + headline + (props (copy-sequence (nth 1 org-node))) + (new (list (car org-node) props)) + (new-children (cl-loop + for x in (org-element-contents org-node) + with exit = nil + do (if (and + (consp x) + (eq (org-element-type x) 'headline)) + (if (and (car keep-first-subheadlines) (zerop num-subheadlines)) + (progn + (setf num-subheadlines (1+ num-subheadlines)) + (if (< (org-element-property :level x) max-toc-depth) + (setq x (org-html-element-remove-subheadlines + x (cdr keep-first-subheadlines) max-toc-depth)))) + (progn + (setq contents-end (org-element-property :begin x)) + (setq exit t)))) + until exit + collect x))) + (unless keep-parent (setf (org-element-property :parent new) nil)) + (apply 'org-element-adopt-elements new new-children))) + + (defun org-html-find-headline (headline-number headline-numbering) + "return the headline in headline numbering for a given + headline-number." + (cond + ((null headline-numbering) nil) + ((equal headline-number (cdar headline-numbering)) + (caar headline-numbering)) + (t (org-html-find-headline headline-number (cdr headline-numbering))))) + + (defun org-html-element-body-text (element info) + "check if transcoding of the contents of element until the next + subheadline returns an empty string." + (let ((strings + (cl-loop + for elem in (org-element-contents element) + while (not (eq 'headline (org-element-type elem))) + collect (org-export-data elem info)))) + (string-trim + (apply 'concat + (with-temp-buffer + (mapcar 'insert strings) + (dom-strings (libxml-parse-html-region (point-min) (point-max)))))))) + + (defun org-html-element-body-text? (element info) + "check if transcoded element produces any text." + (not (eq "" (org-html-element-body-text element info)))) + + (defun org-html-page-headlines (headlines info) + "collect the headlines of all pages to export. In case of + html-multipage-join-empty-bodies don't collect the headlines to + be joined and keep track by collecting them for each page + headline in :keep-first-subhls. + `org-html-element-remove-subheadlines'" + (if (plist-get info :html-multipage-join-empty-bodies) + (cl-loop for (prev curr-headline) on (cons nil headlines) + with collect-hl = nil + with tmp = nil + with keep-shl = nil + while curr-headline + do (progn + (setf + collect-hl + (or ;; collect curr-headline either + (not prev) ;; when it is the first headline + (<= (length (cdr curr-headline)) + (length (cdr prev))) ;; when it is not a subheadline of prev. + ;; or when the previous headline contains body text + (org-html-element-body-text? (car prev) info))) + (if collect-hl + (progn (push (reverse tmp) keep-shl) + (setf tmp nil)) + (push t tmp))) + if collect-hl collect curr-headline + finally (progn (push tmp keep-shl) + (plist-put info :keep-first-subhls (cdr (reverse keep-shl))))) + headlines)) + + (defun org-html-transcode-org-page (page info) + "transcode the headline tree in the contents of the org-page + pseudo element PAGE into a string according to the backend and + return the string. + + INFO is used as communication channel." + (let* ((body-only (org-element-property :body-only page)) + (headline (org-element-property :tl-headline page)) + (info (cl-list* + :tl-headline headline + :tl-headline-number (org-element-property :tl-headline-number page) + info)) + (body (org-element-normalize-string + (or (org-export-data headline info) + ""))) + (inner-template (if (plist-get info :multipage) + (alist-get 'multipage-inner-template + (plist-get info :translate-alist)) + (alist-get 'inner-template + (plist-get info :translate-alist)))) + (full-body (org-export-filter-apply-functions + (plist-get info :filter-body) + (if (not (functionp inner-template)) body + (funcall inner-template body info)) + info)) + (template (if (plist-get info :multipage) + (cdr (assq 'multipage-template + (plist-get info :translate-alist))) + (cdr (assq 'template + (plist-get info :translate-alist))))) + (output + (if (or (not (functionp template)) body-only) full-body + (funcall template full-body info)))) + ;; Call citation export finalizer. + (setq output (org-cite-finalize-export output info)) + ;; Remove all text properties since they cannot be + ;; retrieved from an external process. Finally call + ;; final-output filter and return result. + (org-no-properties + (org-export-filter-apply-functions + (plist-get info :filter-final-output) + output info)))) + + (defun org-html-export-to-multipage + (&optional async subtreep visible-only body-only ext-plist post-process) + "Export current buffer to multipage HTML files. + + 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 files 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 \"<body>\" and \"</body>\" 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 directory's name." + (interactive) + (let* ((extension (concat + (when (> (length org-html-extension) 0) ".") + (or (plist-get ext-plist :html-extension) + org-html-extension + "html"))) + (backend 'html) + (encoding (or org-export-coding-system buffer-file-coding-system)) + (org-export-coding-system org-html-coding-system) + (environment (org-export-get-environment 'html nil nil)) + (dir (org-html-multipage-ensure-export-dir + (plist-get environment :html-multipage-export-directory)))) + (if (not (file-writable-p dir)) (error "Output dir not writable") + (progn + (message "collecting multipage output...") + (let ((output + (org-export-as backend subtreep visible-only body-only + (cl-list* + :async async + :multipage t + :verified-export-directory dir + ext-plist)))) + (when (plist-get environment :html-multipage-clear-export-directory) + (message "clearing export-directory.") + (dolist + (file (directory-files dir nil ".html$")) + (delete-file (format "%s/%s" dir file)))) + (dolist (out output) + (if async + (org-export-async-start + (lambda (file) + (org-export-add-to-stack (expand-file-name file) backend)) + `(let ((file (get-text-property 0 :ouput-file out))) + (setq file (org-export--write-output output ',encoding)) + (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f)))) + (if (listp file) (mapcar post file) (funcall post file))))) + (let (file) + (setq file (org-export--write-output out encoding)) + (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) + (org-kill-new output)) + ;; Get proper return value. + (let ((post (lambda (f) + (or (and (functionp post-process) + (funcall post-process f)) + f)))) + (if (listp file) (mapcar post file) (funcall post file)))))) + (if (member system-type '(darwin gnu/linux gnu)) + (shell-command (format "ln -s %s %s/index.html" (get-text-property 0 :output-file (car output)) dir))) + (message "done!\n") + (cl-case (plist-get environment :html-multipage-open) + ('browser (org-open-file (format "%s" (get-text-property 0 :output-file (car output))))) + ('buffer (find-file (format "%s" (get-text-property 0 :output-file (car output))))))))))) + + (defun org-html--hidden-in-toc? (headline-number tl-headline-number) + "Check if the entry of HEADLINE-NUMBER should be hidden in the + toc of the page containing TL-HEADLINE-NUMBER." + (and + (> (length headline-number) 1) + (let ((l1 (length headline-number)) + (l2 (length tl-headline-number))) + (cond + ((= l1 l2) (not (equal (butlast headline-number) + (butlast tl-headline-number)))) + ((> l1 l2) (not (equal tl-headline-number + (butlast headline-number)))) + (t (not (equal (butlast headline-number) + (butlast (butlast tl-headline-number))))))))) + + (defun org-html-collect-local-headlines (info scope) + "Collect all headlines of headline-numbering from their local + tl-headlines counterparts." + (let ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering)) + (headline-numbering (plist-get info :headline-numbering))) + (mapcar + (lambda (global-headline) + (car + (rassoc (cdr (assoc global-headline headline-numbering)) + stripped-section-headline-numbering))) + (org-export-collect-headlines + info + (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)) + scope)))) + + (defun org-html-nav-left (nav-lookup) + "Return nav string for multipage Navigation in page-main-body. + + INFO is a plist used as a communication channel. + " + (let* ((prev-url (plist-get nav-lookup :prev-url)) + (prev-title (plist-get nav-lookup :prev-title))) + (if prev-url + (format "<nav id=\"nav-left\"><a href=\"%s\" class=\"nav-left\"><i class=\"angle-left\"></i></a></nav>" + prev-url) + (format "<nav id=\"nav-left\"><a href=\"%s\" class=\"nav-left\"><i class=\"angle-left-inactive\"></i></a></nav>" + "")))) + + (defun org-html-nav-right (nav-lookup) + "Return nav string for multipage Navigation in page-main-body. + + INFO is a plist used as a communication channel. + " + (let* ((next-url (plist-get nav-lookup :next-url)) + (next-title (plist-get nav-lookup :next-title))) + (if next-url + (format "<nav id=\"nav-right\"><a href=\"%s\" class=\"nav-right\"><i class=\"angle-right\"></i></a></nav>" + next-url) + (format "<nav id=\"nav-right\"><a href=\"%s\" class=\"nav-right\"><i class=\"angle-right-inactive\"></i></a></nav>" + "")))) + + (defun org-html-multipage-nav (info) + "Return the string for the multipage navigation anchors. + + INFO is a plist used as a communication channel. + " + (let ((section-nav-lookup + (alist-get + (plist-get info :tl-headline) + (plist-get info :section-nav-lookup))) + (nav-format (plist-get info :html-multipage-nav-format))) + (format (car nav-format) + (concat + (when (plist-get section-nav-lookup :next-url) + (format (cadr nav-format) + (plist-get section-nav-lookup :next-url) + (plist-get section-nav-lookup :next-title))) + (when (plist-get section-nav-lookup :prev-url) + (format (caddr nav-format) + (plist-get section-nav-lookup :prev-url) + (plist-get section-nav-lookup :prev-title))) + (when (plist-get section-nav-lookup :up-url) + (format (cadddr nav-format) + (plist-get section-nav-lookup :up-url) + (plist-get section-nav-lookup :up-title))) + (when (plist-get info :html-top-url) + (format (nth 4 nav-format) + (plist-get info :html-top-url) + (plist-get info :html-top-title))))))) + + (defun org-html-multipage-template (contents info) + "Return complete document string after HTML conversion. + CONTENTS is the transcoded contents string. INFO is a plist + holding export options." + (concat + (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info)) + (let* ((xml-declaration (plist-get info :html-xml-declaration)) + (decl (or (and (stringp xml-declaration) xml-declaration) + (cdr (assoc (plist-get info :html-extension) + xml-declaration)) + (cdr (assoc "html" xml-declaration)) + ""))) + (when (not (or (not decl) (string= "" decl))) + (format "%s\n" + (format decl + (or (and org-html-coding-system + ;; FIXME: Use Emacs 22 style here, see `coding-system-get'. + (coding-system-get org-html-coding-system 'mime-charset)) + "iso-8859-1")))))) + (org-html-doctype info) + "\n" + (concat "<html" + (cond ((org-html-xhtml-p info) + (format + " xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"%s\" xml:lang=\"%s\"" + (plist-get info :language) (plist-get info :language))) + ((org-html-html5-p info) + (format " lang=\"%s\"" (plist-get info :language)))) + ">\n") + "<head>\n" + (org-html--build-meta-info info) + (org-html--build-head info) + (org-html--build-mathjax-config info) + "</head>\n" + "<body>\n" + (when (eq org-html-multipage-preamble-position 'top) + (org-html--build-pre/postamble 'preamble info)) + (org-html-multipage-nav info) + ;; Preamble. + (unless (eq org-html-multipage-preamble-position 'top) + (org-html--build-pre/postamble 'preamble info)) + ;; Document contents. + (let ((div (assq 'content (plist-get info :html-divs)))) + (format "<%s id=\"%s\" class=\"%s\">\n" + (nth 1 div) + (nth 2 div) + (plist-get info :html-content-class))) + ;; Table of contents. + (let ((depth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)))) + (when depth (org-html-multipage-toc depth info))) + ;; Document title. + (when (plist-get info :with-title) + (let ((title (and (plist-get info :with-title) + (plist-get info :title))) + (subtitle (plist-get info :subtitle)) + (html5-fancy (org-html--html5-fancy-p info))) + (when title + (format + (if html5-fancy + "<header>\n<h1 class=\"title\">%s</h1>\n%s</header>" + "<h1 class=\"title\">%s%s</h1>\n") + (org-export-data title info) + (if subtitle + (format + (if html5-fancy + "<p class=\"subtitle\" role=\"doc-subtitle\">%s</p>\n" + (concat "\n" (org-html-close-tag "br" nil info) "\n" + "<span class=\"subtitle\">%s</span>\n")) + (org-export-data subtitle info)) + ""))))) + contents + (format "</%s>\n" (nth 1 (assq 'content (plist-get info :html-divs)))) + ;; Possibly use the Klipse library live code blocks. + (when (plist-get info :html-klipsify-src) + (concat "<script>" (plist-get info :html-klipse-selection-script) + "</script><script src=\"" + org-html-klipse-js + "\"></script><link rel=\"stylesheet\" type=\"text/css\" href=\"" + org-html-klipse-css "\"/>")) + (when (eq org-html-multipage-postamble-position 'bottom) + (org-html--build-pre/postamble 'postamble info)) + ;; Closing document. + "</body>\n</html>")) + + (defun org-html-multipage-inner-template (contents info) + "Return body of document string after HTML conversion. + CONTENTS is the transcoded contents string. INFO is a plist + holding export options. + + DATA contains the subtree of the parse tree of the section to be + exported for multipage export. + " + ;; Navigation + (let* ((data (plist-get info :tl-headline)) + (section-nav-lookup + (alist-get + data + (plist-get info :section-nav-lookup)))) + (format "<div id=\"page-main-body\">%s\n<div id=\"page-text-body\">%s</div>%s</div>" + (org-html-nav-left section-nav-lookup) + (concat + ;; Document contents. + contents + ;; Footnotes section. + (or (org-html-footnote-section info) "") + ;; Postamble. + (unless (eq org-html-multipage-postamble-position 'bottom) + (org-html--build-pre/postamble 'postamble info))) + (org-html-nav-right section-nav-lookup)))) + + (defun org-html-transcode-org-data (data content info) + "Transcode the top org-data node of the org file to export. + + It is called by `org-export-as' after all necessary information + has been added to info and the final parse-tree has been + generated. Multipage information has already been collected by + calling `org-html-multipage-filter' in `org-export-annotate-info' + using the :multipage-split property. + + INFO is a plist used as a communication channel." + (message "transcoding data!") + (if (plist-get info :multipage) + ;;; for multipage output we don't need data and content as all + ;;; information is already collected in info. + (org-html-transcode-multipage info) + (org-export-transcode-org-data data content info))) (provide 'ox-html) *************** *** 4100,4102 **** --- 5485,5489 ---- ;; End: ;;; ox-html.el ends here + + [-- Attachment #5: org-manual.org.patch --] [-- Type: text/plain, Size: 16184 bytes --] *** org-mode/doc/org-manual.org 2024-08-05 17:15:57.585261838 +0200 --- org-mode-multipage/doc/org-manual.org 2024-08-05 15:40:24.679134249 +0200 *************** *** 772,781 **** where you can use the following keys to find your destination: #+attr_texinfo: :columns 0.3 0.7 ! | {{{kbd(TAB)}}} | Cycle visibility. | | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. | ! | {{{kbd(RET)}}} | Select this location. | ! | {{{kbd(/)}}} | Do a Sparse-tree search | #+texinfo: @noindent The following keys work if you turn off ~org-goto-auto-isearch~ --- 772,781 ---- where you can use the following keys to find your destination: #+attr_texinfo: :columns 0.3 0.7 ! | {{{kbd(TAB)}}} | Cycle visibility. | | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. | ! | {{{kbd(RET)}}} | Select this location. | ! | {{{kbd(/)}}} | Do a Sparse-tree search | #+texinfo: @noindent The following keys work if you turn off ~org-goto-auto-isearch~ *************** *** 783,791 **** #+attr_texinfo: :columns 0.3 0.7 | {{{kbd(n)}}} / {{{kbd(p)}}} | Next/previous visible headline. | | {{{kbd(f)}}} / {{{kbd(b)}}} | Next/previous headline same level. | ! | {{{kbd(u)}}} | One level up. | | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument. | ! | {{{kbd(q)}}} | Quit. | #+vindex: org-goto-interface #+texinfo: @noindent --- 783,791 ---- #+attr_texinfo: :columns 0.3 0.7 | {{{kbd(n)}}} / {{{kbd(p)}}} | Next/previous visible headline. | | {{{kbd(f)}}} / {{{kbd(b)}}} | Next/previous headline same level. | ! | {{{kbd(u)}}} | One level up. | | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument. | ! | {{{kbd(q)}}} | Quit. | #+vindex: org-goto-interface #+texinfo: @noindent *************** *** 2044,2050 **** #+attr_texinfo: :columns 0.2 0.8 | =$1..$3= | first three fields in the current row | ! | =$P..$Q= | range, using column names (see [[*Advanced features]]) | | =$<<<..$>>= | start in third column, continue to the last but one | | =@2$1..@4$3= | nine fields between these two fields (same as =A2..C4=) | | =@-1$-2..@-1= | 3 fields in the row above, starting from 2 columns on the left | --- 2044,2050 ---- #+attr_texinfo: :columns 0.2 0.8 | =$1..$3= | first three fields in the current row | ! | =$P..$Q= | range, using column names (see [[*Advanced features]]) | | =$<<<..$>>= | start in third column, continue to the last but one | | =@2$1..@4$3= | nine fields between these two fields (same as =A2..C4=) | | =@-1$-2..@-1= | 3 fields in the row above, starting from 2 columns on the left | *************** *** 2248,2255 **** | =$1+$2;%.2f= | Same, format result to two decimals | | =exp($2)+exp($1)= | Math functions can be used | | =$0;%.1f= | Reformat current cell to 1 decimal | ! | =($3-32)*5/9= | Degrees F \to C conversion | ! | =$c/$1/$cm= | Hz \to cm conversion, using =constants.el= | | =tan($1);Dp3s1= | Compute in degrees, precision 3, display SCI 1 | | =sin($1);Dp3%.1e= | Same, but use ~printf~ specifier for display | | =vmean($2..$7)= | Compute column range mean, using vector function | --- 2248,2255 ---- | =$1+$2;%.2f= | Same, format result to two decimals | | =exp($2)+exp($1)= | Math functions can be used | | =$0;%.1f= | Reformat current cell to 1 decimal | ! | =($3-32)*5/9= | Degrees F \to C conversion | ! | =$c/$1/$cm= | Hz \to cm conversion, using =constants.el= | | =tan($1);Dp3s1= | Compute in degrees, precision 3, display SCI 1 | | =sin($1);Dp3%.1e= | Same, but use ~printf~ specifier for display | | =vmean($2..$7)= | Compute column range mean, using vector function | *************** *** 11995,12001 **** #+attr_texinfo: :columns 0.1 0.9 | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence. | | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes. | ! | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action. | | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence. | | {{{kbd(d)}}} | Delete the footnote at point, including definition and references. | --- 11995,12001 ---- #+attr_texinfo: :columns 0.1 0.9 | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence. | | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes. | ! | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action. | | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence. | | {{{kbd(d)}}} | Delete the footnote at point, including definition and references. | *************** *** 13283,13288 **** --- 13283,13299 ---- Exports to a temporary buffer. Does not create a file. + - {{{kbd(C-c C-e h m)}}} (~org-html-export-to-multipage~) :: + #+kindex: C-c C-e h m + #+findex: org-html-export-to-multipage + + Export as multiple HTML files with a =.html= extension. The + exported files are written into a directory specified with the + customization variable =org-html-multipage-export-dir=. If + =org-html-clear-export-directory= is non-nil, all files with a + =.html= extension will be removed before writing the files. Files + with duplicate names will be overwritten without warning. + *** HTML specific export settings :PROPERTIES: :DESCRIPTION: Settings for HTML export. *************** *** 13823,13831 **** #+vindex: org-html-head-extra #+cindex: @samp{HTML_INCLUDE_STYLE}, keyword The HTML export backend includes a compact default style in each ! exported HTML file. To override the default style with another style, ! use these keywords in the Org file. They will replace the global ! defaults the HTML exporter uses. #+cindex: @samp{HTML_HEAD}, keyword #+cindex: @samp{HTML_HEAD_EXTRA}, keyword --- 13834,13844 ---- #+vindex: org-html-head-extra #+cindex: @samp{HTML_INCLUDE_STYLE}, keyword The HTML export backend includes a compact default style in each ! exported HTML file[fn:: The constant is called ! ~org-html-style-default~ for single page output and ! ~org-html-multipage-style-default~ for multipage output]. To override ! the default style with another style, use these keywords in the Org ! file. They will replace the global defaults the HTML exporter uses. #+cindex: @samp{HTML_HEAD}, keyword #+cindex: @samp{HTML_HEAD_EXTRA}, keyword *************** *** 13855,13861 **** a =CUSTOM_ID= property. You can also assign a specific class to a headline with the =HTML_HEADLINE_CLASS= property. ! Never change the ~org-html-style-default~ constant. Instead, use other simpler ways of customizing as described above. *** JavaScript supported display of web pages --- 13868,13875 ---- a =CUSTOM_ID= property. You can also assign a specific class to a headline with the =HTML_HEADLINE_CLASS= property. ! Never change the ~org-html-style-default~ and ! ~org-html-multipage-style-default~ constants. Instead, use other simpler ways of customizing as described above. *** JavaScript supported display of web pages *************** *** 13944,13949 **** --- 13958,14124 ---- variable ~org-infojs-options~. If you always want to apply the script to your pages, configure the variable ~org-export-html-use-infojs~. + *** Multipage HTML specific export options + The options and custom variables for HTML export also apply to + multipage export. In addition the variables below are applying to + multipage export. They can be set using the listed variable name + or using an in buffer option using the name without the =org-= at + the beginning as in the following example: + #+begin_src + #+OPTIONS: html-multipage-clear-export-directory:t + #+end_src + + - ~org-html-multipage-clear-export-directory~ :: + + #+vindex: org-html-multipage-clear-export-directory + Whether to clear all =.html= files in the export directory before + writing. + + - ~org-html-multipage-export-directory~ :: + + #+vindex: org-html-multipage-export-directory + The directory where the multiple files will be written. Relative to + the path of the Org document or absolute. + + - ~org-html-multipage-head-include-default-style~ :: + + #+vindex: org-html-multipage-head-include-default-style + Whether to include the default CSS style + (=org-html-multipage-style-default=) into every exported file. + + - ~org-html-multipage-join-empty-bodies~ :: + + #+vindex: org-html-multipage-join-empty-bodies + Recursively join subheadlines, if a headline doesn't contain any + text before its subheadline. + + Example: + #+begin_example + ,* Headline 1 + ,** Subheadline 1.1 + ,*** Subsubheadline 1.1.1 + Text of Subsubheadline 1.1.1 + #+end_example + will be put on the same HTML page if this option is set, otherwise + Headline 1 and Subheadline 1.1 will each be put on a separate HTML + page with empty content. + + - ~org-html-multipage-nav-format~ :: + + #+vindex: org-html-multipage-nav-format + The HTML format string for the four navigation elements in the top + navigation menu of each page. See explanation of the variable + ~org-html-multipage-nav-format~. + + - ~org-html-multipage-numbered-filenames~ :: + + #+vindex: org-html-multipage-numbered-filenames + Boolean indicating whether filenames in multipage export should get + their headline-numbering prepended. Note that this option is + independent of the =num:= option and that the backend guarantees + that filenames are unique in any case. + + - ~org-html-multipage-open~ :: + + #+vindex: org-html-multipage-open + If and where to open the top page of the multipage html after + export. Possible values are =browser=, =buffer= or =nil=. Note that + all files will always be written, even for the =buffer= case. + + - ~org-html-multipage-postamble-position~ :: + + #+vindex: org-html-multipage-postamble-position + The position of the postamble in the html output. + Possible choices are =bottom= or =text-content=. + See [[*Multipage HTML specific CSS support]] + + - ~org-html-multipage-preamble-position~ :: + + #+vindex: org-html-multipage-preamble-position + The position of the postamble in the html output. + Possible choices are =top= or =text-content=. + See [[*Multipage HTML specific CSS support]] + + - ~org-html-multipage-split-hooks~ :: + + #+vindex: org-html-multipage-split-hooks + list of additional custom functions to be called during the export + after multipage splitting has taken place and before transcoding + with the =info= communication channel as input. + + - ~org-html-multipage-split-level~ :: + + #+vindex: org-html-multipage-split-level + Where to split the ORG file into multiple HTML pages. Can be either + =toc= for splitting into a separate page for each toc entry or a + number defining the maximum headline level for splitting. + + - ~org-html-multipage-toc-to-top~ :: + + #+vindex: org-html-multipage-toc-to-top + If t links in the table of contents will always point to the top of + the referenced page, otherwise it will link directly to the + referenced headline element. + + *** Multipage HTML specific CSS support + :PROPERTIES: + :DESCRIPTION: Changing the appearance of the Multipage HTML output. + :END: + #+cindex: CSS, for Multipage HTML export + #+cindex: HTML Multipage export, CSS + + #+vindex: org-html-multipage-preamble-position + #+vindex: org-html-multipage-preamble-position + #+vindex: org-html-multipage-postamble-position + In HTML multipage output each page will be generated with the + following structure: + + #+begin_example + ,* html + ,** head + ,** body + ,*** preamble + ,*** org-div-nav-menu + ,*** content + ,**** table-of-contents + ,**** page-main-body + ,***** nav-left + ,***** page-text-body + ,***** nav-right + ,*** postamble + #+end_example + + The default CSS shipped with org-mode will place a table of contents + to the left of the page content below the preamble and the top + navigation menu. This table of contents will contain /all/ headlines + according to the =toc= option, ignoring any =notoc= option within the + document to make every exported page of the document accessible. + + Preamble and postamble can be moved inside the page text body at its + top and bottom using =org-html-multipage-preamble-position= and + =org-html-multipage-postamble-position= respectively. Elements to be + skipped can be hidden by setting their =display= property to =none= in + the CSS. Note that the table of contents will only be generated if + + In addition to the single page HTML CSS support (see [[*CSS support]]) + the HTML Multipage exporter assigns the following special CSS classes + to appropriate parts of the document. They are mainly concerned with + navigation elements. The table of contents CSS below refers to the + table of contents generated for every page of the multipage HTML + output and /not/ to any additional toc inside the text body. + + | ~#org-div-nav-menu~ | Top Navigation Menu | + | ~#table-of-contents~ | the Table of Contents generated for every output page | + | ~#text-table-of-contents~ | the Table of Contents text area after its title | + | ~.ul-toc-level-N~ | the ul element of a toc entry with level N. | + | ~.toc-level-N~ | the li element of a toc entry with level N. | + | ~.toc-hidden~ | the li element of a toc entry to be (optionally) hidden | + | ~.toc-entry~ | the a element of a toc entry. | + | ~.toc-entry-active~ | The anchor of the toc entry currently active. | + | ~#nav-left~ | Navigation contained in the page-main-body div to the previous page. | + | ~#nav-right~ | Navigation contained in the page-main-body div to the next page | + | | | + ** LaTeX Export :PROPERTIES: :DESCRIPTION: Exporting to @LaTeX{} and processing to PDF. *************** *** 16655,16666 **** :UNNUMBERED: notoc :END: ! The Org export can filter not just for backends, but also for ! specific files through the =BIND= keyword. Here is an example with ! two filters; one removes brackets from time stamps, and the other ! removes strike-through text. The filter functions are defined in ! a code block in the same Org file, which is a handy location for ! debugging. #+begin_example ,#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp) --- 16830,16842 ---- :UNNUMBERED: notoc :END: ! The Org export can filter not just for backends, but also for specific ! files through the =BIND= keyword. Here is an example with two ! filters; one removes brackets from time stamps, and the other removes ! strike-through text. The filter functions are defined in a code block ! in the same Org file, which is a handy location for debugging. Note ! that ~org-export-allow-bind-keywords~ has to be non-nil for this to ! work. #+begin_example ,#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp) ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-05 16:52 ` Orm Finnendahl @ 2024-08-05 18:22 ` Ihor Radchenko 2024-08-06 7:19 ` Orm Finnendahl 2024-08-06 18:47 ` Orm Finnendahl 0 siblings, 2 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-08-05 18:22 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > attached are the patches for the multipage html export proposal. The > tgz file contains all commits after branching from the main branch to > the org-html-multipage branch (see: > https://github.com/ormf/org-mode/tree/org-html-multipage) Thanks! Although creating patches is not necessary in your case - remote git repo is good enough for me to check things. I am also a bit surprised that you went as far as adding documentation to the manual. We are a bit early into the review, so things are still going to change. Let's focus on the code first. > + (setq tmp-info info) > ... > + (setq global-prop org-export-filters-alist) I noticed temporary debug statements and some (message ...) statements sprinkled around. They are ok for the time being, but will need to be removed before merging upstream. > +(defvar org-export-multipage-split-functions nil > + "List of functions applied when multipage output has to be split.") Please be a bit more specific about what these functions are. Here is an example of a complete docstring: (defvar org-export-filter-parse-tree-functions nil "List of functions applied to the parsed tree. Each filter is called with three arguments: the parse tree, as returned by `org-element-parse-buffer', the backend, as a symbol, and the communication channel, as a plist. It must return the modified parse tree to transcode.") Also, please mention that `org-export-multipage-split-functions' are called _only_ when multipage output is requested. This means that `org-html-multipage-split' does not need to check :multipage property. > +(defun org-html-transcode-org-data (data content info) > + "Transcode the top org-data node of the org file to export. > ... > +(defun org-html-transcode-multipage (info &optional body-only) > + "Central routine transcoding to multipage output called by > +`org-html-transcode-org-data' called from `org-export-as'. > ... I see nothing specific to HTML in these two functions. Please, factor them out into ox.el. I think that they can be all merged into the default `org-export-transcode-org-data'. > +(defun org-html-multipage-split (data _backend info) > ... > + (if (not (file-writable-p dir)) (error "Output dir not writable") > + (let* ((encoding (or org-export-coding-system buffer-file-coding-system)) Checking output dir does not belong here. You should probably do it in `org-html-export-to-multipage' instead. Ideally, split function should do splitting, but not other things. > + ;; collect all org-pages to be exported. > + (plist-put info :multipage-org-pages > + (cl-loop > + for file in section-filenames > + for tl-headline in section-trees > + collect > + (list 'org-page > + (list :output-file (format "%s/%s" dir file) > + :tl-headline tl-headline > + :tl-headline-number > + (alist-get > + tl-headline > + stripped-section-headline-numbering)) > + nil)))))))) This is awkward. Why not modifying DATA directly? Say, you can transform it into (org-data (...) (org-page ...) (org-page ...) ...). -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-05 18:22 ` Ihor Radchenko @ 2024-08-06 7:19 ` Orm Finnendahl 2024-08-06 18:47 ` Orm Finnendahl 1 sibling, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-08-06 7:19 UTC (permalink / raw) To: emacs-orgmode; +Cc: Ihor Radchenko Hi Ihor, as always much appreciated. I'll look into that and get back. It might take a bit depending on how complicated it is as I have some other things on my org list right now, but we'll get there ;-) Best, Orm Am Montag, den 05. August 2024 um 18:22:22 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > attached are the patches for the multipage html export proposal. The > > tgz file contains all commits after branching from the main branch to > > the org-html-multipage branch (see: > > https://github.com/ormf/org-mode/tree/org-html-multipage) > > Thanks! Although creating patches is not necessary in your case - remote > git repo is good enough for me to check things. > > I am also a bit surprised that you went as far as adding documentation > to the manual. We are a bit early into the review, so things are still > going to change. Let's focus on the code first. > > > + (setq tmp-info info) > > ... > > + (setq global-prop org-export-filters-alist) > > I noticed temporary debug statements and some (message ...) statements > sprinkled around. They are ok for the time being, but will need to be > removed before merging upstream. > > > +(defvar org-export-multipage-split-functions nil > > + "List of functions applied when multipage output has to be split.") > > Please be a bit more specific about what these functions are. Here is an > example of a complete docstring: > > (defvar org-export-filter-parse-tree-functions nil > "List of functions applied to the parsed tree. > Each filter is called with three arguments: the parse tree, as > returned by `org-element-parse-buffer', the backend, as > a symbol, and the communication channel, as a plist. It must > return the modified parse tree to transcode.") > > Also, please mention that `org-export-multipage-split-functions' are > called _only_ when multipage output is requested. This means that > `org-html-multipage-split' does not need to check :multipage property. > > > +(defun org-html-transcode-org-data (data content info) > > + "Transcode the top org-data node of the org file to export. > > ... > > > +(defun org-html-transcode-multipage (info &optional body-only) > > + "Central routine transcoding to multipage output called by > > +`org-html-transcode-org-data' called from `org-export-as'. > > ... > > I see nothing specific to HTML in these two functions. Please, factor > them out into ox.el. I think that they can be all merged into the > default `org-export-transcode-org-data'. > > > +(defun org-html-multipage-split (data _backend info) > > ... > > + (if (not (file-writable-p dir)) (error "Output dir not writable") > > + (let* ((encoding (or org-export-coding-system buffer-file-coding-system)) > > Checking output dir does not belong here. > You should probably do it in `org-html-export-to-multipage' instead. > Ideally, split function should do splitting, but not other things. > > > + ;; collect all org-pages to be exported. > > + (plist-put info :multipage-org-pages > > + (cl-loop > > + for file in section-filenames > > + for tl-headline in section-trees > > + collect > > + (list 'org-page > > + (list :output-file (format "%s/%s" dir file) > > + :tl-headline tl-headline > > + :tl-headline-number > > + (alist-get > > + tl-headline > > + stripped-section-headline-numbering)) > > + nil)))))))) > > This is awkward. Why not modifying DATA directly? Say, you can > transform it into (org-data (...) (org-page ...) (org-page ...) ...). > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-05 18:22 ` Ihor Radchenko 2024-08-06 7:19 ` Orm Finnendahl @ 2024-08-06 18:47 ` Orm Finnendahl 2024-08-06 20:04 ` Orm Finnendahl 2024-08-10 12:32 ` Ihor Radchenko 1 sibling, 2 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-08-06 18:47 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi Ihor, it was easier than I thought, although still nasty: https://github.com/ormf/org-mode/tree/org-html-multipage Maybe you can check whether this is along the lines of what you had in mind. Am Montag, den 05. August 2024 um 18:22:22 Uhr (+0000) schrieb Ihor Radchenko: > I am also a bit surprised that you went as far as adding documentation > to the manual. We are a bit early into the review, so things are still > going to change. Let's focus on the code first. Don't be, it was just an exercise, not much work and I expect there are probably changes. I just thought to present it for commentary. > > + (setq tmp-info info) > > ... > > + (setq global-prop org-export-filters-alist) > > I noticed temporary debug statements and some (message ...) statements > sprinkled around. They are ok for the time being, but will need to be > removed before merging upstream. of course. I removed most of them now. > > +(defvar org-export-multipage-split-functions nil > > + "List of functions applied when multipage output has to be split.") > > Please be a bit more specific about what these functions are. Here is an > example of a complete docstring: > > (defvar org-export-filter-parse-tree-functions nil > "List of functions applied to the parsed tree. > Each filter is called with three arguments: the parse tree, as > returned by `org-element-parse-buffer', the backend, as > a symbol, and the communication channel, as a plist. It must > return the modified parse tree to transcode.") done. > Also, please mention that `org-export-multipage-split-functions' are > called _only_ when multipage output is requested. This means that > `org-html-multipage-split' does not need to check :multipage property. done. > > +(defun org-html-transcode-org-data (data content info) > > + "Transcode the top org-data node of the org file to export. > > ... > > > +(defun org-html-transcode-multipage (info &optional body-only) > > + "Central routine transcoding to multipage output called by > > +`org-html-transcode-org-data' called from `org-export-as'. > > ... > > I see nothing specific to HTML in these two functions. Please, factor > them out into ox.el. I think that they can be all merged into the > default `org-export-transcode-org-data'. I factored out org-html-transcode-multipage to org-export-transcode-multipage and got rid of org-html-transcode-multipage. > > +(defun org-html-multipage-split (data _backend info) > > ... > > + (if (not (file-writable-p dir)) (error "Output dir not writable") > > + (let* ((encoding (or org-export-coding-system buffer-file-coding-system)) > > Checking output dir does not belong here. That was a leftover, I had already fixed but forgot to delete the condition statement, thanks. > > This is awkward. Why not modifying DATA directly? Say, you can > transform it into (org-data (...) (org-page ...) (org-page ...) ...). I implemented it now by making org-page elements full citizens, adopting their contents so that you can org-export-data on them. It was quite nasty concerning link resolution but I found a reasonable way to solve this. This is just a proposal to check whether this architecture is the way to go. I got the idea that it might be feasible to integrate all page related properties directly into the properties of each org-page element rather than annotating info with this information. I will look into that in the following days as it might simplify the code somewhat, but it won't be a drastic change (just again probably a chasing of many nasty details ;-). -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-06 18:47 ` Orm Finnendahl @ 2024-08-06 20:04 ` Orm Finnendahl 2024-08-10 12:32 ` Ihor Radchenko 1 sibling, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-08-06 20:04 UTC (permalink / raw) To: emacs-orgmode; +Cc: Ihor Radchenko Am Dienstag, den 06. August 2024 um 20:47:22 Uhr (+0200) schrieb Orm Finnendahl: > > I factored out org-html-transcode-multipage to > org-export-transcode-multipage and got rid of > org-html-transcode-multipage. Sorry, I meant "I factored out org-html-transcode-org-data to org-export-transcode-org-data and got rid of org-html-transcode-multipage". ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-06 18:47 ` Orm Finnendahl 2024-08-06 20:04 ` Orm Finnendahl @ 2024-08-10 12:32 ` Ihor Radchenko 2024-08-11 10:54 ` Orm Finnendahl 1 sibling, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-08-10 12:32 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > it was easier than I thought, although still nasty: > > https://github.com/ormf/org-mode/tree/org-html-multipage > > Maybe you can check whether this is along the lines of what you had in > mind. >> Also, please mention that `org-export-multipage-split-functions' are >> called _only_ when multipage output is requested. This means that >> `org-html-multipage-split' does not need to check :multipage property. > > done. I do not see it in > (defvar org-export-multipage-split-functions nil > "List of functions applied to the parse tree after it has been > split for multipage output. Each function is called with three > arguments: The parse tree, as returned by > `org-element-parse-buffer', the backend, as a symbol, and the > communication channel, as a plist. It must return the modified > parse tree to transcode.") Also, as a side note, this docstring does not follow docstring conventions. Try M-x checkdoc >> > +(defun org-html-transcode-org-data (data content info) >> > + "Transcode the top org-data node of the org file to export. >> > ... >> >> > +(defun org-html-transcode-multipage (info &optional body-only) >> > + "Central routine transcoding to multipage output called by >> > +`org-html-transcode-org-data' called from `org-export-as'. >> > ... >> >> I see nothing specific to HTML in these two functions. Please, factor >> them out into ox.el. I think that they can be all merged into the >> default `org-export-transcode-org-data'. > > I factored out org-html-transcode-multipage to > org-export-transcode-multipage and got rid of > org-html-transcode-multipage. I do not see `org-export-transcode-multipage' in https://github.com/ormf/org-mode/tree/org-html-multipage Did you forget to push some commits? >> This is awkward. Why not modifying DATA directly? Say, you can >> transform it into (org-data (...) (org-page ...) (org-page ...) ...). > > I implemented it now by making org-page elements full citizens, > adopting their contents so that you can org-export-data on them. It > was quite nasty concerning link resolution but I found a reasonable > way to solve this. > > This is just a proposal to check whether this architecture is the way > to go. I got the idea that it might be feasible to integrate all page > related properties directly into the properties of each org-page > element rather than annotating info with this information. I will look > into that in the following days as it might simplify the code > somewhat, but it won't be a drastic change (just again probably a > chasing of many nasty details ;-). Looking forward. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-10 12:32 ` Ihor Radchenko @ 2024-08-11 10:54 ` Orm Finnendahl 2024-08-11 13:47 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-08-11 10:54 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi, Am Samstag, den 10. August 2024 um 12:32:12 Uhr (+0000) schrieb Ihor Radchenko: > I do not see it in > > > (defvar org-export-multipage-split-functions nil > > "List of functions applied to the parse tree after it has been > > split for multipage output. Each function is called with three > > arguments: The parse tree, as returned by > > `org-element-parse-buffer', the backend, as a symbol, and the > > communication channel, as a plist. It must return the modified > > parse tree to transcode.") > > Also, as a side note, this docstring does not follow docstring > conventions. Try M-x checkdoc I corrected it adding your suggestion explicitely. Checkdoc doesn't complain about this one any more, but complains all over the place with other docstrings not written by me as well, so I'm not sure. Please check again. > > > > I factored out org-html-transcode-multipage to > > org-export-transcode-multipage and got rid of > > org-html-transcode-multipage. > > I do not see `org-export-transcode-multipage' in > https://github.com/ormf/org-mode/tree/org-html-multipage > > Did you forget to push some commits? No, that was a typo in my mail. It should have said: > I factored out org-html-transcode-multipage to > org-export-transcode-org-data and got rid of > org-html-transcode-multipage. > > Looking forward. :-) I'll keep you posted... -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-11 10:54 ` Orm Finnendahl @ 2024-08-11 13:47 ` Ihor Radchenko 2024-08-11 14:44 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-08-11 13:47 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> Also, as a side note, this docstring does not follow docstring >> conventions. Try M-x checkdoc > > I corrected it adding your suggestion explicitely. Checkdoc doesn't > complain about this one any more, but complains all over the place > with other docstrings not written by me as well, so I'm not > sure. Please check again. > (defvar org-export-multipage-split-functions nil > "List of functions applied to the parse tree. > The functions are applied only, when multipage output is > requested. They are called after the parse tree has been split > for multipage output. This is kind of accurate (because of the implementation details), but very confusing. Mostly because this docstring also serves as the docstring for :filter-multipage-split export option. I'd prefer to be a bit more explicit in the design. Maybe, instead of using the same :filter-multipage-split option both to perform the document splitting and to post-process it, we can introduce two export options: 1. :multipage-split-function - the function (always one function!) to perform the split 2. :filter-multipage - functions applied on document AST after it is processed by :multipage-split-function. >> I do not see `org-export-transcode-multipage' in >> https://github.com/ormf/org-mode/tree/org-html-multipage >> >> Did you forget to push some commits? > > No, that was a typo in my mail. It should have said: > >> I factored out org-html-transcode-multipage to >> org-export-transcode-org-data and got rid of >> org-html-transcode-multipage. I think you misunderstood what I was asking about. My point is that `org-html-transcode-org-page' largely duplicates what is already done in `org-export-transcode-org-data' - processing 'inner-templtate and 'template. My suggestion is to move generic parts of `org-html-transcode-org-page' to ox.el and call it `org-export-transcode-org-page'. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-11 13:47 ` Ihor Radchenko @ 2024-08-11 14:44 ` Orm Finnendahl 2024-08-12 8:35 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-08-11 14:44 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list [-- Attachment #1: Type: text/plain, Size: 2615 bytes --] Hi, OK, got it, I'll check and implement everything tomorrow when I'm back on my desk... Am 11. August 2024 15:47:30 MESZ schrieb Ihor Radchenko <yantar92@posteo.net>: >Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > >>> Also, as a side note, this docstring does not follow docstring >>> conventions. Try M-x checkdoc >> >> I corrected it adding your suggestion explicitely. Checkdoc doesn't >> complain about this one any more, but complains all over the place >> with other docstrings not written by me as well, so I'm not >> sure. Please check again. > >> (defvar org-export-multipage-split-functions nil >> "List of functions applied to the parse tree. >> The functions are applied only, when multipage output is >> requested. They are called after the parse tree has been split >> for multipage output. > >This is kind of accurate (because of the implementation details), but >very confusing. Mostly because this docstring also serves as the >docstring for :filter-multipage-split export option. I'd prefer to be a >bit more explicit in the design. > >Maybe, instead of using the same :filter-multipage-split option both to >perform the document splitting and to post-process it, we can introduce >two export options: > >1. :multipage-split-function - the function (always one function!) to > perform the split > >2. :filter-multipage - functions applied on document AST after it is > processed by :multipage-split-function. > >>> I do not see `org-export-transcode-multipage' in >>> https://github.com/ormf/org-mode/tree/org-html-multipage >>> >>> Did you forget to push some commits? >> >> No, that was a typo in my mail. It should have said: >> >>> I factored out org-html-transcode-multipage to >>> org-export-transcode-org-data and got rid of >>> org-html-transcode-multipage. > >I think you misunderstood what I was asking about. >My point is that `org-html-transcode-org-page' largely duplicates what >is already done in `org-export-transcode-org-data' - processing >'inner-templtate and 'template. My suggestion is to move generic parts >of `org-html-transcode-org-page' to ox.el and call it >`org-export-transcode-org-page'. > >-- >Ihor Radchenko // yantar92, >Org mode contributor, >Learn more about Org mode at <https://orgmode.org/>. >Support Org development at <https://liberapay.com/org-mode>, >or support my work at <https://liberapay.com/yantar92> ----------------- Prof. Orm Finnendahl Komposition Hochschule für Musik und Darstellende Kunst Eschersheimer Landstr. 29-39 60322 Frankfurt am Main [-- Attachment #2: Type: text/html, Size: 3962 bytes --] ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-11 14:44 ` Orm Finnendahl @ 2024-08-12 8:35 ` Orm Finnendahl 2024-08-12 17:10 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-08-12 8:35 UTC (permalink / raw) To: emacs-orgmode Hi, I made the changes Ihor suggested and made all docstrings compliant with checkdoc. Please check whether this is now how you imagined it. Concerning the options stored in the org-page properties rather than in info I mentioned in an earlier mail, I found out it actually doesn't really change anything substantially or clarifies/reduces the code, so I decided against it. ATM it doesn't make all that much sense to me. If we're nearing code completion, we could also start tackling the documentation. I think there should be an addition for the multipage filter in ox.el (under "Filter System") and maybe some other additions to explain the mechanism for multipage output (where?) Maybe I can also get some assessment what's needed in org-manual and what to change in order to make the doc additions proposals I made compliant with the rest of org-manual. -- Orm Am Sonntag, den 11. August 2024 um 16:44:47 Uhr (+0200) schrieb Orm Finnendahl: > Hi, > > OK, got it, I'll check and implement everything tomorrow when I'm back on my desk... > > Am 11. August 2024 15:47:30 MESZ schrieb Ihor Radchenko <yantar92@posteo.net>: > >Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > >>> Also, as a side note, this docstring does not follow docstring > >>> conventions. Try M-x checkdoc > >> > >> I corrected it adding your suggestion explicitely. Checkdoc doesn't > >> complain about this one any more, but complains all over the place > >> with other docstrings not written by me as well, so I'm not > >> sure. Please check again. > > > >> (defvar org-export-multipage-split-functions nil > >> "List of functions applied to the parse tree. > >> The functions are applied only, when multipage output is > >> requested. They are called after the parse tree has been split > >> for multipage output. > > > >This is kind of accurate (because of the implementation details), but > >very confusing. Mostly because this docstring also serves as the > >docstring for :filter-multipage-split export option. I'd prefer to be a > >bit more explicit in the design. > > > >Maybe, instead of using the same :filter-multipage-split option both to > >perform the document splitting and to post-process it, we can introduce > >two export options: > > > >1. :multipage-split-function - the function (always one function!) to > > perform the split > > > >2. :filter-multipage - functions applied on document AST after it is > > processed by :multipage-split-function. > > > >>> I do not see `org-export-transcode-multipage' in > >>> https://github.com/ormf/org-mode/tree/org-html-multipage > >>> > >>> Did you forget to push some commits? > >> > >> No, that was a typo in my mail. It should have said: > >> > >>> I factored out org-html-transcode-multipage to > >>> org-export-transcode-org-data and got rid of > >>> org-html-transcode-multipage. > > > >I think you misunderstood what I was asking about. > >My point is that `org-html-transcode-org-page' largely duplicates what > >is already done in `org-export-transcode-org-data' - processing > >'inner-templtate and 'template. My suggestion is to move generic parts > >of `org-html-transcode-org-page' to ox.el and call it > >`org-export-transcode-org-page'. > > > >-- > >Ihor Radchenko // yantar92, > >Org mode contributor, > >Learn more about Org mode at <https://orgmode.org/>. > >Support Org development at <https://liberapay.com/org-mode>, > >or support my work at <https://liberapay.com/yantar92> > > ----------------- > Prof. Orm Finnendahl > Komposition > Hochschule für Musik und Darstellende Kunst > Eschersheimer Landstr. 29-39 > 60322 Frankfurt am Main ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-12 8:35 ` Orm Finnendahl @ 2024-08-12 17:10 ` Ihor Radchenko 2024-08-12 18:58 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-08-12 17:10 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > I made the changes Ihor suggested and made all docstrings compliant > with checkdoc. Please check whether this is now how you imagined it. Thanks! I still have comments, but let's not focus on this minor issue yet. > Concerning the options stored in the org-page properties rather than > in info I mentioned in an earlier mail, I found out it actually > doesn't really change anything substantially or clarifies/reduces the > code, so I decided against it. ATM it doesn't make all that much > sense to me. Ok, but I am seeing > (defun org-export-transcode-org-page (org-page _ info) > ... > (let* ((body-only (org-element-property :body-only org-page)) > ... > (put-text-property > 0 1 :output-file (org-element-property :output-file org-page) final-output) which is still relying upon custom properties. > If we're nearing code completion, we could also start tackling the > documentation. I think there should be an addition for the multipage > filter in ox.el (under "Filter System") and maybe some other additions > to explain the mechanism for multipage output (where?) > Maybe I can also get some assessment what's needed in org-manual and > what to change in order to make the doc additions proposals I made > compliant with the rest of org-manual. No, we are not nearing code completion. I am just getting started on the review process. We still need to decide and finalize the changes to export system that we need to adapt globally, without tying it to ox-html exporter. We are still at high-level review stage. See the next set of comments below > (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) > ... > (when (plist-get info :multipage) > (setq tree (org-export-filter-apply-functions > (plist-get info :filter-multipage) > (funcall > (plist-get info :multipage-split-function) tree info) :multipage-split-function should be added to the :translate-alist I think. It should be documented what :multipage-split-function is supposed to do in the docstring of `org-export-define-backend'. I do not feel like :multipage-split-function is supposed to be export _option_. It is more internal. That's why :translate-alist, where the internals like templates and transcoders lie. > (defun org-export-transcode-org-page (org-page _ info) > ... > (let* ((body-only (org-element-property :body-only org-page)) > (info (cl-list* ;; add :tl-headline and :tl-headline-number to info > :tl-headline headline > :tl-headline-number > (alist-get > headline > (plist-get info :headline-numbering)) > info)) May you please explain what is the purpose of constructing custom INFO plist, what all these parameters do, and why you re-do the export again in the transcoder discarding the CONTENTS argument provided? > (defun org-export-transcode-org-data (data body info) > "Transcode DATA with BODY. Return transcoded string. > DATA is the top `org-data' node of the parse-tree. INFO is the > communication channel plist." > (if (plist-get info :multipage) > ;;; for multipage output the `org-data' node contains `org-page' > ;;; pseudo elements as contents, so we call `org-export-data' on > ;;; each of them and return the collected results. > (mapcar (lambda (org-page) > (org-export-data org-page info)) > (org-element-contents data)) This is not a transcoder's job to export its contents. Please move special handling of org-page AST nodes to `org-export-data'. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-12 17:10 ` Ihor Radchenko @ 2024-08-12 18:58 ` Orm Finnendahl 2024-08-17 7:21 ` Rudolf Adamkovič 2024-08-17 14:05 ` Ihor Radchenko 0 siblings, 2 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-08-12 18:58 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi, again thanks for checking. Am Montag, den 12. August 2024 um 17:10:25 Uhr (+0000) schrieb Ihor Radchenko: > > :multipage-split-function should be added to the :translate-alist I > think. It should be documented what :multipage-split-function is > supposed to do in the docstring of `org-export-define-backend'. > > > I do not feel like :multipage-split-function is supposed to be export > _option_. It is more internal. That's why :translate-alist, where the > internals like templates and transcoders lie. That's how I had it before, but I reasoned it is not a transcoding function either, so I was unsure. Anyway I reversed it. > > (defun org-export-transcode-org-page (org-page _ info) > > ... > > (let* ((body-only (org-element-property :body-only org-page)) > > (info (cl-list* ;; add :tl-headline and :tl-headline-number to info > > :tl-headline headline > > :tl-headline-number > > (alist-get > > headline > > (plist-get info :headline-numbering)) > > info)) > > May you please explain what is the purpose of constructing custom INFO > plist, what all these parameters do, and why you re-do the export again > in the transcoder discarding the CONTENTS argument provided? > The redo of the transcoding was a leftover from debugging an earlier stage. Removed now. :tl-headline and :tl-headline-numbering are needed for constructing the side toc and the footnote section on each page. They are needed in org-html-multipage-toc, called by org-html-multipage-template and in org-html-footnote-section called from org-html-multipage-inner-template. At that stage there is no information about the page, the templates are on. Let me know if you have a better idea how to provide/access that information, I found a temporary addition to info the most natural way. As it will be needed by any multipage backend which wants to determine the footnotes for a page, I think there should be a generic solution in ox.el. As :tl-headline-numbering can be determined from the tl-headline within org-html-multipage-toc, I can get rid of that if you prefer. Let me know how to proceed. > > (defun org-export-transcode-org-data (data body info) > > "Transcode DATA with BODY. Return transcoded string. > > DATA is the top `org-data' node of the parse-tree. INFO is the > > communication channel plist." > > (if (plist-get info :multipage) > > ;;; for multipage output the `org-data' node contains `org-page' > > ;;; pseudo elements as contents, so we call `org-export-data' on > > ;;; each of them and return the collected results. > > (mapcar (lambda (org-page) > > (org-export-data org-page info)) > > (org-element-contents data)) > > This is not a transcoder's job to export its contents. > Please move special handling of org-page AST nodes to `org-export-data'. done. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-12 18:58 ` Orm Finnendahl @ 2024-08-17 7:21 ` Rudolf Adamkovič 2024-08-17 14:05 ` Ihor Radchenko 1 sibling, 0 replies; 72+ messages in thread From: Rudolf Adamkovič @ 2024-08-17 7:21 UTC (permalink / raw) To: Orm Finnendahl, Ihor Radchenko; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > [...] Let me know how to proceed. CC: Ihor :) Rudy -- "Chop your own wood and it will warm you twice." --- Henry Ford; Francis Kinloch, 1819; Henry David Thoreau, 1854 Rudolf Adamkovič <rudolf@adamkovic.org> [he/him] http://adamkovic.org ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-12 18:58 ` Orm Finnendahl 2024-08-17 7:21 ` Rudolf Adamkovič @ 2024-08-17 14:05 ` Ihor Radchenko 2024-08-19 16:31 ` Orm Finnendahl 1 sibling, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-08-17 14:05 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> I do not feel like :multipage-split-function is supposed to be export >> _option_. It is more internal. That's why :translate-alist, where the >> internals like templates and transcoders lie. > > That's how I had it before, but I reasoned it is not a transcoding > function either, so I was unsure. Anyway I reversed it. Thanks! >> This is not a transcoder's job to export its contents. >> Please move special handling of org-page AST nodes to `org-export-data'. > > done. > + ((and (eq (org-element-type data) 'org-data) > + (plist-get info :multipage)) > + (mapcar (lambda (org-page) > + (org-export-data org-page info)) > + (org-element-contents data))) > + ;; Element/Object with contents. I am looking at this, and it feels like a wrong direction to go, especially if we want to generalize multi-file export to non-pages as well (e.g. formula exported as mathml file and as a link inside actual exported .odt file). Let's try to do it differently: 1. Introduce a new INFO plist field :multipage-pages - a list of extra pages to be exported in addition to the main document 2. Transocders can populate the list as needed, in addition to their normal return value, which may be a link to the page, for example 3. "pages" in the list, can be constructed using `org-export-with-backend' or other usual means to export data. 4. org-export-as will process all the pages from :multipage-pages in addition to the one returned by `org-export-data'. I believe that this approach should be the least breaking and the most flexible. WDYT? >> > (info (cl-list* ;; add :tl-headline and :tl-headline-number to info >> > :tl-headline headline >> > :tl-headline-number >> > (alist-get >> > headline >> > (plist-get info :headline-numbering)) >> > info)) >> >> May you please explain what is the purpose of constructing custom INFO >> plist, what all these parameters do, and why you re-do the export again >> in the transcoder discarding the CONTENTS argument provided? >> ... > :tl-headline and :tl-headline-numbering are needed for constructing > the side toc and the footnote section on each page. They are needed in > org-html-multipage-toc, called by org-html-multipage-template and in > org-html-footnote-section called from > org-html-multipage-inner-template. At that stage there is no > information about the page, the templates are on. Let me know if you > have a better idea how to provide/access that information, I found a > temporary addition to info the most natural way. As it will be needed > by any multipage backend which wants to determine the footnotes for a > page, I think there should be a generic solution in ox.el. > > As :tl-headline-numbering can be determined from the tl-headline > within org-html-multipage-toc, I can get rid of that if you > prefer. Let me know how to proceed. With my idea above, we handle the actual page rendering to a custom backend, which can reuse the normal TOC machinery, possibly encapsulated into sub-backend parameters. We can provide any additional info that is necessary within such sub-backend. Do note that we should not assume that each page corresponds to a headline in ox.el. It may be anything. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-17 14:05 ` Ihor Radchenko @ 2024-08-19 16:31 ` Orm Finnendahl 2024-08-22 12:27 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-08-19 16:31 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi, don't know, I understand what you're after. Questions below. Am Samstag, den 17. August 2024 um 14:05:07 Uhr (+0000) schrieb Ihor Radchenko: > > Let's try to do it differently: > > 1. Introduce a new INFO plist field :multipage-pages - a list of extra > pages to be exported in addition to the main document > > 2. Transcoders can populate the list as needed, in addition to their > normal return value, which may be a link to the page, for example > 3. "pages" in the list, can be constructed using > `org-export-with-backend' or other usual means to export data. > 4. org-export-as will process all the pages from :multipage-pages in > addition to the one returned by `org-export-data'. > What does "in addition to the main document" or "to the one returned by `org-export-data'" mean? In the current multipage code, org-export-data returns a list of strings corresponding to the exported pages. In the case of html multipage output: Should :multipage-pages contain what is supposed to get exported by the multipage-html subbackend, or should the pages to be exported be left as subpages of org-data in the :parse-tree like as it is now? If they are contained in :multipage-pages, we don't need any rendering of the org-data node in the :parse-tree. Should the elements of org-data then just get deleted and we return an empty string from org-export-as in addition to the list of strings from :multipage-pages? > I believe that this approach should be the least breaking and the most flexible. > > WDYT? Can't tell until I've fully understood your proposal. > With my idea above, we handle the actual page rendering to a custom > backend, which can reuse the normal TOC machinery, possibly encapsulated > into sub-backend parameters. We can provide any additional info that is > necessary within such sub-backend. It's not clear to me, how the encapsulation of parameters is handled, who is writing the output files, etc. Sorry, I'm just confused... > > Do note that we should not assume that each page corresponds to a > headline in ox.el. It may be anything. Sure. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-08-19 16:31 ` Orm Finnendahl @ 2024-08-22 12:27 ` Ihor Radchenko 0 siblings, 0 replies; 72+ messages in thread From: Ihor Radchenko @ 2024-08-22 12:27 UTC (permalink / raw) To: Orm Finnendahl; +Cc: Org mailing list Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > ... >> With my idea above, we handle the actual page rendering to a custom >> backend, which can reuse the normal TOC machinery, possibly encapsulated >> into sub-backend parameters. We can provide any additional info that is >> necessary within such sub-backend. > > It's not clear to me, how the encapsulation of parameters is handled, > who is writing the output files, etc. Sorry, I'm just confused... Well... I think that I need to rethink it again. I still do not have a fully clear idea on how to incorporate multipage export into the existing APIs. May take some time. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-24 10:20 ` Ihor Radchenko ` (2 preceding siblings ...) 2024-07-25 9:57 ` Orm Finnendahl @ 2024-07-26 8:22 ` Orm Finnendahl 2024-07-27 13:01 ` Ihor Radchenko 3 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-26 8:22 UTC (permalink / raw) To: emacs-orgmode Hi, I can implement everything now with your changes, but not exactly in the way you propose: Am Mittwoch, den 24. Juli 2024 um 10:20:16 Uhr (+0000) schrieb Ihor Radchenko: > I believe that my changes should allow you to implement multipage export > in the following way: > > 1. You can use :filter-parse-tree in ox-html backend to replace the > original (org-data ...) AST with a list of ((org-page ...) > (org-page ...) ...) pseudo-elements and populate INFO channel > with auxiliary information you now compute in > `org-html-process-multipage' :filter-parse-tree kicks in before `org-export--collect-tree-properties' adds the headline-numbering, which needs to be present before the multipage code can do its work. I can do everything in `org-html-transcode-org-data' (processing the parse-tree and transcoding to lists), but it is semantically not as clean as you propose with org-page pseudo-elements. I see 3 options: 1. I just finish it doing everything in `org-html-transcode-org-data'. 2. We change the order of `org-export--collect-tree-properties' and the call to :filter-parse-tree in ox.el, but that might be breaking other backends. 3. Add another filter function property to be called after `org-export--collect-tree-properties' has been executed (:filter-final-parse-tree?). wdyt? -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-26 8:22 ` Orm Finnendahl @ 2024-07-27 13:01 ` Ihor Radchenko 2024-07-27 14:25 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-27 13:01 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> 1. You can use :filter-parse-tree in ox-html backend to replace the >> original (org-data ...) AST with a list of ((org-page ...) >> (org-page ...) ...) pseudo-elements and populate INFO channel >> with auxiliary information you now compute in >> `org-html-process-multipage' > > :filter-parse-tree kicks in before > `org-export--collect-tree-properties' adds the headline-numbering, > which needs to be present before the multipage code can do its work. Your concern raises a more important question on headline numbering across individual pages. It may or may not be desirable to have fall-through numbering of headings. I can see how some variants of multipage export may choose to number headings either using continuous numbering across the pages or to restart the numbering for each page individually. Moreover, things like :headline-offset or citations may or may not need to be computed across the pages. :headline-offset should probably be limited to a single page, for example. For citations, multiple options may be considered (think about numbered references that may either be global across the pages or local, per-page). To address the above concerns, we will probably need to introduce global :multipage setting alongside with multiple others (like settings controlling headline numbering). Further, we will need to make sure that the splitter runs last, after normal split functions, so that nothing can interfere with it. But for now, let's do minimal required change that does not introduce too many new things and simply modify `org-export--annotate-info' as the following (setq tree (org-export-filter-apply-functions (plist-get info :filter-parse-tree) tree info)) (setq info (org-export--collect-tree-properties tree info)) (when (plist-get info :multipage) (setq tree (org-export-filter-apply-functions (plist-get info :multipage-split) tree info))) (when (plist-get info :with-cite-processors) (org-cite-process-citations info) (org-cite-process-bibliography info)) :multipage-split and :multipage are new global export options. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-27 13:01 ` Ihor Radchenko @ 2024-07-27 14:25 ` Orm Finnendahl 0 siblings, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-27 14:25 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Hi Ihor, that's spot on what I wanted to suggest, thanks! -- Orm Am Samstag, den 27. Juli 2024 um 13:01:12 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > >> 1. You can use :filter-parse-tree in ox-html backend to replace the > >> original (org-data ...) AST with a list of ((org-page ...) > >> (org-page ...) ...) pseudo-elements and populate INFO channel > >> with auxiliary information you now compute in > >> `org-html-process-multipage' > > > > :filter-parse-tree kicks in before > > `org-export--collect-tree-properties' adds the headline-numbering, > > which needs to be present before the multipage code can do its work. > > Your concern raises a more important question on headline numbering > across individual pages. It may or may not be desirable to have > fall-through numbering of headings. I can see how some variants of > multipage export may choose to number headings either using continuous > numbering across the pages or to restart the numbering for each page > individually. > > Moreover, things like :headline-offset or citations may or may not need > to be computed across the pages. :headline-offset should probably be > limited to a single page, for example. For citations, multiple options > may be considered (think about numbered references that may either be > global across the pages or local, per-page). > > To address the above concerns, we will probably need to introduce global > :multipage setting alongside with multiple others (like settings > controlling headline numbering). Further, we will need to make sure that > the splitter runs last, after normal split functions, so that nothing > can interfere with it. > > But for now, let's do minimal required change that does not introduce too > many new things and simply modify `org-export--annotate-info' as the > following > > (setq tree (org-export-filter-apply-functions (plist-get info :filter-parse-tree) tree info)) > (setq info (org-export--collect-tree-properties tree info)) > > (when (plist-get info :multipage) > (setq tree (org-export-filter-apply-functions (plist-get info :multipage-split) tree info))) > > (when (plist-get info :with-cite-processors) > (org-cite-process-citations info) > (org-cite-process-bibliography info)) > > > :multipage-split and :multipage are new global export options. > > -- > Ihor Radchenko // yantar92, > Org mode contributor, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> > ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 11:35 ` Orm Finnendahl 2024-07-23 12:52 ` Ihor Radchenko 2024-07-23 14:13 ` Ihor Radchenko @ 2024-07-23 14:19 ` Ihor Radchenko 2024-07-23 15:13 ` Orm Finnendahl 2 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 14:19 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > ... I think printing > headline numbers should get handled in the transcoding stage of the > backend and not before. I am confused here. What do you mean by "printing"? > ... Multipage export behind the scenes is > completely dependant on headline numbering, even if headlines aren't > displayed, so the code in ox.el first proceeds, as if headline > numbering is turned on and moves the check for headline numbering to > the transcoding stage. I didn't change the behaviour in the > single-page html situation. Although I think that it might make sense > that headline-numbering in general only gets checked at the > transcoding stage that would affect all backends, so I didn't change > anything. I am again confused. There are three main functions handling headline numbering: 1. `org-export--collect-headline-numbering' 2. `org-export-get-headline-number' 3. `org-export-numbered-headline-p' `org-export--collect-headline-numbering' is evaluated unconditionally, regardless of num:t or num:nil settings. `org-export-get-headline-number' and `org-export-numbered-headline-p' are API functions that get called by the individual backends as needed. If they deem it necessary to ignore :section-numbers setting, they are free to. What is wrong with these three functions? -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 14:19 ` Ihor Radchenko @ 2024-07-23 15:13 ` Orm Finnendahl 2024-07-23 16:20 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 15:13 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode tAm Dienstag, den 23. Juli 2024 um 14:19:00 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > > ... I think printing > > headline numbers should get handled in the transcoding stage of the > > backend and not before. > > I am confused here. > What do you mean by "printing"? I mean creating the output string. > `org-export--collect-headline-numbering' is evaluated unconditionally, > regardless of num:t or num:nil settings. Are you sure? org-export--collect-headline-numbering has this in its body: (org-element-map data 'headline (lambda (headline) (when (and (org-export-numbered-headline-p headline options) (not (org-element-property :footnote-section-p headline))) ...))) If num:nil headline numbers don't get collected, or am I missing something? But I will doublecheck just to be sure... -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 15:13 ` Orm Finnendahl @ 2024-07-23 16:20 ` Ihor Radchenko 2024-07-23 17:02 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 16:20 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> `org-export--collect-headline-numbering' is evaluated unconditionally, >> regardless of num:t or num:nil settings. > > Are you sure? org-export--collect-headline-numbering has this in its > body: > > (org-element-map data 'headline > (lambda (headline) > (when (and (org-export-numbered-headline-p headline options) > (not (org-element-property :footnote-section-p headline))) > ...))) > > If num:nil headline numbers don't get collected, or am I missing > something? You are right. However, changing `org-export-numbered-headline-p' to use :multipage is not the right approach to achieve what you need. If you think that multipage export should use a different set of options, we need to implement it differently. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 16:20 ` Ihor Radchenko @ 2024-07-23 17:02 ` Orm Finnendahl 2024-07-23 17:13 ` Ihor Radchenko 0 siblings, 1 reply; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 17:02 UTC (permalink / raw) To: emacs-orgmode Am Dienstag, den 23. Juli 2024 um 16:20:39 Uhr (+0000) schrieb Ihor Radchenko: > Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > > >> `org-export--collect-headline-numbering' is evaluated unconditionally, > >> regardless of num:t or num:nil settings. > > > > Are you sure? org-export--collect-headline-numbering has this in its > > body: > > > > (org-element-map data 'headline > > (lambda (headline) > > (when (and (org-export-numbered-headline-p headline options) > > (not (org-element-property :footnote-section-p headline))) > > ...))) > > > > If num:nil headline numbers don't get collected, or am I missing > > something? > > You are right. > However, changing `org-export-numbered-headline-p' to use :multipage is > not the right approach to achieve what you need. > > If you think that multipage export should use a different set of > options, we need to implement it differently. Is that a semantic problem so we need to implement an option like :always-collect-headline-numbering instead of :multipage in org-export-numbered-headline-p? If on the other hand we define a replacement of org-export--collect-headline-numbering, we also have to do so for all functions up the stack, like org-export--annotate-info and org-export--collect-tree-properties. Or what did you have in mind? -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 17:02 ` Orm Finnendahl @ 2024-07-23 17:13 ` Ihor Radchenko 2024-07-23 19:00 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Ihor Radchenko @ 2024-07-23 17:13 UTC (permalink / raw) To: Orm Finnendahl; +Cc: emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: >> If you think that multipage export should use a different set of >> options, we need to implement it differently. > > Is that a semantic problem so we need to implement an option like > :always-collect-headline-numbering instead of :multipage in > org-export-numbered-headline-p? If on the other hand we define a > replacement of org-export--collect-headline-numbering, we also have to > do so for all functions up the stack, like org-export--annotate-info > and org-export--collect-tree-properties. Or what did you have in mind? What I had in mind if using backend-specific :filter-options. If a backends needs to enable headline numbering unconditionally, when :multipage is used, it can install :filter-options filter that will set :section-numbers to t. Does it make sense? -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-23 17:13 ` Ihor Radchenko @ 2024-07-23 19:00 ` Orm Finnendahl 0 siblings, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-23 19:00 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Org mailing list Am Dienstag, den 23. Juli 2024 um 17:13:56 Uhr (+0000) schrieb Ihor Radchenko: > > What I had in mind if using backend-specific :filter-options. > If a backends needs to enable headline numbering unconditionally, when > :multipage is used, it can install :filter-options filter that will set > :section-numbers to t. > > Does it make sense? Yes, but I have to check whether this can be reverted afterwards, as in the :multipage case we still need the information of the initial setting of :section-numbers when transcoding finally happens. It's a bit late today to digest it all, but I'll look into it tomorrow and will get back to you with questions in case I don't get it. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-03 9:44 multipage html output Orm Finnendahl 2024-07-03 10:33 ` Dr. Arne Babenhauserheide 2024-07-03 10:58 ` Christian Moe @ 2024-07-03 21:11 ` Rudolf Adamkovič 2 siblings, 0 replies; 72+ messages in thread From: Rudolf Adamkovič @ 2024-07-03 21:11 UTC (permalink / raw) To: Orm Finnendahl, emacs-orgmode Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes: > - Is there widespread interest to fully integrate it into org mode? Definitely. :) Rudy -- "It is no paradox to say that in our most theoretical moods we may be nearest to our most practical applications." --- Alfred North Whitehead, 1861-1947 Rudolf Adamkovič <rudolf@adamkovic.org> [he/him] http://adamkovic.org ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output @ 2024-07-06 5:47 Pedro Andres Aranda Gutierrez 2024-07-06 9:04 ` Orm Finnendahl 0 siblings, 1 reply; 72+ messages in thread From: Pedro Andres Aranda Gutierrez @ 2024-07-06 5:47 UTC (permalink / raw) To: orm.finnendahl; +Cc: Ihor Radchenko, Org Mode List [-- Attachment #1: Type: text/plain, Size: 586 bytes --] Sorry for bumping in, I've been more off than on in the last couple of weeks... Just a stupid question: have you considered any marker to force a page break? That would make this functionality portable to other exporters like LaTeX, where you can force a page break with \clearpage or \cleardoublepage. (Hopefully) my .2 cents, /PA -- Fragen sind nicht da, um beantwortet zu werden, Fragen sind da um gestellt zu werden Georg Kreisler Headaches with a Juju log: unit-basic-16: 09:17:36 WARNING juju.worker.uniter.operation we should run a leader-deposed hook here, but we can't yet [-- Attachment #2: Type: text/html, Size: 947 bytes --] ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: multipage html output 2024-07-06 5:47 Pedro Andres Aranda Gutierrez @ 2024-07-06 9:04 ` Orm Finnendahl 0 siblings, 0 replies; 72+ messages in thread From: Orm Finnendahl @ 2024-07-06 9:04 UTC (permalink / raw) To: Org Mode List Hi, Am Samstag, den 06. Juli 2024 um 07:47:43 Uhr (+0200) schrieb Pedro Andres Aranda Gutierrez: > Sorry for bumping in, I've been more off than on in the last couple of > weeks... > Just a stupid question: have you considered any marker to force a page > break? > That would make this functionality portable to other exporters like LaTeX, > where > you can force a page break with \clearpage or \cleardoublepage. although this is of course possible, currently I'm not planning to implement it. Regarding html export I see some problems with that idea: 1. It would either open a new can of worms if this page would be added to the toc with all sorts of ensuing problems like naming, etc. and getting out of sync with the Latex document's toc. or 2. Those additinal pages don't get added to the toc and are only reachable by navigation elements, which I consider suboptimal (and you'd still have to name them). In any case, currently I'm facing many problems concerning the glorious hairy details and am glad if I can sort them out in a way that they are general enough to be added to ox. Adding additional engines to handle page breaks the way you envision should then be feasible without reinventing the wheel. -- Orm ^ permalink raw reply [flat|nested] 72+ messages in thread
end of thread, other threads:[~2024-08-22 12:27 UTC | newest] Thread overview: 72+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-07-03 9:44 multipage html output Orm Finnendahl 2024-07-03 10:33 ` Dr. Arne Babenhauserheide 2024-07-03 10:58 ` Christian Moe 2024-07-03 11:05 ` Ihor Radchenko 2024-07-03 14:34 ` Christian Moe 2024-07-04 9:50 ` Orm Finnendahl 2024-07-04 11:41 ` Ihor Radchenko 2024-07-04 13:33 ` Orm Finnendahl 2024-07-04 16:20 ` Ihor Radchenko 2024-07-07 19:33 ` Orm Finnendahl 2024-07-08 15:29 ` Ihor Radchenko 2024-07-08 19:12 ` Orm Finnendahl 2024-07-09 17:55 ` Ihor Radchenko 2024-07-10 18:03 ` Orm Finnendahl 2024-07-10 18:53 ` Ihor Radchenko 2024-07-07 20:50 ` Orm Finnendahl 2024-07-08 15:05 ` Ihor Radchenko 2024-07-08 15:41 ` Orm Finnendahl 2024-07-08 15:56 ` Ihor Radchenko 2024-07-08 19:18 ` Orm Finnendahl 2024-07-09 18:08 ` Ihor Radchenko 2024-07-10 19:37 ` Orm Finnendahl 2024-07-11 12:35 ` Ihor Radchenko 2024-07-13 7:44 ` Orm Finnendahl 2024-07-13 10:13 ` Ihor Radchenko 2024-07-13 11:01 ` Orm Finnendahl 2024-07-23 8:56 ` Orm Finnendahl 2024-07-23 10:24 ` Ihor Radchenko 2024-07-23 11:35 ` Orm Finnendahl 2024-07-23 12:52 ` Ihor Radchenko 2024-07-23 14:56 ` Orm Finnendahl [not found] ` <Zp_EhDDxxYRWKFPL@orm-t14s> [not found] ` <874j8g2lvq.fsf@localhost> 2024-07-23 15:36 ` Orm Finnendahl 2024-07-23 14:13 ` Ihor Radchenko [not found] ` <Zp_b2lL2SzDswa-w@orm-t14s> 2024-07-23 17:10 ` Ihor Radchenko 2024-07-23 20:35 ` Orm Finnendahl 2024-07-24 10:20 ` Ihor Radchenko 2024-07-24 11:24 ` Orm Finnendahl 2024-07-25 9:49 ` Orm Finnendahl 2024-07-25 9:57 ` Ihor Radchenko 2024-07-25 9:57 ` Orm Finnendahl 2024-07-25 10:04 ` Ihor Radchenko 2024-07-25 14:59 ` Orm Finnendahl 2024-07-27 19:24 ` Orm Finnendahl 2024-07-27 19:39 ` Ihor Radchenko 2024-08-05 16:52 ` Orm Finnendahl 2024-08-05 18:22 ` Ihor Radchenko 2024-08-06 7:19 ` Orm Finnendahl 2024-08-06 18:47 ` Orm Finnendahl 2024-08-06 20:04 ` Orm Finnendahl 2024-08-10 12:32 ` Ihor Radchenko 2024-08-11 10:54 ` Orm Finnendahl 2024-08-11 13:47 ` Ihor Radchenko 2024-08-11 14:44 ` Orm Finnendahl 2024-08-12 8:35 ` Orm Finnendahl 2024-08-12 17:10 ` Ihor Radchenko 2024-08-12 18:58 ` Orm Finnendahl 2024-08-17 7:21 ` Rudolf Adamkovič 2024-08-17 14:05 ` Ihor Radchenko 2024-08-19 16:31 ` Orm Finnendahl 2024-08-22 12:27 ` Ihor Radchenko 2024-07-26 8:22 ` Orm Finnendahl 2024-07-27 13:01 ` Ihor Radchenko 2024-07-27 14:25 ` Orm Finnendahl 2024-07-23 14:19 ` Ihor Radchenko 2024-07-23 15:13 ` Orm Finnendahl 2024-07-23 16:20 ` Ihor Radchenko 2024-07-23 17:02 ` Orm Finnendahl 2024-07-23 17:13 ` Ihor Radchenko 2024-07-23 19:00 ` Orm Finnendahl 2024-07-03 21:11 ` Rudolf Adamkovič -- strict thread matches above, loose matches on Subject: below -- 2024-07-06 5:47 Pedro Andres Aranda Gutierrez 2024-07-06 9:04 ` Orm Finnendahl
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).