Skip to content

当使用updateBlock api的markdown方式更新带有自定义属性的行内元素时,会使自定义属性失效 #15048

Closed
@wish5115

Description

@wish5115

Is there an existing issue for this?

  • I have searched the existing issues

Can the issue be reproduced with the default theme (daylight/midnight)?

  • I was able to reproduce the issue with the default theme

Could the issue be due to extensions?

  • I've ruled out the possibility that the extension is causing the problem.

Describe the problem

比如,

首先,先用api fetchSyncPost('/api/block/getBlockKramdown', {id:'20250617110555-4hmh5wu'})获取文档的kramdown内容如下:

const result = {
    "code": 0,
    "msg": "",
    "data": {
        "id": "20250617110555-4hmh5wu",
        "kramdown": "$return 'Hello Inline JS';${: custom-js=\"Base64Text:cmV0dXJuICdIZWxsbyBJbmxpbmUgSlMnOw==\"}​\n{: updated=\"20250617110607\" id=\"20250617110555-4hmh5wu\"}"
    }
}

注意,这里有{: custom-js="“ }自定义属性

然后,再用api fetchSyncPost('/api/block/updateBlock', {
"dataType": "markdown",
"data": result .data.kramdown,
"id": "20250617110555-4hmh5wu"
}) 更新文档内容后,自定义属性{: custom-js="“ }消失。

dom结构也从原来的

<span data-type="inline-math" data-subtype="math" data-content="Base64Text:SGVsbG8gSW5saW5lIEpT" contenteditable="false" class="render-node" custom-js="Base64Text:cmV0dXJuICdIZWxsbyBJbmxpbmUgSlMnOw==" data-render="true">Hello Inline JS</span>

注意这里有自定义属性custom-js="”

变成了

<span data-type="inline-math" data-subtype="math" data-content="Base64Text:SGVsbG8gSW5saW5lIEpT" contenteditable="false" class="render-node" data-render="true">Hello Inline JS</span>

自定义属性custom-js="”消失

建议,/api/block/updateBlock api用markdown方式更新后,自定义属性不消失,这会导致vscode插件通过kramdown编辑后,导致自定义属性消失,进一步会导致那些依赖自定义属性的功能失效或错误。

详情可参考 Zuoqiu-Yingyi/siyuan-plugin-monaco-editor#37

提醒下:更新文档块时也是同样的问题。 vscode插件应该是用的更新文档块的方式更新的。

Expected result

/api/block/updateBlock api用markdown方式更新后,自定义属性不消失

Screenshot or screen recording presentation

No response

Version environment

- Version: 3.1.29 3.1.32
- Operating System: macos windows
- Browser (if used):no

Log file

no

More information

No response

Activity

self-assigned this
on Jun 17, 2025
88250

88250 commented on Jun 18, 2025

@88250
Member

我这里测试没有发现问题。

getBlockKramdown req:

{
    "id": "20250618113253-s4y0c38",
    "mode": "md"
}

getBlockKramdown res:

{
    "code": 0,
    "msg": "",
    "data": {
        "id": "20250618113253-s4y0c38",
        "kramdown": "$foo${: custom-js=\"bar\"}\n{: custom-foo=\"bar\" id=\"20250618113253-s4y0c38\" updated=\"20250618115520\"}"
    }
}

updateBlock req:

{
    "data": "$foo${: custom-js=\"bar\"}\n{: custom-foo=\"bar\" id=\"20250618113253-s4y0c38\" updated=\"20250618115520\"}",
    "dataType": "markdown",
    "id": "20250618113253-s4y0c38"
}

updateBlock res:

{
    "code": 0,
    "msg": "",
    "data": [
        {
            "timestamp": 0,
            "doOperations": [
                {
                    "action": "update",
                    "data": "<div data-node-id=\"20250618113253-s4y0c38\" data-node-index=\"1\" data-type=\"NodeParagraph\" class=\"p\" updated=\"20250618115520\" custom-foo=\"bar\"><div contenteditable=\"true\" spellcheck=\"false\"><span data-type=\"inline-math\" data-subtype=\"math\" data-content=\"foo\" contenteditable=\"false\" class=\"render-node\"></span>{: custom-js=&quot;bar&quot;}</div><div class=\"protyle-attr\" contenteditable=\"false\">​</div></div>",
                    "id": "20250618113253-s4y0c38",
                    "parentID": "",
                    "previousID": "",
                    "nextID": "",
                    "retData": null,
                    "blockIDs": null,
                    "blockID": "",
                    "deckID": "",
                    "avID": "",
                    "srcIDs": null,
                    "srcs": null,
                    "isDetached": false,
                    "ignoreFillFilter": false,
                    "name": "",
                    "type": "",
                    "format": "",
                    "keyID": "",
                    "rowID": "",
                    "isTwoWay": false,
                    "backRelationKeyID": "",
                    "removeDest": false,
                    "layout": ""
                }
            ],
            "undoOperations": null
        }
    ]
}

再次 getBlockKramdown 返回值不变。

TCOTC

TCOTC commented on Jun 18, 2025

@TCOTC
Contributor

试了一下好像没问题:(文档块我也试了,没录屏)

async function getBlockKramdown(id) {
    const response = await fetch('/api/block/getBlockKramdown', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ id })
    });
    const data = await response.json();
    return data;
}

let kramdown;

kramdown = (await getBlockKramdown('20250618115351-i5p1n95')).data.kramdown;
console.log("更新前 kramdown:", kramdown);

async function updateBlock(id, data, dataType = 'markdown') {
    const requestBody = {
        dataType,
        data,
        id
    };
    const response = await fetch('/api/block/updateBlock', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestBody)
    });
    const responseData = await response.json();
    return responseData;
}

await updateBlock('20250618115351-i5p1n95', "update " + kramdown, 'markdown');

console.log("更新后 kramdown:", (await getBlockKramdown('20250618115351-i5p1n95')).data.kramdown);
video.webm
wish5115

wish5115 commented on Jun 18, 2025

@wish5115
Author

试了一下好像没问题:(文档块我也试了,没录屏)

不是块的自定义属性,是块内的行内元素的自定义属性,比如

<span data-type="inline-math" data-subtype="math" data-content="Base64Text:SGVsbG8gSW5saW5lIEpT" contenteditable="false" class="render-node" custom-js="Base64Text:cmV0dXJuICdIZWxsbyBJbmxpbmUgSlMnOw==" data-render="true">Hello Inline JS</span>

是带有自定义属性的行内元素

TCOTC

TCOTC commented on Jun 18, 2025

@TCOTC
wish5115

wish5115 commented on Jun 18, 2025

@wish5115
Author

我这里测试没有发现问题。

好像行级公式才有问题

"<div data-node-id=\"20250618113253-s4y0c38\" data-node-index=\"1\" data-type=\"NodeParagraph\" class=\"p\" updated=\"20250618115520\" custom-foo=\"bar\"><div contenteditable=\"true\" spellcheck=\"false\"><span data-type=\"inline-math\" data-subtype=\"math\" data-content=\"foo\" contenteditable=\"false\" class=\"render-node\"></span>{: custom-js=&quot;bar&quot;}</div><div class=\"protyle-attr\" contenteditable=\"false\">​</div></div>"

这个返回结果本身就有问题吧,dom结构中,为何出现>{: custom-js=&quot;bar&quot;} 这样的字符?

直接看dom结构最明显,很清楚的看到问题,不管返回还是中间过程是什么,比如修改前 dom结构如下

<span date-type="inline-math" data-subtype="math" custom-js="test">demo</span>

修改后dom变成了

<span date-type="inline-math" data-subtype="math">demo</span>

custom-js属性丢失了。

如下演示录屏

安装行内js的情况

Image

新空间测试,未安装行内js的情况

Image

测试代码

// 插入带自定义属性的行内公式
document.execCommand('insertHTML', false, `<span data-type="inline-math" data-subtype="math" data-content="Base64Text:SGVsbG8gSW5saW5lIEpT" contenteditable="false" class="render-node" custom-js="Base64Text:cmV0dXJuICdIZWxsbyBJbmxpbmUgSlMnOw==" data-render="true">Hello Inline JS</span>`)

// 以markdown方式修改
id = "20250618153329-k09jo7n";
result = await openAny.fn.fetchSyncPost('/api/block/getBlockKramdown', {id});
await openAny.fn.fetchSyncPost('/api/block/updateBlock', {
"dataType": "markdown",
"data": result.data.kramdown,
"id": id
})
wish5115

wish5115 commented on Jun 18, 2025

@wish5115
Author

#13325 (comment)

刚才试了下非行内公式也支持的

TCOTC

TCOTC commented on Jun 18, 2025

@TCOTC
Contributor

#13325 (comment)

刚才试了下非行内公式也支持的

我试了一下粗体元素不支持

wish5115

wish5115 commented on Jun 18, 2025

@wish5115
Author

#13325 (comment)

刚才试了下非行内公式也支持的

我试了一下粗体元素不支持

支持

Image

再说了,即使以前不支持,也可以支持嘛,总不能一开始不支持就以后永远不支持吧。

感觉不是不支持,更像bug,因为.sy文件中已经有了对应属性,只不过markdown编辑时丢失了这个属性,并且我测试的仅inline-math有这种情况

Image

TCOTC

TCOTC commented on Jun 18, 2025

@TCOTC
Contributor

刚刚我又试了一下发现加粗确实可以,行级公式是有点问题

async function getBlockKramdown(id) {
    const response = await fetch('/api/block/getBlockKramdown', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ id })
    });
    const data = await response.json();
    return data;
}

async function updateBlock(id, data, dataType = 'markdown') {
    const requestBody = {
        dataType,
        data,
        id
    };
    const response = await fetch('/api/block/updateBlock', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestBody)
    });
    const responseData = await response.json();
    return responseData;
}

await updateBlock('20250618145542-6tqf80z', `文字:**$加粗$**{: custom-js="Base64Text:cmV0dXJuICdIZWxsbyBJbmxpbmUgSlMnOw=="}文本
{: id="20250618145542-6tqf80z" updated="20250618213800"}`, 'markdown');

console.log("更新后 kramdown:", (await getBlockKramdown('20250618145542-6tqf80z')).data.kramdown);
wish5115

wish5115 commented on Jun 18, 2025

@wish5115
Author

刚刚我又试了一下发现加粗确实可以,行级公式是有点问题

是的,这个修复了思源自定义属性这块就完美了。

不然,行内元素无法自定义的话,在某些个性化操作方面,将失去灵活性。

我能想到的唯一办法就是借助data-type实现,比如

<span data-type="inline-math js jscode:alert(1);" data-subtype="math">Hello Inline JS</span>

然后js代码最好用base64编码,以防特殊字符产生意外。

不过,这样看起来有点搓。

added a commit that references this issue on Jun 20, 2025
88250

88250 commented on Jun 20, 2025

@88250
Member

v3.2.0 改进,感谢反馈

TCOTC

TCOTC commented on Jun 20, 2025

@TCOTC
Contributor

@88250 行级元素为 data-type="inline-math" 的情况没问题,但行级元素为 data-type="strong inline-math" 的情况下还是不行

88250

88250 commented on Jun 21, 2025

@88250
Member

稍后改进

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @88250@wish5115@TCOTC

      Issue actions

        当使用updateBlock api的markdown方式更新带有自定义属性的行内元素时,会使自定义属性失效 · Issue #15048 · siyuan-note/siyuan