2

I want to publish each of my org-mode posts so the HTML output uses a separate folder for each post. I want to avoid .html in the URL. I want the posts to look like http://example.com/my-org-post/ instead of http://example.com/my-org-post.html.

Is there a publishing setting to achieve this?

2 Answers 2

4

There's no way to just configure this, but you can modify the behavior without too much work if you want.

There's a function called org-export-output-file-name which computes the file name for the export. You can write a modification for this function using defadvice.

I've not tested it specifically, but something like this may get you started:

(defadvice org-export-output-file-name (around export-to-directories activate)
  "alters the org export process to create a subdirectory for each exported org file"
  (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
         (dir-name (file-name-sans-extension (file-name-nondirectory visited-file))))
    (setf pub-dir
          (concat (file-name-as-directory (or pub-dir "."))
                  dir-name))
    ad-do-it))

org-export-output-file-name takes an argument called pub-dir which contains the directory to publish to; this is generally taken from your project configuration. This advice sets pub-dir to a new value before calling ad-do-it to call the original function.

Of course, even if I haven't made any other mistakes, there's still one potential problem here. The original org-export-output-file-name is still going to use the current file name again when constructing the output file name. For example, when exporting the file foo.org this advised function is going to return the file name ./foo/foo.html. For your use-case, it sounds like a better value would be ./foo/index.html.

If the code had been written to pass the file name in as an argument this would be easy to fix; just override that argument. It seems to me that the only way to fix this is to modify the return value as well as the arguments:

(defadvice org-export-output-file-name (around export-to-directories activate)
  "alters the org export process to create a subdirectory for each exported org file"
  (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
         (dir-name (file-name-sans-extension (file-name-nondirectory visited-file))))
    (setf pub-dir
          (concat (file-name-as-directory (or pub-dir "."))
                  dir-name))
    ad-do-it
    (setf ad-return-value
          (replace-regexp-in-string (regexp-quote (concat dir-name "." extension))
                                    (concat "index." extension)
                                    ad-return-value))))

It's also possible that you could handle that with a rewrite rule (or similar) in your web server config.

2
  • This is pretty close, but causes the error "Output file not writable", probably because the directory doesn't exist. I'm looking at advising org-html-publish-to-html.
    – Joe
    Commented Oct 30, 2015 at 5:00
  • Good point. You could throw a call to make-directory.
    – db48x
    Commented Oct 30, 2015 at 19:19
2

Okay, this was a little bit involved, but I have a solution now. There were two main steps:

  • Create the appropriate folder in the output directory. I used the new advice system, inspired by db48x.
  • Fix links to point to "example/index.html" instead of "example.html". I created a new backend, derived from ox-html.el. It was a one-line change. But the change was inside a lambda within a function meaning I couldn't modify the lambda even with advice.

I made a quick project at https://github.com/jschaf/org-export-html-clean

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.