Netlify-cms: Feature Request: Add ability to register preview script

Created on 12 Aug 2020  路  4Comments  路  Source: netlify/netlify-cms

Is your feature request related to a problem? Please describe.

While trying to generate previews that depend on AlpineJS for interaction, none of my interactions were working. I was able to get the site and content to render just fine. At first I wondered if Alpine didn't work in React for some weird reason (directives?) but was able to proof of concept that working so I was able to isolate the unexpected behavior/problem to the Preview Pane.

Describe the solution you'd like

Because there's a way for CSS to be injected into the iframe document with registerPreviewStyle, it would be great if we could also registerPreviewScript so that libraries like jQuery/Alpine/etc (any non-React lib) could function inside the preview pane. I think I've isolated that down to

  • Edit registry.js#L59-L80 to allow collecting registered scripts
  • Edit EditorPreviewPane.js#L188-L233 to loop through registered scripts and put them somewhere (footer by default? maybe the register function needs a placement option?)
  • Write tests

Describe alternatives you've considered

  • Including Alpine in the admin/index.html doesn't work because Alpine needs to be available in the iframe document.
  • Inlining a script tag in the Preview Template doesn't work. (security feature?)
  • Injecting a script tag from within the Preview Template using componentDidMount doesn't work, it only appends it to the parent document (because I think that's the prior context?)

Additional context

I started a thread on the forums with more detail, some reduced test cases, etc. and was told to file an issue here.

extensionpreview-templates feature

All 4 comments

Thanks for opening this @davatron5000 and for the detailed description in the community.

  • Injecting a script tag from within the Preview Template using componentDidMount doesn't work, it only appends it to the parent document (because I think that's the prior context?)

I would expect this to work. Maybe it shouldn't actually due to security reasons.

Do you mind sharing a repo with your setup (especially with the componentDidMount one) so I can try to reproduce and dig into this a little bit?

I wonder if we can pass in as props the frame window and document as specified here:
https://github.com/ryanseddon/react-frame-component#accessing-the-iframes-window-and-document

That would allow much more flexibility.

Update:
Please let me know if this resembles your reproduction:
https://github.com/erezrokah/netlify-cms-reproductions/blob/64c4a86a91366f899a9022b2d7c19a8f9d98c047/public/index.html#L17

Yup! That's pretty much it!

class Preview extends React.Component {
  componentDidUpdate() {
    const script = document.createElement('script')
    script.src = 'https://unpkg.com/[email protected]/dist/alpine.js'
    document.head.appendChild(script)
  }

  render() {
    const html = `
      <div x-data="{ open: false }">
        <button x-on:click="open = true">Open Dropdown</button>

        <ul x-show="open" x-on:click.away="open = false">
          Dropdown Body
        </ul>
      </div>
    `;
    return (
      <div dangerouslySetInnerHTML={{ __html: html }}></div> 
    )
  }
}

It's my first exposure to react-frame-component so not sure how the window and document traversal stuff works. But if you think it can be done via componentDidMount, then that's probably the easiest way to resolve this without a new registry.

WOW. Thanks so much for the help on this! This is incredible.

Was this page helpful?
0 / 5 - 0 ratings