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

How import Codemirror.Next in NextJS #277

Closed
jefer94 opened this issue Aug 28, 2020 · 7 comments
Closed

How import Codemirror.Next in NextJS #277

jefer94 opened this issue Aug 28, 2020 · 7 comments

Comments

@jefer94
Copy link

jefer94 commented Aug 28, 2020

Next: https://nextjs.org/

My code

import React, { useRef, useEffect, useState, ReactElement } from 'react'
import styled from 'styled-components'
import { EditorView } from '@codemirror/next/view'
import { EditorState } from '@codemirror/next/state'
import { lineNumbers } from '@codemirror/next/gutter'
import { defaultKeymap } from '@codemirror/next/commands'
import { javascript } from '@codemirror/next/lang-javascript'
import { oneDark } from '@codemirror/next/theme-one-dark'
// import { UnControlled as CodeMirror } from 'react-codemirror2'

// const Div = styled.div`
//   & > div {
//     height: ${(v) => v.height};
//     max-height: ${(v) => v.height};
//     outline: 0!important;
//     background-color: ${(v) => v.theme.surface};
//     color: ${(v) => v.theme.white};
//     font-size: ${(v) => v.theme.fontSize};
//     padding-left: 15px;
//   }
// `

type Props = {
  readonly className?: string
  readonly content: string
}

function CodemirrorWrapperBase({ className, content }: Props): ReactElement {
  const [loading, setLoading] = useState(true)
  const div = useRef<HTMLHeadingElement>()
  const editor = useRef<EditorView>()

  useEffect(() => {
    if (loading) {
      // eslint-disable-next-line functional/immutable-data
      editor.current = new EditorView({
        state: EditorState.create({
          doc: content,
          extensions: [lineNumbers(), javascript(), oneDark]
        }),
        dispatch: (v) => console.log('xxxxxxxxxx', v)
        // extensions: [keymap(defaultKeymap)]
        // extensions: []
        // extensions: [keymap(defaultKeymap), new GutterMarker()]
      })
      setLoading(false)
    }

    else if (div && div.current && editor.current) div.current.appendChild(editor.current.dom)
  }, [loading])

  return (
    <div className={className} ref={div} />
    // <CodeMirror
    //   value="<h1>I ♥ react-codemirror2</h1>"
    //   options={{
    //     mode: 'xml',
    //     theme: 'material',
    //     lineNumbers: true
    //   }}
    //   onChange={(editor, data, value) => {
    //     console.log(value)
    //   }}
    // />
  )
}

type CodemirrorWrapperProps = {
  readonly height: string
}

export const CodemirrorWrapper = styled(CodemirrorWrapperBase)`
  & > div {
    height: ${(v: CodemirrorWrapperProps) => v.height};
    max-height: ${(v: CodemirrorWrapperProps) => v.height};
    outline: 0!important;
    background-color: ${(v) => v.theme.surface};
    color: ${(v) => v.theme.white};
    font-size: ${(v) => v.theme.fontSize};
    padding-left: 15px;
  }

Error

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /node_modules/@codemirror/next/view/dist/index.js 
require() of ES modules is not supported.
require() of /node_modules/@codemirror/next/view/dist/index.js from /.next/server/static/development/pages/index.js is an ES module file as it is a .js file whose nearest parent package.
json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename /node_modules/@codemirror/next/view/dist/index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /node_modules/@codemirror/next/view/package.json.

Next internally use Webpack, it only support CommonJS, but the dist folder is ES6, exist one example how use Codemirror.Next with NextJS or Webpack?

@curran
Copy link
Contributor

curran commented Aug 28, 2020

Greetings,

I did some experiments when this repository was very young and I did manage to server render CodeMirror with syntax highlighting. Here's the code if it might be useful https://github.com/datavis-tech/codemirror-6-experiments/tree/master/packages/experiments/src/pages/pad

Writeup: https://medium.com/@currankelleher/codemirror-6-experiments-a3930bf03781

I'm not sure about the Next-specific details, but this may help. Good luck!

@mischnic
Copy link

I think this happens because Next tries to run codemirror in a Node environment, and Node.js's require() function doesn't work with pure ESM packages (so it's not related to Webpack at all).

@jefer94
Copy link
Author

jefer94 commented Aug 28, 2020

Exist one way that one project with require() can load a pure ESM package? I trie build one CommonJS wrapper ( https://github.com/jefer94/choco/tree/master/packages/codemirror ), one build with ( https://github.com/jefer94/choco/blob/master/services/algorithm/package.json ) ( this horrible script https://github.com/jefer94/choco/blob/master/scripts/development/prepare.js )

I clone my Codemirror in one Yarn Workspace

But this error appear

view/src/inlineview.ts(74,61): error TS2339: Property 'text' does not exist on type 'InlineView'.
view/src/blockview.ts(35,48): error TS2339: Property 'attrs' does not exist on type 'BlockView'.
view/src/blockview.ts(49,59): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
  Type 'ContentView' is missing the following properties from type 'InlineView': merge, match, slice, getSide
view/src/blockview.ts(53,29): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(65,46): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(68,47): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(73,58): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(76,115): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(82,71): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
view/src/blockview.ts(86,69): error TS2345: Argument of type 'ContentView' is not assignable to parameter of type 'InlineView'.
 // inlineview.ts
export abstract class InlineView extends ContentView {
  ...
  match(_other: InlineView) { return false } // inlineview.ts line 13
}
// contentview.ts
export abstract class ContentView {
  ...
  abstract children: ContentView[] // contentview.ts line 21
  ...
}
export interface BlockView extends ContentView {
   ...
}
// blockview.ts
export class LineView extends ContentView implements BlockView {
  children: InlineView[] = []
  ...
  let elts = source ? source.children : [] // blockview.ts line 37
  ...
  merge(from: number, to: number, source: BlockView | null, takeDeco: boolean): boolean {
    ...
    // Then try to merge any mergeable nodes at the start and end of
    // the changed range
    while (fromI < toI && elts.length && this.children[toI - 1].match(elts[elts.length - 1])) { // blockview.ts line 82
      elts.pop()
      toI--
    }
    ...
  }
}

That is all I collect about this error

interface BlockView extends ContentView { // blockview.ts line 11
  ..
}

class LineView extends ContentView implements BlockView { // blockview.ts line 21
  ///
}

@marijnh
Copy link
Member

marijnh commented Aug 28, 2020

This package only exposes ES6 modules, which you can import in node 13+, but you can't require. As such, until other tools catch up with the brace new ES6 module world, I guess you'll have to run something like Rollup in between if you want to use CodeMirror with those tools.

@marijnh marijnh closed this as completed Aug 28, 2020
@jefer94
Copy link
Author

jefer94 commented Aug 29, 2020

But ESM support CommonJS modules, why use ESM output instead of CommonJS output? well i still for the NextJS ESM support

@MatthewCaseres
Copy link

vercel/next.js#9607
Might want to try some of the workarounds described here.

@OriginalEXE
Copy link

I got it working by using the next-transpile-modules package. Here is an example of the next.js config for @codemirror/basic-setup + @codemirror/lang-json:

const withTM = require('next-transpile-modules')([
  '@codemirror/basic-setup',
  '@codemirror/autocomplete',
  '@codemirror/closebrackets',
  '@codemirror/commands',
  '@codemirror/comment',
  '@codemirror/fold',
  '@codemirror/gutter',
  '@codemirror/highlight',
  '@codemirror/history',
  '@codemirror/language',
  '@codemirror/lint',
  '@codemirror/matchbrackets',
  '@codemirror/panel',
  '@codemirror/rangeset',
  '@codemirror/rectangular-selection',
  '@codemirror/search',
  '@codemirror/state',
  '@codemirror/text',
  '@codemirror/tooltip',
  '@codemirror/view',
  '@codemirror/lang-json',
]);

module.exports = withTM();

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

6 participants