我正在尝试将codemirror 6(包括

问题描述 投票:0回答:1
i目前在Nicegui v2.0.0,Python 3.12.7,Node v22.13.1和NPM v11.0.0.

这就是我的目录的样子:

nicegui-codemirror-minimal/
├── dist/
│   └── codemirror-bundle.js
├── node_modules/
│   └── ...
├── codemirror_editor.js
├── codemirror_editor.py
├── main.py
├── package.json
├── package-lock.json
└── webpack.config.js
这是我的

package.json

{ "name": "nicegui-codemirror-minimal-test", "version": "1.0.0", "description": "", "main": "codemirror_editor.js", "scripts": { "build": "webpack --config webpack.config.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@codemirror/commands": "^6.4.0", "@codemirror/lang-markdown": "^6.2.4", "@codemirror/merge": "^6.0.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.25.4", "codemirror": "^6.0.1" }, "devDependencies": { "@babel/core": "^7.24.5", "@babel/preset-env": "^7.24.5", "babel-loader": "^9.1.3", "webpack": "^5.91.0", "webpack-cli": "^5.1.4", "vue": "^3.4.21" } }

这是我的

webpack.config.js

const path = require("path"); module.exports = { entry: "./codemirror_editor.js", mode: "development", output: { path: path.resolve(__dirname, "dist"), filename: "codemirror-bundle.js", library: "CodeMirrorEditor", libraryTarget: "window", globalObject: 'this', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, ], }, };

这是我的
codemirror_editor.js

import { EditorView, basicSetup } from "codemirror";
import { EditorState } from "@codemirror/state";
import { markdown } from "@codemirror/lang-markdown";
import { MergeView } from "@codemirror/merge";
import { keymap } from "@codemirror/view";
import { defaultKeymap } from "@codemirror/commands";
import { nextTick } from 'vue';

export default {
  template: `
    <div style="display: flex; gap: 1em;">
      <div ref="editorA" style="flex: 1; border: 1px solid #ddd;"></div>
      <div ref="editorB" style="flex: 1; border: 1px solid #ddd;"></div>
    </div>
  `,
  mounted() {
    nextTick(() => {
      setTimeout(() => {
        const initialValueA = this.value_a || "";
        const initialValueB = this.value_b || "";

        this.mergeView = new MergeView({
          a: {
            doc: initialValueA,
            extensions: [
              basicSetup,
              markdown(),
              EditorView.editable.of(true),
              keymap.of(defaultKeymap),
              EditorView.updateListener.of((update) => {
                if (update.docChanged) {
                  this.sendUpdate('a', update.state.doc.toString());
                }
              })
            ],
          },
          b: {
            doc: initialValueB,
            extensions: [
              basicSetup,
              markdown(),
              EditorView.editable.of(true),
              keymap.of(defaultKeymap),
              EditorView.updateListener.of((update) => {
                if (update.docChanged) {
                  this.sendUpdate('b', update.state.doc.toString());
                }
              }),
            ],
          },
          parent: this.$refs.editorA.parentElement,
          root: document,
        });
      }, 0);
    });
  },
  methods: {
    sendUpdate(side, value) {
      this.$emit('update-value', { side, value });
    },
    setValue(side, value) {
      const editor = side === 'a' ? this.mergeView.a : this.mergeView.b;
      const tr = editor.state.update({
        changes: { from: 0, to: editor.state.doc.length, insert: value }
      });
      editor.dispatch(tr);
    },
  },
  props: {
    value_a: String,
    value_b: String,
  },
  beforeDestroy() {
    this.mergeView.destroy();
  }
};

这是我的
codemirror_editor.py

from nicegui import ui
from typing import Callable, Optional

class CodeMirrorEditor(ui.element, component='codemirror_editor.js', dependencies=['dist/codemirror-bundle.js']):

    def __init__(self,
                 value_a: str = "",
                 value_b: str = "",
                 on_change_a: Optional[Callable] = None,
                 on_change_b: Optional[Callable] = None
                 ) -> None:
        super().__init__()
        self._props['value_a'] = value_a
        self._props['value_b'] = value_b
        self.on_change_a = on_change_a
        self.on_change_b = on_change_b
        self.on('update-value', self.handle_change)

    def handle_change(self, event):
        side = event.args['side']
        value = event.args['value']
        if side == 'a':
            self._props['value_a'] = value
            if self.on_change_a:
                self.on_change_a(value)
        elif side == 'b':
            self._props['value_b'] = value
            if self.on_change_b:
                self.on_change_b(value)
        self.update()

    def set_value(self, side: str, value: str):
        if side not in ('a', 'b'):
            raise ValueError("side must be 'a' or 'b'")
        self.run_method('setValue', side, value)

    @property
    def value_a(self) -> str:
        return self._props['value_a']

    @value_a.setter
    def value_a(self, value: str) -> None:
        self._props['value_a'] = value
        self.set_value('a', value)
        self.update()

    @property
    def value_b(self) -> str:
        return self._props['value_b']

    @value_b.setter
    def value_b(self, value: str) -> None:
        self._props['value_b'] = value
        self.set_value('b', value)
        self.update()

这是我的
main.py

from nicegui import ui
from codemirror_editor import CodeMirrorEditor

@ui.page('/')
async def page():  # Must be async
    editor = CodeMirrorEditor(value_a="# Initial A", value_b="Initial B")
    # That's it! No other UI elements or callbacks.

ui.run()

这就是我的浏览器的样子:
浏览器图像带有错误

count某人可以帮助我理解为什么我会遇到此模块分辨率错误以及如何解决?我遵循了Nicegui文档进行节点模块集成,但是我显然缺少一些东西。关于WebPack配置,
codemirror_editor.js

中的模块导入或任何其他潜在问题的任何建议将不胜感激!
#########################
因此,我已经意识到我的入口点可能是错误的,因为它指向

webpack.config.js

而不是
codemirror_editor.js

中的实际软件包(就像捆绑的节点集成示例中一样)。 同样,我尝试修改我的
node_modules
不做

codemirror_editor.js,而是做import { MergeView } from "@codemirror/merge";

。这已解决了我的相对文件问题,现在我可以看到

await import

正在将网络上传到我的网络中,
merge.js

以前,我只能看到

codemirror_editor.js

。但是,

codemirror_editor.js

显示404误差。控制台输出是以下(我的浏览器页面仍然为空白):
get
Http://127.0.0.1:8080/dist/merge.js
Net:: err_aborted 404(找不到)

我相信这是因为在我的
merge.js
文件中,他们找不到我的
codemirror_editor.js
。我似乎不明白为什么。我也更简单,只安装了NPM。因此,基本上,如果我进行静态导入,我会发现相对路径问题,但是如果我等待进口,我会得到上述问题。
,我的文件如下:
这个是我的同一目录:
merge.js
这是我的

@codemirror/merge

nicegui-codemirror-minimal/ ├── dist/ │ ├── merge.js │ ├── state.js │ └── view.js ├── node_modules/ │ └── ... ├── codemirror_editor.js ├── codemirror_editor.py ├── main.py ├── package.json ├── package-lock.json └── webpack.config.js 这是我的

package.json

{
  "scripts": {
    "build": "webpack --config webpack.config.js"
  },
  "dependencies": {
    "@codemirror/merge": "^6.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.24.5",
    "@babel/preset-env": "^7.24.5",
    "babel-loader": "^9.1.3",
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  }
}
这是我的
codemirror_editor.js

let mergeViewInstance; export default async function createCodeMirrorEditor(element, props) { const initialValueA = props.value_a || ""; const initialValueB = props.value_b || ""; // Dynamically import CodeMirror modules const { MergeView } = await import("/dist/merge.js"); const { EditorView } = await import("/dist/view.js"); const { EditorState } = await import("/dist/state.js"); mergeViewInstance = new MergeView({ a: { doc: initialValueA, extensions: [ EditorView.editable.of(true), // Removed other extensions for simplicity - you can add them back if needed EditorView.updateListener.of((update) => { if (update.docChanged) { sendUpdate('a', update.state.doc.toString()); } }), ], }, b: { doc: initialValueB, extensions: [ EditorView.editable.of(true), // Removed other extensions for simplicity - you can add them back if needed EditorView.updateListener.of((update) => { if (update.docChanged) { sendUpdate('b', update.state.doc.toString()); } }), ], }, parent: element, root: document, }); function sendUpdate(side, value) { element.dispatchEvent(new CustomEvent('update-value', { detail: { side, value } })); } function setValue(side, value) { const editor = side === 'a' ? mergeViewInstance.a : mergeViewInstance.b; const transaction = editor.state.update({ changes: { from: 0, to: editor.state.doc.length, insert: value } }); editor.dispatch(transaction); } return { setValue: setValue, destroy: () => { mergeViewInstance.destroy(); } }; }

这是我的

codemirror_editor.py

from nicegui import ui from typing import Callable, Optional class CodeMirrorEditor(ui.element, component='codemirror_editor.js', dependencies=[ 'dist/merge.js', 'dist/view.js', 'dist/state.js', ]): def __init__(self, value_a: str = "", value_b: str = "", on_change_a: Optional[Callable] = None, on_change_b: Optional[Callable] = None ) -> None: super().__init__() self._props['value_a'] = value_a self._props['value_b'] = value_b self.on_change_a = on_change_a self.on_change_b = on_change_b self.on('update-value', self.handle_change) def handle_change(self, event): side = event.args['detail']['side'] value = event.args['detail']['value'] if side == 'a': self._props['value_a'] = value if self.on_change_a: self.on_change_a(value) elif side == 'b': self._props['value_b'] = value if self.on_change_b: self.on_change_b(value) self.update() def set_value(self, side: str, value: str): if side not in ('a', 'b'): raise ValueError("side must be 'a' or 'b'") self.run_method('setValue', side, value) @property def value_a(self) -> str: return self._props['value_a'] @value_a.setter def value_a(self, value: str) -> None: self._props['value_a'] = value self.set_value('a', value) self.update() @property def value_b(self) -> str: return self._props['value_b'] @value_b.setter def value_b(self, value: str) -> None: self.props['value_b'] = value self.set_value('b', value) self.update()

    

我不熟悉python,但是当我运行此
example
时,我发现了一个问题。 您应该预先编译所有必需的依赖项,例如:

webpack.config.js

此WebPack配置捆绑了CodeMirror模块,运行
const path = require("path");

module.exports = {
  entry: {
    merge: "@codemirror/merge",
    view: "@codemirror/view",
    state: "@codemirror/state",
  },
  mode: "development",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].js",
    library: "CodeMirrorMerge",
    libraryTarget: "umd",
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
};
,然后您可以这样使用:

// webpack.config.js
const path = require("path");

module.exports = {
  entry: "codemirror", // Search in the node_modules folder for modules
  mode: "development",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "codemirror.js", // Bundled module file name
    library: "codemirror", // Module name
    libraryTarget: "umd",
  },
  // ...
};

该字段指定此组件所需的所有依赖关系,您现在可以在
npm run build
.

中使用codemirror。

发生了什么?答案在于生成的HTML内容。导航到DevTools网络选项卡,然后查看HTML内容 - 您会注意到它包含一个类似的字符串:

# codemirror_editor.py from nicegui import ui from typing import Callable, Optional class CodeMirrorEditor(ui.element, component='codemirror_editor.js', dependencies=['dist/codemirror.js']): # ...
webpack npm-package codemirror-6
1个回答
0
投票
定义了一组模块映射,将特定模块路径与名称相关联(webpack.config#output.library),使您可以使用该名称直接导入它。 您可以查看此

Playground(非功能,仅作为DIFF比较的参考)

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.