让EWW支持XSLT!

最近折腾了一下自己的主页,为了方便(不需要在每次发布的时候「构建」静态网页),文章使用RsML写成,可以全部在客户端渲染。

但是EWW缺省配置下不支持XSLT,所以我就糊了一个函数,调用xsltproc(其他实现当然也行)生成HTML再用它预览:

(defun eww-extract-xslt ()
  (save-excursion
    (goto-char (point-min))
    (when (re-search-forward "<\\?xml-stylesheet [^>]*href=['\"]\\([^'\"]+\\)['\"]" nil t)
      (let ((xslt (match-string 1))
            (link (url-generic-parse-url (eww-current-url))))
        (if (file-name-absolute-p xslt)
            (progn
              (setf (url-filename link) xslt)
              (url-recreate-url link))
          (let* ((path (file-name-directory (url-filename link)))
                 (xslt (expand-file-name xslt path)))
            (setf (url-filename link) xslt)
            (url-recreate-url link)))))))

(defun eww-render-xslt ()
  (interactive)
  (when (or (string-match "\\.xml$" (eww-current-url))
            (save-excursion
              (goto-char (point-min))
              (or (looking-at "<\\?xml")
                  (re-search-forward "<\\?xml" nil t))))
    (when-let* ((link (eww-extract-xslt))
                (xslt (make-temp-file "sty" nil ".xsl"))
                (xml (make-temp-file "src" nil ".xml"))
                (html (make-temp-file "res" nil ".html"))
                (command (format "xsltproc %S %S > %S" xslt xml html)))
      (url-copy-file link xslt t)
      (append-to-file nil nil xml)
      (call-process-shell-command command nil nil)
      (eww-open-file html))))

(add-hook 'eww-after-render-hook #'eww-render-xslt)

效果如此:

2 个赞

想法很好,但是 w3m 就支持不了了

用浏览器的 client side XSLT 支持 = 只能用 XSLT 1.0 = FireFox/Safari/Chromium 三家实到有不统一 (当然 CSS 也是这样但是 XSLT1.0 更难用) = 未来可能被砍了=用 Wayback Machine 的人看不了

比如正常能存档的是这样 为小窗优化的Emacs配置

既然是用 GitHub pages,而且是在本地编辑的,可以给 git 加个 hook 调用 makefile。以我的经历来看用 client side XSLT serve XML 的网站通常都不长久,10 年前就不再流行了(

我自已用的是 plan9port 里的 mk。

1 个赞

的确。

Safari/Firefox的支持各有各的问题:

  • Safari不能处理递归大概500次的模版,一片白;
  • Firefox渲染时页面左上角出现一个用系统等宽字体显示的<!DOCTYPE html>

我试下来反而Chrome的支持是最好的。

其实XSLT1我觉得也够用了,感觉上也没什么需求是实现不了的,无非就是需要模版递归处理一下(

你主页介绍Mk那篇文章我看过,之前用Org的时候就是用它构建的:

UTL=chain
SRC=manuscript
DST=article
ART=`{ls -d manuscript/*.org | sed 's/manuscript\/\([^/.]*\)\..*$/\1/'}

default:V: publish validate

$DST/([^/.]+)\.html:RD: $SRC/\\1.org
 emacs --batch --load $UTL/web.el $prereq\
       --eval '(progn (outline-show-all)
                      (font-lock-flush)
                      (font-lock-fontify-buffer)
                      (org-html-export-to-html))'\
       >>/dev/null 2>&1
 mv $SRC/$stem1.html $target

publish:V: ${ART:%=$DST/%.html}

%-valid:V: $DST/%.html
 tidy -quiet -modify $prereq

validate:V: ${ART:%=%-valid}

All in XML的主要原因其实还是每次更新都要生成对应的静态网页不优雅,需要在服务器上放两份内容一样的东西也不优雅(

现在打算搞一个comp子域名,下面是HTML版的,也许可以用CF托管(划掉),然后搞一个banner提醒看不了XSL的人跳过去。

不妨部署一个在线跑xslt的cloudflare worker

edit: client侧渲染xml的浏览器支持感觉不大行, 我电脑里的chromium就不支持, android上的chrome反而支持.

另外firefox对 disable-output-escaping 的支持是残的就很难受.

1 个赞