Let's port another Imba 1 app to Imba 2 - JSON Beautifier, which you can see in action here.
The app is very simple, has just one component, and outsources all logic to json-stringify-pretty-compact
package.
The most interesting part about it is that it uses Cypress for integration testing, so in the next post I'll also try to setup Cypress integration tests for the Imba 2 version too.
Imba 1 app.imba
let stringify = require("json-stringify-pretty-compact")
tag App
def setup
@maxlen = 80
@indent = 2
@text = JSON.stringify({hello: "world"})
@error = null
def prettify
try
let indent = parseInt(@indent)
let json = JSON.parse(@text)
let spaces = Array.from({length: indent+1}).join(" ")
@text = stringify(json, {maxLength: @maxlen, indent: spaces})
catch e
@error = e
def clear_error
@error = null
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>
<header>
"JSON Beautifier"
<textarea[@text] rows=10 :input.clear_error>
if @error
<div.error>
@error
<div.controls>
<input#file type="file" :change.upload>
<label for="indent">
"Indent"
<input#indent[@indent] type="number" min=0>
<label for="maxlen">
"Max row length"
<input#maxlen[@maxlen] type="number" min=0>
<button :click.prettify>
"Prettify"
Imba.mount <App>
Imba 1 app.scss
@import 'normalize-scss';
@include normalize();
.App {
display: flex;
flex-direction: column;
align-items: center;
header {
font-size: 64px;
text-align: center;
}
textarea {
min-width: 50vw;
margin-bottom: 10px;
}
.controls {
display: grid;
grid-row-gap: 5px;
margin: auto;
label { grid-column: 1; }
input { grid-column: 2; }
button { grid-column: 2; }
}
.error {
background-color: #fcc;
min-width: 50vw;
padding: 5px;
border: 1px solid #800;
}
}
Imba 2 app.imba
import stringify from "json-stringify-pretty-compact"
tag app
prop maxlen = 80
prop indent = 2
prop text = JSON.stringify({hello: "world"})
prop error
def prettify
try
let json = JSON.parse(text)
let spaces = Array.from({length: parseInt(indent)+1}).join(" ")
text = stringify(json, {maxLength: parseInt(maxlen), indent: spaces})
catch e
error = ""+e
imba.commit()
def clear_error
error = null
def upload(event)
let file = event.target.files[0]
return unless file
let reader = new FileReader
reader.onload = do |event|
text = event.target.result
error = nil
imba.commit()
reader.readAsText(file)
<self>
<header>
"JSON Beautifier"
<textarea bind=text rows=10 :input.clear_error>
if error
<div.error>
error
<div.controls>
<input#file type="file" :change.upload>
<label for="indent">
"Indent"
<input#indent bind=indent type="number" min=0>
<label for="maxlen">
"Max row length"
<input#maxlen bind=maxlen type="number" min=0>
<button :click.prettify>
"Prettify"
css
display: flex
flex-direction: column
align-items: center
ff: sans
header
font-size: 64px
text-align: center
textarea
min-width: 50vw
margin-bottom: 10px
.controls
display: grid
grid-row-gap: 5px
margin: auto
label
grid-column: 1
input, button
grid-column: 2
.error
background-color: #fcc
min-width: 50vw
padding: 5px
border: 1px solid #800
imba.mount <app>
This is a very straightforward translation.
We need to convert Error
to String
, as Imba 2 doesn't like putting Error
objects directly in the output, but that's probably a good idea anyway.
Other than that, it's just minor syntactic changes.
By the way I wonder if any framework will ever offer good solution for the label for
problem. Right now they inherently use globally scoped ids.
Source code
Source code is in imba2-json-beautifier repository.
You can also see the live version here.
Coming next
In the next episode we'll try to add Cypress tests to this app.
Top comments (0)