mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-01-24 01:06:09 +01:00
🎨 Element attribute names are uniformly lowercase English letters https://github.com/siyuan-note/siyuan/issues/16604 (#16657)
部分属性名大写字母改为小写 兼容旧版带大写字母的属性名 更新用户指南说明 优化性能 统一前后端验证属性名的逻辑 改进验证属性名格式报错信息
This commit is contained in:
parent
e1f6b83d35
commit
2d1618e639
27 changed files with 10420 additions and 10359 deletions
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "كلمة التحقق غير صحيحة",
|
||||
"23": "مستودع البيانات تالف، الرجاء إعادة تعيينه",
|
||||
"24": "انتهت مهلة الشبكة، يرجى المحاولة مرة أخرى في وقت لاحق",
|
||||
"25": "اسم السمة يدعم فقط الأحرف الإنجليزية والأرقام",
|
||||
"25": "يمكن أن يحتوي اسم السمة فقط على أحرف إنجليزية صغيرة وأرقام وشرطات، ويجب أن يبدأ بحرف إنجليزي صغير",
|
||||
"26": "الرجاء تهيئة مفتاح مستودع البيانات أولاً في [الإعدادات - حول - مفتاح مستودع البيانات]",
|
||||
"27": "جارٍ رفع [%v]",
|
||||
"28": "الشبكة غير طبيعية، يرجى المحاولة مرة أخرى لاحقاً",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "The captcha is incorrect",
|
||||
"23": "The data repo is corrupted, please reset the data repo",
|
||||
"24": "Network timed out, please try again later",
|
||||
"25": "The attribute name only supports English letters and digits",
|
||||
"25": "The attribute name can only contain lowercase English letters, digits, and hyphens, and must start with a lowercase English letter",
|
||||
"26": "Please initialize the data repo key first in [Settings - About - Data repo key]",
|
||||
"27": "Uploading [%v]",
|
||||
"28": "The network is abnormal, please try again later",
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "El captcha es incorrecto",
|
||||
"23": "El repositorio de datos está dañado, reinicie el repositorio de datos",
|
||||
"24": "Se agotó el tiempo de espera de la red. Vuelva a intentarlo más tarde.",
|
||||
"25": "El nombre del atributo sólo admite letras y dígitos en inglés",
|
||||
"25": "El nombre del atributo solo puede contener letras minúsculas, dígitos y guiones, y debe comenzar con una letra minúscula",
|
||||
"26": "Por favor, inicialice primero la clave de repositorio de datos en [Configuración - Acerca de - Clave de repositorio de datos]",
|
||||
"27": "Subiendo [%v]",
|
||||
"28": "La red es anómala, inténtalo de nuevo más tarde",
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "Le captcha est incorrect",
|
||||
"23": "Le référentiel de données est corrompu, veuillez réinitialiser le référentiel de données",
|
||||
"24": "Le réseau a expiré, veuillez réessayer plus tard",
|
||||
"25": "Le nom de l'attribut ne supporte que les lettres et les chiffres anglais.",
|
||||
"25": "Le nom de l'attribut ne peut contenir que des lettres minuscules, des chiffres et des tirets, et doit commencer par une lettre minuscule",
|
||||
"26": "Veuillez d'abord initialiser la clé du référentiel de données dans [Paramètres - À propos - Clé du référentiel de données]",
|
||||
"27": "Téléchargement de [%v]",
|
||||
"28": "Le réseau est anormal, veuillez réessayer plus tard",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "キャプチャが正しくありません",
|
||||
"23": "データリポジトリが壊れています。データリポジトリをリセットしてください",
|
||||
"24": "ネットワークがタイムアウトしました。後でまた試してださい",
|
||||
"25": "属性名は英字と数字のみ対応しています",
|
||||
"25": "属性名は小文字の英字、数字、ハイフンのみを含むことができ、小文字の英字で始まる必要があります",
|
||||
"26": "[設定] - [情報] - [データリポジトリキー] でデータリポジトリキーを初期化してください",
|
||||
"27": "[%v] をアップロード中",
|
||||
"28": "ネットワークに問題があります。後でまた試してださい",
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "보안 문자가 올바르지 않습니다",
|
||||
"23": "데이터 저장소가 손상되었습니다. 데이터 저장소를 재설정하세요",
|
||||
"24": "네트워크 시간 초과, 나중에 다시 시도하세요",
|
||||
"25": "속성 이름은 영문자와 숫자만 지원합니다",
|
||||
"25": "속성 이름은 소문자 영문자, 숫자, 하이픈만 포함할 수 있으며 소문자 영문자로 시작해야 합니다",
|
||||
"26": "먼저 [설정 - 정보 - 데이터 저장소 키]에서 데이터 저장소 키를 초기화하세요",
|
||||
"27": "업로드 중 [%v]",
|
||||
"28": "네트워크가 비정상입니다. 나중에 다시 시도하세요",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "Doğrulama kodu hatalı",
|
||||
"23": "Veri deposu bozulmuş, lütfen veri deposunu sıfırla",
|
||||
"24": "Ağ zaman aşımına uğradı, lütfen daha sonra tekrar dene",
|
||||
"25": "Öznitelik adı yalnızca İngilizce harf ve rakam içerebilir",
|
||||
"25": "Öznitelik adı yalnızca küçük harf İngilizce harf, rakam ve tire içerebilir ve küçük harf İngilizce harf ile başlamalıdır",
|
||||
"26": "Lütfen önce [Ayarlar - Hakkında - Veri deposu anahtarı] kısmından veri deposu anahtarını başlat",
|
||||
"27": "[%v] yükleniyor",
|
||||
"28": "Ağ hatalı, lütfen daha sonra tekrar dene",
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "驗證碼不正確",
|
||||
"23": "資料倉庫已被損壞,請重置資料倉庫",
|
||||
"24": "網絡超時,請稍後再試",
|
||||
"25": "屬性名僅支援英文字母和阿拉伯數字",
|
||||
"25": "屬性名只能包含小寫英文字母、數字和連字符,並且以小寫英文字母開頭",
|
||||
"26": "請先在 [設置 - 關於 - 資料倉庫密鑰] 中初始化資料倉庫密鑰",
|
||||
"27": "正在上傳 [%v]",
|
||||
"28": "網絡異常,請稍後再試",
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,7 @@
|
|||
"22": "验证码不正确",
|
||||
"23": "数据仓库已被损坏,请重置数据仓库",
|
||||
"24": "网络超时,请稍后再试",
|
||||
"25": "属性名仅支持英文字母和阿拉伯数字",
|
||||
"25": "属性名只能包含小写英文字母、数字和连字符,并且以小写英文字母开头",
|
||||
"26": "请先在 [设置 - 关于 - 数据仓库密钥] 中初始化数据仓库密钥",
|
||||
"27": "正在上传 [%v]",
|
||||
"28": "网络异常,请稍后再试",
|
||||
|
|
|
|||
|
|
@ -265,6 +265,15 @@
|
|||
"Type": "NodeText",
|
||||
"Data": "After sharing, write the attribute "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "custom-liandi-articleid"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " (previously "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
|
|
@ -272,7 +281,7 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " to the document to associate the link post ID"
|
||||
"Data": " ) to the document to associate the link post ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,15 @@
|
|||
"Type": "NodeText",
|
||||
"Data": "分享完毕后对文档写入属性 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "custom-liandi-articleid"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "(原为 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
|
|
@ -272,7 +281,7 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 用于关联链滴帖子 ID"
|
||||
"Data": " )用于关联链滴帖子 ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,15 @@
|
|||
"Type": "NodeText",
|
||||
"Data": "分享完畢後對文檔寫入屬性 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "custom-liandi-articleid"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "(原為 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
|
|
@ -272,7 +281,7 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 用於關聯鏈滴帖子 ID"
|
||||
"Data": " )用於關聯鏈滴帖子 ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,6 +282,15 @@
|
|||
"Type": "NodeText",
|
||||
"Data": "公開されると、ドキュメントに "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "custom-liandi-articleid"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "(以前は "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
|
|
@ -289,7 +298,7 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 属性が書き込まれ、リンクされた投稿 ID を関連付けます"
|
||||
"Data": " )属性が書き込まれ、リンクされた投稿 ID を関連付けます"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ export class Wnd {
|
|||
if (!oldTab) { // 从主窗口拖拽到页签新窗口
|
||||
JSONToCenter(app, tabData, this);
|
||||
this.children.find(item => {
|
||||
if (item.headElement.getAttribute("data-activeTime") === tabData.activeTime) {
|
||||
if (item.headElement.getAttribute("data-activetime") === tabData.activeTime) {
|
||||
oldTab = item;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -869,7 +869,7 @@ export class Dock {
|
|||
if (typeof tabIndex === "undefined" && !TYPES.includes(item.type)) {
|
||||
return;
|
||||
}
|
||||
html += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkey="${item.hotkey || ""}" data-hotkeyLangId="${item.hotkeyLangId || ""}" data-title="${item.title}" class="dock__item${item.show ? " dock__item--active" : ""} ariaLabel" aria-label="<span style='white-space:pre'>${item.title} ${item.hotkey ? updateHotkeyTip(item.hotkey) : ""}${window.siyuan.languages.dockTip}</span>">
|
||||
html += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkey="${item.hotkey || ""}" data-hotkeylangid="${item.hotkeyLangId || ""}" data-title="${item.title}" class="dock__item${item.show ? " dock__item--active" : ""} ariaLabel" aria-label="<span style='white-space:pre'>${item.title} ${item.hotkey ? updateHotkeyTip(item.hotkey) : ""}${window.siyuan.languages.dockTip}</span>">
|
||||
<svg><use xlink:href="#${item.icon}"></use></svg>
|
||||
</span>`;
|
||||
this.data[item.type] = true;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ const dockToJSON = (dock: Dock) => {
|
|||
show: item.classList.contains("dock__item--active"),
|
||||
icon: item.querySelector("use").getAttribute("xlink:href").substring(1),
|
||||
hotkey: item.getAttribute("data-hotkey") || "",
|
||||
hotkeyLangId: item.getAttribute("data-hotkeyLangId") || ""
|
||||
hotkeyLangId: item.getAttribute("data-hotkeylangid") || ""
|
||||
});
|
||||
});
|
||||
return data;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import {shell} from "electron";
|
||||
/// #endif
|
||||
import {confirmDialog} from "../dialog/confirmDialog";
|
||||
import {getSearch, isMobile, isValidAttrName} from "../util/functions";
|
||||
import {getSearch, isMobile, isValidCustomAttrName} from "../util/functions";
|
||||
import {isLocalPath, movePathTo, moveToPath, pathPosix} from "../util/pathName";
|
||||
import {MenuItem} from "./Menu";
|
||||
import {onExport, saveExport} from "../protyle/export";
|
||||
|
|
@ -353,8 +353,8 @@ export const openFileAttr = (attrs: IObject, focusName = "bookmark", protyle?: I
|
|||
});
|
||||
btnsElement[1].addEventListener("click", () => {
|
||||
const value = inputElement.value.toLowerCase();
|
||||
if (!isValidAttrName(value)) {
|
||||
showMessage(window.siyuan.languages.attrName + " <b>" + escapeHtml(value) + "</b> " + window.siyuan.languages.invalid);
|
||||
if (!isValidCustomAttrName(value)) {
|
||||
showMessage(window.siyuan.languages._kernel[25]);
|
||||
return false;
|
||||
}
|
||||
let existElement: HTMLElement | false;
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ export const isFileAnnotation = (text: string) => {
|
|||
return /^<<assets\/.+\/\d{14}-\w{7} ".+">>$/.test(text);
|
||||
};
|
||||
|
||||
export const isValidAttrName = (name: string) => {
|
||||
return /^[_a-zA-Z][_.\-0-9a-zA-Z]*$/.test(name);
|
||||
export const isValidCustomAttrName = (name: string) => {
|
||||
return /^[a-z][\-0-9a-z]*$/.test(name);
|
||||
};
|
||||
|
||||
// REF https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ package model
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
"github.com/88250/lute/ast"
|
||||
"github.com/88250/lute/editor"
|
||||
"github.com/88250/lute/lex"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/siyuan-note/siyuan/kernel/cache"
|
||||
|
|
@ -35,6 +35,32 @@ import (
|
|||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
// isValidAttrName 验证属性名是否合法
|
||||
func isValidAttrName(name string) bool {
|
||||
if len(name) == 0 {
|
||||
return false
|
||||
}
|
||||
// 首字符必须是小写字母
|
||||
if name[0] < 'a' || name[0] > 'z' {
|
||||
return false
|
||||
}
|
||||
// 自定义属性 custom- 之后的首个字符必须是小写字母
|
||||
if strings.HasPrefix(name, "custom-") {
|
||||
if len(name) <= 7 || name[7] < 'a' || name[7] > 'z' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// 后续字符只能是小写字母、数字、连字符
|
||||
for i := 1; i < len(name); i++ {
|
||||
c := name[i]
|
||||
if c == '-' || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func SetBlockReminder(id string, timed string) (err error) {
|
||||
if !IsSubscriber() {
|
||||
if "ios" == util.Container {
|
||||
|
|
@ -205,68 +231,64 @@ func setNodeAttrsWithTx(tx *Transaction, node *ast.Node, tree *parse.Tree, nameV
|
|||
|
||||
func setNodeAttrs0(node *ast.Node, nameValues map[string]string) (oldAttrs map[string]string, err error) {
|
||||
oldAttrs = parse.IAL2Map(node.KramdownIAL)
|
||||
|
||||
for name := range nameValues {
|
||||
for i := 0; i < len(name); i++ {
|
||||
if !lex.IsASCIILetterNumHyphen(name[i]) {
|
||||
err = errors.New(fmt.Sprintf(Conf.Language(25), node.ID))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tag, ok := nameValues["tags"]; ok {
|
||||
var tags []string
|
||||
tmp := strings.Split(tag, ",")
|
||||
for _, t := range tmp {
|
||||
t = util.RemoveInvalid(t)
|
||||
t = strings.TrimSpace(t)
|
||||
if "" != t {
|
||||
tags = append(tags, t)
|
||||
}
|
||||
}
|
||||
tags = gulu.Str.RemoveDuplicatedElem(tags)
|
||||
if 0 < len(tags) {
|
||||
nameValues["tags"] = strings.Join(tags, ",")
|
||||
}
|
||||
}
|
||||
|
||||
normalizeKeysToLower(nameValues)
|
||||
newAttrs := maps.Clone(oldAttrs)
|
||||
|
||||
for name, value := range nameValues {
|
||||
value = util.RemoveInvalidRetainCtrl(value)
|
||||
value = strings.TrimSpace(value)
|
||||
value = strings.TrimSuffix(value, ",")
|
||||
lowerName := strings.ToLower(name)
|
||||
// 转换为小写再验证属性名
|
||||
if !isValidAttrName(lowerName) {
|
||||
err = errors.New(Conf.Language(25) + " [" + node.ID + "]")
|
||||
return
|
||||
}
|
||||
|
||||
// 处理文档标签 https://github.com/siyuan-note/siyuan/issues/13311
|
||||
if lowerName == "tags" {
|
||||
var tags []string
|
||||
tmp := strings.Split(value, ",")
|
||||
for _, t := range tmp {
|
||||
t = util.RemoveInvalid(t)
|
||||
t = strings.TrimSpace(t)
|
||||
if "" != t {
|
||||
tags = append(tags, t)
|
||||
}
|
||||
}
|
||||
tags = gulu.Str.RemoveDuplicatedElem(tags)
|
||||
if 0 < len(tags) {
|
||||
value = strings.Join(tags, ",")
|
||||
} else {
|
||||
value = ""
|
||||
}
|
||||
}
|
||||
|
||||
if "" == value {
|
||||
node.RemoveIALAttr(name)
|
||||
// 删除属性
|
||||
if name != lowerName {
|
||||
if _, exists := newAttrs[name]; exists {
|
||||
// 仅删除完全匹配的包含大写字母的属性
|
||||
delete(newAttrs, name)
|
||||
continue
|
||||
}
|
||||
}
|
||||
delete(newAttrs, lowerName)
|
||||
} else {
|
||||
node.SetIALAttr(name, value)
|
||||
// 添加或更新属性
|
||||
// 删除大小写完全匹配的属性
|
||||
delete(newAttrs, name)
|
||||
// 保存小写的属性 https://github.com/siyuan-note/siyuan/issues/16447
|
||||
newAttrs[lowerName] = value
|
||||
}
|
||||
}
|
||||
|
||||
if oldAttrs["tags"] != nameValues["tags"] {
|
||||
node.KramdownIAL = parse.Map2IAL(newAttrs)
|
||||
|
||||
if oldAttrs["tags"] != newAttrs["tags"] {
|
||||
ReloadTag()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// normalizeKeysToLower 将 nameValues 的键统一为小写 https://github.com/siyuan-note/siyuan/issues/16447
|
||||
func normalizeKeysToLower(nameValues map[string]string) {
|
||||
newMap := make(map[string]string, len(nameValues))
|
||||
for name, value := range nameValues {
|
||||
lower := strings.ToLower(name)
|
||||
newMap[lower] = value
|
||||
}
|
||||
|
||||
for k := range nameValues {
|
||||
delete(nameValues, k)
|
||||
}
|
||||
|
||||
for k, v := range newMap {
|
||||
nameValues[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func pushBroadcastAttrTransactions(oldAttrs map[string]string, node *ast.Node) {
|
||||
newAttrs := parse.IAL2Map(node.KramdownIAL)
|
||||
data := map[string]interface{}{"old": oldAttrs, "new": newAttrs}
|
||||
|
|
@ -294,15 +316,15 @@ func ResetBlockAttrs(id string, nameValues map[string]string) (err error) {
|
|||
}
|
||||
|
||||
for name := range nameValues {
|
||||
for i := 0; i < len(name); i++ {
|
||||
if !lex.IsASCIILetterNumHyphen(name[i]) {
|
||||
return errors.New(fmt.Sprintf(Conf.Language(25), id))
|
||||
}
|
||||
if !isValidAttrName(name) {
|
||||
return errors.New(Conf.Language(25) + " [" + id + "]")
|
||||
}
|
||||
}
|
||||
|
||||
node.ClearIALAttrs()
|
||||
for name, value := range nameValues {
|
||||
value = util.RemoveInvalidRetainCtrl(value)
|
||||
value = strings.TrimSpace(value)
|
||||
if "" != value {
|
||||
node.SetIALAttr(name, value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,9 +245,14 @@ func Export2Liandi(id string) (err error) {
|
|||
defer util.PushClearMsg(msgId)
|
||||
|
||||
// 判断帖子是否已经存在,存在则使用更新接口
|
||||
const liandiArticleIdAttrName = "custom-liandi-articleId"
|
||||
const liandiArticleIdAttrName = "custom-liandi-articleid"
|
||||
const liandiArticleIdAttrNameOld = "custom-liandi-articleId" // 兼容旧属性名
|
||||
foundArticle := false
|
||||
// 优先使用新属性名,如果不存在则尝试旧属性名
|
||||
articleId := tree.Root.IALAttr(liandiArticleIdAttrName)
|
||||
if "" == articleId {
|
||||
articleId = tree.Root.IALAttr(liandiArticleIdAttrNameOld)
|
||||
}
|
||||
if "" != articleId {
|
||||
result := gulu.Ret.NewResult()
|
||||
request := httpclient.NewCloudRequest30s()
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/88250/lute"
|
||||
"github.com/88250/lute/ast"
|
||||
"github.com/88250/lute/editor"
|
||||
"github.com/88250/lute/lex"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/siyuan-note/filelock"
|
||||
"github.com/siyuan-note/logging"
|
||||
|
|
@ -1736,11 +1735,9 @@ func (tx *Transaction) doSetAttrs(operation *Operation) (ret *TxErr) {
|
|||
|
||||
var invalidNames []string
|
||||
for name := range attrs {
|
||||
for i := 0; i < len(name); i++ {
|
||||
if !lex.IsASCIILetterNumHyphen(name[i]) {
|
||||
logging.LogWarnf("invalid attr name [%s]", name)
|
||||
invalidNames = append(invalidNames, name)
|
||||
}
|
||||
if !isValidAttrName(name) {
|
||||
logging.LogWarnf("invalid attr name [%s]", name)
|
||||
invalidNames = append(invalidNames, name)
|
||||
}
|
||||
}
|
||||
for _, name := range invalidNames {
|
||||
|
|
@ -1748,6 +1745,7 @@ func (tx *Transaction) doSetAttrs(operation *Operation) (ret *TxErr) {
|
|||
}
|
||||
|
||||
for name, value := range attrs {
|
||||
name := strings.ToLower(name)
|
||||
if "" == value {
|
||||
node.RemoveIALAttr(name)
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue