receptive 0.1.0.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +43 -0
- data/HANDBOOK.md +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +76 -0
- data/Rakefile +22 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib-opal/receptive.js.rb +13 -0
- data/lib-opal/receptive/app.rb +48 -0
- data/lib-opal/receptive/incremental-dom-0.5.1.js +1223 -0
- data/lib-opal/receptive/incremental_dom.js.rb +87 -0
- data/lib-opal/receptive/view.rb +95 -0
- data/lib/receptive.rb +14 -0
- data/lib/receptive/version.rb +3 -0
- data/receptive.gemspec +31 -0
- data/test-opal/receptive_test.rb +12 -0
- data/test-opal/receptive_view_test.rb +13 -0
- data/test-opal/test_helper.rb +8 -0
- metadata +155 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'receptive/incremental-dom-0.5.1'
|
2
|
+
require 'console'
|
3
|
+
require 'js'
|
4
|
+
|
5
|
+
module Receptive::IncrementalDOM
|
6
|
+
extend self
|
7
|
+
# Keep the var in the closure
|
8
|
+
`var native = #{JS.global.JS[:IncrementalDOM]}`
|
9
|
+
|
10
|
+
def patch_element(element, patch, data = nil)
|
11
|
+
`native`.JS.patch(element, patch.to_n, data.to_n)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add a tag
|
15
|
+
# @param tagname [String]
|
16
|
+
def tag(tagname, uid = nil, static_props = nil, dynamic_props = nil, &block)
|
17
|
+
if Hash === static_props
|
18
|
+
static_props = static_props.to_a.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
if Hash === dynamic_props
|
22
|
+
innerHTML = dynamic_props.delete(:innerHTML) if Hash === dynamic_props
|
23
|
+
dynamic_props = dynamic_props.to_a.flatten
|
24
|
+
# l innerHTML: innerHTML
|
25
|
+
end
|
26
|
+
|
27
|
+
dynamic_props ||= []
|
28
|
+
if block_given?
|
29
|
+
raise ArgumentError, 'cannot accept both a block and innerHTML' if innerHTML
|
30
|
+
`native`.JS.elementOpen(tagname, uid.to_n, static_props.to_n, *dynamic_props)
|
31
|
+
result = block.call
|
32
|
+
text result if String === result
|
33
|
+
`native`.JS.elementClose(tagname)
|
34
|
+
else
|
35
|
+
node = `native`.JS.elementVoid(tagname, uid.to_n, static_props.to_n, *dynamic_props)
|
36
|
+
node.JS[:innerHTML] = innerHTML
|
37
|
+
node
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add a text node
|
42
|
+
def text(value, &formatter)
|
43
|
+
if block_given?
|
44
|
+
`native`.JS.text(value, formatter)
|
45
|
+
else
|
46
|
+
`native`.JS.text(value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param element [DOM Node] doesn't accept jQuery elements
|
51
|
+
def update_element(element, data = nil, &block)
|
52
|
+
t0 = `performance.now()` if $DEBUG
|
53
|
+
patch_element(element, -> { block.call(self) }, data)
|
54
|
+
if $DEBUG
|
55
|
+
t1 = `performance.now()`
|
56
|
+
$console.log(
|
57
|
+
"%c render/incremental %c #{inspect} %c #{t1 - t0}ms ",
|
58
|
+
'background-color:#eee;color:#444;border-radius:2px 0 0 2px',
|
59
|
+
'background-color:#94E2C8;color:#193F32;border-radius:0 2px 2px 0',
|
60
|
+
'background-color:none;border:none;font-family:monospace;',
|
61
|
+
data.to_n,
|
62
|
+
element
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module DSL
|
68
|
+
HTML_TAGS = %w(a abbr address area article aside audio b base bdi bdo big blockquote body br
|
69
|
+
button canvas caption cite code col colgroup data datalist dd del details dfn
|
70
|
+
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
|
71
|
+
h6 head header hr html i iframe img input ins kbd keygen label legend li link
|
72
|
+
main map mark menu menuitem meta meter nav noscript object ol optgroup option
|
73
|
+
output p param picture pre progress q rp rt ruby s samp script section select
|
74
|
+
small source span strong style sub summary sup table tbody td textarea tfoot th
|
75
|
+
thead time title tr track u ul var video wbr)
|
76
|
+
|
77
|
+
HTML_TAGS.each do |tagname|
|
78
|
+
define_method tagname do |params, &block|
|
79
|
+
tag tagname, nil, nil, params, &block
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def _p(*args)
|
84
|
+
Kernel.p(*args)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Receptive::View
|
2
|
+
def self.extenders
|
3
|
+
@extenders ||= []
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
extenders << base
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :selector
|
11
|
+
|
12
|
+
def setup
|
13
|
+
# noop, this is hook for extenders
|
14
|
+
end
|
15
|
+
|
16
|
+
def selector
|
17
|
+
@selector or raise('Please set the selector')
|
18
|
+
end
|
19
|
+
|
20
|
+
def persistent_events
|
21
|
+
@persistent_events ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_persistent_events
|
25
|
+
setup
|
26
|
+
persistent_events.each do |persistent_event|
|
27
|
+
element, event, selector, block = *persistent_event
|
28
|
+
selector ?
|
29
|
+
element.on(event, selector, &block) :
|
30
|
+
element.on(event, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def on event, selector = '', &block
|
35
|
+
selector = combine_selectors([self.selector, selector])
|
36
|
+
persistent_events << [Document, event, selector, block]
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_window(event, selector = nil, &block)
|
40
|
+
window = Window.element
|
41
|
+
on_document('page:change', selector) { window.on(event, &block) }
|
42
|
+
on_document('page:before-unload', selector) { window.off(event, &block) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_document(event, selector = nil, &block)
|
46
|
+
persistent_events << [Document, event, nil, block_with_guard(block, selector)]
|
47
|
+
end
|
48
|
+
|
49
|
+
def block_with_guard(block, selector)
|
50
|
+
selector = combine_selectors([self.selector, selector])
|
51
|
+
block_with_guard = -> *args { block.call(*args) if Document.has? selector }
|
52
|
+
end
|
53
|
+
|
54
|
+
def find(selector = '')
|
55
|
+
Document.find(combine_selectors([self.selector, selector]))
|
56
|
+
end
|
57
|
+
|
58
|
+
# Support combining multiple selectors with commas
|
59
|
+
def combine_selectors(*selectors)
|
60
|
+
selectors = selectors.flatten.compact
|
61
|
+
splitted = selectors.map { |s| next if s.nil? or s.empty?; s.split(',') }.compact
|
62
|
+
return '' if splitted.size.zero?
|
63
|
+
return splitted.join(', ') if splitted.size == 1
|
64
|
+
|
65
|
+
# About Array#product:
|
66
|
+
#
|
67
|
+
# >> ['a,b', 'c,d'].map{|s| s.split(',')}.reduce(:product)
|
68
|
+
# => [["a", "c"], ["a", "d"], ["b", "c"], ["b", "d"]]
|
69
|
+
#
|
70
|
+
return splitted.reduce(:product).map {|s| s.join(' ')}.join(', ')
|
71
|
+
end
|
72
|
+
|
73
|
+
alias :element :find
|
74
|
+
|
75
|
+
|
76
|
+
# Rendering
|
77
|
+
|
78
|
+
def render
|
79
|
+
warn "#{name}#render not found, should be implemented!"
|
80
|
+
end
|
81
|
+
|
82
|
+
def render!
|
83
|
+
$console.log(
|
84
|
+
"%c render %c #{inspect} %c #{selector} ",
|
85
|
+
'background-color:#eee;color:#444;border-radius:2px 0 0 2px',
|
86
|
+
'background-color:#BFE99C;color:#30491B;border-radius:0 2px 2px 0',
|
87
|
+
'background-color:none;border:none;font-family:monospace;',
|
88
|
+
self
|
89
|
+
) if $DEBUG
|
90
|
+
`window`.JS.requestAnimationFrame(&method(:render))
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
alias_method :on_event, :on_document
|
95
|
+
end
|
data/lib/receptive.rb
ADDED
data/receptive.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "receptive/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "receptive"
|
9
|
+
spec.version = Receptive::VERSION
|
10
|
+
spec.authors = ["Elia Schito"]
|
11
|
+
spec.email = ["elia@schito.me"]
|
12
|
+
|
13
|
+
spec.summary = %q{The perfect toolkit to lighten up your existing HTML}
|
14
|
+
spec.homepage = "https://github.com/elia/receptive#readme"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "opal", [">= 0.10.5", "< 0.12"]
|
25
|
+
spec.add_dependency "opal-jquery", ["~> 0.4.2"]
|
26
|
+
spec.add_dependency "opal-minitest", "0.0.5"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ReceptiveTest < Minitest::Test
|
4
|
+
def test_silence_logs
|
5
|
+
$DEBUG = true
|
6
|
+
debug_value_inside_block = nil
|
7
|
+
Receptive.silence_logs do
|
8
|
+
debug_value_inside_block = $DEBUG
|
9
|
+
end
|
10
|
+
assert_equal(false, debug_value_inside_block)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ReceptiveViewTest < Minitest::Test
|
4
|
+
def test_combine_selectors
|
5
|
+
subject = Object.new.tap {|o| o.extend Receptive::View}
|
6
|
+
|
7
|
+
assert_equal('' , subject.combine_selectors(nil ))
|
8
|
+
assert_equal('a' , subject.combine_selectors('a' ))
|
9
|
+
assert_equal('a b' , subject.combine_selectors('a', 'b' ))
|
10
|
+
assert_equal('a c, b c' , subject.combine_selectors('a,b', 'c' ))
|
11
|
+
assert_equal('a c, a d, b c, b d' , subject.combine_selectors('a,b', 'c,d'))
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
2
|
+
require "receptive"
|
3
|
+
|
4
|
+
# require "minitest/autorun"
|
5
|
+
require 'opal/platform'
|
6
|
+
require 'minitest'
|
7
|
+
`if (typeof(window) === 'undefined') window = Opal.global;` # for nodejs
|
8
|
+
at_exit { Minitest.run ARGV; exit `Opal.global.OPAL_TEST_EXIT_STATUS` || 1 }
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: receptive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Elia Schito
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: opal
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.5
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0.12'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.10.5
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.12'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: opal-jquery
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.4.2
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.4.2
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: opal-minitest
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - '='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.0.5
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - '='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.0.5
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: bundler
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.16'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.16'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rake
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '10.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '10.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: minitest
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '5.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '5.0'
|
103
|
+
description:
|
104
|
+
email:
|
105
|
+
- elia@schito.me
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- ".gitignore"
|
111
|
+
- ".travis.yml"
|
112
|
+
- Gemfile
|
113
|
+
- Gemfile.lock
|
114
|
+
- HANDBOOK.md
|
115
|
+
- LICENSE.txt
|
116
|
+
- README.md
|
117
|
+
- Rakefile
|
118
|
+
- bin/console
|
119
|
+
- bin/setup
|
120
|
+
- lib-opal/receptive.js.rb
|
121
|
+
- lib-opal/receptive/app.rb
|
122
|
+
- lib-opal/receptive/incremental-dom-0.5.1.js
|
123
|
+
- lib-opal/receptive/incremental_dom.js.rb
|
124
|
+
- lib-opal/receptive/view.rb
|
125
|
+
- lib/receptive.rb
|
126
|
+
- lib/receptive/version.rb
|
127
|
+
- receptive.gemspec
|
128
|
+
- test-opal/receptive_test.rb
|
129
|
+
- test-opal/receptive_view_test.rb
|
130
|
+
- test-opal/test_helper.rb
|
131
|
+
homepage: https://github.com/elia/receptive#readme
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 1.3.1
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.7.4
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: The perfect toolkit to lighten up your existing HTML
|
155
|
+
test_files: []
|