问题:
将内容从Gutenberg外部源粘贴到古腾堡丢失了一些HTML / CSS格式。[1]古腾堡保留大多数HTML(语义)元素,但会删除CSS(样式/非语义)元素。这意味着在粘贴事件期间,诸如字体大小,文本对齐方式,文本颜色等属性均被删除。
没有问题: ,自定义HTML块等(例如Wordable,JetPack)可用于将外部内容源(例如Google Docs)转换为WP友好内容,但这绝对不是这些解决方案的问题。相反,此问题仅集中在如何以编程方式更改Gutenberg的粘贴处理行为。例如,尝试将以下HTML块粘贴到Gutenberg的段落块中:
<p style="color:red">Hello WordPress StackExchange!</p>
然后查看该段落块的HTML,您将看到:
<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
函数“将HTML字符串转换为已知块。剥离所有其他内容。”根据JSDoc。此函数有五个参数:
/gutenberg/packages/blocks/src/api/raw-handling/paste-handler.js
=如果是HTML格式,则要转换的源内容pasteHandler
=如果是文本格式,则要转换的源内容HTML
=是将内容粘贴为块还是内联内容到现有块中。plainText
=我们是什么标记将内容插入其中。mode
=最初,我认为这确定了是否可以使用所需的任何HTML / CSS,但似乎更受限制,AFAIK仅确定是否针对粘贴的内容(仅与切线相关)。我们可以看到
tagName
是导入的(canUserUseUnfilteredHTML
): iframeRemover
然后从
pasteHandler
调用index.js
: import {
pasteHandler,
children as childrenSource,
getBlockTransforms,
findTransform,
isUnmodifiedDefaultBlock
} from '@wordpress/blocks';
出于我们的目的,我们只对pasteHandler函数的一部分感兴趣:
pasteHandler
即使在这里,大部分发生的事情与我们无关 当前的问题。例如,我们不在乎删除Google Doc UID或转换Word列表。
相反,我们感兴趣的是:
>
onPaste
-包含对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,
} );
...
}
的调用的结果,也定义在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
的结果。这似乎删除了一些不可见的属性(u,abbr,data等)可能是此问题的一部分,但人们会遇到的更多问题是CSS样式,而不是这些属性。phrasingContentSchema
-包含对getPhrasingContentSchema
的调用的结果,该调用在phrasing-content.js
中定义。 。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
JSDoc指出:“给出一个模式,解开或删除节点上的节点,属性和类”。您会注意到一些未列入清单的功能-在查看它们的代码后,我认为它们不参与当前的问题(例如
cleanNodeList
,utils.js
,cleanNodeList
等)。结论
我只是重写了大部分问题,稍后我将尝试进行细化并分享更多有关特定sni当我有机会看的时候,我不理解的代码片段就会出现。希望这可能对其他人有帮助/某人也许可以向我解释我所缺少的东西...或者我可以不停地走开。 :)
[1]从技术上讲,这并不总是正确的。某些块可能接受粘贴到其中的大多数/所有内容-例如HTML块。但是保留粘贴内容是一个例外,而不是规则。
[2]您可以在
normaliseBlocks
函数的brRemover
中找到引用。#1 楼
我在Gutenberg玩的还不是很多,但是将来我很可能需要解决类似的问题,我要做的就是直接编辑函数,以便快速调试。
const rawTransforms = getRawTransformations();
const phrasingContentSchema = getPhrasingContentSchema( 'paste' );
const blockContentSchema = getBlockContentSchema( rawTransforms, phrasingContentSchema, true );
const blocks = compact( flatMap( pieces, ( piece ) => {
...
// console.log( "Piece - deepFilterHTML" )
// console.log( piece );
piece = deepFilterHTML( piece, filters, blockContentSchema );
// console.log( "Piece - removeInvalidHTML" )
// console.log( piece );
piece = removeInvalidHTML( piece, schema );
// console.log( "Piece - normaliseBlocks" )
// console.log( piece );
piece = normaliseBlocks( piece );
// console.log( "Piece - deepFilterHTML" )
// console.log( piece );
piece = deepFilterHTML( piece, [
htmlFormattingRemover,
brRemover,
emptyParagraphRemover,
], blockContentSchema );
...
return htmlToBlocks( { html: piece, rawTransforms } );
} ) );
我很确定对文档粘贴和HTML起作用的地方是“ cleanNodeList”函数,该函数具有4个参数:nodeList,doc, schema,内联
schema参数是“可以与提供的节点发生变异的函数数组。”
我想出了在您的情况下这将输出什么html / doc已过滤而不是未过滤
然后我想出了如何更改该参数的方法,因为我认为当它被“过滤”时,它将采用默认值。
这是在默认值上运行的代码多么苗条:
cleanNodeList(node.childNodes, doc, schema, inline); // For inline mode, insert a line break when unwrapping nodes that
// are not phrasing content.
if (inline && !isPhrasingContent(node) && node.nextElementSibling) {
Object(external_this_wp_dom_["insertAfter"])(doc.createElement('br'), node);
}
Object(external_this_wp_dom_["unwrap"])(node);
external_this_wp_dom _ [“ unwrap”]最有可能在运行默认过滤时依赖phrasing_content_phrasingContentSchema,并且从
<span>
标签的外观未定义都全部。var phrasing_content_phrasingContentSchema = {
strong: {},
em: {},
s: {},
del: {},
ins: {},
a: {
attributes: ['href', 'target', 'rel']
},
code: {},
abbr: {
attributes: ['title']
},
sub: {},
sup: {},
br: {},
'#text': {}
}
希望能有所帮助。
#2 楼
在wp-includes / js / dist /中的我的blocks.js中,我找到RemoveInvalidHTML
函数,该函数似乎负责从粘贴的HTML中删除样式。 /**
* Given a schema, unwraps or removes nodes, attributes and classes on HTML.
*
* @param {string} HTML The HTML to clean up.
* @param {Object} schema Schema for the HTML.
* @param {Object} inline Whether to clean for inline mode.
*
* @return {string} The cleaned up HTML.
*/
function removeInvalidHTML(HTML, schema, inline) {
var doc = document.implementation.createHTMLDocument('');
doc.body.innerHTML = HTML;
cleanNodeList(doc.body.childNodes, doc, schema, inline);
return doc.body.innerHTML;
}
如您所见,这仅返回innerHTML。修改(创建此版本的自定义版本)此功能可能会解决您的问题。
评论
数据可能不在剪贴板中吗?如果您知道一种使数据保持适当机制的方法,那么我认为GB团队会很乐意做出贡献,以便所有用户都能从中受益,我很好奇自己@TomJNowell-我使用了一个名为ClipView的小应用程序来查看剪贴板的原始内容,并显示了CSS。另外,根据有关Github问题的一些对话,似乎决定剥离CSS并仅保留语义(HTML)内容。
您是否已经看过文档的这一部分?
嗨,Cas,我做到了。这些文档非常稀疏。