diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index ceef89e39..41a035290 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -459,7 +459,7 @@ "newNameFile": "The name of the new document is", "newContentFile": "The content of the new document is", "exporting": "Exporting, please wait...", - "exported": "Export complete: ", + "exported": "Export complete", "refExpired": "Search content block does not exist", "emptyContent": "No related content", "useBrowserView": "View in the browser", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 2110493af..137a02e4c 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -458,7 +458,7 @@ "newNameFile": "El nombre del nuevo documento es", "newContentFile": "El contenido del nuevo documento es", "exporting": "Exportando, por favor espere...", - "exported": "Exportación completada: ", + "exported": "Exportación completada", "refExpired": "El bloque de contenido de búsqueda no existe", "emptyContent": "No hay contenido relacionado", "useBrowserView": "Ver en el navegador", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 7b8e41671..d881cc0b6 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -459,7 +459,7 @@ "newNameFile": "Le nom du nouveau document est", "newContentFile": "Le contenu du nouveau document est", "exporting": "En cours d'exportation, veuillez patienter...", - "exported": "Exportation terminée: ", + "exported": "Exportation terminée", "refExpired": "Le bloc de contenu de recherche n'existe pas", "emptyContent": "Aucun contenu pertinent pour le moment", "useBrowserView": "Afficher dans le navigateur", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index 38951d1fa..4d2ff6d99 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -459,7 +459,7 @@ "newNameFile": "新建文檔名為", "newContentFile": "新建文檔內容為", "exporting": "正在匯出,請稍等...", - "exported": "匯出完成:", + "exported": "匯出完成", "refExpired": "不存在符合條件的內容塊", "emptyContent": "暫無相關內容", "useBrowserView": "在瀏覽器中查看", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 55773d451..36cc7ccab 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -459,7 +459,7 @@ "newNameFile": "新建文档名为", "newContentFile": "新建文档内容为", "exporting": "正在导出,请稍等...", - "exported": "导出完成:", + "exported": "导出完成", "refExpired": "不存在符合条件的内容块", "emptyContent": "暂无相关内容", "useBrowserView": "在浏览器中查看", diff --git a/app/src/protyle/export/util.ts b/app/src/protyle/export/util.ts index 935bb92ef..69e264a83 100644 --- a/app/src/protyle/export/util.ts +++ b/app/src/protyle/export/util.ts @@ -15,7 +15,7 @@ import {openByMobile} from "../util/compatibility"; export const afterExport = (exportPath: string, msgId: string) => { /// #if !BROWSER - showMessage(`${window.siyuan.languages.exported}${escapeHtml(exportPath)} + showMessage(`${window.siyuan.languages.exported} ${escapeHtml(exportPath)}
`, 6000, "info", msgId); document.querySelector(`#message [data-id="${msgId}"] button`).addEventListener("click", () => { diff --git a/app/src/util/onGetConfig.ts b/app/src/util/onGetConfig.ts index cac6d6020..e82b5c4bb 100644 --- a/app/src/util/onGetConfig.ts +++ b/app/src/util/onGetConfig.ts @@ -383,6 +383,7 @@ const initWindow = () => { id: ipcData.rootId, pdf: true, removeAssets: ipcData.removeAssets, + merge: ipcData.mergeSubdocs, savePath: result.filePaths[0] }, () => { const pdfFilePath = path.join(result.filePaths[0], replaceLocalPath(ipcData.rootTitle) + ".pdf"); diff --git a/kernel/model/export.go b/kernel/model/export.go index dc37da427..debfedbcc 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -341,6 +341,16 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string func ExportHTML(id, savePath string, pdf, keepFold, merge bool) (name, dom string) { savePath = strings.TrimSpace(savePath) tree, _ := loadTreeByBlockID(id) + + if merge { + var mergeErr error + tree, mergeErr = mergeSubDocs(tree) + if nil != mergeErr { + logging.LogErrorf("merge sub docs failed: %s", mergeErr) + return + } + } + var headings []*ast.Node if pdf { // 导出 PDF 需要标记目录书签 ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { @@ -363,14 +373,6 @@ func ExportHTML(id, savePath string, pdf, keepFold, merge bool) (name, dom strin } } - if merge { - var mergeErr error - tree, mergeErr = mergeSubDocs(tree) - if nil != mergeErr { - logging.LogErrorf("merge sub docs failed: %s", mergeErr) - return - } - } tree = exportTree(tree, true, true, keepFold) name = path.Base(tree.HPath) name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614 @@ -502,8 +504,12 @@ func AddPDFOutline(id, p string) (err error) { footnotes := map[string]*pdfcpu.Bookmark{} for _, link := range links { linkID := link.URI[strings.LastIndex(link.URI, "/")+1:] - - title := sql.GetBlock(linkID).Content + b := sql.GetBlock(linkID) + if nil == b { + logging.LogWarnf("pdf outline block [%s] not found", linkID) + continue + } + title := b.Content title, _ = url.QueryUnescape(title) bm := &pdfcpu.Bookmark{ Title: title, diff --git a/kernel/model/export_merge.go b/kernel/model/export_merge.go index 2bab6eea1..00ca2f024 100644 --- a/kernel/model/export_merge.go +++ b/kernel/model/export_merge.go @@ -29,12 +29,22 @@ func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) { } insertPoint := rootTree.Root.LastChild + if nil == insertPoint { + insertPoint = rootTree.Root + } + + // 跳过空段落插入点,向上寻找非空段落 + for ; nil != insertPoint && ast.NodeParagraph == insertPoint.Type; insertPoint = insertPoint.Previous { + if nil != insertPoint.FirstChild { + break + } + } + for { i := 0 if err = walkBlock(insertPoint, rootBlock, i); nil != err { return } - if nil == rootBlock.Children { break } @@ -44,13 +54,12 @@ func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) { func walkBlock(insertPoint *ast.Node, block *Block, level int) (err error) { level++ - for _, c := range block.Children { + for i := len(block.Children) - 1; i >= 0; i-- { + c := block.Children[i] if err = walkBlock(insertPoint, c, level); nil != err { return } - } - for _, c := range block.Children { nodes, loadErr := loadTreeNodes(c.Box, c.Path, level) if nil != loadErr { return diff --git a/kernel/model/file.go b/kernel/model/file.go index 2e5f800c3..577e3d628 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -660,7 +660,7 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size luteEngine.RenderOptions.NodeIndexStart = index dom = luteEngine.Tree2BlockDOM(subTree, luteEngine.RenderOptions) - SetRecentDocByTree(id, tree) + SetRecentDocByTree(tree) return } diff --git a/kernel/model/storage.go b/kernel/model/storage.go index 4d3520f13..cf6252bae 100644 --- a/kernel/model/storage.go +++ b/kernel/model/storage.go @@ -30,11 +30,8 @@ import ( type RecentDoc struct { RootID string `json:"rootID"` - ID string `json:"id"` Icon string `json:"icon"` Title string `json:"title"` - Mode string `json:"mode"` - Action string `json:"action"` } var recentDocLock = sync.Mutex{} @@ -63,10 +60,9 @@ func RemoveRecentDoc(ids []string) { return } -func SetRecentDocByTree(id string, tree *parse.Tree) { +func SetRecentDocByTree(tree *parse.Tree) { recentDoc := &RecentDoc{ RootID: tree.Root.ID, - ID: id, Icon: tree.Root.IALAttr("icon"), Title: tree.Root.IALAttr("title"), }