Note: 我正在添加我发现的信息,这些信息似乎会导致注释中的解决方案。
问题是:
When pasting content from a source external to Gutenberg into Gutenberg some HTML/CSS formatting is lost.[1] Gutenberg保留了大多数HTML(语义)元素,但删除了CSS(样式/非语义)元素。这意味着在粘贴事件期间,字体大小、文本对齐方式、文本颜色等属性都将被删除。不是问题:
我们可以讨论用于将外部内容源(如谷歌文档)转换为WP友好内容的插件、自定义HTML块等(如Wordable、JetPack),但这个问题显然与这些解决方案无关。相反this question is exclusively focused on how to programmatically alter 古腾堡的糊处理行为。看到问题在行动
这个问题在很多情况下都会发生。例如,尝试将以下HTML块粘贴到Gutenberg中的段落块中:<p style="color:red">Hello WordPress StackExchange!</p>
<p>Hello WordPress StackExchange!</p>
style="color:red"
已被剥离。查看段落块
受此剥离影响的一个块是段落块(/gutenberg/packages/block-library/src/paragraph
). 此块[2]使用RichText
组件(/gutenberg/packages/block-editor/rich-text
) 实现其富文本编辑功能。查看中的RichText组件/rich-text/index.js
我们发现onPaste
段落块继承的方法。此函数依次调用pasteHandler
功能(/gutenberg/packages/blocks/src/api/raw-handling/paste-handler.js
).
查看粘贴处理程序pasteHandler
函数“将HTML字符串转换为已知块。删除所有其他内容。”根据JSDoc。
此函数采用五个参数:
HTML
= 如果为HTML格式,则要转换的源内容plainText
= 以文本格式转换的源内容mode
= 是将内容粘贴为块还是将内联内容粘贴到现有块中tagName
= 我们正在将内容插入的标签canUserUseUnfilteredHTML
= 起初我认为这决定了一个人是否可以使用任何想要的HTML/CSS,但它似乎更有限,因为它只决定iframeRemover
函数针对粘贴的内容运行,粘贴的内容仅与内容相关pasteHandler 已导入(index.js
):import { pasteHandler, children as childrenSource, getBlockTransforms, findTransform, isUnmodifiedDefaultBlock } from \'@wordpress/blocks\';
pasteHandler
然后从调用onPaste
:
出于我们的目的,我们只对pasteHandler函数的一部分感兴趣:onPaste( { value, onChange, html, plainText, files } ) { ... if ( files && files.length && ! html ) { const content = pasteHandler( { HTML: filePasteHandler( files), mode: \'BLOCKS\', tagName, } ); ... const content = pasteHandler ( { HTML: html, plainText, mode, tagName, canUserUseUnfilteredHTML, } ); ... }
即使在这里,发生的大多数事情与我们当前的问题无关。例如,我们不关心Google文档UID被删除或单词列表被转换。const rawTransforms = getRawTransformations(); const phrasingContentSchema = getPhrasingContentSchema( \'paste\' ); const blockContentSchema = getBlockContentSchema( rawTransforms, phrasingContentSchema, true ); const blocks = compact( flatMap( pieces, ( piece ) => { ... if ( ! canUserUseUnfilteredHTML ) { // Should run before `figureContentReducer`. filters.unshift( iframeRemover ); } const schema = { ...blockContentSchema, // Keep top-level phrasing content, normalised by `normaliseBlocks`. ...phrasingContentSchema, }; piece = deepFilterHTML( piece, filters, blockContentSchema ); piece = removeInvalidHTML( piece, schema ); piece = normaliseBlocks( piece ); piece = deepFilterHTML( piece, [ htmlFormattingRemover, brRemover, emptyParagraphRemover, ], blockContentSchema ); ... return htmlToBlocks( { html: piece, rawTransforms } ); } ) );
相反,我们感兴趣的是:
rawTransforms
- 包含调用的结果getRawTransformations
, 也在中定义paste-handler.js
.<我不认为这段代码涉及其中,但也许有人可以帮助我理解它的功能:)
phrasingContentSchema
- 包含调用的结果getPhrasingContentSchema
, 定义于phrasing-content.js
.<这似乎删除了一些不可见的属性(u、abbr、data等),这些属性可能是这个问题的一部分,但人们更可能遇到的问题是CSS样式,而不是这些属性
blockContentSchema
- 包含调用的结果getBlockContentSchema
, 定义于utils.js
.<再一次,我不完全确定我理解它的作用,但我认为它与此无关phrasingContentReducer
- 过滤器之一,在中定义phrasing-content-reducer.js
.<我不确定,但我怀疑可能涉及到这个片段:if ( node.nodeName === \'SPAN\' && node.style ) {
const {
fontWeight,
fontStyle,
textDecorationLine,
textDecoration,
verticalAlign,
} = node.style;
deepFilterHTML
- 定义于utils.js
, 本质上是deepFilterNodeList
, 也可在中找到utils.js
.<再一次,我不确定我是否理解这段代码,可能涉及其中
removeInvalidHTML
- 定义于utils.js
, 本质上是cleanNodeList
, 也可在中找到utils.js
.<相信这其中有牵连,cleanNodeList
JSDoc指出,“给定一个模式,展开或删除节点上的节点、属性和类”normaliseBlocks
, brRemover
, emptyParagraphRemover
, 等等)。结论是,我刚刚重写了这个问题的大部分内容,稍后我将尝试对其进行细化,并分享更多关于我不理解的特定代码片段在我有机会查看时的作用。希望这可能对其他人有帮助/有人可以向我解释我错过了什么。。。或者我可以继续努力。:)
[1] 从技术上讲,这并不总是正确的。某些块可能接受粘贴到其中的大部分/所有内容,例如HTML块。但保留粘贴的内容是一个例外,而不是规则。
[2] 您可以在中找到参考/paragraph/edit.js
在ParagraphBlock
作用