首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将Javascript导出的类转换为Kotlin/JS?

如何将Javascript导出的类转换为Kotlin/JS?
EN

Stack Overflow用户
提问于 2021-07-07 21:11:58
回答 1查看 950关注 0票数 6

我是JS和Kotlin/JS的新手。下面是一个示例中的黑云石插件的最低限度工作Javascript代码。它如预期的那样运作:

代码语言:javascript
复制
var obsidian = require('obsidian');
class SomePlugin extends obsidian.Plugin {
    onload() {
        new obsidian.Notice('This is a notice!');
    }
}
module.exports = Plugin;

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

可以找到可运行的项目这里是吉突布。运行gradle build生成生成文件夹。它将在浏览器步骤中失败,但是这个步骤是不必要的。构建之后,可以在build\js\packages\main\kotlin\main.js中找到生成的js文件。

main.kt

代码语言:javascript
复制
@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

代码语言:javascript
复制
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'。但是至少有一个.js文件是在build/js/packages/test/kotlin/test.js下创建的。然而,代码与我期望的代码完全不同,也不被黑社会接受为一个有效的插件代码。我也尝试了一些其他的梯度选择。比如"umd“、"amd”、“平原”、遗留编译器而不是IR、nodejs而不是浏览器。但是没有创建一个可运行的js文件。错误信息不同。使用遗留编译器,它需要kotlin.js文件,即使我将它放在文件夹中或将内容复制到脚本中,它也找不到它。

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

从obisidan调试器获得的错误消息:

代码语言:javascript
复制
Plugin failure: obsidian-sample-plugin TypeError: Object prototype may only be an Object or null: undefined

所产生的守则:

代码语言:javascript
复制
    (function (root, factory) {
  if (typeof define === 'function' && define.amd)
    define(['exports', 'obsidian', 'obsidian', 'obsidian'], factory);
  else if (typeof exports === 'object')
    factory(module.exports, require('obsidian'), 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 (_, Component, Plugin, 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 _;
}));
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-12 13:07:23

您可以找到一个关于这里.的工作示例,我将在这个答复中逐一对您的代码进行一些更改。

无法解析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

代码语言:javascript
复制
config.externals = {
    obsidian: 'obsidian',
};

(您实际上也可以在官方的样例插件配置中找到一个等价的片段,因为这不是Kotlin/JS特有的问题)

分组多个@JsModule声明

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

代码语言:javascript
复制
@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()
}

Kotlin's ES5对Obsidian的ES6

此外,您的一些问题源于这样一个事实,即Obsidian的示例隐含地假设您的目标是ES6 (而Kotlin的当前目标是ES5)。具体来说,这在插件如何导出其成员以及类如何被实例化方面产生了影响。

继承

关于继承(因为YourPluginPlugin继承),ES6类会使用所有参数自动初始化父类。这是ES5的原型继承中不支持的东西。这就是为什么在上面的片段中,我们需要显式地传递Plugin类构造函数-- appmanifest参数,并在具体插件的实现中传递它们:

代码语言:javascript
复制
class SomePlugin(
    app: Any,
    manifest: Any
) : Plugin(
    app,
    manifest
)

出口/模块系统

在导出插件方面,Obsidian希望module.exportsexports.default直接成为您的Plugin类。要实现这种精确的导出行为,需要满足几个条件,不幸的是,这有点麻烦:-库目标需要是CommonJS:output.libraryTarget = "commonjs" (而不是CommonJS2) --为了防止创建一个间接级别(通常是这样,导出的库需要设置为nulloutput.library = null ),要将插件导出为default,需要将其类声明标记为@JsName("default")

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68293035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档