浏览代码

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

Vanessa 2 年之前
父节点
当前提交
ecf004a1f0

+ 1 - 0
app/appearance/langs/en_US.json

@@ -1,4 +1,5 @@
 {
 {
+  "htmlBlockTip": "Multiple HTML blocks are formed. To prevent data loss, please use <code class='fn__code'>&lt;div&gt;</code> tags to wrap and remove blank lines",
   "katexMacros": "KaTex macro definition",
   "katexMacros": "KaTex macro definition",
   "katexMacrosTip": "Please use JSON object format (<code class='fn__code'>{}</code>) to wrap macro definitions, eg <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "katexMacrosTip": "Please use JSON object format (<code class='fn__code'>{}</code>) to wrap macro definitions, eg <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "systemLogTip": "Program running records are saved in the system log. By exporting the system log and sending it to developers, it can better help developers diagnose program problems",
   "systemLogTip": "Program running records are saved in the system log. By exporting the system log and sending it to developers, it can better help developers diagnose program problems",

+ 1 - 0
app/appearance/langs/es_ES.json

@@ -1,4 +1,5 @@
 {
 {
+  "htmlBlockTip": "Se forman varios bloques HTML. Para evitar la pérdida de datos, utilice etiquetas <code class='fn__code'>&lt;div&gt;</code> para ajustar y eliminar líneas en blanco",
   "katexMacros": "Definición de macro de KaTex",
   "katexMacros": "Definición de macro de KaTex",
   "katexMacrosTip": "Utilice el formato de objeto JSON (<code class='fn__code'>{}</code>) para envolver definiciones de macro, por ejemplo, <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "katexMacrosTip": "Utilice el formato de objeto JSON (<code class='fn__code'>{}</code>) para envolver definiciones de macro, por ejemplo, <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "systemLogTip": "Los registros de ejecución del programa se guardan en el registro del sistema. Al exportar el registro del sistema y enviarlo a los desarrolladores, puede ayudarlos a diagnosticar mejor los problemas del programa",
   "systemLogTip": "Los registros de ejecución del programa se guardan en el registro del sistema. Al exportar el registro del sistema y enviarlo a los desarrolladores, puede ayudarlos a diagnosticar mejor los problemas del programa",

+ 1 - 0
app/appearance/langs/fr_FR.json

@@ -1,4 +1,5 @@
 {
 {
+  "htmlBlockTip": "Plusieurs blocs HTML sont formés. Pour éviter la perte de données, veuillez utiliser les balises <code class='fn__code'>&lt;div&gt;</code> pour envelopper et supprimer les lignes vides",
   "katexMacros": "Définition de la macro KaTex",
   "katexMacros": "Définition de la macro KaTex",
   "katexMacrosTip": "Veuillez utiliser le format d'objet JSON (<code class='fn__code'>{}</code>) pour envelopper les définitions de macro, par exemple <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "katexMacrosTip": "Veuillez utiliser le format d'objet JSON (<code class='fn__code'>{}</code>) pour envelopper les définitions de macro, par exemple <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "systemLogTip": "Les enregistrements en cours d'exécution du programme sont enregistrés dans le journal système. En exportant le journal système et en l'envoyant aux développeurs, cela peut mieux aider les développeurs à diagnostiquer les problèmes du programme",
   "systemLogTip": "Les enregistrements en cours d'exécution du programme sont enregistrés dans le journal système. En exportant le journal système et en l'envoyant aux développeurs, cela peut mieux aider les développeurs à diagnostiquer les problèmes du programme",

+ 1 - 0
app/appearance/langs/zh_CHT.json

@@ -1,4 +1,5 @@
 {
 {
+  "htmlBlockTip": "形成了多個 HTML 塊,為防止數據丟失請使用 <code class='fn__code'>&lt;div&gt;</code> 標籤包裹並去掉空行",
   "katexMacros": "KaTex 宏定義",
   "katexMacros": "KaTex 宏定義",
   "katexMacrosTip": "請使用 JSON 對象格式(<code class='fn__code'>{}</code>)來包裹宏定義,例如 <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "katexMacrosTip": "請使用 JSON 對象格式(<code class='fn__code'>{}</code>)來包裹宏定義,例如 <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "systemLogTip": "系統日誌中保存了程序運行記錄,通過導出系統日誌發送給開發者可以更好地幫助開發者診斷程序問題",
   "systemLogTip": "系統日誌中保存了程序運行記錄,通過導出系統日誌發送給開發者可以更好地幫助開發者診斷程序問題",

+ 1 - 1
app/appearance/langs/zh_CN.json

@@ -1,5 +1,5 @@
 {
 {
-  "htmlTip": "形成多个 HTML 块,为防止数据丢失请使用 <code class='fn__code'>&lt;div&gt;</code> 标签包裹",
+  "htmlBlockTip": "形成多个 HTML 块,为防止数据丢失请使用 <code class='fn__code'>&lt;div&gt;</code> 标签包裹并去掉空行",
   "katexMacros": "KaTex 宏定义",
   "katexMacros": "KaTex 宏定义",
   "katexMacrosTip": "请使用 JSON 对象格式(<code class='fn__code'>{}</code>)来包裹宏定义,例如 <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "katexMacrosTip": "请使用 JSON 对象格式(<code class='fn__code'>{}</code>)来包裹宏定义,例如 <code class='fn__code'>{ \"\\\\foo\": \"{x^2}\" }</code>",
   "systemLogTip": "系统日志中保存了程序运行记录,通过导出系统日志发送给开发者可以更好地帮助开发者诊断程序问题",
   "systemLogTip": "系统日志中保存了程序运行记录,通过导出系统日志发送给开发者可以更好地帮助开发者诊断程序问题",

+ 1 - 1
app/src/protyle/toolbar/index.ts

@@ -873,7 +873,7 @@ export class Toolbar {
                 const tempElement = document.createElement("template");
                 const tempElement = document.createElement("template");
                 tempElement.innerHTML = newHTML;
                 tempElement.innerHTML = newHTML;
                 if (tempElement.content.childElementCount > 1) {
                 if (tempElement.content.childElementCount > 1) {
-                    showMessage(window.siyuan.languages.htmlTip)
+                    showMessage(window.siyuan.languages.htmlBlockTip)
                 }
                 }
             }
             }
             updateTransaction(protyle, id, newHTML, html);
             updateTransaction(protyle, id, newHTML, html);

+ 25 - 26
kernel/model/block.go

@@ -25,32 +25,31 @@ import (
 
 
 // Block 描述了内容块。
 // Block 描述了内容块。
 type Block struct {
 type Block struct {
-	Box       string            `json:"box"`
-	Path      string            `json:"path"`
-	HPath     string            `json:"hPath"`
-	ID        string            `json:"id"`
-	RootID    string            `json:"rootID"`
-	ParentID  string            `json:"parentID"`
-	Name      string            `json:"name"`
-	Alias     string            `json:"alias"`
-	Memo      string            `json:"memo"`
-	Tag       string            `json:"tag"`
-	Content   string            `json:"content"`
-	FContent  string            `json:"fcontent"`
-	Markdown  string            `json:"markdown"`
-	FMarkdown string            `json:"fmarkdown"`
-	Folded    bool              `json:"folded"`
-	Type      string            `json:"type"`
-	SubType   string            `json:"subType"`
-	RefText   string            `json:"refText"`
-	Defs      []*Block          `json:"-"`    // 当前块引用了这些块,避免序列化 JSON 时产生循环引用
-	Refs      []*Block          `json:"refs"` // 当前块被这些块引用
-	DefID     string            `json:"defID"`
-	DefPath   string            `json:"defPath"`
-	IAL       map[string]string `json:"ial"`
-	Children  []*Block          `json:"children"`
-	Depth     int               `json:"depth"`
-	Count     int               `json:"count"`
+	Box      string            `json:"box"`
+	Path     string            `json:"path"`
+	HPath    string            `json:"hPath"`
+	ID       string            `json:"id"`
+	RootID   string            `json:"rootID"`
+	ParentID string            `json:"parentID"`
+	Name     string            `json:"name"`
+	Alias    string            `json:"alias"`
+	Memo     string            `json:"memo"`
+	Tag      string            `json:"tag"`
+	Content  string            `json:"content"`
+	FContent string            `json:"fcontent"`
+	Markdown string            `json:"markdown"`
+	Folded   bool              `json:"folded"`
+	Type     string            `json:"type"`
+	SubType  string            `json:"subType"`
+	RefText  string            `json:"refText"`
+	Defs     []*Block          `json:"-"`    // 当前块引用了这些块,避免序列化 JSON 时产生循环引用
+	Refs     []*Block          `json:"refs"` // 当前块被这些块引用
+	DefID    string            `json:"defID"`
+	DefPath  string            `json:"defPath"`
+	IAL      map[string]string `json:"ial"`
+	Children []*Block          `json:"children"`
+	Depth    int               `json:"depth"`
+	Count    int               `json:"count"`
 }
 }
 
 
 func (block *Block) IsContainerBlock() bool {
 func (block *Block) IsContainerBlock() bool {

+ 1 - 1
kernel/model/history.go

@@ -718,7 +718,7 @@ func fullTextSearchHistory(query string, page int) (ret []*History, matchedBlock
 	query = stringQuery(query)
 	query = stringQuery(query)
 
 
 	table := "histories_fts_case_insensitive"
 	table := "histories_fts_case_insensitive"
-	projections := "type, op, title, content, path"
+	projections := "type, op, title, content, path, created"
 	stmt := "SELECT " + projections + " FROM " + table + " WHERE " + table + " MATCH '{title content}:(" + query + ")'"
 	stmt := "SELECT " + projections + " FROM " + table + " WHERE " + table + " MATCH '{title content}:(" + query + ")'"
 	stmt += " ORDER BY created DESC LIMIT " + strconv.Itoa(page)
 	stmt += " ORDER BY created DESC LIMIT " + strconv.Itoa(page)
 	sqlHistories := sql.SelectHistoriesRawStmt(stmt)
 	sqlHistories := sql.SelectHistoriesRawStmt(stmt)

+ 16 - 15
kernel/model/search.go

@@ -331,6 +331,8 @@ func fullTextSearchCount(query, box, path, filter string) (matchedBlockCount, ma
 }
 }
 
 
 func fullTextSearch(query, box, path, filter string, beforeLen int, querySyntax bool) (ret []*Block, matchedBlockCount, matchedRootCount int) {
 func fullTextSearch(query, box, path, filter string, beforeLen int, querySyntax bool) (ret []*Block, matchedBlockCount, matchedRootCount int) {
+	fullTextSearchHistory(query, 1)
+
 	query = gulu.Str.RemoveInvisible(query)
 	query = gulu.Str.RemoveInvisible(query)
 	if util.IsIDPattern(query) {
 	if util.IsIDPattern(query) {
 		ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
 		ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
@@ -490,21 +492,20 @@ func fromSQLBlock(sqlBlock *sql.Block, terms string, beforeLen int) (block *Bloc
 	markdown := maxContent(sqlBlock.Markdown, 5120)
 	markdown := maxContent(sqlBlock.Markdown, 5120)
 
 
 	block = &Block{
 	block = &Block{
-		Box:       sqlBlock.Box,
-		Path:      p,
-		ID:        id,
-		RootID:    sqlBlock.RootID,
-		ParentID:  sqlBlock.ParentID,
-		Alias:     sqlBlock.Alias,
-		Name:      sqlBlock.Name,
-		Memo:      sqlBlock.Memo,
-		Tag:       sqlBlock.Tag,
-		Content:   content,
-		FContent:  sqlBlock.FContent,
-		Markdown:  markdown,
-		FMarkdown: sqlBlock.FMarkdown,
-		Type:      treenode.FromAbbrType(sqlBlock.Type),
-		SubType:   sqlBlock.SubType,
+		Box:      sqlBlock.Box,
+		Path:     p,
+		ID:       id,
+		RootID:   sqlBlock.RootID,
+		ParentID: sqlBlock.ParentID,
+		Alias:    sqlBlock.Alias,
+		Name:     sqlBlock.Name,
+		Memo:     sqlBlock.Memo,
+		Tag:      sqlBlock.Tag,
+		Content:  content,
+		FContent: sqlBlock.FContent,
+		Markdown: markdown,
+		Type:     treenode.FromAbbrType(sqlBlock.Type),
+		SubType:  sqlBlock.SubType,
 	}
 	}
 	if "" != sqlBlock.IAL {
 	if "" != sqlBlock.IAL {
 		block.IAL = map[string]string{}
 		block.IAL = map[string]string{}

+ 21 - 22
kernel/sql/block.go

@@ -21,28 +21,27 @@ import (
 )
 )
 
 
 type Block struct {
 type Block struct {
-	ID        string
-	ParentID  string
-	RootID    string
-	Hash      string
-	Box       string
-	Path      string
-	HPath     string
-	Name      string
-	Alias     string
-	Memo      string
-	Tag       string
-	Content   string
-	FContent  string
-	Markdown  string
-	FMarkdown string
-	Length    int
-	Type      string
-	SubType   string
-	IAL       string
-	Sort      int
-	Created   string
-	Updated   string
+	ID       string
+	ParentID string
+	RootID   string
+	Hash     string
+	Box      string
+	Path     string
+	HPath    string
+	Name     string
+	Alias    string
+	Memo     string
+	Tag      string
+	Content  string
+	FContent string
+	Markdown string
+	Length   int
+	Type     string
+	SubType  string
+	IAL      string
+	Sort     int
+	Created  string
+	Updated  string
 }
 }
 
 
 func updateRootContent(tx *sql.Tx, content, id string) {
 func updateRootContent(tx *sql.Tx, content, id string) {

+ 3 - 3
kernel/sql/block_query.go

@@ -62,7 +62,7 @@ func QueryRootBlockByCondition(condition string) (ret []*Block) {
 	for rows.Next() {
 	for rows.Next() {
 		var block Block
 		var block Block
 		var sepCount int
 		var sepCount int
-		if err = rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.FMarkdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated, &sepCount); nil != err {
+		if err = rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated, &sepCount); nil != err {
 			logging.LogErrorf("query scan field failed: %s", err)
 			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
@@ -484,7 +484,7 @@ func selectBlocksRawStmt(stmt string, limit int) (ret []*Block) {
 
 
 func scanBlockRows(rows *sql.Rows) (ret *Block) {
 func scanBlockRows(rows *sql.Rows) (ret *Block) {
 	var block Block
 	var block Block
-	if err := rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.FMarkdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
+	if err := rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
 		logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 		logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 		return
 		return
 	}
 	}
@@ -494,7 +494,7 @@ func scanBlockRows(rows *sql.Rows) (ret *Block) {
 
 
 func scanBlockRow(row *sql.Row) (ret *Block) {
 func scanBlockRow(row *sql.Row) (ret *Block) {
 	var block Block
 	var block Block
-	if err := row.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.FMarkdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
+	if err := row.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
 		if sql.ErrNoRows != err {
 		if sql.ErrNoRows != err {
 			logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 			logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 		}
 		}

+ 1 - 1
kernel/sql/block_ref_query.go

@@ -375,7 +375,7 @@ func DefRefs(condition string) (ret []map[*Block]*Block) {
 	for rows.Next() {
 	for rows.Next() {
 		var ref Block
 		var ref Block
 		var rel string
 		var rel string
-		if err = rows.Scan(&ref.ID, &ref.ParentID, &ref.RootID, &ref.Hash, &ref.Box, &ref.Path, &ref.HPath, &ref.Name, &ref.Alias, &ref.Memo, &ref.Tag, &ref.Content, &ref.FContent, &ref.Markdown, &ref.FMarkdown, &ref.Length, &ref.Type, &ref.SubType, &ref.IAL, &ref.Sort, &ref.Created, &ref.Updated,
+		if err = rows.Scan(&ref.ID, &ref.ParentID, &ref.RootID, &ref.Hash, &ref.Box, &ref.Path, &ref.HPath, &ref.Name, &ref.Alias, &ref.Memo, &ref.Tag, &ref.Content, &ref.FContent, &ref.Markdown, &ref.Length, &ref.Type, &ref.SubType, &ref.IAL, &ref.Sort, &ref.Created, &ref.Updated,
 			&rel); nil != err {
 			&rel); nil != err {
 			logging.LogErrorf("query scan field failed: %s", err)
 			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return

+ 26 - 28
kernel/sql/database.go

@@ -99,19 +99,19 @@ func initDBTables() {
 	setDatabaseVer()
 	setDatabaseVer()
 
 
 	db.Exec("DROP TABLE blocks")
 	db.Exec("DROP TABLE blocks")
-	_, err = db.Exec("CREATE TABLE blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, fmarkdown, length, type, subtype, ial, sort, created, updated)")
+	_, err = db.Exec("CREATE TABLE blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated)")
 	if nil != err {
 	if nil != err {
 		logging.LogFatalf("create table [blocks] failed: %s", err)
 		logging.LogFatalf("create table [blocks] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE blocks_fts")
 	db.Exec("DROP TABLE blocks_fts")
-	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, fmarkdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan\")")
+	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan\")")
 	if nil != err {
 	if nil != err {
 		logging.LogFatalf("create table [blocks_fts] failed: %s", err)
 		logging.LogFatalf("create table [blocks_fts] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE blocks_fts_case_insensitive")
 	db.Exec("DROP TABLE blocks_fts_case_insensitive")
-	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts_case_insensitive USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, fmarkdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan case_insensitive\")")
+	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts_case_insensitive USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan case_insensitive\")")
 	if nil != err {
 	if nil != err {
 		logging.LogFatalf("create table [blocks_fts_case_insensitive] failed: %s", err)
 		logging.LogFatalf("create table [blocks_fts_case_insensitive] failed: %s", err)
 	}
 	}
@@ -712,19 +712,18 @@ func buildBlockFromNode(n *ast.Node, tree *parse.Tree) (block *Block, attributes
 	memo := html.UnescapeString(n.IALAttr("memo"))
 	memo := html.UnescapeString(n.IALAttr("memo"))
 	tag := tagFromNode(n)
 	tag := tagFromNode(n)
 
 
-	var content, fcontent, markdown, fmarkdown, parentID string
+	var content, fcontent, markdown, parentID string
 	ialContent := treenode.IALStr(n)
 	ialContent := treenode.IALStr(n)
 	hash := treenode.NodeHash(n, tree, luteEngine)
 	hash := treenode.NodeHash(n, tree, luteEngine)
 	var length int
 	var length int
 	if ast.NodeDocument == n.Type {
 	if ast.NodeDocument == n.Type {
 		content = n.IALAttr("title")
 		content = n.IALAttr("title")
 		fcontent = content
 		fcontent = content
-		fmarkdown = content
 		length = utf8.RuneCountInString(fcontent)
 		length = utf8.RuneCountInString(fcontent)
 	} else if n.IsContainerBlock() {
 	} else if n.IsContainerBlock() {
 		markdown, content = treenode.NodeStaticMdContent(n, luteEngine)
 		markdown, content = treenode.NodeStaticMdContent(n, luteEngine)
 		fc := treenode.FirstLeafBlock(n)
 		fc := treenode.FirstLeafBlock(n)
-		fmarkdown, fcontent = treenode.NodeStaticMdContent(fc, luteEngine)
+		fcontent = treenode.NodeStaticContent(fc)
 		parentID = n.Parent.ID
 		parentID = n.Parent.ID
 		// 将标题块作为父节点
 		// 将标题块作为父节点
 		if h := heading(n); nil != h {
 		if h := heading(n); nil != h {
@@ -742,28 +741,27 @@ func buildBlockFromNode(n *ast.Node, tree *parse.Tree) (block *Block, attributes
 	}
 	}
 
 
 	block = &Block{
 	block = &Block{
-		ID:        n.ID,
-		ParentID:  parentID,
-		RootID:    rootID,
-		Hash:      hash,
-		Box:       boxID,
-		Path:      p,
-		HPath:     tree.HPath,
-		Name:      name,
-		Alias:     alias,
-		Memo:      memo,
-		Tag:       tag,
-		Content:   content,
-		FContent:  fcontent,
-		Markdown:  markdown,
-		FMarkdown: fmarkdown,
-		Length:    length,
-		Type:      treenode.TypeAbbr(n.Type.String()),
-		SubType:   treenode.SubTypeAbbr(n),
-		IAL:       ialContent,
-		Sort:      nSort(n),
-		Created:   util.TimeFromID(n.ID),
-		Updated:   n.IALAttr("updated"),
+		ID:       n.ID,
+		ParentID: parentID,
+		RootID:   rootID,
+		Hash:     hash,
+		Box:      boxID,
+		Path:     p,
+		HPath:    tree.HPath,
+		Name:     name,
+		Alias:    alias,
+		Memo:     memo,
+		Tag:      tag,
+		Content:  content,
+		FContent: fcontent,
+		Markdown: markdown,
+		Length:   length,
+		Type:     treenode.TypeAbbr(n.Type.String()),
+		SubType:  treenode.SubTypeAbbr(n),
+		IAL:      ialContent,
+		Sort:     nSort(n),
+		Created:  util.TimeFromID(n.ID),
+		Updated:  n.IALAttr("updated"),
 	}
 	}
 
 
 	attrs := parse.IAL2Map(n.KramdownIAL)
 	attrs := parse.IAL2Map(n.KramdownIAL)

+ 4 - 5
kernel/sql/upsert.go

@@ -48,10 +48,10 @@ func InsertRefs(tx *sql.Tx, tree *parse.Tree) {
 }
 }
 
 
 const (
 const (
-	BlocksInsert                   = "INSERT INTO blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, fmarkdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
-	BlocksFTSInsert                = "INSERT INTO blocks_fts (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, fmarkdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
-	BlocksFTSCaseInsensitiveInsert = "INSERT INTO blocks_fts_case_insensitive (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, fmarkdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
-	BlocksPlaceholder              = "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+	BlocksInsert                   = "INSERT INTO blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
+	BlocksFTSInsert                = "INSERT INTO blocks_fts (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
+	BlocksFTSCaseInsensitiveInsert = "INSERT INTO blocks_fts_case_insensitive (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated) VALUES %s"
+	BlocksPlaceholder              = "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
 
 
 	SpansInsert      = "INSERT INTO spans (id, block_id, root_id, box, path, content, markdown, type, ial) VALUES %s"
 	SpansInsert      = "INSERT INTO spans (id, block_id, root_id, box, path, content, markdown, type, ial) VALUES %s"
 	SpansPlaceholder = "(?, ?, ?, ?, ?, ?, ?, ?, ?)"
 	SpansPlaceholder = "(?, ?, ?, ?, ?, ?, ?, ?, ?)"
@@ -106,7 +106,6 @@ func insertBlocks0(tx *sql.Tx, bulk []*Block) (err error) {
 		valueArgs = append(valueArgs, b.Content)
 		valueArgs = append(valueArgs, b.Content)
 		valueArgs = append(valueArgs, b.FContent)
 		valueArgs = append(valueArgs, b.FContent)
 		valueArgs = append(valueArgs, b.Markdown)
 		valueArgs = append(valueArgs, b.Markdown)
-		valueArgs = append(valueArgs, b.FMarkdown)
 		valueArgs = append(valueArgs, b.Length)
 		valueArgs = append(valueArgs, b.Length)
 		valueArgs = append(valueArgs, b.Type)
 		valueArgs = append(valueArgs, b.Type)
 		valueArgs = append(valueArgs, b.SubType)
 		valueArgs = append(valueArgs, b.SubType)