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

Replace SyntaxHighlighter with Monaco Editor. #9728

Closed
wants to merge 15 commits into from

Conversation

nojaf
Copy link

@nojaf nojaf commented Mar 21, 2024

Description

This replaces react-syntax-highlighter with @monaco-editor/react.

Motivation and Context

Fixes #3832.

The key motivation for us is to see large response bodies all the time.

How Has This Been Tested?

I've been playing with this manually on my local machine.
The endpoint I'm testing is retrieving 2.8 MB of JSON and it gets instantly rendered in my browser.

Screenshots (if appropriate):

image

Checklist

My PR contains...

  • No code changes (src/ is unmodified: changes to documentation, CI, metadata, etc.)
  • Dependency changes (any modification to dependencies in package.json)
  • [?] Bug fixes (non-breaking change which fixes an issue)
  • Improvements (misc. changes to existing features)
  • Features (non-breaking change which adds functionality)

My changes...

  • are breaking changes to a public API (config options, System API, major UI change, etc).

I'm not quite sure yet what to do with the syntaxHighlight.theme setting. These themes were tied to SyntaxHighlighter and the Monaco editor has different themes out of the box.
Please let know how we can deal with this.

  • are breaking changes to a private API (Redux, component props, utility functions, etc.).
  • are breaking changes to a developer API (npm script behavior changes, new dev system dependencies, etc).
  • are not breaking changes.

Documentation

  • My changes do not require a change to the project documentation.
  • My changes require a change to the project documentation.

I'm not sure here: please tell me.

  • If yes to above: I have updated the documentation accordingly.

Automated tests

  • My changes can not or do not need to be tested.
  • My changes can and should be tested by unit and/or integration tests.
  • If yes to above: I have added tests to cover my changes.
  • If yes to above: I have taken care to cover edge cases in my tests.
  • All new and existing tests passed.

As I'm new to this, I'm not quite sure what needs to be done here. Again, let me know and I'll look into it.

src/core/syntax-highlighting.js Outdated Show resolved Hide resolved
test/unit/components/highlight-code.jsx Show resolved Hide resolved
@heldersepu
Copy link
Contributor

heldersepu commented Mar 21, 2024

https://raw.githack.com/nojaf/swagger-ui/large-bodies/dist/index.html#/pet/findPetsByStatus
I tested your version and I'm not getting the same as your image...

the <div class="highlight-code"> seem to be just a few pixels of height

image

@heldersepu
Copy link
Contributor

heldersepu commented Mar 23, 2024

https://raw.githack.com/nojaf/swagger-ui/large-bodies/dist/index.html#/pet/findPetsByStatus I tested your version and I'm not getting the same as your image...

the <div class="highlight-code"> seem to be just a few pixels of height

@nojaf I think the issue here might be just an old bundle, I added my changes to my branch and the height is fine:
https://raw.githack.com/heldersepu/swagger-ui/test/dist/index.html?docExpansion=None&defaultModelsExpandDepth=None#/pet/findPetsByStatus

@heldersepu
Copy link
Contributor

heldersepu commented Mar 23, 2024

I changed the theme to be dark and disabled the minimap to get as close as possible as it was:

Screenshot from 2024-03-23 19-43-59

simple changes:
45c7631

@nojaf nojaf marked this pull request as ready for review March 25, 2024 08:14
@nojaf
Copy link
Author

nojaf commented Mar 25, 2024

Hi @heldersepu, thank you for the feedback!
I believe I addressed all your remarks.

Any thoughts on what to do with the syntaxHighlight.theme setting?

And could I get the workflow approval?
image

@heldersepu
Copy link
Contributor

@nojaf rebuild the bundles when you can I still can see the old version:
https://raw.githack.com/nojaf/swagger-ui/large-bodies/dist/index.html#/pet/findPetsByStatus

would be nice to integrate the syntaxHighlight.theme into your changes

I'm not in control of the workflow some one from the team should do that

@heldersepu
Copy link
Contributor

@glowcloud & @char0n 👀

@nojaf
Copy link
Author

nojaf commented Apr 3, 2024

Hi @heldersepu, apologies for the delay. I took some time off.
I've rebuilt all bundles.

would be nice to integrate the syntaxHighlight.theme into your changes

Happy to do this, but could use a pointer. Do we care about the existing values?

@heldersepu
Copy link
Contributor

I don't think the existing theme values are compatible with the Monaco editor
test see what happens if an invalid theme is given, maybe there is a way we can provide a default or validate is one of the allowed themes

@nojaf
Copy link
Author

nojaf commented Apr 4, 2024

So, some e2e tests are failing like:

it("should render oneOf property correctly", () => {
cy
.visit("/?url=/documents/bugs/4943.yaml")
.get("#operations-Test-postTest")
.click()
.get(".try-out__btn")
.click()
.get(".microlight")
.contains("<c>\n\t</c>")
})

#4943 XML example not rendered correctly with oneOf -- should render oneOf property correctly (failed)

The problem presumably is in the assertion and might not be an actual problem.

To run this: npm run cy:start and in a different terminal npm run cy:run -- --spec "**/4943.cy.js".

Could I please get some pointers on how to address this?
I have never seen this Cypress thing up close and it is a tad overwhelming.

@nojaf
Copy link
Author

nojaf commented Apr 4, 2024

I don't think the existing theme values are compatible with the Monaco editor

They are not, I've updated the setting to work with the Monaco themes.

@glowcloud & @char0n what are your thoughts on this PR, please?
I'm trying to get a sense of what my chances of getting this merged are.

@heldersepu
Copy link
Contributor

Nice job @nojaf !
regarding the e2e test failing look at the history of the PR that added that see if this is not accidentally reintroducing that bug

@nojaf
Copy link
Author

nojaf commented Apr 10, 2024

Hey everyone 👋,

With the recent changes in #9783, where the highlighting component got extracted, I've been inspired to pivot my approach a bit. I'm now considering focusing my efforts on developing a plugin, rather than continuing to push for my original PR. It's been a few weeks (three, to be exact), and I'm still not sure if there's any appetite for merging my PR.

For those who might come across this thread in the future and are looking to integrate Monaco into SwaggerUI, I've had some success doing so with a plugin approach. Here’s a quick snippet to show you how I managed to hook in Monaco:

import loader from "https://esm.sh/@monaco-editor/loader@1.4.0"

const nojafPlugin = {
  components: {
    SyntaxHighlighter: (props) => {
      const React = props.React;
      const myRef = React.createRef();
      React.useEffect(() => {
        let editor = null;

        const cancelable = loader.init();
        cancelable.then(monaco => {
          if (myRef.current) {
            editor = monaco.editor.create(myRef.current, {
              value: props.children,
              language: props.language
            })
          }
        }).catch(
          (error) =>
            error?.type !== 'cancelation' && console.error('Monaco initialization: error:', error),
        );

        return () => {
          if (cancelable && !myRef.current) {
            cancelable.cancel();
          }

          if (editor) {
            console.log(editor);
            editor.dispose();
          }
        }

      }, [myRef, props.children]);


      // The container needs a height.
      const maxHeight = 450;
      const newLineCount = !props.children ? 0 : (props.children.match(/\n/g)).length
      const proposedHeight = (newLineCount * 14)
      const minHeight = Math.max(100, Math.min(proposedHeight, maxHeight));

      return React.createElement("div", { ref: myRef, style: { minHeight: `${minHeight}px` } }, null);
    }
  }
}

And you can integrate it like so:

window.onload = function() {
  // Build a system
  const ui = SwaggerUIBundle({
    ...,
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl,
      nojafPlugin
    ],
  })

  window.ui = ui

  ui.initOAuth({...})
}

A few key takeaways from my experience:

  • Make sure your script tag includes type=module when using the Monaco loader import.
  • While this component does a decent job, be aware that Monaco's resize quirks haven't been completely ironed out. Still, it's a solid step forward!
  • For an illustrative example, check out 7d1ddec.

I hope this helps someone down the line!

@heldersepu
Copy link
Contributor

@nojaf don't feel discouraged this PR is great, the syntax highlighter was in need of a major refactor...
The team must be busy with other priorities

@heldersepu
Copy link
Contributor

When you can address the:
This branch has conflicts that must be resolved

@char0n
Copy link
Member

char0n commented Apr 10, 2024

Thanks for all the work on this, but we'll not be incorporating this major architectural change into core SwaggerUI. Due to #9783, this can now be approached using the standard SwaggerUI plugin system. More information in #3832 (comment)

I've also created a wiki page with your MonacoEditor plugin - https://github.com/swagger-api/swagger-ui/wiki/Plugins

@char0n char0n closed this Apr 10, 2024
@nojaf
Copy link
Author

nojaf commented Apr 10, 2024

Hi @char0n, thanks for the update and for putting my experiment into the wiki!

@char0n
Copy link
Member

char0n commented Apr 10, 2024

@nojaf it's experiments like these that push the evolution of SwaggerUI forward. Your PR did directly inspire #9783

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

Successfully merging this pull request may close these issues.

Large response bodies cause hanging
3 participants