emacs/org/elpa/ox-hugo-20221028.1631/ox-hugo-deprecated.el

443 lines
21 KiB
EmacsLisp
Raw Normal View History

2022-11-08 03:54:27 +00:00
;;; ox-hugo-deprecated.el --- Deprecated stuff from ox-hugo -*- lexical-binding: t -*-
;; Authors: Kaushal Modi <kaushal.modi@gmail.com>
;; URL: https://ox-hugo.scripter.co
;;; Commentary:
;; This file contains variables and functions deprecated from ox-hugo.
;; Do not depend on this file as it may disappear any day.
;;; Obsoletions
;; Blackfriday support is being removed from `ox-hugo' as Hugo has
;; deprecated its support for a while.
;; https://github.com/kaushalmodi/ox-hugo/discussions/485
;;; Code:
;; Silence byte-compiler
(defvar org-hugo--date-time-regexp)
(defvar org-hugo--subtree-coord)
(declare-function org-string-nw-p "org-macs")
(declare-function org-hugo--calc-weight "ox-hugo")
(declare-function org-hugo-slug "ox-hugo")
(declare-function org-hugo--front-matter-value-booleanize "ox-hugo")
(declare-function org-hugo--delim-str-to-list "ox-hugo")
(declare-function org-hugo--parse-property-arguments "ox-hugo")
;;
(make-obsolete-variable 'org-hugo-blackfriday-options nil "Hugo has switched to use Goldmark as the default Markdown parser since v0.60." "Jan 15, 2022")
(make-obsolete-variable 'org-hugo-blackfriday-extensions nil "Hugo has switched to use Goldmark as the default Markdown parser since v0.60." "Jan 15, 2022")
;;; Variables
(defvar org-hugo-blackfriday-options
'("taskLists"
"smartypants"
"smartypantsQuotesNBSP"
"angledQuotes"
"fractions"
"smartDashes"
"latexDashes"
"hrefTargetBlank"
"plainIDAnchors"
"extensions"
"extensionsmask")
"Deprecated Blackfriday parser option names.")
(defvar org-hugo-blackfriday-extensions
'("noIntraEmphasis"
"tables"
"fencedCode"
"autolink"
"strikethrough"
"laxHtmlBlocks"
"spaceHeaders"
"hardLineBreak"
"tabSizeEight"
"footnotes"
"noEmptyLineBeforeBlock"
"headerIds"
"titleblock"
"autoHeaderIds"
"backslashLineBreak"
"definitionLists"
"joinLines")
"Deprecated Blackfriday extension names.")
;;; Functions
(defun org-hugo--parse-blackfriday-prop-to-alist (str)
"Return an alist of valid Hugo blackfriday properties converted from STR.
For example, input STR:
\":fractions :smartdashes nil :angledquotes t\"
would convert to:
((fractions . \"false\") (smartDashes . \"false\") (angledQuotes . \"true\"))
The \"true\" and \"false\" strings in the return value are due to
`org-hugo--front-matter-value-booleanize'."
(let ((blackfriday-alist (org-hugo--parse-property-arguments str))
valid-blackfriday-alist)
(dolist (ref-prop org-hugo-blackfriday-options)
(dolist (user-prop blackfriday-alist)
(when (string= (downcase (symbol-name (car user-prop)))
(downcase ref-prop))
(let* ((key (intern ref-prop))
(value (cdr user-prop))
(value (if (or (equal key 'extensions)
(equal key 'extensionsmask))
(org-hugo--delim-str-to-list value)
(org-hugo--front-matter-value-booleanize value))))
(push (cons key value)
valid-blackfriday-alist)))))
valid-blackfriday-alist))
(defun org-hugo--return-valid-blackfriday-extension (ext)
"Return valid case-sensitive string for Blackfriday extension EXT.
Example: If EXT is \"hardlinebreak\",
\"\"hardLineBreak\"\" (quoted string) is returned."
(let (ret)
(dolist (ref-ext org-hugo-blackfriday-extensions)
;; (message "ox-hugo bf valid ext DBG: ext=%s ref-ext=%s" ext ref-ext)
(when (string= (downcase ext) (downcase ref-ext))
(setq ret ref-ext)))
(unless ret
(user-error "Invalid Blackfriday extension name %S, see `org-hugo-blackfriday-extensions'"
ext))
(org-hugo--yaml-quote-string ret)))
;;; YAML Support
(defun org-hugo--yaml-quote-string (val &optional prefer-no-quotes)
"Wrap VAL with quotes as appropriate.
VAL can be a string, symbol, number or nil.
VAL is returned as-it-is under the following cases:
- It is a number.
- It is a string and is already wrapped with double quotes.
- It is a string and it's value is \"true\" or \"false\".
- It is a string representing a date.
- It is a string representing an integer or float.
If VAL is nil or an empty string, a quoted empty string \"\" is
returned.
If optional argument PREFER-NO-QUOTES is non-nil, return the VAL
as-it-is if it's a string with just alphanumeric characters."
(cond
((null val) ;nil
val)
((numberp val)
val)
((symbolp val)
(format "\"%s\"" (symbol-name val)))
((stringp val)
(cond
((org-string-nw-p val) ;If `val' is a non-empty string
(cond
((or (and (string= (substring val 0 1) "\"") ;First char is literally a "
(string= (substring val -1) "\"")) ;Last char is literally a "
(and prefer-no-quotes ;If quotes are not preferred and `val' is only alpha-numeric
(string-match-p "\\`[a-zA-Z0-9]+\\'" val))
;; or if it an integer that can be stored in the system as
;; a fixnum. For example, if `val' is
;; "10040216507682529280" that needs more than 64 bits to
;; be stored as a signed integer, it will be automatically
;; stored as a float. So (integerp (string-to-number
;; val)) will return nil [or `fixnump' instead of
;; `integerp' in Emacs 27 or newer]
;; https://github.com/toml-lang/toml#integer Integer
;; examples: 7, +7, -7, 7_000
(and (string-match-p "\\`[+-]?[[:digit:]_]+\\'" val)
(if (functionp #'fixnump) ;`fixnump' and `bignump' get introduced in Emacs 27.x
(fixnump (string-to-number val))
(integerp (string-to-number val)))) ;On older Emacsen, `integerp' behaved the same as the new `fixnump'
(string= "true" val)
(string= "false" val)
;; or if it is a date (date, publishDate, expiryDate, lastmod)
(string-match-p org-hugo--date-time-regexp val)
;; or if it is a float
;; https://github.com/toml-lang/toml#float
;; Float examples (decimals): 7.8, +7.8, -7.8
(string-match-p "\\`[+-]?[[:digit:]_]+\\.[[:digit:]_]+\\'" val)
;; Float examples (exponentials): 7e-8, -7E+8, 1.7e-05
(string-match-p "\\`[+-]?[[:digit:]_]+\\(\\.[[:digit:]_]+\\)*[eE][+-]?[[:digit:]_]+\\'" val)
;; Special float values (infinity/NaN)
;; Looks like Hugo is not supporting these.. Tue Mar 20 18:05:40 EDT 2018 - kmodi
;; (let ((case-fold-search nil))
;; (string-match-p "\\`[+-]?\\(inf\\|nan\\)\\'" val))
)
val)
((string-match-p "\n" val) ;Multi-line string
;; The indentation of the multi-line string is needed only for the
;; YAML format. But the same is done for TOML too just for better
;; presentation.
(setq val (replace-regexp-in-string "^" " " val))
;; https://yaml-multiline.info/
;;
;; | |foo : >
;; |abc | abc
;; | >>> |
;; |def |
;; | | def
;;
;; In Org, a single blank line is used to start a new
;; paragraph. In the YAML multi-line string, that needs to
;; be 2 blank lines.
(setq val (replace-regexp-in-string "\n[[:blank:]]*\n" "\n\n\n" val))
(format ">\n%s" val))
(t ;Single-line string
;; Below 2 replacements are order-dependent.. first escape the
;; backslashes, then escape the quotes with backslashes.
;; Escape the backslashes (for both TOML and YAML).
(setq val (replace-regexp-in-string "\\\\" "\\\\\\\\" val))
;; Escape the double-quotes.
(setq val (replace-regexp-in-string "\"" "\\\\\"" val))
(concat "\"" val "\""))))
(t ;If `val' is any empty string
"\"\"")))
(t ;Return empty string if anything else
"\"\"")))
(defun org-hugo--get-yaml-list-string (key list)
"Return KEY's LIST value as a YAML list, represented as a string.
KEY is a string and LIST is a list where an element can be a
symbol, number or a non-empty string. Examples:
\(\"abc\" \"def\") -> \"[\\\"abc\\\", \\\"def\\\"]\"."
(concat "["
(mapconcat #'identity
(mapcar (lambda (v)
(org-hugo--yaml-quote-string
(cond
((symbolp v)
(symbol-name v))
((numberp v)
(number-to-string v))
((org-string-nw-p v)
v)
(t
(user-error "Invalid element %S in `%s' value %S" v key list)))))
list)
", ")
"]"))
(defun org-hugo--gen-yaml-front-matter (data)
"Generate Hugo front-matter in YAML format, and return that string.
DATA is an alist of the form \((KEY1 . VAL1) (KEY2 . VAL2) .. \),
where KEY is a symbol and VAL is a string."
(let ((sep "---\n")
(sign ":")
(front-matter "")
(indent (make-string 2 ? ))
(nested-string "")
(menu-string "")
(res-string ""))
(dolist (pair data)
(let ((key (symbol-name (car pair)))
(value (cdr pair)))
;; (message "[hugo fm key value DBG] %S %S" key value)
(unless (or (null value) ;Skip writing front-matter variables whose value is nil
(and (stringp value) ;or an empty string.
(string= "" value)))
;; In TOML/YAML, the value portion needs to be wrapped in
;; double quotes.
;; TOML example:
;; title = "My Post"
;; YAML example:
;; title: "My Post"
(cond
((string= key "menu")
(unless (listp value)
(user-error (concat "The `menu' front-matter did not get the expected "
"list value; probably because HUGO_MENU was not "
"used to set its value.\n"
"Usage examples: \":EXPORT_HUGO_MENU: :menu main\" or "
"\"#+hugo_menu: :menu main\"")))
;; Menu name needs to be non-nil to insert menu info in front-matter.
(when (assoc 'menu value)
(let* ((menu-alist value)
;; Menu entry string might need to be quoted if
;; it contains spaces, for example.
(menu-entry (org-hugo--yaml-quote-string (cdr (assoc 'menu menu-alist)) :prefer-no-quotes))
(menu-entry-str "")
(menu-value-str ""))
;; Auto-set menu identifier if not already set by user.
(unless (assoc 'identifier menu-alist)
(let ((title (cdr (assoc 'title data))))
(push `(identifier . ,(org-hugo-slug title)) menu-alist)))
;; Auto-set menu weight if not already set by user.
(unless (assoc 'weight menu-alist)
(when org-hugo--subtree-coord
(push `(weight . ,(org-hugo--calc-weight)) menu-alist)))
;; (message "[menu alist DBG] = %S" menu-alist)
(when menu-entry
(setq menu-entry-str (prog1
(format "menu%s\n%s%s%s\n"
sign indent menu-entry sign)
(setq indent (concat indent indent)))) ;Double the indent for next use
(dolist (menu-pair menu-alist)
(let ((menu-key (symbol-name (car menu-pair)))
(menu-value (cdr menu-pair)))
;; (message "menu DBG: %S %S %S" menu-entry menu-key menu-value)
(unless (string= "menu" menu-key)
(when menu-value
;; Cannot skip quote wrapping for values of keys inside menu.
;; Attempting to do:
;; [menu.foo]
;; parent = main
;; # parent = "main" # But this works
;; gives this error:
;; ERROR 2017/07/21 10:56:07 failed to parse page metadata
;; for "singles/post-draft.md": Near line 10 (last key parsed
;; 'menu.foo.parent'): expected value but found "main" instead.
(setq menu-value (org-hugo--yaml-quote-string menu-value))
(setq menu-value-str
(concat menu-value-str
(format "%s%s%s %s\n"
indent menu-key sign menu-value)))))))
(setq menu-string (concat menu-entry-str menu-value-str))))))
((string= key "resources")
(unless (listp value)
(user-error (concat "The `resources' front-matter did not get the expected "
"list value; probably because HUGO_RESOURCES was not "
"used to set its value.\n"
"Usage examples: \":EXPORT_HUGO_RESOURCES: :src \"my-image.png\" :title \"My Image\" "
"or \"#+hugo_resources: :src \"my-image.png\" :title \"My Image\"")))
(when value
(dolist (res-alist value)
(let ((res-entry-str "")
(res-value-str "")
res-src-present
res-param-str)
(setq res-entry-str
;; For YAML, this string
;; needs to be inserted
;; only once.
(if (org-string-nw-p res-string)
""
(format "resources%s\n" sign)))
(dolist (res-pair res-alist)
;; (message "[resources DBG] res-pair: %S" res-pair)
(let* ((res-key (symbol-name (car res-pair)))
(res-value (cdr res-pair)))
;; (message "[resources DBG]: %S %S" res-key res-value)
(cond ((string= res-key "params")
(setq indent (make-string 4 ? ))
(setq res-param-str (format " %s%s\n" res-key sign))
(dolist (param-pair res-value) ;res-value would be an alist of params
(let ((param-key (symbol-name (car param-pair)))
(param-value (cdr param-pair))
param-value-str)
;; (message "[resources DBG] param-key: %S" param-key)
;; (message "[resources DBG] param-value: %S" param-value)
(setq param-value-str (if (listp param-value)
(org-hugo--get-yaml-list-string param-key param-value)
(org-hugo--yaml-quote-string param-value)))
(setq res-param-str
(concat res-param-str
(format "%s%s%s %s\n"
indent param-key sign param-value-str)))))
;; (message "[resources params DBG] %s" res-param-str)
)
(t
(when (string= res-key "src")
(setq res-src-present t))
(if (string= res-key "src")
(setq indent "- ")
(setq indent " "))
(setq res-value (org-hugo--yaml-quote-string res-value))
(setq res-value-str
(concat res-value-str
(format "%s%s%s %s\n"
indent res-key sign res-value)))))))
(unless res-src-present
(user-error "`src' must be set for the `resources'"))
(setq res-string (concat res-string res-entry-str res-value-str res-param-str))))))
(;; Front-matter with nested map values: blackfriday, custom front-matter.
;; Only 1 level of nesting is supported.
(and (listp value) ;Example value: '((legs . 4) ("eyes" . 2) (friends . (poo boo)))
(eq 0 (cl-count-if (lambda (el) ;Check if value is a list of lists (or conses)
(not (listp el)))
value)))
(let ((nested-parent-key key)
(nested-alist value)
(nested-parent-key-str "")
(nested-keyval-str ""))
;; (message "[nested entry DBG] = %s" nested-parent-key)
;; (message "[nested alist DBG] = %S" nested-alist)
(setq nested-parent-key-str (format "%s%s\n" nested-parent-key sign))
(dolist (nested-pair nested-alist)
(unless (consp nested-pair)
(user-error "Ox-hugo: Custom front-matter values with nested maps need to be an alist of conses"))
;; (message "[nested pair DBG] = %S" nested-pair)
(let* ((nested-key (car nested-pair))
(nested-key (cond
((symbolp nested-key)
(symbol-name nested-key))
(t
nested-key)))
(nested-value (cdr nested-pair))
(nested-value (cond
((and nested-value
(listp nested-value))
(if (and (string= nested-parent-key "blackfriday")
(or (string= nested-key "extensions")
(string= nested-key "extensionsmask")))
(org-hugo--get-yaml-list-string
nested-key
(mapcar #'org-hugo--return-valid-blackfriday-extension
nested-value))
(org-hugo--get-yaml-list-string nested-key nested-value)))
((null nested-value)
"false")
((equal nested-value 't)
"true")
(t
(org-hugo--yaml-quote-string nested-value)))))
;; (message "nested DBG: %S KEY %S->%S VALUE %S->%S" nested-parent-key
;; (car nested-pair) nested-key
;; (cdr nested-pair) nested-value)
(when nested-value
(setq nested-keyval-str
(concat nested-keyval-str
(format "%s%s%s %s\n"
indent nested-key sign nested-value))))))
(when (org-string-nw-p nested-keyval-str)
(setq nested-string (concat nested-string nested-parent-key-str
nested-keyval-str)))))
(t
(setq front-matter
(concat front-matter
(format "%s%s %s\n"
key
sign
(cond (;; Tags, categories, keywords, aliases,
;; custom front-matter which are lists.
(listp value)
(org-hugo--get-yaml-list-string key value))
(t
(org-hugo--yaml-quote-string value nil)))))))))))
(concat sep front-matter nested-string menu-string res-string sep)))
(provide 'ox-hugo-deprecated)
;;; ox-hugo-deprecated.el ends here