Skip to content

Commit 5b8b336

Browse files
committed
added react calculator example, improved hyperscript
1 parent 9af39fc commit 5b8b336

File tree

4 files changed

+140
-18
lines changed

4 files changed

+140
-18
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ examples/package.json
88
examples/package-lock.json
99
examples/basic-example.js
1010
examples/electron-example.js
11+
examples/react-example.js
1112
examples/tmp/
1213
examples/coffee-example.js
14+
examples/rollup.config.js
1315
examples/svelte-example.js

examples/react-calculator.coffee

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/singlefile
2+
3+
@npm =
4+
name: 'r'
5+
dependencies:
6+
react: '*'
7+
'react-dom': '*'
8+
'create-react-class': '*'
9+
'react-hyperscript': '*'
10+
'hyperscript': '*'
11+
'hyperscript-helpers': '*'
12+
'jquery': '*'
13+
'bss': '*'
14+
'mathjs': '*'
15+
16+
h = require('hyperscript')
17+
{ html, head, body, link, script } = require('hyperscript-helpers')(h)
18+
19+
@pub = pub =
20+
'index.html': [
21+
'<!DOCTYPE html>',
22+
html {lang:'en'}, [
23+
head [
24+
link {rel:'stylesheet', href:'main.css'}
25+
],
26+
body [
27+
h('div#root'),
28+
script({src:'client.js'})
29+
]
30+
],
31+
]
32+
33+
@views =
34+
'main.styl': '''
35+
body
36+
background-color: #bbbbbb
37+
input
38+
width: 89%
39+
button
40+
width: 9%
41+
'''
42+
43+
@client = ->
44+
window.jQuery = global.jQuery = $ = require('jquery')
45+
h = require('react-hyperscript')
46+
React = require('react')
47+
createReactClass = require('create-react-class')
48+
ReactDOM = require('react-dom')
49+
{ p, link, script, html, head, body, div, button, ul, li, h3, form, label, input, br } = require('hyperscript-helpers')(h)
50+
css = require('bss')
51+
math = require('mathjs').evaluate
52+
53+
class CalcApp extends React.Component
54+
constructor: (props) ->
55+
super props
56+
@state =
57+
items: []
58+
text: ''
59+
@handleChange = @handleChange.bind(this)
60+
@handleSubmit = @handleSubmit.bind(this)
61+
handleChange: (e)->
62+
@setState
63+
text: e.target.value
64+
handleSubmit: (e)->
65+
e.preventDefault()
66+
if @state.text.length == 0
67+
return
68+
try
69+
m = math(@state.text)
70+
catch
71+
m = 'ERROR'
72+
newItem =
73+
text: @state.text + ' = ' + m
74+
id: Date.now()
75+
@setState (state)->
76+
items: [newItem].concat state.items
77+
render: ->
78+
div [
79+
form({onSubmit:@handleSubmit},[
80+
input({id:'new-entry',onChange:@handleChange,value:@state.text}),
81+
button('=')
82+
]),
83+
br(),
84+
h(CalcHistory, {items:@state.items}),
85+
]
86+
87+
class CalcHistory extends React.Component
88+
render: ->
89+
return h [
90+
h('div.ui.message', [
91+
h('div.list', @props.items.map (item)-> h 'div.item', {key:item.id}, item.text),
92+
]),
93+
br()
94+
]
95+
96+
ReactDOM.render React.createElement(CalcApp), document.getElementById('root')
97+
98+
@server = (app)->
99+
app.get '/', (req,res) ->
100+
res.render 'index.html'
101+
102+
await app.run()
103+
console.log 'server running @ port 3000'
104+

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"typescript-require": "*",
2020
"coffeescript": "2.*",
2121
"livescript": "*",
22+
"hyperscript": "*",
2223
"babel-cli": "*",
2324
"grunt": "*",
2425
"dentist": "*"

singlefile.ls

+33-18
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ fs = require('fs')
99
#async = require('async')
1010
path = require('path')
1111

12+
defaultstack = ['default', 'pug', 'stylus']
13+
1214
plugin = (script, name)->
1315
if !!script.config
1416
if !!script.config.stack
1517
return name in script.config.stack
1618
else
17-
if name in ['pug','stylus'] # defaults
19+
if name in defaultstack
1820
return true
1921
return false
2022

@@ -38,6 +40,7 @@ client_libs = [
3840
]
3941

4042
plugin_libs = {
43+
'default': ['dentist'],
4144
'pug': ['pug'],
4245
'stylus': ['stylus', 'nib'],
4346
'electron': ['electron'],
@@ -48,20 +51,22 @@ plugin_libs = {
4851
]
4952
}
5053

51-
if process.env.SINGLEFILE # launching wrapper
54+
if process.env.SINGLEFILE_EXT # launching wrapper
5255
# include interpreter since we're generating singlefile.js and we need script require()s
5356

5457
interpreter = void
55-
if process.env.SINGLEFILE == 'coffee'
58+
if process.env.SINGLEFILE_EXT == 'coffee'
5659
require('coffeescript').register()
57-
else if process.env.SINGLEFILE == 'ts'
60+
else if process.env.SINGLEFILE_EXT == 'ts'
5861
require('typescript-require')
59-
else if process.env.SINGLEFILE != 'js'
60-
interpreter = require(interpreters[process.env.SINGLEFILE])
62+
else if process.env.SINGLEFILE_EXT != 'js'
63+
interpreter = require(interpreters[process.env.SINGLEFILE_EXT])
6164

6265
fn = path.resolve(process.env.SINGLEFILE_SCRIPT)
6366
scriptdir = path.dirname(fn)
6467
script = require(fn)
68+
if !script.config
69+
script.config = {}
6570
cfg = script.config
6671
if cfg.stack or cfg.stack == ''
6772
cfg.stack = cfg.stack.split(' ')
@@ -144,6 +149,9 @@ if process.env.SINGLEFILE # launching wrapper
144149
return cb err
145150
else
146151
app = {}
152+
if not script.server
153+
script.server = ->
154+
<- app.run()
147155
if script.server.constructor.name == 'AsyncFunction'
148156
app.run = promisify(app.run)
149157
script.server(app)
@@ -435,13 +443,14 @@ if not script.pub
435443
script.pub = {}
436444

437445
if script.config.base == 'svelte'
438-
if not ('index.pug' in script.views)
439-
# default index
440-
script.views['index.pug'] = '''
441-
head
442-
script(defer src='bundle.js')
443-
body
444-
'''
446+
if not ('index.html' in script.pub)
447+
if not ('index.pug' in script.views)
448+
# default index
449+
script.views['index.pug'] = '''
450+
head
451+
script(defer src='bundle.js')
452+
body
453+
'''
445454
if not ('App.svelte' in script.pub)
446455
script.pub['App.svelte'] = '''
447456
<script src="client.js"></script>
@@ -462,18 +471,24 @@ if script.config.base == 'svelte'
462471

463472
try
464473
fs.mkdirSync path.join(scriptdir,'views')
465-
for template, content of script.views
466-
fs.writeFileSync path.join(scriptdir,'views',template), dedent(content), {'flag':'w'}
474+
for fn, content of script.views
475+
if fn.toLowerCase().endsWith '.html'
476+
if Array.isArray content
477+
content = _.map(content, (x)-> x.outerHTML || x).join('')
478+
fs.writeFileSync path.join(scriptdir,'views',fn), dedent(content), {'flag':'w'}
467479

468480
# generate static/public dir
469481
try
470482
fs.mkdirSync path.join(scriptdir,'public')
471-
for staticfile, content of script.pub
472-
fs.writeFileSync path.join(scriptdir,'public', staticfile), dedent(content), {'flag':'w'}
483+
for fn, content of script.pub
484+
if fn.toLowerCase().endsWith '.html'
485+
if Array.isArray content
486+
content = _.map(content, (x)-> x.outerHTML || x).join('')
487+
fs.writeFileSync path.join(scriptdir,'public', fn), dedent(content), {'flag':'w'}
473488

474489
env =
475490
#NODE_PATH: path.join(scriptdir,'node_modules')
476-
SINGLEFILE: ext
491+
SINGLEFILE_EXT: ext
477492
SINGLEFILE_SCRIPT: argv[argv.length-1]
478493

479494
if script.config.base=='svelte'

0 commit comments

Comments
 (0)