Using Kotlin/JS compiler in Svelte "compiler"

Hi,

I am trying to use Kotlin/JS to develop a Svelte application, since Svelte is basically a compiler, any language targeting Javascript could theoretically be used to create a Svelte Web application. The Svelte framework use a tag to delimit any dynamic behavior in javascript. A project which is called svelte-preprocess takes what inside the script tag and converts it to pure Javascript. The project already supports coffeescript and typescript.

Here is how a .svelte file looks with javascript:

<script>
	let name = 'world';
</script>

<h1>Hello {name}!</h1>

the same in typescript:

<script lang="typescript">
    export let name: string = 'world'
</script>

<h1>Hello {name}!</h1>

And what I would like to be able to do in Kotlin:

<script lang="kotlin">
    val name = "world"
</script>

<h1>Hello {name}!</h1>

I am close to a solution with Kotlin/JS but the Kotlin/JS compiler is built around the concept of “output file” which is way to tell the compiler where to write the side effect of running it. This way of doing thing does not play nicely with the process used by Svelte,

Here is for example the typescript code handling typescript in svelte-preprocess:

  const {
    outputText: code,
    sourceMapText: map,
    diagnostics,
  } = ts.transpileModule(content, {
    fileName: filename,
    compilerOptions,
    reportDiagnostics: options.reportDiagnostics !== false,
    transformers: {
      before: [importTransformer],
    },
  });

We can see that the compiler takes a string as input and returns the transformed javascript code, plus the source map and some diagnostics information. The precise definition of the return type is:

declare namespace ts {
    interface TranspileOptions {
        compilerOptions?: CompilerOptions;
        fileName?: string;
        reportDiagnostics?: boolean;
        moduleName?: string;
        renamedDependencies?: MapLike<string>;
        transformers?: CustomTransformers;
    }
    interface TranspileOutput {
        outputText: string;
        diagnostics?: Diagnostic[];
        sourceMapText?: string;
    }
    function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput;
    function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string;
}

Would it be possible to include such changes in the kotlin/JS trans/compiler? What would be the best way to push for such a change? Or, maybe I am wrong, and there is already a way… or a technical solution I am not thinking about. I thought about writing temporary files but this solution seems quite inelegant to me, I may resort to it as a last option though.

I personally think Svelte would be quite a nice addition to the web frameworks supported by Kotlin/JS. It’s a new framework but the potential is definitely there and I think the steps to better integrate with from the Kotlin side are quite minimal.

Thanks!
SĂ©bastien

7 Likes

This is a super interesting idea! Although there weren’t any replies yet, I wonder whether you made any progress towards integrating Kotlin/JS into the Svelte compiler yet?

For now, the project is pretty much on hold.

I thought there would be interest from the Kotlin team for what I consider an “easy target” or “low hanging fruit” but for now without this change to the compiler (which would probably makes it also easier to integrate Kotlin/JS in other toolchains) I have to resort to some hacks that I am reluctant to apply. Sadly, without a clear will from Kotlin team, I will not go forward with this.

There is also the question of bad symbols handling that I needed to test e.g. this line in the following code

$: clicks = proofCount + replayCount,
		 feedback = clicks > 20 && clicks < 50? 'that\'s a lot of damage' : clicks >= 50? 'your dedication is impressive' : '';

Taken from:

    import { fly } from 'svelte/transition';
	import { onMount } from 'svelte';		
	import { backOut, elasticOut } from 'svelte/easing';
	import { data } from './paths.js';
	
	let loaded, skew, color, proof, replayCount = 0, proofCount = 0, clicks, feedback;
	
	onMount(() => {
		loaded = true; 
		setTimeout(()=> skew = true, 1075);
		setTimeout(()=> color = true, 1100);
	});
	
	$: clicks = proofCount + replayCount,
		 feedback = clicks > 20 && clicks < 50? 'that\'s a lot of damage' : clicks >= 50? 'your dedication is impressive' : '';
	
	function prove() {
		proofCount += 1;
		proof = !proof	
	}
	
	function replay() {
		replayCount += 1;
		if (color) {
			loaded = false;
			skew = false;
			color = false;
			setTimeout(()=> loaded = true, 25);
			setTimeout(()=> skew = true, 1100);
			setTimeout(()=> color = true, 1125);
			return;
		}
		return;
	}

The compiler needs to leave them as is for svelte to work properly, I have no idea at this point how Kotlin/JS compiler is handling this.

The other question would be: does dukat could convert these libraries:

    import { fly } from 'svelte/transition';
	import { onMount } from 'svelte';		
	import { backOut, elasticOut } from 'svelte/easing';
	import { data } from './paths.js';

So, there is some work to do even if it is mostly validating things here and there, but the core, is the compiler. One, could fork it, but then have to maintain a separate branch which in itself might be a lot of work.

This is pretty much where things stands at this moment.

Anyway, thanks for the interest :slight_smile: I also thought it was a good idea!

It would be awesome if we could use Kotlin with Svelte.

I guess the challenge with svelte’s reactive declarations e.g. “$: clicks = proofCount + replayCount” could be solved by using an annotation like @Reactive. However, annotations don’t seem supported yet by Kotlin JS.

My understanding is that these declarations need not to be handled by the compiler/transpiler but left as is. Svelte implements its own transformation step that handles these from the transpiled Javascript code, In the end, Svelte only expects javascript. Support for Svelte in Kotlin would only require the compiler/transpiler to leave them as is. I might be wrong though, I didn’t go deep until I faced the aforementioned problem.

In fact, ignoring compilation errors seems to be supported with the new backend: Ignoring compilation errors so, this part of Svelte support should work.

yeah, but how do you write them in a first place in a valid Kotlin codebase? Wonder if you could do something like a Delegate, that would generate that code for you somehow :thinking:

Any advancements on this ?

Hi, looks promising, this should have been reported as feature request in my opinion: https://youtrack.jetbrains.com/issues

Yes. Svelte is pretty much revolution in Front-End, would be cool to have Kotlin support.

But I’m afraid it won’t be possible without the compiler modification. As svelte is not just TypeScript, it changes the semantic of the TypeScript, it’s Reactive TypeScript. And to do the same in Kotlin it may require a whole new concept of Reactive Kotlin.

2 Likes

I would love to see this too, if anyone starts a repo, I’d be happy to contribute a bit :slight_smile: