🎨 Improve exporting document HTML (#16219)

* 🎨 The browser-side supports exporting document HTML

fix https://github.com/siyuan-note/siyuan/issues/16213

* 修复导出 HTML 时引入资源没有使用相对路径,修复文档导出 HTML/PDF 时缺失图标

fix https://github.com/siyuan-note/siyuan/issues/16217

fix https://github.com/siyuan-note/siyuan/issues/16216 01

* 修复文档导出 HTML/PDF 时冗余图标

fix https://github.com/siyuan-note/siyuan/issues/16216 02
This commit is contained in:
Jeffrey Chen 2025-10-28 09:28:56 +08:00 committed by GitHub
parent bca1f1eda6
commit 90a447f914
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 241 additions and 40 deletions

View file

@ -20,6 +20,7 @@ import (
"io"
"mime"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
@ -30,6 +31,7 @@ import (
"github.com/88250/lute/parse"
"github.com/gin-gonic/gin"
"github.com/mssola/useragent"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/model"
"github.com/siyuan-note/siyuan/kernel/util"
@ -489,6 +491,21 @@ func exportMdHTML(c *gin.Context) {
id := arg["id"].(string)
savePath := arg["savePath"].(string)
savePath = strings.TrimSpace(savePath)
if savePath == "" {
folderName := "htmlmd-" + id + "-" + util.CurrentTimeSecondsStr()
tmpDir := filepath.Join(util.TempDir, "export", folderName)
name, content := model.ExportMarkdownHTML(id, tmpDir, false, false)
ret.Data = map[string]interface{}{
"id": id,
"name": name,
"content": content,
"folder": folderName,
}
return
}
name, content := model.ExportMarkdownHTML(id, savePath, false, false)
ret.Data = map[string]interface{}{
"id": id,
@ -527,6 +544,62 @@ func exportTempContent(c *gin.Context) {
}
}
func exportBrowserHTML(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
folder := arg["folder"].(string)
htmlContent := arg["html"].(string)
name := arg["name"].(string)
tmpDir := filepath.Join(util.TempDir, "export", folder)
htmlPath := filepath.Join(tmpDir, "index.html")
if err := filelock.WriteFile(htmlPath, []byte(htmlContent)); err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = nil
return
}
zipFileName := util.FilterFileName(name) + ".zip"
zipPath := filepath.Join(util.TempDir, "export", zipFileName)
zip, err := gulu.Zip.Create(zipPath)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = nil
return
}
err = zip.AddDirectory("", tmpDir, func(string) {})
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = nil
return
}
if err = zip.Close(); err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = nil
return
}
os.RemoveAll(tmpDir)
zipURL := "/export/" + url.PathEscape(filepath.Base(zipPath))
ret.Data = map[string]interface{}{
"zip": zipURL,
}
}
func exportPreviewHTML(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
@ -590,6 +663,21 @@ func exportHTML(c *gin.Context) {
if nil != arg["merge"] {
merge = arg["merge"].(bool)
}
savePath = strings.TrimSpace(savePath)
if savePath == "" {
folderName := "html-" + id + "-" + util.CurrentTimeSecondsStr()
tmpDir := filepath.Join(util.TempDir, "export", folderName)
name, content, _ := model.ExportHTML(id, tmpDir, pdf, false, keepFold, merge)
ret.Data = map[string]interface{}{
"id": id,
"name": name,
"content": content,
"folder": folderName,
}
return
}
name, content, _ := model.ExportHTML(id, savePath, pdf, false, keepFold, merge)
ret.Data = map[string]interface{}{
"id": id,

View file

@ -325,6 +325,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/export/exportData", model.CheckAuth, model.CheckAdminRole, exportData)
ginServer.Handle("POST", "/api/export/exportDataInFolder", model.CheckAuth, model.CheckAdminRole, exportDataInFolder)
ginServer.Handle("POST", "/api/export/exportTempContent", model.CheckAuth, model.CheckAdminRole, exportTempContent)
ginServer.Handle("POST", "/api/export/exportBrowserHTML", model.CheckAuth, model.CheckAdminRole, exportBrowserHTML)
ginServer.Handle("POST", "/api/export/export2Liandi", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, export2Liandi)
ginServer.Handle("POST", "/api/export/exportReStructuredText", model.CheckAuth, model.CheckAdminRole, exportReStructuredText)
ginServer.Handle("POST", "/api/export/exportAsciiDoc", model.CheckAuth, model.CheckAdminRole, exportAsciiDoc)