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

# Conflicts:
#	app/src/util/history.ts
This commit is contained in:
Vanessa 2022-10-18 23:00:55 +08:00
commit 1e671307d8
14 changed files with 71 additions and 30 deletions

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -1,7 +1,8 @@
{
"docNameAndContent": "文檔名和內容",
"breadcrumb": "麵包屑",
"embedBlockBreadcrumb": "嵌入塊麵包屑",
"embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑",
"embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑,在超級塊中的嵌入塊忽略該選項,始終不顯示麵包屑",
"appearanceMode": "外觀模式",
"editMode": "編輯模式",
"editReadonly": "只讀模式",

View file

@ -1,7 +1,8 @@
{
"docNameAndContent": "文档名和内容",
"breadcrumb": "面包屑",
"embedBlockBreadcrumb": "嵌入块面包屑",
"embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑",
"embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑,在超级块中的嵌入块忽略该选项,始终不显示面包屑",
"appearanceMode": "外观模式",
"editMode": "编辑模式",
"editReadonly": "只读模式",

View file

@ -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],

View file

@ -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">

View file

@ -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,
}

View file

@ -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 {

View file

@ -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{}

View file

@ -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
}

View file

@ -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) {

View file

@ -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
}

View file

@ -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)