ardumont / org2jekyll

Blogging with org-mode and jekyll without alien yaml headers.
GNU General Public License v2.0
71 stars 19 forks source link

Is it possible to add freeform extra yaml headers? 1/2 #34

Closed yefeiyu closed 8 years ago

yefeiyu commented 8 years ago

add it into org2jekyll.el, and it can use when org file export to html file.


---
layout: post
title: Custom Color Scheme
category: note
tags: curtana
scheme-text: "#0029ff"         <<<--here
scheme-link: "#ff00b4"                  ...
scheme-hover: "#ff00b4"               ...
scheme-code: "#ad00ff"                ...
scheme-bg: "#00ebff"                   ...
scheme-hero-text: "#00ebff"         ...
scheme-hero-link: "#00ebff"         ...
scheme-hero-bg: "#0029ff"          ...
plugin: lightense                         ---until here>>>

---

I use the Super-fast Jekyll framework for Github blog, Almace Scaffolding. It need this Markdown Head. the address is : http://sparanoid.com/lab/amsf/

Thank you for your help!

ardumont commented 8 years ago

Hello,

Well, right now you cannot ^^.

It makes total sense to permit this on a user basis though.

I'll see what i can do to improve on this.

Cheers,

ardumont commented 8 years ago

So monkey patching your current org2jkeyll install with the following:

(defcustom org2jekyll-extra-yaml-headers nil
  "An entry of static yaml header (already formatted).
E.g. from https://github.com/ardumont/org2jekyll/issues/34#issue-148684715:
scheme-text: \"#0029ff\"
scheme-link: \"#ff00b4\"
scheme-hover: \"#ff00b4\"
scheme-code: \"#ad00ff\"
scheme-bg: \"#00ebff\"
scheme-hero-text: \"#00ebff\"
scheme-hero-link: \"#00ebff\"
scheme-hero-bg: \"#0029ff\"
plugin: lightense"
  :group 'org2jekyll)

(defun org2jekyll--to-yaml-header (org-metadata)
  "Given a list of ORG-METADATA, compute the yaml header string."
  (-let (((begin end) (if (org2jekyll--old-org-version-p)
                          '("#+BEGIN_HTML" "#+END_HTML\n")
                        '("#+BEGIN_EXPORT HTML" "#+END_EXPORT\n"))))
    (--> org-metadata
         org2jekyll--org-to-yaml-metadata
         (--map (format "%s: %s" (car it) (cdr it)) it)
         (cons "---" it)
         (cons begin it)
         (-snoc it org2jekyll-extra-yaml-headers)
         (-snoc it "---")
         (-snoc it end)
         (s-join "\n" it)
         (s-replace "\n\n" "\n" it))))

To install it: M-: paste-previous-snippet RET

Add adding this to your org2jekyll customization variables to have your initial snippet ready to be exported as well:

(custom-set-variables '(org2jekyll-extra-yaml-headers "scheme-text: \"#0029ff\"
scheme-link: \"#ff00b4\"
scheme-hover: \"#ff00b4\"
scheme-code: \"#ad00ff\"
scheme-bg: \"#00ebff\"
scheme-hero-text: \"#00ebff\"
scheme-hero-link: \"#00ebff\"
scheme-hero-bg: \"#0029ff\"
plugin: lightense"))

Then org2jekyll-publish your page or post. This will add those extra-headers when exporting.

Cheers,

ardumont commented 8 years ago

Done in 781bcb8634f5ad9e01abed94bb574d5c07a81371

yefeiyu commented 8 years ago

I couldnt get what I wanted. The result is :

<!DOCTYPE html>
<html>
<head>
<title>e</title>
<!-- 2016-04-17 日 13:42 -->
<meta  charset="utf-8">
<meta  name="generator" content="Org-mode">
<meta  name="author" content="yefeiyu">
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center; }
  .todo   { font-family: monospace; color: red; }
  .done   { color: green; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .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 #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  pre.src-sh:before    { content: 'sh'; }
  pre.src-bash:before  { content: 'sh'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-R:before     { content: 'R'; }
  pre.src-perl:before  { content: 'Perl'; }
  pre.src-java:before  { content: 'Java'; }
  pre.src-sql:before   { content: 'SQL'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.right  { text-align: center;  }
  th.left   { text-align: center;   }
  th.center { text-align: center; }
  td.right  { text-align: right;  }
  td.left   { text-align: left;   }
  td.center { text-align: center; }
  dt { font-weight: bold; }
  .footpara:nth-child(2) { display: inline; }
  .footpara { display: block; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .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; }
  /*]]>*/-->
</style>
<link rel='stylesheet' href='http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css'>
<link rel='stylesheet' href='http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css'>
<script src='http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js'>
</script><script src='http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js'></script>
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2013 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.

@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">e</h1>
---
layout: post
title: e
date: 2016-04-17
categories: 
-
tags: 
-
author: yefeiyu
excerpt: 
---

<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"></h2>
</div>
</div>
<div id="postamble" class="status">
<p class="date">Date: 2016-04-17 日 13:42</p>
<p class="author">Author: yefeiyu</p>
<p class="date">Created: 2016-04-17 日 13:42</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 25.0.92.3 (<a href="http://orgmode.org">Org</a> mode 8.2.10)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>

My blog-pack.el is :

;;; blog-pack.el --- Blog with org-mode and jekyll/github
;;; Commentary:
;;; Code:
(org-babel-do-load-languages
 'org-babel-load-languages
 '( (scheme . t)
    (latex . t)
    (css . t)
    (markdown . t)
    (ruby . t)
    (sh . t)
    (python . t)
    (emacs-lisp . t)
    (matlab . t)
    (C . t)))
(setq org-confirm-babel-evaluate nil)
;;(setq org-src-fontify-natively t)
;; (setq org-export-with-sub-superscripts nil)
;;(use-package org2jekyll
;;  :defer 3
;;  :config
(require 'org)
(require 'org2jekyll)

(custom-set-variables
 '(org2jekyll-extra-yaml-headers "scheme-text: 
scheme-link: 
scheme-hover: 
scheme-code: 
scheme-bg: 
scheme-hero-text: 
scheme-hero-link: 
scheme-hero-bg: 
plugin: lightense")
'(org2jekyll-blog-author       "yefeiyu")
'(org2jekyll-source-directory  (expand-file-name "~/gh/yefeiyu.github.io/_app/"))
'(org2jekyll-jekyll-directory  (expand-file-name "~/gh/yefeiyu.github.io/_app/"))
'(org2jekyll-jekyll-drafts-dir "_org/")
'(org2jekyll-jekyll-posts-dir  "_drafts/")
'(org-publish-project-alist
  `(("default"
     :base-directory ,(org2jekyll-input-directory)
     :base-extension "org"
     ;; :publishing-directory "/ssh:user@host:~/html/notebook/"
     :publishing-directory ,(org2jekyll-output-directory)
     :publishing-function org-html-publish-to-html
     :headline-levels 6
      :section-numbers t
      :with-toc t
      :html_head "<link rel=\"stylesheet\" type=\"text/css\" href=\"~/gh/yefeiyu.github.io/assets/themes/curtana/css/app.css\" />"
      :html-preamble t
      :recursive t
      :make-index t
      :html-extension "html"
      :body-only nil)

                            ("post"
                             :base-directory ,(org2jekyll-input-directory)
                             :base-extension "org"
                             :publishing-directory ,(org2jekyll-output-directory org2jekyll-jekyll-posts-dir)
                             :publishing-function org-html-publish-to-html
                             :headline-levels 6
                             :section-numbers t
                             :with-toc t
                 :html_head "<link rel=\"stylesheet\" type=\"text/css\" href=\"~/gh/yefeiyu.github.io/assets/themes/curtana/css/app.css\" />"
                             :html-preamble t
                             :recursive t
                             :make-index t
                             :html-extension "html"
                             :body-only nil)

                            ("images"
                             :base-directory ,(org2jekyll-input-directory "assets/img")
                             :base-extension "jpg\\|gif\\|png"
                             :publishing-directory ,(org2jekyll-output-directory "assets/img")
                             :publishing-function org-publish-attachment
                             :recursive t)

                            ("js"
                             :base-directory ,(org2jekyll-input-directory "assets/js")
                             :base-extension "js"
                             :publishing-directory ,(org2jekyll-output-directory "assets/js")
                             :publishing-function org-publish-attachment
                             :recursive t)

                            ("css"
                             :base-directory ,(org2jekyll-input-directory "assets/themes/curtana/css")
                             :base-extension "css\\|el"
                             :publishing-directory ,(org2jekyll-output-directory "assets/themes/curtana/css")
                             :publishing-function org-publish-attachment
                             :recursive t)

                            ("web" :components ("images" "js" "css")))))
(defun org-md-publish-to-md (plist filename pub-dir)
"Publish an org file to Markdown.

FILENAME is the filename of the Org file to be published.  PLIST
is the property list for the given project.  PUB-DIR is the
publishing directory.

Return output file name."
(org-publish-org-to 'md filename ".md" plist pub-dir))
(provide 'blog-pack)
;;; blog-pack.el ends here

My org2jekyll.el is:

;;; org2jekyll.el --- Minor mode to publish org-mode post to jekyll without specific yaml

;; Copyright (C) 2014 Antoine R. Dumont <eniotna.t AT gmail.com>

;; Author: Antoine R. Dumont <eniotna.t AT gmail.com>
;; Maintainer: Antoine R. Dumont <eniotna.t AT gmail.com>
;; Version: 0.1.8
;; Package-Requires: ((dash-functional "2.11.0") (s "1.9.0") (deferred "0.3.1"))
;; Keywords: org-mode jekyll blog publish
;; URL: https://github.com/ardumont/org2jekyll

;; This file is NOT part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:

;; Functions to ease publishing jekyll posts from org-mode file

;; Providing you have a working `'jekyll`' and `'org-publish`'
;; This will permit you to simply export an org-mode file with the right jekyll
;; format to the right folder
;;
;; M-x org2jekyll-create-draft create a draft with the necessary metadata
;;
;; M-x org2jekyll-publish publish the current post (or page) to the jekyll folder
;;
;; M-x org2jekyll-publish-pages to publish all pages (layout 'default')
;;
;; M-x org2jekyll-publish-posts to publish all post pages (layout 'post')
;;
;; M-x org2jekyll-mode to activate org2jekyll's minor mode
;;
;; You can customize using M-x customize-group RET org2jekyll RET
;;
;; More information on https://github.com/ardumont/org2jekyll

;;; Code:

(require 'org)
(require (if (version< emacs-version "24.4") 'org-publish 'ox-publish))

(require 'dash-functional)
(require 's)
(require 'deferred)
(require 'ido)

(defgroup org2jekyll nil "Publish org-mode posts to jekyll"
  :tag "org2jekyll"
  :version "0.0.3"
  :group 'org)

(defcustom org2jekyll-blog-author nil
  "Blog entry author."
  :type 'string
  :require 'org2jekyll
  :group 'org2jekyll)

(defalias 'org2jekyll/blog-author 'org2jekyll-blog-author) ;; for compatibility

(defcustom org2jekyll-source-directory nil
  "Path to the source directory."
  :type 'string
  :require 'org2jekyll
  :group 'org2jekyll)

(defalias 'org2jekyll/source-directory 'org2jekyll-source-directory)

(defcustom org2jekyll-jekyll-directory nil
  "Path to Jekyll blog."
  :type 'string
  :require 'org2jekyll
  :group 'org2jekyll)

(defalias 'org2jekyll/jekyll-directory 'org2jekyll-jekyll-directory)

(defcustom org2jekyll-jekyll-drafts-dir nil
  "Relative path to drafts directory."
  :type 'string
  :require 'org2jekyll
  :group 'org2jekyll)

(defalias 'org2jekyll/jekyll-drafts-dir 'org2jekyll-jekyll-drafts-dir)

(defcustom org2jekyll-jekyll-posts-dir nil
  "Relative path to posts directory."
  :type 'string
  :require 'org2jekyll
  :group 'org2jekyll)

(defalias 'org2jekyll/jekyll-posts-dir 'org2jekyll-jekyll-posts-dir)

(defcustom org2jekyll-extra-yaml-headers nil
          "An entry of static yaml header (already formatted).
        E.g. from https://github.com/ardumont/org2jekyll/issues/34#issue-148684715:
        scheme-text: \"#0029ff\"
        scheme-link: \"#ff00b4\"
        scheme-hover: \"#ff00b4\"
        scheme-code: \"#ad00ff\"
        scheme-bg: \"#00ebff\"
        scheme-hero-text: \"#00ebff\"
        scheme-hero-link: \"#00ebff\"
        scheme-hero-bg: \"#0029ff\"
        plugin: lightense"
          :group 'org2jekyll)

(defvar org2jekyll-jekyll-post-ext ".org"
  "File extension of Jekyll posts.")

(defvar org2jekyll-jekyll-org-post-template nil
  "Default template for org2jekyll draft posts.
The `'%s`' will be replaced respectively by name, author, generated date, title,
 description and categories.")

(setq org2jekyll-jekyll-org-post-template
      "#+STARTUP: showall
#+STARTUP: hidestars
#+OPTIONS: H:2 num:nil tags:nil toc:nil timestamps:t 
#+LAYOUT: %s
#+AUTHOR: %s
#+DATE: %s
#+TITLE: %s
#+DESCRIPTION: %s
#+TAGS: %s
#+CATEGORIES: %s
#+THUMB:%s
#+SCHEME-TEXT: %s
#+SCHEME-LINK: %s
#+SCHEME-HOVER: %s
#+SCHEME-CODE: %s
#+SCHEME-BG: %s
\n")

(defun org2jekyll--optional-folder (folder-source &optional folder-name)
  "Compute the folder name from a FOLDER-SOURCE and an optional FOLDER-NAME."
  (format "%s/%s" folder-source (if folder-name folder-name "")))

(defun org2jekyll-input-directory (&optional folder-name)
  "Compute the input folder from the FOLDER-NAME."
  (org2jekyll--optional-folder org2jekyll-source-directory folder-name))

(defun org2jekyll-output-directory (&optional folder-name)
  "Compute the output folder from the optional FOLDER-NAME."
  (org2jekyll--optional-folder org2jekyll-jekyll-directory folder-name))

(defun org2jekyll--make-slug (s)
  "Turn a string S into a slug."
  (->> s
       (replace-regexp-in-string "[\]\[(){}!#$~^\\]" "")
       downcase
       (replace-regexp-in-string " " "-")))

(defun org2jekyll--yaml-escape (s)
  "Escape a string S for YAML."
  (if (or (string-match ":" s)
          (string-match "\"" s))
      (concat "\"" (replace-regexp-in-string "\"" "\\\\\"" s) "\"")
    s))

(defun org2jekyll-now ()
  "Generate a formatted now date."
  (format-time-string "%Y-%m-%d %a %H:%M"))

(defun org2jekyll-default-headers-template (blog-layout
                                            blog-author
                                            post-date
                                            post-title
                                            post-description
                                            post-tags
                                            post-categories
                        post-thumb
                        post-scheme-text
                        post-scheme-link
                        post-scheme-hover
                        post-scheme-code
                        post-scheme-bg
                        )
  "Compute default headers.
BLOG-LAYOUT is the layout of the post.
BLOG-AUTHOR is the author.
POST-DATE is the date of the post.
POST-TITLE is the title.
POST-DESCRIPTION is the description.
POST-TAGS is the tags
POST-THUMB is the thumb
POST-CATEGORIES is the categories."
  (format org2jekyll-jekyll-org-post-template
          blog-layout
          blog-author
          post-date
          (org2jekyll--yaml-escape post-title)
          post-description
          post-tags
          post-categories
      post-thumb
      post-scheme-text
      post-scheme-link
      post-scheme-hover
      post-scheme-code
      post-scheme-bg))

(defun org2jekyll--draft-filename (draft-dir title)
  "Compute the draft's filename from the DRAFT-DIR and TITLE."
  (concat draft-dir (org2jekyll--make-slug title) org2jekyll-jekyll-post-ext))

(defun org2jekyll--read-title ()
  "Read the title."
  (read-string "Title: "))

(defun org2jekyll--read-description ()
  "Read the description."
  (read-string "Description: "))

(defun org2jekyll--read-tags ()
  "Read the tags."
  (read-string "Tags (csv): "))

(defun org2jekyll--read-categories ()
  "Read the categories."
  (read-string "Categories (csv): "))

(defun org2jekyll--read-thumb ()
  "Read the thumb."
  (read-string "thumb: "))

(defun org2jekyll--input-read (prompt collection)
  "Input PROMPT with possibilities limited to COLLECTION."
  (ido-completing-read prompt
                       collection
                       nil
                       'require-match))

(defun org2jekyll--init-buffer-metadata ()
  "Initialize a DRAFT-FILE or current buffer routine.
:: () -> [(Symbol, String)]"
  (list :author      org2jekyll-blog-author
        :date        (org2jekyll-now)
        :layout      (org2jekyll--input-read "Layout: " '("post" "default"))
        :title       (org2jekyll--read-title)
        :description (org2jekyll--read-description)
        :tags        (org2jekyll--read-tags)
        :categories  (org2jekyll--read-categories)
        :thumb  (org2jekyll--read-thumb)))

;;;###autoload
(defun org2jekyll-init-current-buffer ()
  "Given an existing buffer, add the needed metadata to make it a post or page."
  (interactive)
  (let* ((metadata (org2jekyll--init-buffer-metadata))
         (author      (plist-get metadata :author))
         (date        (plist-get metadata :date))
         (layout      (plist-get metadata :layout))
         (title       (plist-get metadata :title))
         (description (plist-get metadata :description))
         (tags        (plist-get metadata :tags))
     (categories  (plist-get metadata :categories))
         (thumb  (plist-get metadata :thumb)))
    (save-excursion
      (with-current-buffer (buffer-name)
        (goto-char (point-min))
        (insert (org2jekyll-default-headers-template layout
                                                     author
                                                     date
                                                     title
                                                     description
                                                     tags
                                                     categories
                             thumb
                             scheme-text
                             scheme-link
                             scheme-hover
                             scheme-code
                             scheme-bg))))))

;;;###autoload
(defun org2jekyll-create-draft ()
  "Create a new Jekyll blog post with TITLE.
The `'%s`' will be replaced respectively by the blog entry name, the author, the
 generated date, the title, the description, the tags and the categories."
  (interactive)
  (let* ((metadata (org2jekyll--init-buffer-metadata))
         (author      (plist-get metadata :author))
         (date        (plist-get metadata :date))
         (layout      (plist-get metadata :layout))
         (title       (plist-get metadata :title))
         (description (plist-get metadata :description))
         (tags        (plist-get metadata :tags))
         (categories  (plist-get metadata :categories))
         (thumb  (plist-get metadata :thumb))
         (draft-file  (org2jekyll--draft-filename
                       (org2jekyll-input-directory org2jekyll-jekyll-drafts-dir)
                       title)))
    (unless (file-exists-p draft-file)
      (with-temp-file draft-file
        (insert (org2jekyll-default-headers-template layout
                                                     author
                                                     date
                                                     title
                                                     description
                                                     tags
                                                     categories
                             thumb
                             scheme-text
                             scheme-link
                             scheme-hover
                             scheme-code
                             scheme-bg))
        (insert "* ")))
    (find-file draft-file)))

(defalias 'org2jekyll/create-draft! 'org2jekyll-create-draft)

(defun org2jekyll--list-dir (dir)
  "List the content of DIR."
  (find-file dir))

;;;###autoload
(defun org2jekyll-list-posts ()
  "Lists the posts folder."
  (interactive)
  (org2jekyll--list-dir
   (org2jekyll-output-directory org2jekyll-jekyll-posts-dir)))

(defalias 'org2jekyll/list-posts 'org2jekyll-list-posts)

;;;###autoload
(defun org2jekyll-list-drafts ()
  "List the drafts folder."
  (interactive)
  (org2jekyll--list-dir
   (org2jekyll-input-directory org2jekyll-jekyll-drafts-dir)))

(defalias 'org2jekyll/list-drafts 'org2jekyll-list-drafts)

(defun org2jekyll-get-option-at-point (opt)
  "Gets the header value of the option OPT from a buffer."
  (let* ((regexp (org-make-options-regexp (list (upcase opt) (downcase opt)))))
    (save-excursion
      (goto-char (point-min))
      (if (re-search-forward regexp nil t 1)
          (match-string-no-properties 2)))))

(defun org2jekyll-get-option-from-file (orgfile option)
  "Return the ORGFILE's OPTION."
  (with-temp-buffer
    (when (file-exists-p orgfile)
      (insert-file-contents orgfile)
      (goto-char (point-min))
      (org2jekyll-get-option-at-point option))))

(defun org2jekyll-get-options-from-file (orgfile options)
  "Return the ORGFILE's OPTIONS."
  (with-temp-buffer
    (when (file-exists-p orgfile)
      (insert-file-contents orgfile)
      (mapcar (lambda (option)
                (save-excursion
                  (goto-char (point-min))
                  (cons option (org2jekyll-get-option-at-point option))))
              options))))

(defun org2jekyll-layout (org-file)
  "Determine if the current ORG-FILE's layout.
Depends on the metadata header #+LAYOUT."
  (org2jekyll-get-option-from-file org-file "layout"))

(defalias 'org2jekyll-article-p 'org2jekyll-layout)

(defvar org2jekyll-map-keys '(("title"       . "title")
                              ("categories"  . "categories")
                              ("thumb"  . "thumb")                
                              ("tags"        . "tags")
                              ("date"        . "date")
                              ("description" . "excerpt")
                              ("author"      . "author")
                              ("layout"      . "layout"))
  "Keys to map from org headers to jekyll's headers.")

(defun org2jekyll--org-to-yaml-metadata (org-metadata)
  "Given an ORG-METADATA map, return a yaml one with transformed data."
  (--map `(,(assoc-default (car it) org2jekyll-map-keys) . ,(cdr it))
         org-metadata))

(defun org2jekyll--convert-timestamp-to-yyyy-dd-mm (timestamp)
  "Convert org TIMESTAMP to ."
  (format-time-string "%Y-%m-%d"
                      (apply 'encode-time (org-parse-time-string timestamp))))

(defun org2jekyll--old-org-version-p ()
  "Determine if we are in old version or not."
  ;; HACK: support both pre-9.0 and 9.0+ Org export block syntax. Instead of
  ;; checking for the version, check for org-element-block-name-alist
  ;; availability to detect pre-release 9.0 Git snapshots with the new syntax,
  ;; see http://orgmode.org/cgit.cgi/org-mode.git/commit/?id=54318ad
  (boundp 'org-element-block-name-alist))

(defun org2jekyll--to-yaml-header (org-metadata)
  "Given a list of ORG-METADATA, compute the yaml header string."
  (-let (((begin end) (if (org2jekyll--old-org-version-p)
                          '("#+BEGIN_HTML" "#+END_HTML\n")
                        '("#+BEGIN_EXPORT HTML" "#+END_EXPORT\n"))))
    (--> org-metadata
         org2jekyll--org-to-yaml-metadata
         (--map (format "%s: %s" (car it) (cdr it)) it)
         (cons "---" it)
         (cons begin it)
     (-snoc it org2jekyll-extra-yaml-headers)
         (-snoc it "---")
         (-snoc it end)
     (s-join "\n" it)
     (s-replace "\n\n" "\n" it))))

(defun org2jekyll--csv-to-yaml (str-csv)
  "Transform a STR-CSV entries into a yaml entries."
  (->> str-csv
       (concat ",")
       (s-replace ", " ",")
       (s-replace "," "\n- ")
       s-trim
       (concat "\n")))

(defun org2jekyll--compute-ready-jekyll-file-name (date org-file)
  "Given a DATE and an ORG-FILE, compute a ready jekyll file name.
If the current path contains the `'org2jekyll-jekyll-drafts-dir`', removes it."
  (let ((temp-org-jekyll-filename (format "%s-%s" date
                                          (file-name-nondirectory org-file)))
        (temp-org-jekyll-directory (file-name-directory org-file)))
    (->> temp-org-jekyll-filename
         (format "%s%s" temp-org-jekyll-directory)
         (replace-regexp-in-string (format "%s" org2jekyll-jekyll-drafts-dir) "")
         (replace-regexp-in-string "//" "/"))))

(defun org2jekyll--copy-org-file-to-jekyll-org-file (date org-file yaml-headers)
  "Given DATE, ORG-FILE and YAML-HEADERS, copy content as org-jekyll ready file.
This returns the new filename path."
  (let ((jekyll-filename (org2jekyll--compute-ready-jekyll-file-name date
                                                                     org-file)))
    (with-temp-file jekyll-filename ;; write file updated with jekyll specifics
      (insert-file-contents org-file)
      (goto-char (point-min))
      (insert (org2jekyll--to-yaml-header yaml-headers)))
    jekyll-filename))

(defun org2jekyll-assoc-default (key org-data default-value)
  "Given KEY, ORG-DATA and DEFAULT-VALUE, return the value associated with key.
Return DEFAULT-VALUE if not found."
  (-if-let (data (assoc-default key org-data nil default-value))
      data
    default-value))

(defvar org2jekyll-header-metadata nil
  "The needed headers for org buffer for org2jekyll to work.")

(setq org2jekyll-header-metadata '(("title"       . 'mandatory)
                                   ("date")
                                   ("categories"  . 'mandatory)
                                   ("thumb"  . 'mandatory)                 
                                   ("thumb")
                   ("tags")
                                   ("description" . 'mandatory)
                                   ("author")
                                   ("layout"      . 'mandatory)))

(defun org2jekyll-check-metadata (org-metadata)
  "Check that the mandatory header metadata in ORG-METADATA are provided.
Return the error messages if any or nil if everything is alright."
  (let ((mandatory-values (funcall (-compose (lambda (l) (mapcar #'car l))
                                             (lambda (l) (-filter #'cdr l)))
                                   org2jekyll-header-metadata)))
    (-when-let (error-messages
                (->> mandatory-values
                     (--map (when (null (assoc-default it org-metadata))
                              (format "- The %s is mandatory, please add '#+%s' at the top of your org buffer." it (upcase it))))
                     (s-join "\n")
                     s-trim))
      (if (string= "" error-messages) nil error-messages))))

(defun org2jekyll-read-metadata (org-file)
  "Given an ORG-FILE, return its org metadata.
If non-mandatory values are missing, they are replaced with dummy ones.
Otherwise, display the error messages about the missing mandatory values."
  (let* ((org-metadata-list (mapcar #'car org2jekyll-header-metadata))
         (org-metadata (org2jekyll-get-options-from-file org-file
                                                         org-metadata-list)))
    (-if-let (error-messages (org2jekyll-check-metadata org-metadata))
        (format "This org-mode file is missing mandatory header(s):
%s
Publication skipped" error-messages)
      `(("layout"      . ,(-> "layout"
                              (org2jekyll-assoc-default org-metadata "post")))
        ("title"       . ,(-> "title"
                              (org2jekyll-assoc-default
                               org-metadata
                               "dummy-title-should-be-replaced")))
        ("date"        . ,(-> "date"
                              (org2jekyll-assoc-default
                               org-metadata
                               (org2jekyll-now))
                              org2jekyll--convert-timestamp-to-yyyy-dd-mm))
        ("categories"  . ,(-> "categories"
                              (org2jekyll-assoc-default
                               org-metadata
                               "dummy-category-should-be-replaced")
                              org2jekyll--csv-to-yaml))
        ("tags"        . ,(-> "tags"
                              (org2jekyll-assoc-default
                               org-metadata
                               "dummy-tags-should-be-replaced")
                              org2jekyll--csv-to-yaml))
        ("author"      . ,(-> "author"
                              (org2jekyll-assoc-default org-metadata "")))
        ("thumb"      . ,(-> "thumb"
                              (org2jekyll-assoc-default org-metadata "")))
        ("description" . ,(-> "description"
                              (org2jekyll-assoc-default org-metadata "")))))))

(defun org2jekyll-read-metadata-and-execute (action-fn org-file)
  "Execute ACTION-FN function after checking metadata from the ORG-FILE."
  (let ((filename-non-dir (file-name-nondirectory org-file)))
    (if (org2jekyll-article-p org-file)
        (let ((org-metadata (org2jekyll-read-metadata org-file)))
          (if (stringp org-metadata)
              (org2jekyll-message org-metadata)
            (let ((page-or-post (if (org2jekyll-post-p
                                     (assoc-default "layout" org-metadata))
                                    "Post"
                                  "Page")))
              (funcall action-fn org-metadata org-file)
              (format "%s '%s' published!" page-or-post filename-non-dir))))
      (format "'%s' is not an article, publication skipped!" filename-non-dir))))

(defun org2jekyll-message (&rest args)
  "Log formatted ARGS."
  (apply 'message (format "org2jekyll - %s" (car args)) (cdr args)))

(defun org2jekyll--publish-post-org-file-with-metadata (org-metadata org-file)
  "Publish as post with ORG-METADATA the ORG-FILE."
  (let ((blog-project    (assoc-default "layout" org-metadata))
        (jekyll-filename (org2jekyll--copy-org-file-to-jekyll-org-file
                          (assoc-default "date" org-metadata)
                          org-file org-metadata)))
    (org-publish-file jekyll-filename
                      (assoc blog-project org-publish-project-alist))
    (delete-file jekyll-filename)))

(defun org2jekyll-publish-post (org-file)
  "Publish ORG-FILE as a post."
  (org2jekyll-read-metadata-and-execute
   'org2jekyll--publish-post-org-file-with-metadata
   org-file))

(defun org2ekyll--publish-page-org-file-with-metadata (org-metadata org-file)
  "Publish as page with ORG-METADATA the ORG-FILE."
  (let* ((blog-project (assoc-default "layout" org-metadata))
         (ext (file-name-extension org-file))
         (temp-file (format "%sorg2jekyll" (s-chop-suffix ext org-file))))
    (copy-file org-file temp-file t t t)
    (with-temp-file temp-file
      (insert-file-contents temp-file)
      (goto-char (point-min))
      (insert (org2jekyll--to-yaml-header org-metadata))
      (write-file temp-file)
      (org-publish-file temp-file
                        (assoc blog-project org-publish-project-alist)))
    (delete-file temp-file)))

(defun org2jekyll-publish-page (org-file)
  "Publish ORG-FILE as a page."
  (org2jekyll-read-metadata-and-execute
   'org2ekyll--publish-page-org-file-with-metadata
   org-file))

(defun org2jekyll-post-p (layout)
  "Determine if the LAYOUT corresponds to a post."
  (string= "post" layout))

(defun org2jekyll-page-p (layout)
  "Determine if the LAYOUT corresponds to a page."
  (string= "default" layout))

(defun org2jekyll-publish-web-project ()
  "Publish the 'web' project."
  (org2jekyll-message "Publish `'web`' project (images, css, js, etc...).")
  (org-publish-project "web"))

;;;###autoload
(defun org2jekyll-publish ()
  "Publish the current org file as post or page depending on the chosen layout.
Layout `'post`' is a jekyll post.
Layout `'default`' is a page."
  (interactive)
  (lexical-let ((org-file (buffer-file-name (current-buffer))))
    (deferred:$
      (deferred:next (lambda ()
                       (-> "layout"
                           org2jekyll-get-option-at-point
                           org2jekyll-post-p
                           (if 'org2jekyll-publish-post
                               'org2jekyll-publish-page))))
      (deferred:nextc it (lambda (publish-fn) (funcall publish-fn org-file)))
      (deferred:nextc it (lambda (final-message)
                           (org2jekyll-publish-web-project)
                           final-message))
      (deferred:nextc it (lambda (final-message)
                           (org2jekyll-message final-message))))))

(defalias 'org2jekyll/publish! 'org2jekyll-publish)

(defvar org2jekyll-mode-map nil "Default Bindings map for org2jekyll mode.")

(setq org2jekyll-mode-map
      (let ((map (make-sparse-keymap)))
;;        (define-key map (kbd "C-c C-, n") 'org2jekyll-create-draft)
;;        (define-key map (kbd "C-c C-, p") 'org2jekyll-publish)
;;        (define-key map (kbd "C-c C-,") 'org2jekyll-publish-posts)
;;        (define-key map (kbd "C-c C-, l") 'org2jekyll-list-posts)
;;        (define-key map (kbd "C-c C-, d") 'org2jekyll-list-drafts)
        map))

;;;###autoload
(defun org2jekyll-publish-posts ()
  "Publish all the posts."
  (interactive)
  (deferred:$
    (deferred:next
      (lambda () (->> (assoc "post" org-publish-project-alist)
                 org-publish-get-base-files
                 (--filter (org2jekyll-post-p (org2jekyll-article-p it))))))
    (deferred:nextc it
      (lambda (posts)
        (mapc #'org2jekyll-publish-post posts)))))

(defalias 'org2jekyll/publish-posts! 'org2jekyll-publish-posts)

;;;###autoload
(defun org2jekyll-publish-pages ()
  "Publish all the pages."
  (interactive)
  (deferred:$
    (deferred:next
      (lambda () (->> (assoc "default" org-publish-project-alist)
                 org-publish-get-base-files
                 (--filter (org2jekyll-page-p (org2jekyll-article-p it))))))
    (deferred:nextc it
      (lambda (pages)
        (mapc #'org2jekyll-publish-page pages)))))

(defalias 'org2jekyll/publish-pages! 'org2jekyll-publish-pages)

;;;###autoload
(define-minor-mode org2jekyll-mode
  "Functionality for publishing the current org-mode post to jekyll.
With no argument, the mode is toggled on/off.
Non-nil argument turns mode on.
Nil argument turns mode off.

Commands:
\\{org2jekyll-mode-map}"

  :init-value nil
  :lighter " o2j"
  :group 'org2jekyll
  :keymap org2jekyll-mode-map)

(provide 'org2jekyll)
;;; org2jekyll.el ends here
ardumont commented 8 years ago

Hello,

Can you please quote your text using ``` quote? (Take a look for example at your initial issue (using the pen image to update your quote). i reformated it to have a nicer display to the eye, thanks. I do use github's ui and what you pasted here, without formatting, is just noise. It's difficult to read through.

I couldn't get what i wanted

... Well, i think you missed some steps. You need to evaluate all the snippet samples i gave you, including the user custom using M-: ... i showed you.

As a note, your org2jekyll code dump is not useful here. Also the following snippet, extracted from your data dump, does not match either the original one nor the one i provided you with:

'(org2jekyll-extra-yaml-headers "scheme-text:
scheme-link:
scheme-hover:
scheme-code:
scheme-bg:
scheme-hero-text:
scheme-hero-link:
scheme-hero-bg:
plugin: lightense")

Can you please try to fix and evaluate accordingly?

I did tests on my side and there are also unit tests (see the commit mentionned in this thread) which agree with me.

Cheers,

ardumont commented 8 years ago

Also, it's not really necessary for you to edit your installed source code. Just evaluate it, which means altering your emacs version running.

I am waiting for your feedback as a double check and then i merge the #35 PR, then release a new version.

Cheers,

ardumont commented 8 years ago

Following thread is #36