Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2025-10-10 13:06:50 +08:00
commit f515eae955
8 changed files with 91 additions and 18 deletions

View file

@ -114,11 +114,11 @@ func listDocTree(c *gin.Context) {
ids := map[string]bool{} ids := map[string]bool{}
for _, entry := range dir { for _, entry := range dir {
if entry.IsDir() { if strings.HasPrefix(entry.Name(), ".") {
if strings.HasPrefix(entry.Name(), ".") { continue
continue }
}
if entry.IsDir() {
if !ast.IsNodeIDPattern(entry.Name()) { if !ast.IsNodeIDPattern(entry.Name()) {
continue continue
} }
@ -134,7 +134,12 @@ func listDocTree(c *gin.Context) {
return return
} }
} else { } else {
doc := &DocFile{ID: strings.TrimSuffix(entry.Name(), ".sy")} id := strings.TrimSuffix(entry.Name(), ".sy")
if !ast.IsNodeIDPattern(id) {
continue
}
doc := &DocFile{ID: id}
if !ids[doc.ID] { if !ids[doc.ID] {
doctree = append(doctree, doc) doctree = append(doctree, doc)
} }

View file

@ -146,11 +146,13 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
return true return true
} }
switch filter.Operator { if "" == filter.Qualifier {
case FilterOperatorIsEmpty: switch filter.Operator {
return value.IsEmpty() case FilterOperatorIsEmpty:
case FilterOperatorIsNotEmpty: return value.IsEmpty()
return !value.IsEmpty() case FilterOperatorIsNotEmpty:
return !value.IsEmpty()
}
} }
// 单独处理汇总 // 单独处理汇总
@ -194,12 +196,30 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
switch filter.Qualifier { switch filter.Qualifier {
case FilterQuantifierUndefined, FilterQuantifierAny: case FilterQuantifierUndefined, FilterQuantifierAny:
if len(value.Rollup.Contents) < len(relVal.Relation.Contents) { // 说明汇总的目标字段存在空值
if FilterOperatorIsEmpty == filter.Operator {
return true
} else if FilterOperatorIsNotEmpty == filter.Operator {
return false
}
}
for _, content := range value.Rollup.Contents { for _, content := range value.Rollup.Contents {
if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
return true return true
} }
} }
case FilterQuantifierAll: case FilterQuantifierAll:
if len(value.Rollup.Contents) < len(relVal.Relation.Contents) {
if FilterOperatorIsEmpty == filter.Operator {
if 1 > len(value.Rollup.Contents) {
return true
}
} else if FilterOperatorIsNotEmpty == filter.Operator {
return false
}
}
for _, content := range value.Rollup.Contents { for _, content := range value.Rollup.Contents {
if !content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { if !content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
return false return false
@ -207,6 +227,14 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
} }
return true return true
case FilterQuantifierNone: case FilterQuantifierNone:
if len(value.Rollup.Contents) < len(relVal.Relation.Contents) {
if FilterOperatorIsEmpty == filter.Operator {
return false
} else if FilterOperatorIsNotEmpty == filter.Operator {
return true
}
}
for _, content := range value.Rollup.Contents { for _, content := range value.Rollup.Contents {
if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
return false return false
@ -265,6 +293,14 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
switch filter.Qualifier { switch filter.Qualifier {
case FilterQuantifierUndefined, FilterQuantifierAny: case FilterQuantifierUndefined, FilterQuantifierAny:
if 1 > len(value.MAsset) { // 说明资源字段为空
if FilterOperatorIsEmpty == filter.Operator {
return true
} else if FilterOperatorIsNotEmpty == filter.Operator {
return false
}
}
for _, asset := range value.MAsset { for _, asset := range value.MAsset {
switch asset.Type { switch asset.Type {
case AssetTypeFile: case AssetTypeFile:
@ -279,6 +315,14 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
} }
} }
case FilterQuantifierAll: case FilterQuantifierAll:
if 1 > len(value.MAsset) {
if FilterOperatorIsEmpty == filter.Operator {
return true
} else if FilterOperatorIsNotEmpty == filter.Operator {
return false
}
}
for _, asset := range value.MAsset { for _, asset := range value.MAsset {
switch asset.Type { switch asset.Type {
case AssetTypeFile: case AssetTypeFile:
@ -294,6 +338,14 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID s
} }
return true return true
case FilterQuantifierNone: case FilterQuantifierNone:
if 1 > len(value.MAsset) {
if FilterOperatorIsEmpty == filter.Operator {
return false
} else if FilterOperatorIsNotEmpty == filter.Operator {
return true
}
}
for _, asset := range value.MAsset { for _, asset := range value.MAsset {
switch asset.Type { switch asset.Type {
case AssetTypeFile: case AssetTypeFile:

View file

@ -1959,7 +1959,7 @@ func genAttrViewGroups(view *av.View, attrView *av.AttributeView) {
// 过去 30 天、过去 7 天、昨天、今天、明天、未来 7 天、未来 30 天 // 过去 30 天、过去 7 天、昨天、今天、明天、未来 7 天、未来 30 天
// 未来 30 天之后的按月分组 // 未来 30 天之后的按月分组
if contentTime.Before(todayStart.AddDate(0, 0, -30)) { if contentTime.Before(todayStart.AddDate(0, 0, -30)) {
groupVal = contentTime.Format("2006-01") // 开头的数字用于排序,下同 groupVal = contentTime.Format("2006-01") // 开头的数字用于排序
} else if contentTime.Before(todayStart.AddDate(0, 0, -7)) { } else if contentTime.Before(todayStart.AddDate(0, 0, -7)) {
groupVal = groupValueLast30Days groupVal = groupValueLast30Days
} else if contentTime.Before(todayStart.AddDate(0, 0, -1)) { } else if contentTime.Before(todayStart.AddDate(0, 0, -1)) {

View file

@ -786,6 +786,11 @@ func GetBlockDOMs(ids []string) (ret map[string]string) {
if nil == node { if nil == node {
continue continue
} }
if parentFoldedHeading := treenode.GetParentFoldedHeading(node); nil != parentFoldedHeading {
node.SetIALAttr("parent-heading", parentFoldedHeading.ID)
}
ret[id] = luteEngine.RenderNodeBlockDOM(node) ret[id] = luteEngine.RenderNodeBlockDOM(node)
} }
return return

View file

@ -102,17 +102,22 @@ func ListNotebooks() (ret []*Box, err error) {
continue continue
} }
if !ast.IsNodeIDPattern(dir.Name()) { id := dir.Name()
if !ast.IsNodeIDPattern(id) {
continue continue
} }
boxConf := conf.NewBoxConf() boxConf := conf.NewBoxConf()
boxDirPath := filepath.Join(util.DataDir, dir.Name()) boxDirPath := filepath.Join(util.DataDir, id)
boxConfPath := filepath.Join(boxDirPath, ".siyuan", "conf.json") boxConfPath := filepath.Join(boxDirPath, ".siyuan", "conf.json")
isExistConf := filelock.IsExist(boxConfPath) isExistConf := filelock.IsExist(boxConfPath)
if !isExistConf { if !isExistConf {
// 数据同步时展开文档树操作可能导致数据丢失 https://github.com/siyuan-note/siyuan/issues/7129 if !IsUserGuide(id) {
logging.LogWarnf("found a corrupted box [%s]", boxDirPath) // 数据同步时展开文档树操作可能导致数据丢失 https://github.com/siyuan-note/siyuan/issues/7129
logging.LogWarnf("found a corrupted box [%s]", boxDirPath)
} else {
continue
}
} else { } else {
data, readErr := filelock.ReadFile(boxConfPath) data, readErr := filelock.ReadFile(boxConfPath)
if nil != readErr { if nil != readErr {
@ -126,7 +131,6 @@ func ListNotebooks() (ret []*Box, err error) {
} }
} }
id := dir.Name()
icon := boxConf.Icon icon := boxConf.Icon
if strings.Contains(icon, ".") { // 说明是自定义图标 if strings.Contains(icon, ".") { // 说明是自定义图标
// XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034 // XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034

View file

@ -1131,6 +1131,7 @@ func closeUserGuide() {
unindex(boxID) unindex(boxID)
sql.FlushQueue()
if removeErr := filelock.Remove(boxDirPath); nil != removeErr { if removeErr := filelock.Remove(boxDirPath); nil != removeErr {
logging.LogErrorf("remove corrupted user guide box [%s] failed: %s", boxDirPath, removeErr) logging.LogErrorf("remove corrupted user guide box [%s] failed: %s", boxDirPath, removeErr)
} }

View file

@ -2162,9 +2162,11 @@ func exportMarkdownContent0(id string, tree *parse.Tree, cloudAssetsBase string,
href = "#" + defID href = "#" + defID
} }
} }
href = strings.TrimPrefix(href, currentDocDir) newHref := strings.TrimPrefix(href, currentDocDir)
if !strings.HasPrefix(newHref, ".md") {
href = newHref
}
href = util.FilterFilePath(href) href = util.FilterFilePath(href)
href = strings.TrimPrefix(href, "/")
blockRefLink := &ast.Node{Type: ast.NodeTextMark, TextMarkType: "a", TextMarkTextContent: linkText, TextMarkAHref: href} blockRefLink := &ast.Node{Type: ast.NodeTextMark, TextMarkType: "a", TextMarkTextContent: linkText, TextMarkAHref: href}
blockRefLink.KramdownIAL = n.KramdownIAL blockRefLink.KramdownIAL = n.KramdownIAL
n.InsertBefore(blockRefLink) n.InsertBefore(blockRefLink)

View file

@ -912,8 +912,12 @@ func (tx *Transaction) doDelete(operation *Operation) (ret *TxErr) {
node.Next.Unlink() node.Next.Unlink()
} }
next := node.Next
node.Unlink() node.Unlink()
parentFoldedHeading := treenode.GetParentFoldedHeading(next)
unfoldHeading(parentFoldedHeading)
if nil != parent && ast.NodeListItem == parent.Type && nil == parent.FirstChild { if nil != parent && ast.NodeListItem == parent.Type && nil == parent.FirstChild {
needAppendEmptyListItem := true needAppendEmptyListItem := true
for _, op := range tx.DoOperations { for _, op := range tx.DoOperations {