Summary
ve.dm.LinearData#sanitize( { plainText: true } ) removes every element that is not a paragraph, but a node's text is often held in its attributes rather than in the linear data, so the text is deleted with the node. The patches on T431638 avoid this for ordinary pastes by preferring the clipboard's own text/plain, which leaves the lossy primitive in place on the two paths that cannot use it: paste-special, and any paste or drop that carries no text/plain.
Technical notes
Parsoid wraps every literal {, | and } in <span typeof="mw:Entity">, so on those two paths the characters are deleted with the nodes. Measured on the current code: paste-special of {{subst:Foo|1=bar}} and a nbsp inserts subst:Foo1=bar and anbsp, and a source-mode paste whose clipboard holds only text/html turns the {{tlxs}} example from Wikipedia:Barnstars into subst:The Random Acts of Kindness Barnstar1=message ~~~~2=alt. A copied <pre> or <syntaxhighlight> block sanitizes to nothing at all, because its source lives in mw.body.extsrc.
ve.dm.Node.static.getText already exists for this (added for T418474) and ve.dm.MWEntityNode implements it, but sanitize() deletes the node before anything consults it. Substituting a node's own plain text fixes all three cases: a content node becomes characters, a block node is wrapped in a paragraph per line, since characters cannot live outside a content branch node. This is a no-op for node types that do not implement getText, so extension nodes that render their own source opt in through a new usesSourceAsPlainText static reading mw.body.extsrc — <pre> in ve-mw, <syntaxhighlight> in SyntaxHighlight_GeSHi. Nodes whose rendering is not their source, such as transclusions and references, stay excluded and keep relying on the clipboard text or on conversion.
Plain text can only ever summarise these nodes: it gives the source of a <syntaxhighlight> without its tag. Today that loss is silent, because wasPlain calls isPlainText() with ignoreNonContentNodes, which skips block nodes, so a paste that is entirely a <pre> looks plain and the "Convert wikitext?" context item is never offered. Until now the emptiness itself triggered an immediate conversion instead; once the extraction stops being empty, that rescue no longer fires, so wasPlain has to account for nodes whose content is not in the linear data.
Acceptance criteria
- Paste-special of Parsoid-rendered template markup keeps its braces, pipes and non-breaking spaces, in both visual and source mode.
- A source-mode paste or drop whose clipboard carries only text/html inserts the same text as one that also carries text/plain.
- A copied <pre> or <syntaxhighlight> block inserts its source text instead of nothing, and still offers to convert the paste to wikitext so the tag can be recovered.