Hugo向けorgファイルのIn-Buffer Settings風の項目にブラケット付与が必須になる件

先日から再びHugoを使うようになり、orgファイルからHTMLを生成しているのですが、 hugo server を実行したときに警告文が表示されるようになり、気になったので調べてみたら、orgファイルに記載しているHugo向けIn-Buffer Settings風1の項目にブラケット付与をしてほしいとのことでした。

Hugoが出力した警告文はこちらです。

1
2
Please use '#+tags[]:' notation, automatic conversion is deprecated.
Please use '#+categories[]:' notation, automatic conversion is deprecated.

気になったので調べてみたところ、以下の通りでした。

  1. 2019年4月ごろにリリースされたHogo v0.69.2でorgファイルのパーサーに変更が入った
  2. org-modeの In-Buffer Settings 風にorgファイル冒頭で宣言可能な #+tags, #+categories, #+aliases 項目の末尾に [] が必要となった

上記の理由からorgファイルを書き換えなくてはなりません。 automatic conversion is deprecated とありますから「手動でやってほしい」と依頼事項があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Bad. Print warning while building.
#+title: HugoのorgファイルのIn-Buffer Settings風の項目にブラケット付与が必須になる件
#+tags: Hugo Org-mode
#+categories: example
#+aliases: example

// Good
#+title: HugoのorgファイルのIn-Buffer Settings風の項目にブラケット付与が必須になる件
#+tags[]: Hugo Org-mode
#+categories[]: example
#+aliases[]: example

上記の件に関係するコードはこちらです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func (d Decoder) unmarshalORG(data []byte, v interface{}) error {
	config := org.New()
	config.Log = jww.WARN
	document := config.Parse(bytes.NewReader(data), "")
	if document.Error != nil {
		return document.Error
	}
	frontMatter := make(map[string]interface{}, len(document.BufferSettings))
	for k, v := range document.BufferSettings {
		k = strings.ToLower(k)
		if strings.HasSuffix(k, "[]") {
			frontMatter[k[:len(k)-2]] = strings.Fields(v)
		} else if k == "tags" || k == "categories" || k == "aliases" {
			jww.WARN.Printf("Please use '#+%s[]:' notation, automatic conversion is deprecated.", k) 
			frontMatter[k] = strings.Fields(v)
		} else {
			frontMatter[k] = v
		}
	}
	switch v.(type) {
	case *map[string]interface{}:
		*v.(*map[string]interface{}) = frontMatter
	default:
		*v.(*interface{}) = frontMatter
	}
	return nil
}

こちらのコードは以下の情報と併せてご覧ください。

とはいえ

実は項目の末尾に何故 [] をつけるのかが理解が追いついていないのです。 先頭に hugo プリフィックスをつけたほうが良いようにも思うのだけど、org-modeのIFを考慮するとこうするしかないのかな。

そうするとこっちのコードと釣り合っていない感じがするのですよね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// GetOption returns the value associated to the export option key
// Currently supported options:
// - < (export timestamps)
// - e (export org entities)
// - f (export footnotes)
// - toc (export table of content. an int limits the included org headline lvl)
// - todo (export headline todo status)
// - pri (export headline priority)
// - tags (export headline tags)
// see https://orgmode.org/manual/Export-settings.html for more information
func (d *Document) GetOption(key string) string {
	get := func(settings map[string]string) string {
		for _, field := range strings.Fields(settings["OPTIONS"]) {
			if strings.HasPrefix(field, key+":") {
				return field[len(key)+1:]
			}
		}
		return ""
	}
	value := get(d.BufferSettings)
	if value == "" {
		value = get(d.DefaultSettings)
	}
	if value == "" {
		value = "nil"
		d.Log.Printf("Missing value for export option %s", key)
	}
	return value
}

1

Orgの仕様には #+tags:#+category: が明記されていますが、Hugoのものとは異なります