微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将 Javascript 导出类转换为 Kotlin/JS? 无法解决obsidian对多个 @JsModule 声明进行分组Kotlin 的 ES5 与 Obsidian 的 ES6

如何解决如何将 Javascript 导出类转换为 Kotlin/JS? 无法解决obsidian对多个 @JsModule 声明进行分组Kotlin 的 ES5 与 Obsidian 的 ES6

我是 JS 和 Kotlin/JS 的新手。我从示例中为 Obsidian插件提供了以下最少的工作 Javascript 代码。它按预期工作:

var obsidian = require('obsidian');
class SomePlugin extends obsidian.Plugin {
    onload() {
        new obsidian.Notice('This is a notice!');
    }
}
module.exports = Plugin;

我希望使用 Kotlin 来扩展这个插件,因为我知道这门语言,但是我在将它转换为 Kotlin/JS 时遇到了一些问题。到目前为止我的方法

可以在 here on Github 中找到可运行的项目。运行 gradle build生成构建文件夹。它会在浏览器步骤中失败,但该步骤不是必需的。构建后生成的js文件可以在build\js\packages\main\kotlin\main.js中找到。

main.kt

@JsExport
class SomePlugin: Plugin() {
    override fun onload() {
        Notice("This is a notice!")
    }
}
@JsModule("obsidian")
@JsNonModule // required by the umd moduletype
external open class Component {
    open fun onload()
}
@JsModule("obsidian")
@JsNonModule
external open class Plugin : Component {
}
@JsModule("obsidian")
@JsNonModule
external open class Notice(message: String,timeout: Number = definedExternally) {
    open fun hide()
}

编辑:感谢@S.Janssen 的评论,我将模块类型切换为 umd

build.gradle.kts

plugins {
    kotlin("js") version "1.5.20"
}
group = "de.example"
version = "1.0-SNAPSHOT"
repositories {
    mavenCentral()
}
dependencies {
    implementation(npm("obsidian","0.12.5",false))
}
kotlin {
    js(IR) {
        binaries.executable()
        browser {
            webpackTask {
                output.libraryTarget = "umd"
            }
        }
    }
}

tasks.withType<KotlinjsCompile>().configureEach {
    kotlinoptions.moduleKind = "umd"
}

我实际上并不需要可以在 browser 中运行的结果,但是如果没有 browser 定义,它甚至不会生成 js 文件。对于 browser 部分,会抛出一个异常,表示 Can't resolve 'obsidian' in 'path\kotlin'。但至少在 build/js/packages/test/kotlin/test.js 下创建了一个 .js 文件。然而,该代码与我预期的代码完全不同,也不被黑曜石接受为有效的插件代码。我还尝试了其他一些 gradle 选项。像“umd”、“amd”、“plain”、传统编译器而不是 IR、nodejs 而不是浏览器。但是没有任何东西可以创建可运行的 js 文件错误信息不同。使用旧版编译器时,它需要 kotlin.js 文件,即使我将它放在文件夹旁边或将内容复制到脚本中,它也找不到。

如何获得与上面发布的 Javascript 代码功能类似的代码?我知道它会有开销,但目前生成代码根据我的理解甚至没有定义或导出我的类。

我从 obisidan 调试器得到的错误信息:

Plugin failure: obsidian-sample-plugin TypeError: Object prototype may only be an Object or null: undefined

生成代码

    (function (root,factory) {
  if (typeof define === 'function' && define.amd)
    define(['exports','obsidian','obsidian'],factory);
  else if (typeof exports === 'object')
    factory(module.exports,require('obsidian'),require('obsidian'));
  else {
    if (typeof Component === 'undefined') {
      throw new Error("Error loading module 'main'. Its dependency 'obsidian' was not found. Please,check whether 'obsidian' is loaded prior to 'main'.");
    }if (typeof Plugin === 'undefined') {
      throw new Error("Error loading module 'main'. Its dependency 'obsidian' was not found. Please,check whether 'obsidian' is loaded prior to 'main'.");
    }if (typeof Notice === 'undefined') {
      throw new Error("Error loading module 'main'. Its dependency 'obsidian' was not found. Please,check whether 'obsidian' is loaded prior to 'main'.");
    }root.main = factory(typeof main === 'undefined' ? {} : main,Component,Plugin,Notice);
  }
}(this,function (_,Notice) {
  'use strict';
  SomePlugin.prototype = Object.create(Plugin.prototype);
  SomePlugin.prototype.constructor = SomePlugin;
  function Unit() {
    Unit_instance = this;
  }
  Unit.$Metadata$ = {
    simpleName: 'Unit',kind: 'object',interfaces: []
  };
  var Unit_instance;
  function Unit_getInstance() {
    if (Unit_instance == null)
      new Unit();
    return Unit_instance;
  }
  function SomePlugin() {
    Plugin.call(this);
  }
  SomePlugin.prototype.onload_sv8swh_k$ = function () {
    new Notice('This is a notice!');
    Unit_getInstance();
  };
  SomePlugin.prototype.onload = function () {
    return this.onload_sv8swh_k$();
  };
  SomePlugin.$Metadata$ = {
    simpleName: 'SomePlugin',kind: 'class',interfaces: []
  };
  _.somePlugin = SomePlugin;
  return _;
}));

解决方法

您可以找到一个工作示例来说明您要做什么here我将逐一介绍需要对您的代码进行的一些更改-此回复中的一个。

无法解决obsidian

Can't resolve 'obsidian' in 'path\kotlin' 的出现是因为 obsidian-api 包不是一个独立的库。相反,它只包含一个 obsidian.d.ts 文件,它是一个 TypeScript 声明文件。与其他语言的头文件类似,这个头文件不提供任何实现,而只提供库的签名和类型——这意味着 Kotlin/JS 的 webpack(或任何 JavaScript 工具,就此而言)将无法解决实际的实现。这是意料之中的,可以通过将模块声明为 external 来解决。为此,请在 Kotlin/JS 中创建一个名为 webpack.config.d 的目录,并添加一个包含以下内容的文件 01.externals.js

config.externals = {
    obsidian: 'obsidian',};

(您实际上也可以在官方 sample-plugin configuration 中找到等效的代码段,因为这不是 Kotlin/JS 特定问题)

对多个 @JsModule 声明进行分组

因为您要从同一个包中导入多个声明,而不是用 @JsModule / @JsNonModule 注释多个签名,所以您必须创建一个单独的文件,并用 {{1 注释它}} / @file:@JsModule("...")

@file:JsNonModule

Kotlin 的 ES5 与 Obsidian 的 ES6

此外,您的一些问题源于这样一个事实,即 Obsidian 的示例隐含地假设您的目标是 ES6(而 Kotlin 当前的目标是 ES5)。具体来说,这在插件导出其成员的方式以及类的实例化方式方面会有所不同。

继承

关于继承(由于 @file:JsModule("obsidian") @file:JsNonModule open external class Component { open fun onload() open fun onunload() } open external class Plugin( app: Any,manifest: Any ) : Component open external class Notice(message: String,timeout: Number = definedExternally) { open fun hide() } 继承自 YourPlugin),ES6 类会自动使用所有参数初始化父类。这在 ES5 的原型继承中是不支持的。这就是为什么在上面的代码片段中,我们需要显式地将 PluginPlugin 参数传递给 app 类构造函数,并在您的特定插件的实现中传递它们:

manifest

导出/模块系统

关于导出您的插件,Obsidian 希望 class SomePlugin( app: Any,manifest: Any ) : Plugin( app,manifest ) module.exports 直接成为您的 exports.default 类。要实现这种精确的导出行为,需要满足几个条件,不幸的是,这有点麻烦: - 库目标需要是 CommonJS:Pluginnot CommonJS2) - 通常情况下,为了防止创建间接级别,需要将导出的库设置为 output.libraryTarget = "commonjs"null - 要将您的插件导出为 output.library = null,其类声明需要标记为 default

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?