Describe the bug
I've added custom editor component:
javascript
CMS.registerEditorComponent({
id: "youtube",
label: "Youtube",
fields: [{name: 'id', label: 'Youtube Video ID', widget: 'string'}],
pattern: /^<div class="yo-youtube"><iframe src="\/\/www.youtube.com\/embed\/(.*)" frameborder="0" allowfullscreen><\/iframe><\/div>/,
fromBlock: function(match) {
console.log(match)
return {
id: match[1]
};
},
toBlock: function(obj) {
return (
`<div class="yo-youtube"><iframe src="//www.youtube.com/embed/${obj.id}" frameborder="0" allowfullscreen></iframe></div>`
);
},
toPreview: function(obj) {
return (
`<div class="yo-youtube"><iframe src="//www.youtube.com/embed/${obj.id}" frameborder="0" allowfullscreen></iframe></div>`
);
}
});
I works well when I add widget in markdown. But if I save and reopen entity or switch to markdown and back to rich text , it is displayed as html, not as widget
Expected behavior
It should be displayed as widget, not as html
Screenshots
screenshot
Applicable Versions:
I think this is the same problem as https://github.com/netlify/netlify-cms/issues/1044
Basically only simple text paragraphs without markdown or inline HTML can be matched by editor components. At present custom components are only really suited for hooking into simple shortcode-like syntax.
text paragraphs without markdown or inline HTML can be matched by editor components.
Hmm...here is an example with inline HTML and it works like a charm
CMS.registerEditorComponent({
id: "sidenote",
label: "Sidenote",
fields: [{
name: 'element',
label: 'In-Text Element',
widget: 'string'
}, {
name: 'sidenote',
label: 'Sidenote',
widget: 'markdown'
}],
pattern: /^<span class="sidenote"><span class="sidenote__toggle">(.*)<\/span><span class="sidenote__note">(.*)<\/span><\/span>/,
fromBlock: function(match) {
return {
element: match[1],
sidenote: match[2],
};
},
toBlock: function(obj) {
return (
'<span class="sidenote"><span class="sidenote__toggle">' + obj.element + '</span><span class="sidenote__note">' + obj.sidenote + '</span></span>'
);
},
toPreview: function(obj) {
return (
'<span class="sidenote"><span class="sidenote__toggle">' + obj.element + '</span><span class="sidenote__note">' + obj.sidenote + '</span></span>'
);
},
});
this is really weird
if i replace span with div in example above, it breaks
this is really weird
if i replace span with div in example above, it breaks
I guess this is because netlify breaks up the source into chunks ("lines") and might be creating separate chunks for each block level html element (and not for inline elements like span, img…). The regex that is using your specified pattern matches only individual chunks, not the whole body, so as soon as your regex would have to match across chunks, it will not work anymore.
The reason given is that this is for performance reasons – which I understand, but it might be nice to disable this performance-tweak on a per-component basis? One could still be smart about regexing by optimizing how to check for multiple matches…
This is a major deal breaker, since this makes it impossible to use netlify-cms for any serious sites – custom blocks fail for simple things like multi column setups…
Thanks for clarification!
found a solution to that. I create my editor component in React and stringify it.
the stringified component also has to match the 'pattern' regex. here's how:
import React from 'react';
import { renderToString } from 'react-dom/server';
import CMS from 'netlify-cms-app';
const TravelQuote = (props) => {
const authorIsAnonymous = authorName && authorName.toLowerCase() === 'anonymous';
const authorImg = props.authorPic ? props.authorPic : ""; // src needs to exist *
// * the React components automatically removes the src attr if
// its attribute is undefined when it creates it.
// With no src though, the component structur won't match the regex.
return (
`<div class="travel-quote">
<p class="travel-quote__copy">{props.quote}</p>
<span class="travel-quote__author">{props.authorName}</span>
<img class="travel-quote__author-pic" src={authorImg} alt={props.authorName} />
</div>`
)
}
// create string from component to create the regex
// for CMS.registerEditorComponent 'pattern'
const patternString = renderToString(
`
<TravelQuote
quote='(.*)'
authorName='(.*)'
authorPic='(.*)'/>
`
);
// create the regex
const travelQuoteRegex = new RegExp(patternString.replace(/\//g, '\\/'));
CMS.registerEditorComponent({
id: "travelQuote",
label: "Travel quote",
fields: [
{ name: 'quote', label: 'Quote', widget: 'string' },
{ name: 'authorName', label: 'Author name', widget: 'string' },
{ name: 'authorPic', label: 'Author picture', widget: 'image' },
],
pattern: travelQuoteRegex,
fromBlock: function(match) {
return {
quote: match[1],
authorName: match[2],
authorPic: match[3],
};
},
toBlock: function(obj) {
return renderToString(
`<TravelQuote
quote={obj.quote}
authorName={obj.authorName}
authorPic={obj.authorPic} />`
)
},
toPreview: function(obj) {
return renderToString(
`<TravelQuote
quote={obj.quote}
authorName={obj.authorName}
authorPic={obj.authorPic} />`
)
},
});
// Note: renderToString() works only if the project is runned with the Production
// environment, with gatsby build and gatsby serve.
Most helpful comment
I guess this is because netlify breaks up the source into chunks ("lines") and might be creating separate chunks for each block level html element (and not for inline elements like span, img…). The regex that is using your specified pattern matches only individual chunks, not the whole body, so as soon as your regex would have to match across chunks, it will not work anymore.
The reason given is that this is for performance reasons – which I understand, but it might be nice to disable this performance-tweak on a per-component basis? One could still be smart about regexing by optimizing how to check for multiple matches…
This is a major deal breaker, since this makes it impossible to use netlify-cms for any serious sites – custom blocks fail for simple things like multi column setups…
1044 Same issue