Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom editor components cannot contain multiple pattern matches when using non-inline html tags #3490

Closed
apolopena opened this issue Mar 28, 2020 · 1 comment

Comments

@apolopena
Copy link

apolopena commented Mar 28, 2020

Custom editor components are an awesome feature however the documentation for CMS.registerEditorComponent is very brief so I need to ask the question here. Please correct me if I am wrong but actually implementing anything more complex than the example...

CMS.registerEditorComponent({
  // Internal id of the component
  id: "youtube",
  // Visible label
  label: "Youtube",
  // Fields the user need to fill out when adding an instance of the component
  fields: [{name: 'id', label: 'Youtube Video ID', widget: 'string'}],
  // Pattern to identify a block as being an instance of this component
  pattern: /^youtube (\S+)$/,
  // Function to extract data elements from the regexp match
  fromBlock: function(match) {
    return {
      id: match[1]
    };
  },
  // Function to create a text block from an instance of this component
  toBlock: function(obj) {
    return 'youtube ' + obj.id;
  },
  // Preview output for this component. Can either be a string or a React component
  // (component gives better render performance)
  toPreview: function(obj) {
    return (
      '<img src="http://img.youtube.com/vi/' + obj.id + '/maxresdefault.jpg" alt="Youtube Video"/>'
    );
  }
});

Such as needing to make multiple matches in some nested non-inline html tags
makes you run up against #1806 which is a basically a showstopper.

In my case I have a React component that conditionally renders html in a general pattern like this

<blockquote><p><small>FIRST MATCH GOES HERE<cite>SECOND MATCH GOES HERE  <a href="THIRD MATCH GOES HERE" target="_blank" rel="noopener noreferrer">CONTINUATION OF THE SECOND MATCH HERE</a></cite></small></p></blockquote>

I can match the first section but not more than that. Is there anyway for me to look the entire string I am trying to run my multi matching regex against? I feel like I am flying blind here so I will shelf my efforts on this front until I can figure out how to at least look at the 'block/chunk/body' or whatever it is that the regexp pattern is trying to match. Is there a way to output that?

Perhaps what I am trying to do is just not possible, if so perhaps the documentation could be updated to reflect the limitations of working with CMS.registerEditorComponent or updated to include more information about the blocks and pattern matching?

Thanks.

@apolopena apolopena changed the title Custom editor components cannot contain multipe pattern matches when using non-inline html tags Custom editor components cannot contain multiple pattern matches when using non-inline html tags Mar 28, 2020
@apolopena
Copy link
Author

I realized that my actual issue was more that I was unsure on how to match more than one field in the block, mostly because I wasn't sure what the entire block looked like. Since the matches only showed a portion of the block, I was flying blind and could only match the first field of a component. I still don't know how to see the entire block but when digging around the existing issues in the repo I did come across a way to match each field in a component block and I modified that to my needs. However this approach does trigger a Sent invalid data to remark. Plugin: smartcaption. ... warning from react_devtools_backend.js:6 but it appears to be benign. This is what ended up working out for me, allthough its not super performant, it serves my use-case well enough.

CMS.registerEditorComponent({
  // Internal id of the component
  id: "smartcaption",
  // Visible label
  label: "SmartCaption",
  // Fields the user need to fill out when adding an instance of the component
  fields: [
    {
      name: 'caption', 
      widget: 'string', 
      required: true,
      default: ' ', /* white space placeholder allows for a placeholder message in the preview */
      hint: 'Required: A description.',
    },
    {
      name: 'credit', 
      widget: 'string', 
      default: ' ',
      hint: 'Optional: A citation to be appended to the caption.'
    }
  ],
   // Pattern to identify a block as being an instance of this component
  pattern: /{"widget":"smartcaption","caption":"(.*)","credit":"(.*)?"}/,
  // Function to extract data elements from the regexp match
  fromBlock: function(match) {
    // remove leading space
    const caption = match[1] ? match[1].replace(/^\s+/,'') : null
    const credit = match[2] ? match[2].replace(/^\s+/,'') : null
    /*
    console.log(`caption=${caption}`)
    console.log(`credit=${credit}`)
    */
    return {
      caption, 
      credit,
    };
  },
  // Function to create a text block from an instance of this component
  toBlock: function(obj) {
    const data = JSON.stringify({
			widget: 'smartcaption',
			caption: obj.caption,
			credit: obj.credit,
    });
    return data
  },
  // Preview output for this component. Can either be a string or a React component
  // (component gives better render performance)
  toPreview: function(obj) {
    if (obj.caption === '') obj.caption = 'CAPTION PLACEHOLDER'
    return (
      <SmartCaption credit={obj.credit}>{obj.caption}</SmartCaption>
    );
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant