#+STARTUP: showall * [[https://orgmode.org/manual/Publishing.html][Publishing]] Org includes a publishing management system that allows you to configure automatic HTML conversion of /projects/ composed of interlinked Org files. You can also configure Org to automatically upload your exported HTML pages and related attachments, such as images and source code files, to a web server. You can also use Org to convert files into PDF, or even combine HTML and PDF conversion so that files are available in both formats on the server. Publishing has been contributed to Org by David O’Toole. ** [[https://orgmode.org/manual/Configuration.html][Configuration]] Publishing needs significant configuration to specify files, destination and many other properties of a project. #+NAME: www-test-data #+BEGIN_SRC elisp :tangle www-test-data.el ;; -*- lexical-binding: t; -*- ( load "~/src/channel/www/build-site" ) ( print "publish-test-1" ) ( let ( ( publication-instance ( publication-object ) ) ) ( publish publication-instance ( list "test.pl" "example.org" ) ) ) ( print "publish-test-2" ) ( let ( ( publication-instance ( publication-object ) ) ) ( publish publication-instance ( list "test.pl" :property1 "value1" :property2 "value2" ) ) ) ( print "publish-test-3" ) ( let ( ( publication-instance ( publication-object ) ) ) ( publish publication-instance ( list "test.pl" :components ( list "example.pl" "example.org" )) ) ) #+END_SRC *** [[https://orgmode.org/manual/Project-alist.html][The variable =org-publish-project-alist=]] Publishing is configured almost entirely through setting the value of one variable, called =org-publish-project-alist=. Each element of the list configures one project, and may be in one of the two following forms: #+BEGIN_EXAMPLE ( "project-name" :property value :property value ... ) #+END_EXAMPLE i.e., a well-formed property list with alternating keys and values, or: #+BEGIN_EXAMPLE ( "project-name" :components ( "project-name" "project-name" ... ) ) #+END_EXAMPLE In both cases, projects are configured by specifying property values. A project defines the set of files that are to be published, as well as the publishing configuration to use when publishing those files. When a project takes the second form listed above, the individual members of the =:components= property are taken to be sub-projects, which group together files requiring different publishing options. When you publish such a “meta-project”, all the components are also published, in the sequence given. #+NAME: build-site #+BEGIN_SRC elisp :tangle build-site.el ;; -*- lexical-binding: t; -*- ;;; The Object Prototype ( defun publication-object ( ) ( let ( ( object-projects ( list ) ) ( org-publish-project-alist ( list ) ) ( success-report "Build complete!" ) ) ( list :object-compose ( lambda ( ) ( setq org-publish-project-alist ( list object-projects ) ) ) :object-get-projects ( lambda ( project-data ) ( setq object-projects ( append project-data object-projects ) ) ) :object-report ( lambda ( ) ( print org-publish-project-alist ) ( print success-report ) ) ) ) ) ;;; The Object Interface ( defun object-compose ( publication-instance ) ( funcall ( plist-get publication-instance :object-compose ) ) ) ( defun object-get-projects ( publication-instance project-data ) ( funcall ( plist-get publication-instance :object-get-projects ) project-data ) ) ( defun object-report ( publication-instance ) ( funcall ( plist-get publication-instance :object-report ) ) ) ;;; The User Logic ( defun atypical-header-p ( project-data ) ( let ( ( element-1 ( pop project-data ) ) ( element-2 ( pop project-data ) ) ( error-1 "First element is not a string: " ) ( error-2 "Second element is not a keyword: " ) ) ( condition-case error ( cond ( ( not ( stringp element-1 ) ) ( signal 'scan-error ( concat error-1 element-1 ) ) ) ( ( not ( keywordp element-2 ) ) ( signal 'scan-error ( concat error-2 element-2 ) ) ) ) ( scan-error ( print ( cdr error ) ) ) ) ) ) ( defun export-project-alist ( publication-instance ) ( object-compose publication-instance ) ( object-report publication-instance ) ) ( defun get-component ( project-data ) ( let ( ( component ( nth 2 project-data ) ) ) ( print component ) component ) ) ( defun has-component-p ( project-data ) ( let ( ( component-keyword ':components ) ( second ( nth 1 project-data ) ) ) ( eq component-keyword second ) ) ) ( defun import-data ( publication-instance project-data ) ( object-get-projects publication-instance project-data ) ) ( defun too-short-p ( project-data ) ( let ( ( minimal-length 2 ) ) ( < ( length project-data ) minimal-length ) ) ) ;;; The User Interface ( defun publish ( publication-instance &rest project-data-wrapped ) ( let ( ( project-data ( car project-data-wrapped ) ) ) ( pcase project-data ( ( guard ( too-short-p project-data ) ) nil ) ( ( guard ( atypical-header-p project-data ) nil ) ) ( ( pred has-component-p project-data ) ( let ( ( component ( get-component project-data ) ) ( head ( nth 0 project-data ) ) ( tail ( nthcdr 3 project-data ) ) ) ( list head ( publish publication-instance component ) ( publish publication-instance tail ) ) ) ) ( _ ( progn ( import-data publication-instance project-data ) ( export-project-alist publication-instance ) ) ) ) ) ) #+END_SRC * EOF