I want to start porting Imba 1 apps to Imba 2 with the simplest one - ROT-N decoder. Here's Imba 1 version.
You either paste text into the box or use file upload, and then it decodes every ROT-N from ROT-1 to ROT-25. It's somewhat useful for elementary hacking challenges.
Imba 1 app.imba
There's very little complicated here. rot(n)
does the the rotating, upload
handles upload events, and render
renders the view.
tag App
def setup
@text = "Hello, world!"
def rot(n)
@text.replace /[a-z]/gi do |c|
let i = c.charCodeAt(0)
if i >= 97 and i <= 122
String.fromCharCode(((i - 97 + n) % 26) + 97)
else if i >= 65 and i <= 90
String.fromCharCode(((i - 65 + n) % 26) + 65)
else
c
def upload(event)
let file = event.native:target:files[0]
return unless file
let reader = FileReader.new
reader:onload = do |event|
@text = event:target:result
@error = nil
Imba.commit
reader.read-as-text(file)
def render
<self>
<div.contents>
<header>
"ROT-N"
<textarea[@text]>
<div>
<input#file type="file" :change.upload>
<table>
for i in [1..25]
<tr .{"rot-{i}"}>
<th>
i
<td>
rot(i)
Imba.mount <App>
Imba 1 app.scss
@import 'normalize-scss';
@include normalize();
.App {
display: flex;
justify-content: space-around;
max-width: 1000px;
margin: auto;
header {
font-size: 64px;
text-align: center;
}
textarea {
min-width: 50vw;
min-height: 100px;
}
th {
padding-right: 5px;
}
}
Getting started
I had a boilerplate with settings I like, like GitHub Pages, SCSS, but let's start fresh with npx imba create imba2-rotn
.
There are some truly attrocious settings in it - .vscode
and .editorconfig
forcing 4 space indentation, both straight into trash. Even if Imba insists on tabs, they should be visually 2 spaced, or it looks like ass.
OK, with that out of the way we can start coding.
app/index.html
This only requires changing the title, the rest is fine.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Imba 2 ROT-N</title>
<!-- reference to the client script styles -->
<style src='*'></style>
</head>
<body>
<!-- reference to the client script -->
<script type="module" src="./client.imba"></script>
</body>
</html>
app/client.imba
This is fairly close to direct translation:
tag app
prop text = "Hello, World!"
def rot(n)
text.replace /[a-z]/gi do |c|
let i = c.charCodeAt(0)
if i >= 97 and i <= 122
String.fromCharCode(((i - 97 + n) % 26) + 97)
else if i >= 65 and i <= 90
String.fromCharCode(((i - 65 + n) % 26) + 65)
else
c
def upload(event)
let file = event.target.files[0]
return unless file
let reader = new FileReader
reader.onload = do |event|
text = event.target.result
imba.commit()
reader.readAsText(file)
<self>
<div.contents>
<header>
"ROT-N"
<textarea bind=text>
<div>
<input#file type="file" :change.upload>
<table>
for i in [1 .. 25]
<tr>
<th>
i
<td>
rot(i)
css
display: flex
justify-content: space-around
max-width: 1000px
margin: auto
ff: sans
header
font-size: 64px
text-align: center
textarea
min-width: 50vw
min-height: 100px
th
padding-right: 5px
imba.mount <app>
Some differences:
- CSS is not in the component, getting translated the usual way just like Svelte does it
- there's no wrapping
render
function, it's just a<self>
(which becomes<app-tag>
, it's all web components on top level) - syntax is a bit different
<textarea[text]>
becomes<textarea bind=text>
- extra spaces needed in range
[1 .. 25]
- no more
:
vs.
distinction - no more
read-as-text
becomingreadAsText
- Imba 2 still allows-
in names, but it translates them to some Unicode character, so all DOM APIs will beuglyCamelCame
- Ruby-style
FileReader.new
is now JavaScript-stylenew FileReader
- I'm not totally sure where
()
are needed and where they aren't, the rules are different now
But overall it was very straightforward port.
Source code
Source code is in imba2-rotn repository. At some point I'll try to add GitHub Pages support for it.
Coming next
In the next few episodes I'll try to port a few more Imba 1 apps to Imba 2, and then I guess I'll summarize my thoughts about Imba situation.
Top comments (0)