snabberb 0.5.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cedc3e54bfcb4b628750f8a7779975624cb72226c46ca0c2e7ea787d5b31e9f2
4
- data.tar.gz: e0d593a26c2058022d6e6c3df9dc200c235aedf2524a9c774ebcabbfa8df7d3a
3
+ metadata.gz: cb82424f513fedb084f9889e64adc0b3484e3403522d5f0fb1ab3531c9fd627b
4
+ data.tar.gz: '08a6595aa3bed2cde156991811e6a612296e11aaeae9a24a10dd9aca58c2f3f8'
5
5
  SHA512:
6
- metadata.gz: c0d1c3b840a0f0475204cdcdf8a603441bbbcc5f7fb1b3653081e4b8e25690663116ba639775b4ae8f7c045f904207225fa6d7bee27931a778c441c76e8385d9
7
- data.tar.gz: f32c2619a9c422fe33cf7fdeddd97b968c7a68002865619f1077c63349e66caa24c820aad00fa66bf60de623d5e8e7f46f7a16ba374f9836cd9ce653badffddc
6
+ metadata.gz: 9f599f947849c63880508953ec5f096f6ccfc4936c08fe51d7c8a3fd087260b921cdba6d7b64b70e5a6e565c63d2cf02cd1962880c1b5ae4b96f4a793cddfe3d
7
+ data.tar.gz: 06d6ff61cf0853e796f4c8d4896db4e4a74b7dd28a79a421fdc4df947d99e92f7eec63ca604c993ab445142bd9f095d782122730f11936387ee4314313fc4768
data/.rubocop.yml CHANGED
@@ -1,21 +1,24 @@
1
1
  Layout/FirstArrayElementIndentation:
2
2
  Enabled: false
3
3
 
4
+ Layout/LineLength:
5
+ Max: 120
6
+
4
7
  Metrics/AbcSize:
5
8
  Enabled: false
6
9
 
7
10
  Metrics/BlockLength:
8
11
  Enabled: False
9
12
 
13
+ Metrics/ClassLength:
14
+ Enabled: False
15
+
10
16
  Metrics/CyclomaticComplexity:
11
17
  Enabled: False
12
18
 
13
19
  Metrics/PerceivedComplexity:
14
20
  Enabled: False
15
21
 
16
- Metrics/LineLength:
17
- Max: 120
18
-
19
22
  Metrics/MethodLength:
20
23
  Enabled: false
21
24
 
@@ -41,4 +44,6 @@ Style/TrailingCommaInHashLiteral:
41
44
  Enabled: false
42
45
 
43
46
  AllCops:
44
- TargetRubyVersion: 2.3
47
+ NewCops: enable
48
+ TargetRubyVersion: 2.4
49
+ SuggestExtensions: false
data/build.js CHANGED
@@ -1,10 +1,11 @@
1
- // browserify deps.js -p esmify -s snabbdom > opal/vendor/snabbdom.js
1
+ // browserify build.js -p esmify -s snabbdom > opal/vendor/snabbdom.js
2
2
  import { init } from './node_modules/snabbdom/build/package/init'
3
3
  import { h } from './node_modules/snabbdom/build/package/h'
4
4
  import { toVNode } from './node_modules/snabbdom/build/package/tovnode'
5
5
 
6
6
  import { attributesModule } from './node_modules/snabbdom/build/package/modules/attributes'
7
7
  import { classModule } from './node_modules/snabbdom/build/package/modules/class'
8
+ import { datasetModule } from './node_modules/snabbdom/build/package/modules/dataset'
8
9
  import { eventListenersModule } from './node_modules/snabbdom/build/package/modules/eventlisteners'
9
10
  import { propsModule } from './node_modules/snabbdom/build/package/modules/props'
10
11
  import { styleModule } from './node_modules/snabbdom/build/package/modules/style'
@@ -15,6 +16,7 @@ module.exports.toVNode = toVNode
15
16
 
16
17
  module.exports.attributesModule = attributesModule
17
18
  module.exports.classModule = classModule
19
+ module.exports.datasetModule = datasetModule
18
20
  module.exports.eventListenersModule = eventListenersModule
19
21
  module.exports.propsModule = propsModule
20
22
  module.exports.styleModule = styleModule
@@ -2,7 +2,7 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'c_lexer'
6
5
  gem 'opal'
7
6
  gem 'rack'
8
7
  gem 'snabberb', path: '../..'
8
+ gem 'webrick'
@@ -1,31 +1,29 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- snabberb (0.4.2)
5
- opal (~> 1.0)
4
+ snabberb (1.3.0)
5
+ opal (~> 1.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.1)
11
- c_lexer (2.6.4.1.1)
12
- ast (~> 2.4.0)
13
- parser (= 2.6.4.1)
14
- opal (1.0.3)
10
+ ast (2.4.2)
11
+ opal (1.1.1)
15
12
  ast (>= 2.3.0)
16
- parser (~> 2.6)
17
- parser (2.6.4.1)
18
- ast (~> 2.4.0)
13
+ parser (~> 3.0)
14
+ parser (3.0.0.0)
15
+ ast (~> 2.4.1)
19
16
  rack (2.2.3)
17
+ webrick (1.7.0)
20
18
 
21
19
  PLATFORMS
22
20
  ruby
23
21
 
24
22
  DEPENDENCIES
25
- c_lexer
26
23
  opal
27
24
  rack
28
25
  snabberb!
26
+ webrick
29
27
 
30
28
  BUNDLED WITH
31
- 2.1.4
29
+ 2.2.3
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- snabberb (0.4.2)
4
+ snabberb (1.0.0)
5
5
  opal (~> 1.0)
6
6
 
7
7
  GEM
data/lib/snabberb.rb CHANGED
@@ -55,11 +55,11 @@ module Snabberb
55
55
 
56
56
  def self.prerender_script(layout, application, application_id, javascript_include_tags: '', **needs)
57
57
  needs = wrap(needs)
58
- attach_func = wrap_s("Opal.$$.#{application}.$attach(\"#{application_id}\", #{needs})")
58
+ attach_func = wrap_s("Opal.#{application}.$attach(\"#{application_id}\", #{needs})")
59
59
 
60
60
  <<~JS
61
- Opal.$$.#{layout}.$html(Opal.hash({
62
- application: Opal.$$.#{application}.$new(null, #{needs}).$render(),
61
+ Opal.#{layout}.$html(Opal.hash({
62
+ application: Opal.#{application}.$new(null, #{needs}).$render(),
63
63
  javascript_include_tags: '#{javascript_include_tags.gsub("\n", '')}',
64
64
  attach_func: #{attach_func}
65
65
  }))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snabberb
4
- VERSION = '0.5.0'
4
+ VERSION = '1.3.1'
5
5
  end
data/opal/snabberb.rb CHANGED
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erb'
3
4
  require 'native'
4
-
5
5
  require 'vendor/snabbdom'
6
- require 'vendor/snabbdom-to-html'
7
-
8
6
  require 'snabberb/component'
9
7
 
10
8
  module Snabberb
@@ -5,6 +5,99 @@ module Snabberb
5
5
  attr_accessor :node
6
6
  attr_reader :root
7
7
 
8
+ %x{
9
+ const VOID = new Set([
10
+ 'area',
11
+ 'base',
12
+ 'br',
13
+ 'col',
14
+ 'embed',
15
+ 'hr',
16
+ 'img',
17
+ 'input',
18
+ 'keygen',
19
+ 'link',
20
+ 'meta',
21
+ 'param',
22
+ 'source',
23
+ 'track',
24
+ 'wbr',
25
+ ])
26
+
27
+ const IGNORE = new Set([
28
+ 'attributes',
29
+ 'childElementCount',
30
+ 'children',
31
+ 'classList',
32
+ 'clientHeight',
33
+ 'clientLeft',
34
+ 'clientTop',
35
+ 'clientWidth',
36
+ 'currentStyle',
37
+ 'firstElementChild',
38
+ 'innerHTML',
39
+ 'lastElementChild',
40
+ 'nextElementSibling',
41
+ 'ongotpointercapture',
42
+ 'onlostpointercapture',
43
+ 'onwheel',
44
+ 'outerHTML',
45
+ 'previousElementSibling',
46
+ 'runtimeStyle',
47
+ 'scrollHeight',
48
+ 'scrollLeft',
49
+ 'scrollLeftMax',
50
+ 'scrollTop',
51
+ 'scrollTopMax',
52
+ 'scrollWidth',
53
+ 'tabStop',
54
+ 'tagName',
55
+ ])
56
+
57
+ const BOOLEAN = new Set([
58
+ 'disabled',
59
+ 'visible',
60
+ 'checked',
61
+ 'readonly',
62
+ 'required',
63
+ 'allowfullscreen',
64
+ 'autofocus',
65
+ 'autoplay',
66
+ 'compact',
67
+ 'controls',
68
+ 'default',
69
+ 'formnovalidate',
70
+ 'hidden',
71
+ 'ismap',
72
+ 'itemscope',
73
+ 'loop',
74
+ 'multiple',
75
+ 'muted',
76
+ 'noresize',
77
+ 'noshade',
78
+ 'novalidate',
79
+ 'nowrap',
80
+ 'open',
81
+ 'reversed',
82
+ 'seamless',
83
+ 'selected',
84
+ 'sortable',
85
+ 'truespeed',
86
+ 'typemustmatch',
87
+ ])
88
+ }
89
+
90
+ %x{
91
+ const PATCHER = snabbdom.init([
92
+ snabbdom.attributesModule,
93
+ snabbdom.classModule,
94
+ snabbdom.datasetModule,
95
+ snabbdom.eventListenersModule,
96
+ snabbdom.propsModule,
97
+ snabbdom.styleModule,
98
+ ])
99
+ }
100
+
8
101
  # You can define needs in each component. They are automatically set as instance variables
9
102
  #
10
103
  # For example:
@@ -27,7 +120,7 @@ module Snabberb
27
120
  def self.attach(container, **passed_needs)
28
121
  component = new(nil, passed_needs)
29
122
  component.node = `document.getElementById(#{container})`
30
- component.update
123
+ component.update!
31
124
  end
32
125
 
33
126
  # Render the component as an HTML string using snabbdom-to-html.
@@ -57,7 +150,7 @@ module Snabberb
57
150
  end
58
151
 
59
152
  def html
60
- `toHTML(#{render})`
153
+ node_to_s(render)
61
154
  end
62
155
 
63
156
  # Building block for dom elements using Snabbdom h and Snabberb components.
@@ -95,15 +188,8 @@ module Snabberb
95
188
  request_ids.shift
96
189
  return unless request_ids.empty?
97
190
 
98
- @@patcher ||= %x{snabbdom.init([
99
- snabbdom.attributesModule,
100
- snabbdom.classModule,
101
- snabbdom.eventListenersModule,
102
- snabbdom.propsModule,
103
- snabbdom.styleModule,
104
- ])}
105
191
  node = @root.render
106
- @@patcher.call(@root.node, node)
192
+ `PATCHER(#{root.node}, #{node})`
107
193
  @root.node = node
108
194
  end
109
195
 
@@ -151,6 +237,113 @@ module Snabberb
151
237
  end
152
238
  end
153
239
  end
240
+
241
+ # rubocop:disable Lint/UnusedMethodArgument
242
+ def parse_sel(sel)
243
+ %x{
244
+ let tag = ''
245
+ let id = ''
246
+ const classes = {}
247
+ const parts = sel.split(".")
248
+
249
+ parts.forEach((part, index) => {
250
+ if (index == 0) {
251
+ part = part.split('#')
252
+ if (part.length > 1) id = part[1]
253
+ part = part[0]
254
+ index == 0 ? tag = part : classes[part] = true
255
+ } else if (!tag) {
256
+ tag = part
257
+ } else {
258
+ classes[part] = true
259
+ }
260
+ })
261
+
262
+ return {
263
+ tag: tag,
264
+ id: id,
265
+ classes: classes,
266
+ }
267
+ }
268
+ end
269
+
270
+ def node_to_s(vnode)
271
+ %x{
272
+ if (!vnode.sel) return self.$escape(vnode.text)
273
+
274
+ const sel = self.$parse_sel(vnode.sel)
275
+
276
+ for (const key in vnode.data.class) {
277
+ vnode.data.class[key] ? sel['classes'][key] = true : delete sel['classes'][key]
278
+ }
279
+
280
+ let attributes = {}
281
+ if (sel['id'].length > 0) attributes['id'] = sel['id']
282
+
283
+ const classes = Object.keys(sel['classes'])
284
+ if (classes.length > 0) attributes['class'] = classes.join(' ')
285
+
286
+ for (const key in vnode.data.attrs) {
287
+ attributes[key] = vnode.data.attrs[key]
288
+ }
289
+
290
+ for (const key in vnode.data.dataset) {
291
+ attributes['data-' + key] = vnode.data.dataset[key]
292
+ }
293
+
294
+ for (const key in vnode.data.props) {
295
+ if (!IGNORE.has(key)) {
296
+ const value = vnode.data.props[key]
297
+
298
+ if (BOOLEAN.has(key)) {
299
+ if (value) attributes[key] = key
300
+ } else {
301
+ attributes[key] = value
302
+ }
303
+ }
304
+ }
305
+
306
+ const styles = []
307
+
308
+ for (let key in vnode.data.style) {
309
+ const value = vnode.data.style[key]
310
+ key = key.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
311
+ styles.push(key + ': ' + value)
312
+ }
313
+
314
+ if (styles.length > 0) attributes['style'] = styles.join('; ')
315
+
316
+ attributes = Object.keys(attributes).map(key =>
317
+ self.$escape(key) + '="' + self.$escape(attributes[key]) + '"'
318
+ )
319
+
320
+ const tag = sel['tag']
321
+ const elements = ['<' + tag]
322
+ if (attributes.length > 0) elements.push(' ' + attributes.join(' '))
323
+ elements.push('>')
324
+
325
+ if (!VOID.has(tag)) {
326
+ if (vnode.data.props && vnode.data.props.innerHTML) {
327
+ elements.push(vnode.data.props.innerHTML)
328
+ } else if (vnode.text) {
329
+ elements.push(self.$escape(vnode.text))
330
+ } else if (vnode.children) {
331
+ vnode.children.forEach(child =>
332
+ elements.push(self.$node_to_s(child))
333
+ )
334
+ }
335
+
336
+ elements.push('</' + tag + '>')
337
+ }
338
+
339
+ return elements.join('')
340
+ }
341
+ end
342
+ # rubocop:enable Lint/UnusedMethodArgument
343
+
344
+ def escape(html)
345
+ ERB::Util.html_escape(html)
346
+ end
154
347
  end
155
348
 
156
349
  # Sublcass this to prerender applications.
@@ -11,22 +11,26 @@ var _attributes = require("./node_modules/snabbdom/build/package/modules/attribu
11
11
 
12
12
  var _class = require("./node_modules/snabbdom/build/package/modules/class");
13
13
 
14
+ var _dataset = require("./node_modules/snabbdom/build/package/modules/dataset");
15
+
14
16
  var _eventlisteners = require("./node_modules/snabbdom/build/package/modules/eventlisteners");
15
17
 
16
18
  var _props = require("./node_modules/snabbdom/build/package/modules/props");
17
19
 
18
20
  var _style = require("./node_modules/snabbdom/build/package/modules/style");
19
21
 
22
+ // browserify build.js -p esmify -s snabbdom > opal/vendor/snabbdom.js
20
23
  module.exports.init = _init.init;
21
24
  module.exports.h = _h.h;
22
25
  module.exports.toVNode = _tovnode.toVNode;
23
26
  module.exports.attributesModule = _attributes.attributesModule;
24
27
  module.exports.classModule = _class.classModule;
28
+ module.exports.datasetModule = _dataset.datasetModule;
25
29
  module.exports.eventListenersModule = _eventlisteners.eventListenersModule;
26
30
  module.exports.propsModule = _props.propsModule;
27
31
  module.exports.styleModule = _style.styleModule;
28
32
 
29
- },{"./node_modules/snabbdom/build/package/h":2,"./node_modules/snabbdom/build/package/init":4,"./node_modules/snabbdom/build/package/modules/attributes":6,"./node_modules/snabbdom/build/package/modules/class":7,"./node_modules/snabbdom/build/package/modules/eventlisteners":8,"./node_modules/snabbdom/build/package/modules/props":9,"./node_modules/snabbdom/build/package/modules/style":10,"./node_modules/snabbdom/build/package/tovnode":11}],2:[function(require,module,exports){
33
+ },{"./node_modules/snabbdom/build/package/h":2,"./node_modules/snabbdom/build/package/init":4,"./node_modules/snabbdom/build/package/modules/attributes":6,"./node_modules/snabbdom/build/package/modules/class":7,"./node_modules/snabbdom/build/package/modules/dataset":8,"./node_modules/snabbdom/build/package/modules/eventlisteners":9,"./node_modules/snabbdom/build/package/modules/props":10,"./node_modules/snabbdom/build/package/modules/style":11,"./node_modules/snabbdom/build/package/tovnode":12}],2:[function(require,module,exports){
30
34
  "use strict";
31
35
 
32
36
  Object.defineProperty(exports, "__esModule", {
@@ -101,7 +105,7 @@ function h(sel, b, c) {
101
105
 
102
106
  ;
103
107
 
104
- },{"./is.js":5,"./vnode.js":12}],3:[function(require,module,exports){
108
+ },{"./is.js":5,"./vnode.js":13}],3:[function(require,module,exports){
105
109
  "use strict";
106
110
 
107
111
  Object.defineProperty(exports, "__esModule", {
@@ -560,7 +564,7 @@ function init(modules, domApi) {
560
564
  };
561
565
  }
562
566
 
563
- },{"./htmldomapi.js":3,"./is.js":5,"./vnode.js":12}],5:[function(require,module,exports){
567
+ },{"./htmldomapi.js":3,"./is.js":5,"./vnode.js":13}],5:[function(require,module,exports){
564
568
  "use strict";
565
569
 
566
570
  Object.defineProperty(exports, "__esModule", {
@@ -682,6 +686,55 @@ exports.classModule = classModule;
682
686
  },{}],8:[function(require,module,exports){
683
687
  "use strict";
684
688
 
689
+ Object.defineProperty(exports, "__esModule", {
690
+ value: true
691
+ });
692
+ exports.datasetModule = void 0;
693
+ const CAPS_REGEX = /[A-Z]/g;
694
+
695
+ function updateDataset(oldVnode, vnode) {
696
+ const elm = vnode.elm;
697
+ let oldDataset = oldVnode.data.dataset;
698
+ let dataset = vnode.data.dataset;
699
+ let key;
700
+ if (!oldDataset && !dataset) return;
701
+ if (oldDataset === dataset) return;
702
+ oldDataset = oldDataset || {};
703
+ dataset = dataset || {};
704
+ const d = elm.dataset;
705
+
706
+ for (key in oldDataset) {
707
+ if (!dataset[key]) {
708
+ if (d) {
709
+ if (key in d) {
710
+ delete d[key];
711
+ }
712
+ } else {
713
+ elm.removeAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase());
714
+ }
715
+ }
716
+ }
717
+
718
+ for (key in dataset) {
719
+ if (oldDataset[key] !== dataset[key]) {
720
+ if (d) {
721
+ d[key] = dataset[key];
722
+ } else {
723
+ elm.setAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase(), dataset[key]);
724
+ }
725
+ }
726
+ }
727
+ }
728
+
729
+ const datasetModule = {
730
+ create: updateDataset,
731
+ update: updateDataset
732
+ };
733
+ exports.datasetModule = datasetModule;
734
+
735
+ },{}],9:[function(require,module,exports){
736
+ "use strict";
737
+
685
738
  Object.defineProperty(exports, "__esModule", {
686
739
  value: true
687
740
  });
@@ -774,7 +827,7 @@ const eventListenersModule = {
774
827
  };
775
828
  exports.eventListenersModule = eventListenersModule;
776
829
 
777
- },{}],9:[function(require,module,exports){
830
+ },{}],10:[function(require,module,exports){
778
831
  "use strict";
779
832
 
780
833
  Object.defineProperty(exports, "__esModule", {
@@ -810,7 +863,7 @@ const propsModule = {
810
863
  };
811
864
  exports.propsModule = propsModule;
812
865
 
813
- },{}],10:[function(require,module,exports){
866
+ },{}],11:[function(require,module,exports){
814
867
  "use strict";
815
868
 
816
869
  Object.defineProperty(exports, "__esModule", {
@@ -942,7 +995,7 @@ const styleModule = {
942
995
  };
943
996
  exports.styleModule = styleModule;
944
997
 
945
- },{}],11:[function(require,module,exports){
998
+ },{}],12:[function(require,module,exports){
946
999
  "use strict";
947
1000
 
948
1001
  Object.defineProperty(exports, "__esModule", {
@@ -996,7 +1049,7 @@ function toVNode(node, domApi) {
996
1049
  }
997
1050
  }
998
1051
 
999
- },{"./htmldomapi.js":3,"./vnode.js":12}],12:[function(require,module,exports){
1052
+ },{"./htmldomapi.js":3,"./vnode.js":13}],13:[function(require,module,exports){
1000
1053
  "use strict";
1001
1054
 
1002
1055
  Object.defineProperty(exports, "__esModule", {