Je cherche à créer un éditeur avec Slate ou ProseMirror et je vois un comportement étrange avec Chrome autour de la position du curseur et de la zone de sélection lorsque en utilisant un élément intégré. Le problème 1 est illustré dans la première image ci-dessous. Lorsque la position du curseur de texte est derrière le "f", le curseur apparaît en haut de l'image. Le problème 2 se trouve dans la deuxième image - la sélection du texte affiche une zone en surbrillance qui est aussi haute que dans l'élément en ligne. Existe-t-il un moyen de contrôler ce comportement et d'afficher à la place le curseur à la position du texte et de ne mettre en évidence que l'espace autour du texte (même si l'image en ligne crée la ligne hauteur plus grande)
J'aimerais imiter le comportement ici, de Firefox:
Des exemples d'images ont été produits à l'aide de la démo ProseMirror ici: https://prosemirror.net/examples/basic/
Un exemple minimum (merci @Kaiido) avec JSBin :
<div contenteditable>Test text<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png">Testing</div>
Je ne sais pas comment cela se comporte sur d'autres systèmes d'exploitation, mais j'utilise macOS Catalina.
Tout d'abord, ne manipulez pas le DOM ProseMirror comme indiqué dans l'exemple JQuery. En fait, vous rencontrerez probablement des problèmes de DOM ou de contenu. ProseMirror utilise son propre nœud DOM et son propre schéma de balisage. Si vous souhaitez manipuler le DOM ProseMirror ou ajouter un plugin, jetez un œil à Markup, Plugin & Node Apis. J'ai joint un exemple simple de code de marquage d'alignement de texte. Note latérale, la raison Grammarly et d'autres n'ont pas de plugins ProseMirror à cause de l'approche/des modèles DOM.
Cela mis à part, la bonne nouvelle, les problèmes que vous avez un CSS purement. ProseMirror supprime toutes les classes et réinitialise le DOM/CSS donc si vous importez un document ou que vous coupez et collez la totalité/la plupart de vos classes auront disparu.
L'approche la plus simple pour résoudre ce problème consiste à envelopper l'éditeur dans un div et à affecter une classe au div, puis à ajouter des styles et des styles enfants à cette classe. La raison de l'encapsuler est que les sélecteurs css tels que img, p, h, etc. ne s'appliqueront qu'aux balises à l'intérieur de la classe d'éditeur. Sans cela, vous vous retrouvez avec des conflits CSS évidents.
CSS
float: left;
(approche recommandée)vertical-align: baseline;
mais sans flotteurs, vous aurez toujours un curseur qui correspond à la hauteur de l'image et non au texte. De plus, si vous n'utilisez pas de flotteurs, le curseur sera allongé car la hauteur de la ligne est effectivement la même hauteur que l'image. La couleur bleue est juste un sélecteur, que vous modifiez également en utilisant CSS.<html>
<div class="editor">
<!-- <editor></editor>-->
</div>
</html>
<style>
.editor {
position: relative;
display: block;
padding: 10px;
}
.editor p {
font-weight: 400;
font-size: 1rem;
font-family: Roboto, Arial, serif;
color: #777777;
display: inline;
vertical-align: baseline;
}
.editor img {
width: 50px;
float: left;
padding: 20px;
}
</style>
Exemple d'extension de nœud
Exemple de Node extension pour l'alignement de texte qui peut être ajouté comme barre d'outils. Article beaucoup plus long, mais même si vous avez créé un Node/plugin pour les images que vous doivent gérer la manière dont il est rendu, c'est-à-dire base64 par rapport à l'URL, etc.
export default class Paragraph extends Node {
get name() {
return 'paragraph';
}
get defaultOptions() {
return {
textAlign: ['left', 'center', 'right'],
}
}
inputRules({ type }) {
return [
markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
]
}
get schema() {
return {
attrs: {
textAlign: {
default: 'left'
}
},
content: 'inline*',
group: 'block',
draggable: false,
inclusive: false,
defining : true,
parseDOM: [
{
tag: 'p',
style: 'text-align',
getAttrs: value => value
}
],
toDOM: (node) => [ 'p', {
style: 'text-align:' + node.attrs.textAlign,
class: `type--base type--std text-` + node.attrs.textAlign
}, 0 ]
};
}
commands ({ type }) {
return (attrs) => updateMark(type, attrs)
}
}