Update some changed export keybindings
[worg.git] / org-tutorials / org-publish-layersmenu.org
bloba8207804551c694b51811ca576c8adfc87c37d78
1 #+TITLE:      Publishing Treemenus for Org-files
2 #+AUTHOR:     Sebastian Rose
3 #+EMAIL:      sebastian_rose gmx de
4 #+OPTIONS:    H:3 num:nil toc:t \n:nil ::t |:t ^:t -:t f:t *:t tex:t d:(HIDE) tags:not-in-toc
5 #+STARTUP:    align fold nodlcheck hidestars oddeven lognotestate
6 #+SEQ_TODO:   TODO(t) INPROGRESS(i) WAITING(w@) | DONE(d) CANCELED(c@)
7 #+TAGS:       Write(w) Update(u) Fix(f) Check(c)
8 #+LANGUAGE:   en
9 #+CATEGORY:   worg-tutorial
10 #+SETUPFILE:  ../macros.setupfile
12 # This file is released by its authors and contributors under the GNU
13 # Free Documentation license v1.3 or later, code examples are released
14 # under the GNU General Public License v3 or later.
16 [[file:../index.org][{Back to Worg's index}]]
18 * Introduction
20   You should be comfortable with publishing Org-mode fiels to HTML already when
21   you read this. Make sure, to create the tree-style sitemap-file on export.
23   This Tutorial describes a simple technique to include published content into
24   other web applications. I use an external JavaScript treemenu library publish
25   by Marco Pratesi. This treemenu is fast and runs in all Browsers I'm aware
26   of. The techniqe could as well be adopted to other menu libs.
28   You might as well use the Menu as kind of sitemap or top menu.
30   - The homepage of Phplaymenu is here: http://sourceforge.net/projects/phplayersmenu/
31   - A demo can be found on http://phplayersmenu.sourceforge.net/demo.php
33   Here is a screenshot of a treemenu:
35 #+CAPTION: Example phplayersmenu treemenu
36 #+ATTR_HTML: style="margin-left:auto;margin-right:auto;text-align:center;"
37   [[file:../images/sr/phplayermenu-example-tree.png]]
39   {{{BeginInfoBox}}} *Note:* Prior to Org-mode commit
40   [[https://code.orgmode.org/bzg/org-mode/commit/4892c8899e5b99d041836749fb2d1458971be55d][4892c8899e5b99d041836749fb2d1458971be55d]] (version 6.34trans), =sitemap-file=
41   =auto-sitemap= a.s.o. where called =index-file=, =auto-index= and similar. I you
42   have to work with a version released before 25th of February 2010, just
43   replace =sitemap= with =index= throughout this file.
44   {{{EndInfoBox}}}
46 * How the menus work
48   The menus are read from a string of a special structure. While it is beyond
49   this tutorial to explain the usage of the menus in details, the structure of
50   this string is important.
52   Each line of the string consists of these elements:
54   : [dots]|[text]|[link]|[title]|[icon]|[target]|[expanded]
56   Everything in brackets is optional. So are any trailing bars, if empty.
58   The tree structure is represented by prepended dots.
60   Example:
62   : .|Top level directory without link
63   : ..|Article 1|articles/article1.html|||main
64   : ..|Article 2|articles/article2.html|||main
65   : .|Snippets
66   : ..|C++|snippets/c++.html|||main
67   : ..|Perl|snippets/Perl.html|||main
69   will result in either in a tree menu like this here (=[F]= is an optional
70   folder icon:
72   : - [F] Top level directory without link
73   :    |
74   :    +-- Article 1
75   :    `-- Article 2
76   :
77   : - [F] Snippets
78   :    |
79   :    +-- C++
80   :    `-- Perl
82   ...or a menubar like this:
84   : .__________________________________.__________.
85   : | Top level directory without link | Snippets |
86   : `----------------------------------|          |
87   :                                    | C++      |
88   :                                    | Perl     |
89   :                                    `----------'
91 * Creating the menu structure when publishing
93   To create the menu structure, I use a modified version of the elisp function
94   =org-publish-org-sitemap=, defined in =Org-mode/lisp/org-publish.el=, that generates
95   the sitemap for HTML export. The function is called
96   =sr-org-notes-sitemap-complete= and defined in one of my emacs setup files.
98   Fortunately, Org-mode makes it possible to call a function after the
99   publishing process has fineshed. To make use of =sr-org-notes-sitemap-complete=,
100   add this to your publishing project's definition:
102 #+begin_src emacs-lisp
103 (require 'ox-publish)
104 (setq org-publish-project-alist
105       '(("org-notes"
106          :base-directory "~/org/notes/"
108          ;; ...
110          ;; Important:
111          :auto-sitemap t ; generate sitemap.org automagically
112          :sitemap-filename "sitemap.org" ; this is the default
113          :sitemap-style "tree"
115          ;; Layersmenu:
116          :completion-function sr-org-notes-sitemap-complete
117          :menu/structure-file "~/path/to/menu-structure-file.txt"
118          :menu/link-target "mitte" ;; optional
120          ;; ...
122          )))
123 #+end_src
125   Once you re-publish your project, the menu-structure file will be created.
127 * =my-org-notes-sitemap-complete=
129 #+begin_src emacs-lisp
130 (defun sr-org-notes-sitemap-complete ()
131   "Take the sitemap-file and turn it into the menu-structure
132 file for Marco Pratesi's phplayersmenu."
133   (let* ((base-dir (file-name-as-directory (plist-get project-plist :base-directory)))
134          (orig (expand-file-name (concat base-dir (plist-get project-plist :sitemap-filename))))
135          (strip-suffix (or (plist-get project-plist :base-extension) "org"))
136          (add-suffix (or (plist-get project-plist :html-extension) "html"))
137          (link-target (or (plist-get project-plist :menu/link-target) "_blank"))
138          (menu-file (or (plist-get project-plist :menu/structure-file) nil))
140          (visiting (find-buffer-visiting orig))
141          (visiting-output (find-buffer-visiting menu-file))
143          (input-buffer (find-file orig))
144          (output-buffer (find-file menu-file))
146          (old-ndots 1)
147          (sub "")
148          (old-sub ""))
150     (unless menu-file
151       (throw 'sr-org-note-kb-completion-error
152              "No menu structure file provided. Giving up."))
154     (with-current-buffer output-buffer
155       (erase-buffer))
157     (with-current-buffer input-buffer
158       (widen)
159       (goto-char (point-min))
160       (while (re-search-forward org-bracket-link-analytic-regexp (point-max) t)
161         (let ((link (match-string-no-properties 3))
162               (text (match-string-no-properties 5))
163               (pos 0)
164               (ndots 1))
166       (with-current-buffer output-buffer
167         (if (string-match (concat "\\(" strip-suffix "\\)$") link)
168             (setq link (replace-match add-suffix t t link)))
169         (while (setq pos (string-match "/" link pos))
170           (setq ndots (+ ndots 1))
171           (setq pos (+ pos 1)))
173         (when (< 1 ndots)
174           (string-match "\\(/[^/]*\\)$" link)
175           (setq sub (replace-match "" t t link))
177           (unless (string= sub old-sub)
178             (let ((ds 0)
179                   (subs (split-string sub "/"))
180                   (old-subs (split-string old-sub "/")))
181               (while (string= (car old-subs) (car subs))
182                 (setq ds (+ ds 1))
183                 (pop old-subs)
184                 (pop subs))
185               (dolist (d subs)
186                 (setq ds (+ ds 1))
187                 (insert
188                  (concat
189                   (make-string ds ?.) "|" d "\n")))
190               (setq old-sub sub))))
192         (insert
193          (concat
194           (make-string ndots ?.) "|" text "|" link "|||" link-target "\n"))
195         (setq old-ndots ndots)
196         ))))
198     (or visiting (kill-buffer input-buffer))
200     (with-current-buffer output-buffer
201       (save-buffer))
202     (or visiting-output (kill-buffer output-buffer))
204 #+end_src
206 * Include the menu in existing pages
208   To actually use the result, download the Phplayersmenu library and unpack
209   it. Move the following subfolders to your webroot:
211   * =phplayersmenu-3.2.0/lib/=
212   * =phplayersmenu-3.2.0/libjs/=
213   * =phplayersmenu-3.2.0/menuimages/=
215   Also choose one of the stylesheets in =phplayersmenu-3.2.0/=. In the example
216   below, the =layerstreemenu.css= is used.
218   Adjust the file(s) you want to include the menu in. Here is an example:
220 #+begin_src html -n -r
221  <html>
222   <head>
223    <script type="text/javascript">
224     <?php include ("libjs/layersmenu-browser_detection.js"); ?>
225    </script>
226    <link rel="stylesheet" href="layerstreemenu.css" type="text/css"></link> (ref:tree1)
227    <script type="text/javascript" src="libjs/layerstreemenu-cookies.js"></script>
228   </head>
229   <body>
231     ...
233     <div>
234  <?php
235     include ("lib/PHPLIB.php");   // taken from PHPLib
236     include ("lib/layersmenu-common.inc.php");
237     include ("lib/treemenu.inc.php");          (ref:tree2)
238     if ( @ is_file ("../intranet/navigations/org.txt") )
239     {
240       $mid = new TreeMenu();  (ref:tree3)
241       $mid->setMenuStructureFile("navigations/org.txt");
242       $mid->setPrependedUrl("../org-notes/");   (ref:url1)
243       $mid->parseStructureForMenu("treemenu1");
244       print $mid->newTreeMenu("treemenu1"); (ref:tree4)
245     }
246  ?>
247     </div>
248   </body>
249  </html>
250 #+end_src
252   What makes your menu a tree-menu, are
254   * the stylesheet ([[(tree1)][line (tree1)]]),
255   * theinclusion of treemenu.inc.php ([[(tree2)][in line (tree2)]]),
256   * the constructor used ([[(tree3)][line (tree3)]]),
257   * and the =newTreeMenu()= method ([[(tree4)][called in line (tree4)]]).
259   The (optional) [[(url1)][URL provided in line (url1)]] is prepended to all the URLs found
260   in the menu-structure file.
262   See the Phplayersmenu docs on how to create horizontal and vertical menus from
263   the same structure file.