Report Bug
Trying to build customer serializer rules for the slate-html-serializer but when I call
const html = new Html({ rules })
html.serialize(slateValue)
There is an error:
"No serializer defined for node of type "line"."
Comes from:
https://github.com/ianstormtaylor/slate/blob/master/packages/slate-html-serializer/src/index.js#L364
From my understanding, the default TEXT_RULE injected, should at least serialize leaf nodes as text if I have no rules defined. This would mean the nested nodes should all be dropped, which is OK, but it doesn't even do that. It crashes.
I thought #2335 was similar, and tried to ask the question in Slack also.
I think the issue is that I call Plain.deserialize to create an initial value. Then I tried to serialize that as Html. The Plain deserializer introduces the unknown type. In my opinion this should just get ignored, but it somehow breaks the html serializer.
I lost 2 hours with slate as well ... I found out, that slate-html-serializer is not like slate-plain-serializer ... it has first to be instantiated with rules: Html.(rules).serialize(value);
BUT I did not find any rules, that I could use with the RichTextEditor Example.
Slate may be very powerful, but in its current state it is way tooo complicated to get something done.
I know it has to be constructed. They have example clearly in the docs here:
https://docs.slatejs.org/walkthroughs/saving-and-loading-html-content
My code snippet Html.serizlier(slateValue) was misleading and poor. Html was referring to the constructed instance with rules given. I had a capitalized version to make it look similar to Plain.serizlie() but I see how this is confusing as capital is for classes and lowercase for instances.
Slate may be very powerful, but in its current state it is way tooo complicated to get something done.
I don't agree with this. This is adding on opinions unrelated to the issue. As far as I know there are no tools like Slate that offer as clean of API's. I had previous used Draft.js and it was much worse and less capable. Slate is complicated yes, but rich text editing is complicated. Sure they could always strive to be simpler and have better docs, but where they don't we open issues
I would like to keep this focused on understanding why not explicitly having a rule for a specific type throws an error. I would expect it to be ignored and traverse all the way to leaf nodes which get captured by the default TEXT_RULE and it is or serialized the same as the Plain serializer.
@mattmazzola I think I could speak more definitively if there was a fiddle handy to observe the specific chain of events. But based purely on what I'm reading I think this is what's going on:
The html-serializer is completely hands off on its rules, it expects you to define all of these yourself.
If there's something unexpected in your model, I think what needs to happen is that you either need to eliminate that unexpected content, or you need to write rules to handle it.
It also looks like the plain-serializer needs to be provided a block type to be used as its default and pass this in when calling Plain.deserialize(), this should get rid of the line type blocks and at least get them to a type that your editor understands.
So I guess in short:
line type blocksI hope that helps, sorry we didn't catch this in the slack.
EDIT: @zevero
Slate may be very powerful, but in its current state it is way tooo complicated to get something done.
I'm guessing what you're trying to say here is that the documentation for the serializers is weak and they are therefore hard to use. I would agree with that statement. However, this is an open source library and it's driven mostly by one dude. It is unreasonable to expect this one dude to keep _all_ of the documentation up to date at all times. It would be wonderful if when you identify a gap in the documentation, you submit a PR to fill it. This will help improve the experience for everyone.
Yea, I see how it works now.
https://github.com/ianstormtaylor/slate/blob/master/packages/slate/src/models/node.js#L120
Example:
Plain.deserialize(value, { defaultBlock: 'myType' })
I was confused with defaultBlock at first being a string and then being an object from Node.createProperties net re-using the same variable name.
Imo, it would be more clear to have the destructed property be blockType
I originally though the serializers should be completely independent and not be coupled at all (The type used by Plain serializer has to also be known and understood by Html serializer). I feel like this could be true to deserialize/serialize completely but didn't know it was required for default behavior.
My current serializer, working after I added case for 'line':
switch (obj.type) {
case 'line':
case 'paragraph':
return <p>{children}</p>
}
Maybe there was a changes in the past that weren't updated. For example it seems the serializer is operation on Node types but it's named a generic obj which makes it seem like it could be other types as well.
Also, maybe nodes used to have an object property but it was changed to kind property. (I don't use it here, but docs show it)
Historically blocks had a kind property, and now they have an object property. If you have a kind property, that implies that for some reason there's an old slate core version in play. I would check for any dependencies that have locked to an old version and are bringing in an old version unexpectedly.
Reasonable feedback about the property name being confusing as well. When https://github.com/ianstormtaylor/slate/issues/2989 is addressed this is something that should change as well. The defaultBlock name _kind of_ makes sense when we factor in the current convention of using createBlock with a string only for the type but it's pretty obscure otherwise.
Oh that explains it. It's newer instead of older. I had listed my versions in Slack and forgot it didn't mention it here.
https://slate-js.slack.com/archives/C1RH7AXSS/p1568066096302400
When I first saw the errors I didn't know where "line" type was coming from and though I had version mismatch. I was asking:
How do I know which "serializer" package versions match with the slate model version? I assumed the default serializer should work.
I thought that perhaps the "plain" and "html" serializers are updated in sync so if version X works for the plain serializer i should also use X for the HTML serializer but I wasn't sure.
This is my current versions which explains kind property. I had tried upgrading long time ago but I think it broke one of my plugins and I decided to hold off. Maybe time to look again....
"slate-html-serializer": "0.4.16",
"slate-plain-serializer": "0.4.16",
"slate-react": "0.10.17",
This library is managed with lerna, which will ensure that the sub packages are released all at once and have correct dependencies, but otherwise there is nothing there on the NPM/Yarn end of things to ensure they are installed into a project in sync. You may get some warnings about incompatible versions but that's going to be hit or miss depending on how the package.json in the individual packages specify the dependencies on the other slate libraries.
Typically when I choose versions of slate to use, I find the commit that corresponds to a core library release, and then synchronize all my other packages to that:

https://github.com/ianstormtaylor/slate/commit/c42d84dbf664b96bdbc7c2289a5c246f596009f4
As of https://github.com/ianstormtaylor/slate/pull/3093 (which was just merged), I believe this issue is no longer applicable, because a lot has changed. I'm going through and closing out any potential issues that are not out of date with the overhaul. Thanks for understanding.
I'm sure there are many issues to close out and it might be asking too much to leave more detailed comments on all of them, but it would help if there was a more explicit claim about the changes in the next version that would make something (an issue like this) no longer applicable.
Such as, the serializers are re written, specifically the HtmlSerializer so it no longer throws error on unknown type blocks. Or something similar.
Maybe answering these questions:
the serializers should be completely independent and not be coupled at all (The type used by Plain serializer has to also be known and understood by Html serializer)
Is it true that serializers are more decoupled now?
Hmm, I read this from the #3093. I assume this is what you were referring to. I see this list of things changed and can imagine it's too large to detail all of them, disregard.
Things like slate-plain-serializer, slate-base64-serializer, etc. have been removed and can be implemented in userland easily if needed. Even the slate-html-deserializer can now be implemented in userland (in ~10 LOC leveraging slate-hyperscript
@mattmazzola I think an example is what everyone is looking for. Would definitely help with the "learning curve"
Most helpful comment
@mattmazzola I think an example is what everyone is looking for. Would definitely help with the "learning curve"