我是JS和Kotlin/JS的新手。下面是一个示例中的黑云石插件的最低限度工作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
@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'。但是至少有一个.js文件是在build/js/packages/test/kotlin/test.js下创建的。然而,代码与我期望的代码完全不同,也不被黑社会接受为一个有效的插件代码。我也尝试了一些其他的梯度选择。比如"umd“、"amd”、“平原”、遗留编译器而不是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', '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 _;
}));发布于 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:
config.externals = {
obsidian: 'obsidian',
};(您实际上也可以在官方的样例插件配置中找到一个等价的片段,因为这不是Kotlin/JS特有的问题)
分组多个@JsModule声明
因为您要从同一个包导入多个声明,而不是用@JsModule / @JsNonModule注释多个签名,所以必须创建一个单独的文件,并使用@file:@JsModule("...") / @file:JsNonModule对其进行注释。
@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)。具体来说,这在插件如何导出其成员以及类如何被实例化方面产生了影响。
继承
关于继承(因为YourPlugin从Plugin继承),ES6类会使用所有参数自动初始化父类。这是ES5的原型继承中不支持的东西。这就是为什么在上面的片段中,我们需要显式地传递Plugin类构造函数-- app和manifest参数,并在具体插件的实现中传递它们:
class SomePlugin(
app: Any,
manifest: Any
) : Plugin(
app,
manifest
)出口/模块系统
在导出插件方面,Obsidian希望module.exports或exports.default直接成为您的Plugin类。要实现这种精确的导出行为,需要满足几个条件,不幸的是,这有点麻烦:-库目标需要是CommonJS:output.libraryTarget = "commonjs" (而不是CommonJS2) --为了防止创建一个间接级别(通常是这样,导出的库需要设置为null:output.library = null ),要将插件导出为default,需要将其类声明标记为@JsName("default")。
https://stackoverflow.com/questions/68293035
复制相似问题