diff --git a/example-site/content-org/all-posts.org b/example-site/content-org/all-posts.org
index 74badbb..7d916aa 100644
--- a/example-site/content-org/all-posts.org
+++ b/example-site/content-org/all-posts.org
@@ -691,6 +691,31 @@ This is some text[fn:1][fn:2].
This is some text[fn:1].
This is some text[fn:1].
This is some text[fn:1].
+* Hyphens in Org tags
+** Prefer
+:PROPERTIES:
+:EXPORT_HUGO_PREFER_HYPHEN_IN_TAGS: t
+:END:
+*** Prefer Hyphen in Tags :_a:__a:b_:b__:a_b:a__b:a_b__c:_a_b__c__:
+:PROPERTIES:
+:EXPORT_FILE_NAME: hyphen-tags-prefer
+:END:
+*** Prefer Hyphen Categories :@_a:@__a:@b_:@b__:@a_b:@a__b:@a_b__c:@_a_b__c__:
+:PROPERTIES:
+:EXPORT_FILE_NAME: hyphen-categories-prefer
+:END:
+** Don't Prefer
+:PROPERTIES:
+:EXPORT_HUGO_PREFER_HYPHEN_IN_TAGS:
+:END:
+*** Don't Prefer Hyphen in Tags :_a:__a:b_:b__:a_b:a__b:a_b__c:_a_b__c__:
+:PROPERTIES:
+:EXPORT_FILE_NAME: hyphen-tags-dont-prefer
+:END:
+*** Don't Prefer Hyphen Categories :@_a:@__a:@b_:@b__:@a_b:@a__b:@a_b__c:@_a_b__c__:
+:PROPERTIES:
+:EXPORT_FILE_NAME: hyphen-categories-dont-prefer
+:END:
* Tags as Categories
** Category A :@catA:
*** Cat A post 1 :meow:
diff --git a/example-site/content/posts/code-fenced-src-blocks-default.md b/example-site/content/posts/code-fenced-src-blocks-default.md
index b12d625..f1cf29c 100644
--- a/example-site/content/posts/code-fenced-src-blocks-default.md
+++ b/example-site/content/posts/code-fenced-src-blocks-default.md
@@ -1,7 +1,7 @@
+++
title = "Code-fenced source blocks (default behavior)"
date = 2017-07-31
-tags = ["src_block"]
+tags = ["src-block"]
draft = false
+++
diff --git a/example-site/content/posts/code-fenced-src-blocks.md b/example-site/content/posts/code-fenced-src-blocks.md
index 133c335..d8a6da8 100644
--- a/example-site/content/posts/code-fenced-src-blocks.md
+++ b/example-site/content/posts/code-fenced-src-blocks.md
@@ -1,7 +1,7 @@
+++
title = "Code-fenced source blocks"
date = 2017-07-13T17:49:22-04:00
-tags = ["src_block"]
+tags = ["src-block"]
draft = false
+++
diff --git a/example-site/content/posts/custom-front-matter-multiple-lines.md b/example-site/content/posts/custom-front-matter-multiple-lines.md
index bf4d902..e902b76 100644
--- a/example-site/content/posts/custom-front-matter-multiple-lines.md
+++ b/example-site/content/posts/custom-front-matter-multiple-lines.md
@@ -1,7 +1,7 @@
+++
title = "Custom front matter in multiple lines"
date = 2017-07-24
-tags = ["custom_fm"]
+tags = ["custom-fm"]
draft = false
foo = "bar"
baz = "zoo"
diff --git a/example-site/content/posts/custom-front-matter-one-line.md b/example-site/content/posts/custom-front-matter-one-line.md
index 49f03c8..b6c17a9 100644
--- a/example-site/content/posts/custom-front-matter-one-line.md
+++ b/example-site/content/posts/custom-front-matter-one-line.md
@@ -1,7 +1,7 @@
+++
title = "Custom front matter in one line"
date = 2017-07-24
-tags = ["custom_fm"]
+tags = ["custom-fm"]
draft = false
foo = "bar"
baz = "zoo"
diff --git a/example-site/content/posts/highlight-shortcode-src-blocks.md b/example-site/content/posts/highlight-shortcode-src-blocks.md
index a5f5f9e..5954fcf 100644
--- a/example-site/content/posts/highlight-shortcode-src-blocks.md
+++ b/example-site/content/posts/highlight-shortcode-src-blocks.md
@@ -1,7 +1,7 @@
+++
title = "Source blocks with highlight shortcode"
date = 2017-07-31
-tags = ["src_block"]
+tags = ["src-block"]
draft = false
+++
diff --git a/example-site/content/posts/hyphen-categories-dont-prefer.md b/example-site/content/posts/hyphen-categories-dont-prefer.md
new file mode 100644
index 0000000..5a97137
--- /dev/null
+++ b/example-site/content/posts/hyphen-categories-dont-prefer.md
@@ -0,0 +1,5 @@
++++
+title = "Don't Prefer Hyphen Categories"
+categories = ["_a", "__a", "b_", "b__", "a_b", "a__b", "a_b__c", "_a_b__c__"]
+draft = false
++++
diff --git a/example-site/content/posts/hyphen-categories-prefer.md b/example-site/content/posts/hyphen-categories-prefer.md
new file mode 100644
index 0000000..c6eea5b
--- /dev/null
+++ b/example-site/content/posts/hyphen-categories-prefer.md
@@ -0,0 +1,5 @@
++++
+title = "Prefer Hyphen Categories"
+categories = ["-a", "_a", "b-", "b_", "a-b", "a_b", "a-b_c", "-a_b_c_"]
+draft = false
++++
diff --git a/example-site/content/posts/hyphen-tags-dont-prefer.md b/example-site/content/posts/hyphen-tags-dont-prefer.md
new file mode 100644
index 0000000..abb3508
--- /dev/null
+++ b/example-site/content/posts/hyphen-tags-dont-prefer.md
@@ -0,0 +1,5 @@
++++
+title = "Don't Prefer Hyphen in Tags"
+tags = ["_a", "__a", "b_", "b__", "a_b", "a__b", "a_b__c", "_a_b__c__"]
+draft = false
++++
diff --git a/example-site/content/posts/hyphen-tags-prefer.md b/example-site/content/posts/hyphen-tags-prefer.md
new file mode 100644
index 0000000..2a933e9
--- /dev/null
+++ b/example-site/content/posts/hyphen-tags-prefer.md
@@ -0,0 +1,5 @@
++++
+title = "Prefer Hyphen in Tags"
+tags = ["-a", "_a", "b-", "b_", "a-b", "a_b", "a-b_c", "-a-b_c_"]
+draft = false
++++
diff --git a/example-site/content/posts/list-has-src-block-but-no-list-syntax.md b/example-site/content/posts/list-has-src-block-but-no-list-syntax.md
index fb33cfa..26ad73a 100644
--- a/example-site/content/posts/list-has-src-block-but-no-list-syntax.md
+++ b/example-site/content/posts/list-has-src-block-but-no-list-syntax.md
@@ -1,7 +1,7 @@
+++
title = "Source block without list syntax in a list"
date = 2017-08-01
-tags = ["src_block"]
+tags = ["src-block"]
draft = false
+++
diff --git a/example-site/content/posts/list-has-src-block-with-list-syntax.md b/example-site/content/posts/list-has-src-block-with-list-syntax.md
index 1b9b380..53ca8af 100644
--- a/example-site/content/posts/list-has-src-block-with-list-syntax.md
+++ b/example-site/content/posts/list-has-src-block-with-list-syntax.md
@@ -1,7 +1,7 @@
+++
title = "Source block with list syntax in a list"
date = 2017-08-01
-tags = ["src_block", "upstream"]
+tags = ["src-block", "upstream"]
categories = ["fixme"]
draft = false
+++
diff --git a/example-site/content/posts/src-block-outside-list-with-list-syntax.md b/example-site/content/posts/src-block-outside-list-with-list-syntax.md
index f0df63f..f557a2e 100644
--- a/example-site/content/posts/src-block-outside-list-with-list-syntax.md
+++ b/example-site/content/posts/src-block-outside-list-with-list-syntax.md
@@ -1,7 +1,7 @@
+++
title = "Source block with list syntax but not in a list"
date = 2017-08-01
-tags = ["src_block"]
+tags = ["src-block"]
draft = false
+++
diff --git a/ox-hugo.el b/ox-hugo.el
index 65738c2..65e40c4 100644
--- a/ox-hugo.el
+++ b/ox-hugo.el
@@ -44,10 +44,18 @@
"State variable to store the \"draft\" state of the subtree to be exported.")
(defvar org-hugo--tags-list nil
- "State variable to store the tags of the subtree to be exported.")
+ "Cache of tags for the exported post subtree.
+
+These are Org tags linked to a subtree directly or via
+inheritance, that do not begin with the \"@\" character.
+This is a list of strings.")
(defvar org-hugo--categories-list nil
- "State variable to store the categories of the subtree to be exported.")
+ "Cache of categories for the exported post subtree.
+
+These are Org tags linked to a subtree directly or via
+inheritance, that begin with the \"@\" character.
+This is a list of strings.")
(defvar org-hugo--subtree-coord nil
"Variable to store the current valid Hugo subtree coordinates.")
@@ -351,7 +359,17 @@ The string needs to be in a Hugo-compatible Markdown format or HTML."
:safe 'stringp)
(defcustom org-hugo-use-code-for-kbd t
- "When non-nil, ~text~ will translate to text." :group 'org-export-hugo
+ "When non-nil, ~text~ will translate to text."
+ :group 'org-export-hugo
+ :type 'boolean
+ :safe #'booleanp)
+
+(defcustom org-hugo-prefer-hyphen-in-tags t
+ "When non-nil, replace underscores with hyphens in Org tags.
+In that case, use double underscores to represent a single underscore.
+
+This also affects the Hugo categories set via Org tags using the
+\"@\" prefix."
:group 'org-export-hugo
:type 'boolean
:safe #'booleanp)
@@ -407,6 +425,7 @@ The string needs to be in a Hugo-compatible Markdown format or HTML."
(:hugo-menu "HUGO_MENU" nil nil)
(:hugo-menu-override "HUGO_MENU_OVERRIDE" nil nil)
(:hugo-use-code-for-kbd "HUGO_USE_CODE_FOR_KBD" nil org-hugo-use-code-for-kbd)
+ (:hugo-prefer-hyphen-in-tags "HUGO_PREFER_HYPHEN_IN_TAGS" nil org-hugo-prefer-hyphen-in-tags)
(:hugo-custom-front-matter "HUGO_CUSTOM_FRONT_MATTER" nil nil)
(:hugo-blackfriday "HUGO_BLACKFRIDAY" nil nil)
@@ -993,6 +1012,25 @@ INFO is a plist used as a communication channel."
(title (replace-regexp-in-string "\\\\_" "_" title)))
title))
+(defun org-hugo--transform-org-tags (str)
+ "Transform Org tag STR for use in Hugo tags and categories.
+
+- Single underscores will be replaced with hyphens.
+- Double underscores will be replaced with single underscores.
+
+Below shows the example of how the Org tags would translate to
+the tag strings in Hugo front matter.
+
+Example: :some_tag: -> \"some-tag\"
+ :some__tag: -> \"some_tag\"."
+ (let* ((str (replace-regexp-in-string "\\`_\\([^_]\\)" "-\\1" str)) ;"_a" -> "-a"
+ (str (replace-regexp-in-string "\\`__\\([^_]\\)" "_\\1" str)) ;"__a" -> "_a"
+ (str (replace-regexp-in-string "\\([^_]\\)_\\'" "\\1-" str)) ;"a_" -> "a-"
+ (str (replace-regexp-in-string "\\([^_]\\)__\\'" "\\1_" str)) ;"a__" -> "a_"
+ (str (replace-regexp-in-string "\\([^_]\\)_\\([^_]\\)" "\\1-\\2" str)) ;"a_b" -> "a-b"
+ (str (replace-regexp-in-string "\\([^_]\\)__\\([^_]\\)" "\\1_\\2" str))) ;"a__b" -> "a_b"
+ str))
+
(defun org-hugo--get-front-matter (info)
"Return the Hugo front matter string.
@@ -1024,16 +1062,25 @@ INFO is a plist used as a communication channel."
date-nocolon)))
(draft (or org-hugo--draft-state
(org-export-data (plist-get info :hugo-draft) info)))
+ (tag-list (if (org-hugo--plist-value-true-p :hugo-prefer-hyphen-in-tags info)
+ (mapcar #'org-hugo--transform-org-tags
+ org-hugo--tags-list)
+ org-hugo--tags-list))
(tags (org-string-nw-p ;Don't allow tags to be just whitespace
- (or (org-string-nw-p (mapconcat #'identity org-hugo--tags-list " "))
+ (or (org-string-nw-p (mapconcat #'identity tag-list " "))
(concat
(org-export-data (plist-get info :hugo-tags) info) " "
(org-export-data (plist-get info :tags) info)))))
+ (categories-list (if (org-hugo--plist-value-true-p :hugo-prefer-hyphen-in-tags info)
+ (mapcar #'org-hugo--transform-org-tags
+ org-hugo--categories-list)
+ org-hugo--categories-list))
(categories (or (org-string-nw-p
(mapconcat (lambda (str)
;; Remove "@" from beg of categories.
(replace-regexp-in-string "\\`@" "" str))
- org-hugo--categories-list " "))
+ categories-list
+ " "))
(org-export-data (plist-get info :hugo-categories) info)))
(menu-alist (org-hugo--parse-menu-prop-to-alist (plist-get info :hugo-menu)))
(menu-alist-override (org-hugo--parse-menu-prop-to-alist (plist-get info :hugo-menu-override)))
@@ -1226,6 +1273,7 @@ are \"toml\" and \"yaml\"."
(defun org-hugo--selective-property-inheritance ()
"Return a list of properties that should be inherited."
(let ((prop-list '("HUGO_FRONT_MATTER_FORMAT"
+ "HUGO_PREFER_HYPHEN_IN_TAGS"
"HUGO_BLACKFRIDAY"
"HUGO_SECTION"
"HUGO_BASE_DIR"
@@ -1242,12 +1290,10 @@ are \"toml\" and \"yaml\"."
"HUGO_TAGS"
"HUGO_CATEGORIES"
"HUGO_TYPE"
- "HUGO_WEIGHT"))
- prop-list-allow-inheritance)
- (dolist (prop prop-list)
- (let ((prop (concat "EXPORT_" prop)))
- (push prop prop-list-allow-inheritance)))
- prop-list-allow-inheritance))
+ "HUGO_WEIGHT")))
+ (mapcar (lambda (str)
+ (concat "EXPORT_" str))
+ prop-list)))
(defun org-hugo--get-valid-subtree ()
"Return the org element for a valid Hugo post subtree.