Closed ngekoding closed 1 year ago
You don't need this extension to detect the direction since you already know the direction of the span
s. You can create a custom node that selects the span
tags that have text-arabic
class and add dir="rtl"
directly to them:
import { mergeAttributes, Node } from '@tiptap/core'
const ArabicNode = Node.create({
name: "arabic", // a unique name
// You might want to give it a high priority of you have other nodes that select `span` tags
// priority: 1000,
inline: true,
group: "inline",
content: "inline*",
parseHTML() {
return [
{
tag: "span",
getAttrs: (node) => node.classList.contains("text-arabic") && null,
},
];
},
renderHTML({ HTMLAttributes }) {
return ["span", mergeAttributes({ dir: "rtl", class: "text-arabic" }, HTMLAttributes), 0];
},
});
// Dont' forget to register it
const editor = new Editor({
extensions: [
ArabicNode,
// …
],
})
I haven't tested the above code, but you get the idea.
If you're not sure about the direction and want this extension to detect it, you can add the name of the new node ("arabic" in this case) to the types
option:
TextDirection.configure({
types: ["heading", "paragraph", "arabic"],
});
In this case you should remove renderHTML
from the node since the extension doesn't add the dir
attribute if the node already have one.
Let me know if it works for you
I forgot to add inline: true
.
I updated the code
You should also render class="arabic-text"
manually otherwise it would be removed from the element. I updated the code again
I was try it and get nothing, the dir attribute not added.
I want to implement it to this project https://github.com/ngekoding/notes-to-image, so currently I use custom extension to add the text-arabic
class.
Can you give me an official extension to follow (suggestion to learn) for this?
It's wired because it works for me. Did you add ArabicNode
to the list of extensions?
Can you show me your extension code so I can help you?
If you want to learn more about it you can follow the official docs: https://tiptap.dev/api/nodes
I don't know an official extension that uses this technique but almost all extensions has a custom node that you can use as a reference. https://github.com/ueberdosis/tiptap/tree/develop/packages
Thanks for the references, I will try it again and update the info here.
I just copy your code above for the extension.
Did you add the node to the list of extension? for example in React:
const editor = new Editor({
extensions: [
ArabicNode,
// …
],
})
How are you adding the "text-arabic" class to the span? Without that class the code I wrote wouldn't work
Did you add the node to the list of extension? for example in React:
const editor = new Editor({ extensions: [ ArabicNode, // … ], })
Yes, already added it.
How are you adding the "text-arabic" class to the span? Without that class the code I wrote wouldn't work
I use a custom extension, here is the extension I use https://github.com/ngekoding/notes-to-image/blob/master/src/tiptap-extensions/text-class/text-class.js
If you have a time, you can also check the app directly to show it in action.
Just update these two function in you extension and it should work:
parseHTML() {
return [
{
tag: 'span',
getAttrs: (node) => node.classList.contains("text-arabic") && null,
},
];
},
renderHTML({ HTMLAttributes }) {
return ["span", mergeAttributes({ dir: "rtl", class: "text-arabic" }, HTMLAttributes), 0];
},
And delete my custom node since you already have one.
You mean I just use the text-class
extension to also include the dir
attribute?
Yes
MashaAllah, it works! and the text-arabic typed twice.
But, how to make it in different extension?
I think the custom node I wrote conflicts with your extension and therefor it doesn't work. Probably giving a higher priority fixes that:
const ArabicNode = Node.create({
priority: 1000,
// ...
})
But since you already have an extension that selects span
s it's easier to add dir
directly with that.
I think the reason that "text-arabic" class is added twice is that you are adding it twice, once in renderHTML
of the class
attribute and once in the global renderHTML
. Removing it from the global renderHTML
should fix that:
renderHTML({ HTMLAttributes }) {
return ["span", mergeAttributes({ dir: "rtl" }, HTMLAttributes), 0];
},
Also, if you are using the text-class
extension for different purposes (maybe different classes do different things) you can do a little check before adding the dir
attribute:
// Select all `span` tags regardless of the class
parseHTML() {
return [
{
tag: 'span',
},
];
},
// If it had the "text-arabic" class add the `dir` attribute, otherwise just render the `span`
renderHTML({ HTMLAttributes }) {
if (HTMLAttributes.class.includes("text-arabic")) {
return ["span", mergeAttributes({ dir: "rtl" }, HTMLAttributes), 0];
}
return ["span", HTMLAttributes, 0];
},
I think the custom node I wrote conflicts with your extension and therefor it doesn't work. Probably giving a higher priority fixes that:
const ArabicNode = Node.create({ priority: 1000, // ... })
At the first of try I was already use the priority with no works.
Also, if you are using the
text-class
extension for different purposes (maybe different classes do different things) you can do a little check before adding thedir
attribute:
I think it is better to make a separate extension for different purpose, I will try it again.
You extension is actually a Mark, maybe my extension should be a Mark too.
const ArabicMark = Mark.create({ /* ... */ })
You can get more help in the TipTap discord. My extension works but somehow it conflicts with your extension. The problem is identified so probably a more experienced TipTap user knows the solution
You extension is actually a Mark, maybe my extension should be a Mark too.
const ArabicMark = Mark.create({ /* ... */ })
You are right, it works now but...
But I need to refresh the web page to get the updated content with dir="rtl"
, so how can I get it automatically every time I add the text-arabic
class?
It seems like a bug. dir="rtl"
should be added to all nodes that have text-arabic
class. You shouldn't need to refresh the page.
I would say the two extensions are still somehow conflicting with each other. Otherwise whether it's a bug or something beyond my knowledge.
My suggestion would be to render the dir
attribute in the text-class
extension.
It's a good idea to discuss this in the TipTap Discord channel. There are a lot of knowledgeable people there.
So finally I make it as you suggest, here is the code https://github.com/ngekoding/notes-to-image/commit/3423fb4a2c18c2807d6a4a36a1734e17fe32b360
Thank you very much
Hi, thanks for this awesome extension. Can you help how to apply the dir in span tag?
So, I have a content like
<span class="text-arabic">...</span>
and I want to add the dir="rtl" to it. Currently it will wrapped with a<p>
tag, so it make:I want make it:
Thanks in advance.