Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # app/src/util/history.ts
This commit is contained in:
commit
1e671307d8
14 changed files with 71 additions and 30 deletions
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"docNameAndContent": "Doc Name and Content",
|
||||
"breadcrumb": "Breadcrumb",
|
||||
"embedBlockBreadcrumb": "Embed Block Breadcrumb",
|
||||
"embedBlockBreadcrumbTip": "After enabling embed block will show breadcrumbs",
|
||||
"embedBlockBreadcrumbTip": "After enabling embed blocks will display breadcrumbs, embed blocks in super blocks ignore this option and never show breadcrumbs",
|
||||
"appearanceMode": "Appearance Mode",
|
||||
"editMode": "Edit Mode",
|
||||
"editReadonly": "Read-only mode",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"docNameAndContent": "Nombre y contenido del documento",
|
||||
"miga de pan": "Miga de pan",
|
||||
"embedBlockBreadcrumb": "Incrustar migas de pan de bloque",
|
||||
"embedBlockBreadcrumbTip": "Después de habilitar el bloque incrustado, se mostrarán migas de pan",
|
||||
"embedBlockBreadcrumbTip": "Después de habilitar los bloques incrustados, se mostrarán migas de pan, incrustar bloques en superbloques ignora esta opción y nunca muestra migas de pan",
|
||||
"appearanceMode": "Modo de apariencia",
|
||||
"editMode": "Modo de edición",
|
||||
"editReadonly": "Modo de solo lectura",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"docNameAndContent": "Nom et contenu du document",
|
||||
"fil d'Ariane": "Fil d'Ariane",
|
||||
"embedBlockBreadcrumb": "Intégrer le fil d'Ariane du bloc",
|
||||
"embedBlockBreadcrumbTip": "Après avoir activé le bloc d'intégration, le fil d'Ariane s'affichera",
|
||||
"embedBlockBreadcrumbTip": "Après avoir activé l'intégration, les blocs afficheront le fil d'Ariane, intégrer des blocs dans des super blocs ignorent cette option et n'affichent jamais le fil d'Ariane",
|
||||
"appearanceMode": "Mode d'apparence",
|
||||
"editMode": "Mode d'édition",
|
||||
"editReadonly": "Mode lecture seule",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"docNameAndContent": "文檔名和內容",
|
||||
"breadcrumb": "麵包屑",
|
||||
"embedBlockBreadcrumb": "嵌入塊麵包屑",
|
||||
"embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑",
|
||||
"embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑,在超級塊中的嵌入塊忽略該選項,始終不顯示麵包屑",
|
||||
"appearanceMode": "外觀模式",
|
||||
"editMode": "編輯模式",
|
||||
"editReadonly": "只讀模式",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"docNameAndContent": "文档名和内容",
|
||||
"breadcrumb": "面包屑",
|
||||
"embedBlockBreadcrumb": "嵌入块面包屑",
|
||||
"embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑",
|
||||
"embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑,在超级块中的嵌入块忽略该选项,始终不显示面包屑",
|
||||
"appearanceMode": "外观模式",
|
||||
"editMode": "编辑模式",
|
||||
"editReadonly": "只读模式",
|
||||
|
|
|
@ -33,6 +33,7 @@ export const blockRender = (protyle: IProtyle, element: Element) => {
|
|||
breadcrumb = window.siyuan.config.editor.embedBlockBreadcrumb
|
||||
}
|
||||
fetchPost("/api/search/searchEmbedBlock", {
|
||||
embedBlockID: item.getAttribute("data-node-id"),
|
||||
stmt: content,
|
||||
headingMode: item.getAttribute("custom-heading-mode") === "1" ? 1 : 0,
|
||||
excludeIDs: [item.getAttribute("data-node-id"), protyle.block.rootID],
|
||||
|
|
|
@ -29,7 +29,7 @@ const renderDoc = (element: HTMLElement, currentPage: number) => {
|
|||
const mdElement = element.querySelector('.history__text[data-type="mdPanel"]') as HTMLTextAreaElement;
|
||||
docElement.classList.add("fn__none");
|
||||
mdElement.classList.add("fn__none");
|
||||
if (typeElement.value === "0") {
|
||||
if (typeElement.value === "0" || typeElement.value === "1") {
|
||||
opElement.removeAttribute("disabled");
|
||||
notebookElement.removeAttribute("disabled");
|
||||
assetElement.classList.add("fn__none");
|
||||
|
@ -65,7 +65,7 @@ const renderDoc = (element: HTMLElement, currentPage: number) => {
|
|||
if (item.items.length > 0) {
|
||||
logsHTML += `<ul class="${index === 0 ? "" : "fn__none"}">`;
|
||||
item.items.forEach((docItem) => {
|
||||
logsHTML += `<li title="${escapeHtml(docItem.title)}" data-type="${typeElement.value === "1" ? "assets" : "doc"}" data-path="${docItem.path}" class="b3-list-item b3-list-item--hide-action" style="padding-left: 44px">
|
||||
logsHTML += `<li title="${escapeHtml(docItem.title)}" data-type="${typeElement.value === "2" ? "assets" : "doc"}" data-path="${docItem.path}" class="b3-list-item b3-list-item--hide-action" style="padding-left: 44px">
|
||||
<span class="b3-list-item__text">${escapeHtml(docItem.title)}</span>
|
||||
<span class="fn__space"></span>
|
||||
<span class="b3-list-item__action b3-tooltips b3-tooltips__w" data-type="rollback" aria-label="${window.siyuan.languages.rollback}">
|
||||
|
@ -179,14 +179,14 @@ const renderRmNotebook = (element: HTMLElement) => {
|
|||
}
|
||||
let logsHTML = "";
|
||||
response.data.histories.forEach((item: { items: { path: string, title: string }[], hCreated: string }, index: number) => {
|
||||
logsHTML += `<li class="b3-list-item" data-type="toggle">
|
||||
<span class="b3-list-item__toggle b3-list-item__toggle"><svg class="b3-list-item__arrow${index === 0 ? " b3-list-item__arrow--open" : ""}${item.items.length > 0 ? "" : " fn__hidden"}"><use xlink:href="#iconRight"></use></svg></span>
|
||||
<span style="padding-left: 4px" class="b3-list-item__text">${item.hCreated}</span>
|
||||
logsHTML += `<li class="b3-list-item" style="padding-left: 0" data-type="toggle">
|
||||
<span style="padding-left: 8px" class="b3-list-item__toggle"><svg class="b3-list-item__arrow${index === 0 ? " b3-list-item__arrow--open" : ""}${item.items.length > 0 ? "" : " fn__hidden"}"><use xlink:href="#iconRight"></use></svg></span>
|
||||
<span class="b3-list-item__text">${item.hCreated}</span>
|
||||
</li>`;
|
||||
if (item.items.length > 0) {
|
||||
logsHTML += `<ul class="${index === 0 ? "" : "fn__none"}">`;
|
||||
item.items.forEach((docItem) => {
|
||||
logsHTML += `<li data-type="notebook" data-path="${docItem.path}" class="b3-list-item" style="padding-left: 44px">
|
||||
logsHTML += `<li data-type="notebook" data-path="${docItem.path}" class="b3-list-item" style="padding-left: 32px">
|
||||
<span class="b3-list-item__text">${escapeHtml(docItem.title)}</span>
|
||||
<span class="fn__space"></span>
|
||||
<span class="b3-list-item__action" data-type="rollback">
|
||||
|
@ -239,8 +239,9 @@ export const openHistory = () => {
|
|||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<select data-type="typeselect" class="b3-select" style="min-width: auto">
|
||||
<option value="0" selected>${window.siyuan.languages.doc}</option>
|
||||
<option value="1">${window.siyuan.languages.assets}</option>
|
||||
<option value="0" selected>${window.siyuan.languages.docName}</option>
|
||||
<option value="1">${window.siyuan.languages.docNameAndContent}</option>
|
||||
<option value="2">${window.siyuan.languages.assets}</option>
|
||||
</select>
|
||||
<span class="fn__space"></span>
|
||||
<select data-type="opselect" class="b3-select" style="min-width: auto">
|
||||
|
|
|
@ -127,6 +127,7 @@ func searchEmbedBlock(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
embedBlockID := arg["embedBlockID"].(string)
|
||||
stmt := arg["stmt"].(string)
|
||||
excludeIDsArg := arg["excludeIDs"].([]interface{})
|
||||
var excludeIDs []string
|
||||
|
@ -144,7 +145,7 @@ func searchEmbedBlock(c *gin.Context) {
|
|||
breadcrumb = breadcrumbArg.(bool)
|
||||
}
|
||||
|
||||
blocks := model.SearchEmbedBlock(stmt, excludeIDs, headingMode, breadcrumb)
|
||||
blocks := model.SearchEmbedBlock(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb)
|
||||
ret.Data = map[string]interface{}{
|
||||
"blocks": blocks,
|
||||
}
|
||||
|
|
|
@ -405,15 +405,21 @@ func RemoveUnusedAssets() (ret []string) {
|
|||
return
|
||||
}
|
||||
|
||||
var hashes []string
|
||||
for _, p := range unusedAssets {
|
||||
historyPath := filepath.Join(historyDir, p)
|
||||
if p = filepath.Join(util.DataDir, p); gulu.File.IsExist(p) {
|
||||
if err = gulu.File.Copy(p, historyPath); nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
hash, _ := util.GetEtag(p)
|
||||
hashes = append(hashes, hash)
|
||||
}
|
||||
}
|
||||
|
||||
sql.DeleteAssetsByHashes(hashes)
|
||||
|
||||
for _, unusedAsset := range unusedAssets {
|
||||
if unusedAsset = filepath.Join(util.DataDir, unusedAsset); gulu.File.IsExist(unusedAsset) {
|
||||
if err := os.RemoveAll(unusedAsset); nil != err {
|
||||
|
@ -444,8 +450,13 @@ func RemoveUnusedAsset(p string) (ret string) {
|
|||
|
||||
newP := strings.TrimPrefix(p, util.DataDir)
|
||||
historyPath := filepath.Join(historyDir, newP)
|
||||
if err = gulu.File.Copy(p, historyPath); nil != err {
|
||||
return
|
||||
if gulu.File.IsExist(p) {
|
||||
if err = gulu.File.Copy(p, historyPath); nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
hash, _ := util.GetEtag(p)
|
||||
sql.DeleteAssetsByHashes([]string{hash})
|
||||
}
|
||||
|
||||
if err = os.RemoveAll(p); nil != err {
|
||||
|
|
|
@ -381,7 +381,7 @@ func getBlock(id string) (ret *Block, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, headingMode int, breadcrumb bool) (block *Block, blockPaths []*BlockPath) {
|
||||
func getEmbeddedBlock(embedBlockID string, trees map[string]*parse.Tree, sqlBlock *sql.Block, headingMode int, breadcrumb bool) (block *Block, blockPaths []*BlockPath) {
|
||||
tree, _ := trees[sqlBlock.RootID]
|
||||
if nil == tree {
|
||||
tree, _ = loadTreeByBlockID(sqlBlock.RootID)
|
||||
|
@ -434,9 +434,17 @@ func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, heading
|
|||
luteEngine.RenderOptions.ProtyleContenteditable = false // 不可编辑
|
||||
dom := renderBlockDOMByNodes(nodes, luteEngine)
|
||||
block = &Block{Box: def.Box, Path: def.Path, HPath: b.HPath, ID: def.ID, Type: def.Type.String(), Content: dom}
|
||||
if breadcrumb {
|
||||
blockPaths = buildBlockBreadcrumb(def)
|
||||
|
||||
// 位于超级块中的嵌入块不显示面包屑 https://github.com/siyuan-note/siyuan/issues/6258
|
||||
inSuperBlock := false
|
||||
embedNodeTree, _ := loadTreeByBlockID(embedBlockID)
|
||||
if nil != embedNodeTree {
|
||||
embedNode := treenode.GetNodeInTree(embedNodeTree, embedBlockID)
|
||||
inSuperBlock = nil != embedNode && embedNode.ParentIs(ast.NodeSuperBlock)
|
||||
}
|
||||
|
||||
if breadcrumb && !inSuperBlock {
|
||||
blockPaths = buildBlockBreadcrumb(def)
|
||||
}
|
||||
if 1 > len(blockPaths) {
|
||||
blockPaths = []*BlockPath{}
|
||||
|
|
|
@ -1041,7 +1041,7 @@ func exportTree(tree *parse.Tree, wysiwyg, expandKaTexMacros, keepFold bool) (re
|
|||
var defMd string
|
||||
stmt := n.ChildByType(ast.NodeBlockQueryEmbedScript).TokensStr()
|
||||
stmt = html.UnescapeString(stmt)
|
||||
embedBlocks := searchEmbedBlock(stmt, nil, 0, false)
|
||||
embedBlocks := searchEmbedBlock(n.ID, stmt, nil, 0, false)
|
||||
if 1 > len(embedBlocks) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
|
|
@ -343,7 +343,11 @@ func FullTextSearchHistory(query, box, op string, typ, page int) (ret []*History
|
|||
stmt += "1=1"
|
||||
}
|
||||
|
||||
if HistoryTypeDoc == typ {
|
||||
if HistoryTypeDocName == typ {
|
||||
stmt = strings.ReplaceAll(stmt, "{title content}", "{title}")
|
||||
}
|
||||
|
||||
if HistoryTypeDocName == typ || HistoryTypeDoc == typ {
|
||||
if "all" != op {
|
||||
stmt += " AND op = '" + op + "'"
|
||||
}
|
||||
|
@ -578,8 +582,9 @@ func ReindexHistory() (err error) {
|
|||
var validOps = []string{HistoryOpClean, HistoryOpUpdate, HistoryOpDelete, HistoryOpFormat, HistoryOpSync}
|
||||
|
||||
const (
|
||||
HistoryTypeDoc = 0
|
||||
HistoryTypeAsset = 1
|
||||
HistoryTypeDocName = 0
|
||||
HistoryTypeDoc = 1
|
||||
HistoryTypeAsset = 2
|
||||
)
|
||||
|
||||
func indexHistoryDir(name string, luteEngine *lute.Lute) {
|
||||
|
|
|
@ -43,12 +43,13 @@ type EmbedBlock struct {
|
|||
BlockPaths []*BlockPath `json:"blockPaths"`
|
||||
}
|
||||
|
||||
func SearchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
|
||||
func SearchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
|
||||
time.Sleep(512 * time.Millisecond /* 前端队列轮询间隔 */)
|
||||
WaitForWritingFiles()
|
||||
return searchEmbedBlock(stmt, excludeIDs, headingMode, breadcrumb)
|
||||
return searchEmbedBlock(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb)
|
||||
}
|
||||
|
||||
func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
|
||||
func searchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
|
||||
sqlBlocks := sql.SelectBlocksRawStmtNoParse(stmt, Conf.Search.Limit)
|
||||
var tmp []*sql.Block
|
||||
for _, b := range sqlBlocks {
|
||||
|
@ -76,7 +77,7 @@ func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcr
|
|||
}
|
||||
|
||||
for _, sb := range sqlBlocks {
|
||||
block, blockPaths := getEmbeddedBlock(trees, sb, headingMode, breadcrumb)
|
||||
block, blockPaths := getEmbeddedBlock(embedBlockID, trees, sb, headingMode, breadcrumb)
|
||||
if nil == block {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
@ -75,7 +73,7 @@ func docTitleImgAsset(root *ast.Node) *Asset {
|
|||
absPath := filepath.Join(util.DataDir, p)
|
||||
if hash, err = util.GetEtag(absPath); nil != err {
|
||||
logging.LogErrorf("read asset [%s] data failed: %s", absPath, err)
|
||||
hash = fmt.Sprintf("%x", sha256.Sum256([]byte(gulu.Rand.String(7))))
|
||||
return nil
|
||||
}
|
||||
name, _ := util.LastID(p)
|
||||
asset := &Asset{
|
||||
|
@ -94,6 +92,16 @@ func docTitleImgAsset(root *ast.Node) *Asset {
|
|||
return nil
|
||||
}
|
||||
|
||||
func DeleteAssetsByHashes(hashes []string) {
|
||||
sqlStmt := "DELETE FROM assets WHERE hash IN ('" + strings.Join(hashes, "','") + "') OR hash = ''"
|
||||
tx, err := BeginTx()
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
execStmtTx(tx, sqlStmt)
|
||||
CommitTx(tx)
|
||||
}
|
||||
|
||||
func QueryAssetByHash(hash string) (ret *Asset) {
|
||||
sqlStmt := "SELECT * FROM assets WHERE hash = ?"
|
||||
row := queryRow(sqlStmt, hash)
|
||||
|
|
Loading…
Add table
Reference in a new issue