一个把 wikitext 转换成 markdown 的 Emacs 函数

From 清冽之泉
Revision as of 21:23, 19 July 2026 by Mwroot (talk | contribs) (Created page with "<syntaxhighlight lang="elisp" line> (defun wikitext-convert-all (&optional start end) "Convert simple wikitext to GFM markdown." (interactive (if (use-region-p) (list (region-beginning) (region-end)) (list (point-min) (point-max)))) (save-excursion (save-restriction (narrow-to-region start end) ;; -------------------------------------------------- ;; 1. inline <code> ;; --------------------------------------------------...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
(defun wikitext-convert-all (&optional start end)
  "Convert simple wikitext to GFM markdown."

  (interactive
   (if (use-region-p)
       (list (region-beginning) (region-end))
     (list (point-min) (point-max))))

  (save-excursion
    (save-restriction
      (narrow-to-region start end)

      ;; --------------------------------------------------
      ;; 1. inline <code>
      ;; --------------------------------------------------
      (goto-char (point-min))
      (while (re-search-forward "<code>\\([^<\n]*\\)</code>" nil t)
        (replace-match (concat "`" (match-string 1) "`") t t))
      (goto-char (point-min))
      (while (re-search-forward "<code>" nil t)
        (replace-match "`"))
      (goto-char (point-min))
      (while (re-search-forward "</code>" nil t)
        (replace-match "`"))

      ;; --------------------------------------------------
      ;; 2. syntaxhighlight
      ;; --------------------------------------------------
      (goto-char (point-min))
      (while (re-search-forward "<syntaxhighlight\\s-+lang=[\"']\\([^\"']+\\)[\"'][^>]*>" nil t)
        (replace-match (concat "```" (match-string 1)) t t))
      (goto-char (point-min))
      (while (re-search-forward "

" nil t)

       (replace-match "```"))
     ;; --------------------------------------------------
     ;; 3. 列表 # → *
     ;; --------------------------------------------------
     (let ((in-code-block nil))
       (goto-char (point-min))
       (while (not (eobp))
         (let ((line (thing-at-point 'line t)))
           (when (string-match "^```" line)
             (setq in-code-block (not in-code-block)))
           (unless in-code-block
             (beginning-of-line)
             (while (search-forward "#" (line-end-position) t)
               (replace-match "*"))))
         (forward-line 1)))
     ;; --------------------------------------------------
     ;; 4. headings
     ;; --------------------------------------------------
     (dolist (n '(6 5 4 3 2))
       (goto-char (point-min))
       (let ((pat (format "^=\\{%d\\}[ \t]*\\(.*?\\S-\\)[ \t]*=\\{%d\\}[ \t]*$" n n))
             (rep (concat (make-string n ?#) " \\1")))
         (while (re-search-forward pat nil t)
           (replace-match rep))))
     ;; --------------------------------------------------
     ;; 5.  -> ~~
     ;; --------------------------------------------------
     (goto-char (point-min))
     (while (re-search-forward "" nil t)
       (replace-match "~~"))
     (goto-char (point-min))
     (while (re-search-forward "" nil t)
       (replace-match "~~"))
     ;; --------------------------------------------------
     ;; 6. ---- -> ---
     ;; --------------------------------------------------
     (goto-char (point-min))
     (while (re-search-forward "^----[ \t]*$" nil t)
       (replace-match "---"))
     ;; --------------------------------------------------
     ;; 11-12. 行首 ; / : 处理
     ;; --------------------------------------------------
     (goto-char (point-min))
     (while (re-search-forward "^; \\(.*\\)$" nil t)
       (replace-match (concat "" (match-string 1) "") nil nil))
     (goto-char (point-min))
     (while (re-search-forward "^: \\(.*\\)$" nil t)
       (replace-match (match-string 1) nil nil))
     ;; --------------------------------------------------
     ;; 13. File:Xxx -> ![xxx]()
     ;; --------------------------------------------------
     (goto-char (point-min))
     (while (re-search-forward
             "\\[\\[File:\\([^]|]+\\)\\.[a-zA-Z0-9]+[^]]*\\]\\]"
             nil t)
       (replace-match
        (format "![%s]()" (match-string 1))
        t t))
     (widen))))

</syntaxhighlight>