Remark插件自定义标签名失效:md-assist-chip被转为div求助
问题:修改emphasis节点为md-assist-chip时被自动转为div元素
我正尝试修改特定emphasis节点,将其转换为徽章(替换为自定义Material Web组件md-assist-chip标签)。我尝试将节点类型设置为element并指定tagName为md-assist-chip,但页面中插入的却是div元素而非目标元素。
相关代码如下:
/** * * This transformer adds badges to documentation * * See: https://github.com/syntax-tree/mdast-util-to-hast * **/ // Update nodes! // (This is the part that is not working properly) const updateNode = (node, name, description, href, classNames = []) => { // Change tag name to "md-assist-chip" node.type = 'element'; node.tagName = 'md-assist-chip'; // ^^ For some reason, this doesn't work! ^^ // It only renames the element's tag to "div" (this is caused by setting the type to 'element') // Update node data node.data = { hProperties: { label: name, title: description, href, className: ['badge-chip', ...classNames], "data-role": "presentation", tabindex: "-1" } }; node.children[0].value = name; }; // You can ignore the rest of this code, but I included it here in case you needed to check the way I call this function! import { visitParents } from 'unist-util-visit-parents'; export default function attacher() { return transformer; } const BADGES = [ '(omni-js)', '(omni-cpp)', '(omni-java)' ]; const BADGES_INFO = [ { name: 'JS', href: '' }, { name: 'C++', href: '' }, { name: 'Java', href: '' } ]; const DEPRECATED = '(deprecated)'; const EXPERIMENTAL = '(experimental)'; const CAREFUL_USE = '(careful)'; function transformer(tree) { visitParents(tree, 'emphasis', visitor); } function visitor(node) { if (node.children.length === 1 && (node.children[0]).type === 'text') { const tag = node.children[0].value.toLowerCase(); if (BADGES.includes(tag)) { // Get info const i = BADGES.indexOf(tag); const info = BADGES_INFO[i]; const name = info.name; const href = info.href; updateNode( node, name, 'Supported target language', href, ['badge-chip--lang'] ); } else if (tag === DEPRECATED) { updateNode( node, 'Deprecated', 'Deprecated feature (may be removed in the future)', "/", ['badge-chip--deprecated'] ); } else if (tag === EXPERIMENTAL) { updateNode( node, 'Experimental', 'Experimental feature (may change in the future)', "/", ['badge-chip--experimental'] ); } else if (tag === CAREFUL_USE) { updateNode( node, 'Careful', 'Careful use advised!', "/", ['badge-chip--careful'] ); } } }
当前最终输出效果:
可下载对应仓库启动Docusaurus项目在localhost:3000/docs/old/intro页面测试。
疑问:为何将AST中节点类型改为'element'后,tagName被忽略,元素被转为div?
原因及解决方案
核心原因
你混淆了mdast(Markdown语法树)和hast(HTML语法树)的节点规范:
- mdast是用于描述Markdown结构的AST,它的节点类型里没有
element,element是hast专属的节点类型。 - 直接将mdast的
emphasis节点类型修改为element属于非法操作,mdast-util-to-hast处理这种不合法节点时,会默认降级渲染为div。
正确解决方案
无需修改mdast节点的类型,而是通过node.data.hName指定转换为HTML时的目标标签名,同时保留hProperties配置。修改后的updateNode函数如下:
const updateNode = (node, name, description, href, classNames = []) => { // 通过hName指定转换后的HTML标签 node.data = { hName: 'md-assist-chip', hProperties: { label: name, title: description, href, className: ['badge-chip', ...classNames], "data-role": "presentation", tabindex: "-1" } }; node.children[0].value = name; };
补充说明
mdast-util-to-hast允许通过节点的data属性配置转换规则:
hName:指定转换后的HTML标签名hProperties:设置HTML元素的属性- 这种方式符合mdast的规范,转换工具能正确识别并生成目标自定义标签。
另外需要确保项目中已正确引入Material Web的md-assist-chip组件,否则浏览器无法识别该自定义标签,可能会呈现无样式的类似div的元素。
内容的提问来源于stack exchange,提问作者0xENDER
相关产品推荐
相关产品推荐

