六一的部落格


关关难过关关过,前路漫漫亦灿灿。




ox-hugo导出时关于标题锚的设定

Anchors

  • 变量 org-hugo-anchor-functions

    存放若干个函数, 优先级从高到低, 最先返回不为nil, 用作标题锚

    函数 对应属性配置
    org-hugo-get-page-or-bundle-name 导出文件名 :EXPORT_FILE_NAME
    org-hugo-get-custom-id 自定义ID :CUSTOM_ID
    org-hugo-get-heading-slug 标题名称
    org-hugo-get-md5 计算标题名称md5
    org-hugo-get-id 分配ID :ID
  • ID

    之前使用org-roam实现双链笔记本时, 为部分标题添加了ID, 这个是不可能普及的

  • 自定义ID

    需手动配置

  • 标题名称

    当前标题的处理方式, 存在标题重名问题

  • md5

    和标题名称一样的问题, 还不直观

  • 导出文件名

    注意: 这个的优先级最高, 因为会使用到文章锚


Hugo对Markdown文件标题ID的处理

Heading IDs

  1. 当标题后没有跟锚时, 会对重名标题编号

    ## Reference
    ## Reference
    ## Reference

    当id不同时, 在Hugo中可以设置不同锚

    1<h2 id="reference">Reference</h2>
    2<h2 id="reference-1">Reference</h2>
    3<h2 id="reference-2">Reference</h2>
  2. 如果标题后有锚, 标题id为锚移除"#“的内容

    允许重名

    ## Reference A {#foo}
    1<h2 id="foo">Reference A</h2>

对重名id编号

  • 如果Markdown文件中没有锚, 这个就不需要额外处理

  • 如果打算额外处理, 而文章目录依据文章正文生成, 修改Markdown文件好过修改html

  • 如果打算修改Markdown, 即自己找重名标题, 不如ox-hugo导出时所有标题的锚都相同: 全删即可

  • 即, ox-hugo为所有标题生成相同的锚, 或者不生成锚; 后者需要修改ox-hugo源码



影响

部分博文里包含其他博文+标题链接, 这些标题有ID, 且基本不会存在重名的情况

因此, 如让ox-hugo为所有标题生成相同的锚, 不包括文章标题, 即不使用ID作为锚, 就不用修改双链跳转


解决方案


让ox-hugo为所有标题生成相同的锚

设置 org-hugo-anchor-functions , 函数优先级如下

  1. org-hugo-get-page-or-bundle-name
  2. org-hugo-get-custom-id

且仅有这两个函数


修改导出之后的文本内容

  1. 注释之前的定义
    • my/ox-hugo-export-subtree
    • my/ox-hugo-export-all-subtrees
  2. 重新定义: 调用修改文本函数
  3. 实现修改文本函数

修改文本


移除标题锚

1(defun my/remove-anchor-file (file)
2  (interactive)
3  (with-current-buffer (find-file-noselect file)
4    (beginning-of-buffer)
5    (replace-string "{#}" "")
6    (save-buffer)
7    (kill-buffer)
8    )
9  )

移除给定子树标题锚

1(defun my/remove-anchor-file-name (export-name)
2  (interactive)
3  (my/remove-anchor-file (concat (my/subtree-path-str export-name) ".md"))
4  )

移除文件内所有子树标题锚

1(defun my/remove-anchor-pack ()
2  (interactive)
3  (beginning-of-buffer)
4  (while (re-search-forward (rx ":" "EXPORT_FILE_NAME" ": " (group (0+ (not "\n"))) "\n") nil t)
5    (my/remove-anchor-file-name (string-join (mapcar #'string (match-string 1))))
6    )
7  )

导出子树


光标所在子树

 1(defun my/ox-hugo-export-subtree ()
 2  (interactive)
 3  (save-excursion
 4    (outline-next-heading)
 5    (when (re-search-backward (rx ":" "EXPORT_FILE_NAME" ": " (group (0+ (not "\n"))) "\n") nil t)
 6      (let* ((export-name (string-join (mapcar #'string (match-string 1))))
 7             (subtree (my/copy-org-subtree))
 8             (options (my/copy-org-options))
 9             (weight (my/compute-weight))
10             (slotlist '())
11             (slotlist (my/compute-subtree-path export-name))
12             (slot)
13             (section)
14             (cur-level))
15        (with-temp-buffer
16          (org-mode)                  
17          (insert options)
18          (insert subtree)
19          (my/delete-timestamp-link)
20          (my/replace-ue-project-file-link)
21          (my/replace-ue-engine-file-link)             
22          (my/replace-roam-link)
23          (pop slotlist)
24          (setq slotlist (reverse slotlist))
25          (pop slotlist)
26          (setq slotlist (reverse slotlist))
27          (dolist (item slotlist)
28            (setq slot (concat slot "/" item))
29            )
30          (beginning-of-buffer)
31          (when (re-search-forward (rx "+" "HUGO_SECTION" ": " (group (0+ (not "\n")))) nil t)
32            (setq section (string-join (mapcar #'string (match-string 1))))
33            (replace-match (format (concat "+" "HUGO_SECTION" ": %s") (concat section slot)))
34            )
35          (beginning-of-buffer)
36          (when (re-search-forward (rx "EXPORT_HUGO_WEIGHT" ": " (group (0+ (not "\n")))) nil t)
37            (replace-match (format (concat "EXPORT_HUGO_WEIGHT" ": %s") weight))
38            )
39          (beginning-of-buffer)
40          (outline-next-heading)
41          (setq cur-level (funcall outline-level))
42          (while (/= 1 cur-level)
43            (org-shiftmetaleft)
44            (setq cur-level (funcall outline-level))
45            )
46          (org-hugo-export-wim-to-md)
47          (my/amend-pic-link-file-name export-name)
48          (my/remove-anchor-file-name export-name)
49          )
50        )
51      )
52    )
53  )
54(global-set-key (kbd "C-c h s") 'my/ox-hugo-export-subtree)

文件内所有子树

 1(defun my/ox-hugo-export-all-subtrees ()
 2  (interactive)
 3  (save-excursion
 4    (let ((buf-content (buffer-string)))
 5      (with-temp-buffer
 6        (org-mode)                
 7        (insert buf-content)
 8        (my/delete-timestamp-link)
 9        (my/replace-ue-project-file-link)
10        (my/replace-ue-engine-file-link)             
11        (my/replace-roam-link)
12        (org-hugo-export-wim-to-md :all-subtrees)
13        (my/amend-pic-link-pack)
14        (my/remove-anchor-pack)
15        )
16      )
17    )
18  )
19(global-set-key (kbd "C-c h a") 'my/ox-hugo-export-all-subtrees)     

遗留问题

  • 如果有时间和精力, 建议部分标题使用Roam ID作为锚

Hugo对Markdown文件的要求

Guidelines

Markdown文件中的标题级别建议为2-4. ox-hugo导出时, 会将大于4的标题变作列表



修改ox-hugo源码思路

  1. org-hugo–get-anchor函数会读取org-hugo-anchor-functions

  2. org-hugo-heading会调用org-hugo–get-anchor来为标题添加锚, 将 anchor 设置为空即可实现


不建议这么做, ox-hugo的实现可能会改变, 而给出思路仅作为解决问题能力的锻炼


便签

-
ox-hugo锚

标题锚唯一



ox-hugo导出时关于标题锚的设定

Anchors

  • 变量 org-hugo-anchor-functions

    存放若干个函数, 优先级从高到低, 最先返回不为nil, 用作标题锚

    函数 对应属性配置
    org-hugo-get-page-or-bundle-name 导出文件名 :EXPORT_FILE_NAME
    org-hugo-get-custom-id 自定义ID :CUSTOM_ID
    org-hugo-get-heading-slug 标题名称
    org-hugo-get-md5 计算标题名称md5
    org-hugo-get-id 分配ID :ID
  • ID

    之前使用org-roam实现双链笔记本时, 为部分标题添加了ID, 这个是不可能普及的

  • 自定义ID

    需手动配置

  • 标题名称

    当前标题的处理方式, 存在标题重名问题

  • md5

    和标题名称一样的问题, 还不直观

  • 导出文件名

    注意: 这个的优先级最高, 因为会使用到文章锚


Hugo对Markdown文件标题ID的处理

Heading IDs

  1. 当标题后没有跟锚时, 会对重名标题编号

    ## Reference
    ## Reference
    ## Reference

    当id不同时, 在Hugo中可以设置不同锚

    1<h2 id="reference">Reference</h2>
    2<h2 id="reference-1">Reference</h2>
    3<h2 id="reference-2">Reference</h2>
  2. 如果标题后有锚, 标题id为锚移除"#“的内容

    允许重名

    ## Reference A {#foo}
    1<h2 id="foo">Reference A</h2>

对重名id编号

  • 如果Markdown文件中没有锚, 这个就不需要额外处理

  • 如果打算额外处理, 而文章目录依据文章正文生成, 修改Markdown文件好过修改html

  • 如果打算修改Markdown, 即自己找重名标题, 不如ox-hugo导出时所有标题的锚都相同: 全删即可

  • 即, ox-hugo为所有标题生成相同的锚, 或者不生成锚; 后者需要修改ox-hugo源码



影响

部分博文里包含其他博文+标题链接, 这些标题有ID, 且基本不会存在重名的情况

因此, 如让ox-hugo为所有标题生成相同的锚, 不包括文章标题, 即不使用ID作为锚, 就不用修改双链跳转


解决方案


让ox-hugo为所有标题生成相同的锚

设置 org-hugo-anchor-functions , 函数优先级如下

  1. org-hugo-get-page-or-bundle-name
  2. org-hugo-get-custom-id

且仅有这两个函数


修改导出之后的文本内容

  1. 注释之前的定义
    • my/ox-hugo-export-subtree
    • my/ox-hugo-export-all-subtrees
  2. 重新定义: 调用修改文本函数
  3. 实现修改文本函数

修改文本


移除标题锚

1(defun my/remove-anchor-file (file)
2  (interactive)
3  (with-current-buffer (find-file-noselect file)
4    (beginning-of-buffer)
5    (replace-string "{#}" "")
6    (save-buffer)
7    (kill-buffer)
8    )
9  )

移除给定子树标题锚

1(defun my/remove-anchor-file-name (export-name)
2  (interactive)
3  (my/remove-anchor-file (concat (my/subtree-path-str export-name) ".md"))
4  )

移除文件内所有子树标题锚

1(defun my/remove-anchor-pack ()
2  (interactive)
3  (beginning-of-buffer)
4  (while (re-search-forward (rx ":" "EXPORT_FILE_NAME" ": " (group (0+ (not "\n"))) "\n") nil t)
5    (my/remove-anchor-file-name (string-join (mapcar #'string (match-string 1))))
6    )
7  )

导出子树


光标所在子树

 1(defun my/ox-hugo-export-subtree ()
 2  (interactive)
 3  (save-excursion
 4    (outline-next-heading)
 5    (when (re-search-backward (rx ":" "EXPORT_FILE_NAME" ": " (group (0+ (not "\n"))) "\n") nil t)
 6      (let* ((export-name (string-join (mapcar #'string (match-string 1))))
 7             (subtree (my/copy-org-subtree))
 8             (options (my/copy-org-options))
 9             (weight (my/compute-weight))
10             (slotlist '())
11             (slotlist (my/compute-subtree-path export-name))
12             (slot)
13             (section)
14             (cur-level))
15        (with-temp-buffer
16          (org-mode)                  
17          (insert options)
18          (insert subtree)
19          (my/delete-timestamp-link)
20          (my/replace-ue-project-file-link)
21          (my/replace-ue-engine-file-link)             
22          (my/replace-roam-link)
23          (pop slotlist)
24          (setq slotlist (reverse slotlist))
25          (pop slotlist)
26          (setq slotlist (reverse slotlist))
27          (dolist (item slotlist)
28            (setq slot (concat slot "/" item))
29            )
30          (beginning-of-buffer)
31          (when (re-search-forward (rx "+" "HUGO_SECTION" ": " (group (0+ (not "\n")))) nil t)
32            (setq section (string-join (mapcar #'string (match-string 1))))
33            (replace-match (format (concat "+" "HUGO_SECTION" ": %s") (concat section slot)))
34            )
35          (beginning-of-buffer)
36          (when (re-search-forward (rx "EXPORT_HUGO_WEIGHT" ": " (group (0+ (not "\n")))) nil t)
37            (replace-match (format (concat "EXPORT_HUGO_WEIGHT" ": %s") weight))
38            )
39          (beginning-of-buffer)
40          (outline-next-heading)
41          (setq cur-level (funcall outline-level))
42          (while (/= 1 cur-level)
43            (org-shiftmetaleft)
44            (setq cur-level (funcall outline-level))
45            )
46          (org-hugo-export-wim-to-md)
47          (my/amend-pic-link-file-name export-name)
48          (my/remove-anchor-file-name export-name)
49          )
50        )
51      )
52    )
53  )
54(global-set-key (kbd "C-c h s") 'my/ox-hugo-export-subtree)

文件内所有子树

 1(defun my/ox-hugo-export-all-subtrees ()
 2  (interactive)
 3  (save-excursion
 4    (let ((buf-content (buffer-string)))
 5      (with-temp-buffer
 6        (org-mode)                
 7        (insert buf-content)
 8        (my/delete-timestamp-link)
 9        (my/replace-ue-project-file-link)
10        (my/replace-ue-engine-file-link)             
11        (my/replace-roam-link)
12        (org-hugo-export-wim-to-md :all-subtrees)
13        (my/amend-pic-link-pack)
14        (my/remove-anchor-pack)
15        )
16      )
17    )
18  )
19(global-set-key (kbd "C-c h a") 'my/ox-hugo-export-all-subtrees)     

遗留问题

  • 如果有时间和精力, 建议部分标题使用Roam ID作为锚

Hugo对Markdown文件的要求

Guidelines

Markdown文件中的标题级别建议为2-4. ox-hugo导出时, 会将大于4的标题变作列表



修改ox-hugo源码思路

  1. org-hugo–get-anchor函数会读取org-hugo-anchor-functions

  2. org-hugo-heading会调用org-hugo–get-anchor来为标题添加锚, 将 anchor 设置为空即可实现


不建议这么做, ox-hugo的实现可能会改变, 而给出思路仅作为解决问题能力的锻炼


便签

-
ox-hugo锚