snabberb 0.5.0 → 1.0.0

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: 5a1c844a2e4053181db278aeee2cd4c97ccd982e783c6ffb2b6df48391fd0a7b
4
+ data.tar.gz: 53e6e1712e779c653f7d429048f44e77cb9be525619d5276ee441e00e4ccb92b
5
5
  SHA512:
6
- metadata.gz: c0d1c3b840a0f0475204cdcdf8a603441bbbcc5f7fb1b3653081e4b8e25690663116ba639775b4ae8f7c045f904207225fa6d7bee27931a778c441c76e8385d9
7
- data.tar.gz: f32c2619a9c422fe33cf7fdeddd97b968c7a68002865619f1077c63349e66caa24c820aad00fa66bf60de623d5e8e7f46f7a16ba374f9836cd9ce653badffddc
6
+ metadata.gz: 4a0c84b3558683af920af98de8e341f0bb6c7d1a2320d1354a8cea76d7a73b83f6eaf99aae9115b5150e5f0643579b24c4b89076188756b04342dbae237db4a3
7
+ data.tar.gz: 1a3b2bed264e1443d38368dea5b05d93abe6f0a1544c0f88b25357d2c9e042456493418779721b250c0f52db5b9e3bccb33099ecb926ff92e409fbf7423bb8fe
@@ -7,6 +7,9 @@ Metrics/AbcSize:
7
7
  Metrics/BlockLength:
8
8
  Enabled: False
9
9
 
10
+ Metrics/ClassLength:
11
+ Enabled: False
12
+
10
13
  Metrics/CyclomaticComplexity:
11
14
  Enabled: False
12
15
 
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- snabberb (0.4.2)
4
+ snabberb (0.5.0)
5
5
  opal (~> 1.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- snabberb (0.4.2)
4
+ snabberb (0.5.0)
5
5
  opal (~> 1.0)
6
6
 
7
7
  GEM
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snabberb
4
- VERSION = '0.5.0'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -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,88 @@ 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
+
8
90
  # You can define needs in each component. They are automatically set as instance variables
9
91
  #
10
92
  # For example:
@@ -57,7 +139,7 @@ module Snabberb
57
139
  end
58
140
 
59
141
  def html
60
- `toHTML(#{render})`
142
+ node_to_s(render)
61
143
  end
62
144
 
63
145
  # Building block for dom elements using Snabbdom h and Snabberb components.
@@ -98,6 +180,7 @@ module Snabberb
98
180
  @@patcher ||= %x{snabbdom.init([
99
181
  snabbdom.attributesModule,
100
182
  snabbdom.classModule,
183
+ snabbdom.datasetModule,
101
184
  snabbdom.eventListenersModule,
102
185
  snabbdom.propsModule,
103
186
  snabbdom.styleModule,
@@ -151,6 +234,114 @@ module Snabberb
151
234
  end
152
235
  end
153
236
  end
237
+
238
+ # rubocop:disable Lint/UnusedMethodArgument
239
+ def parse_sel(sel)
240
+ %x{
241
+ let tag = ''
242
+ let id = ''
243
+ const classes = {}
244
+ const parts = sel.split(".")
245
+ const last = parts.length - 1
246
+
247
+ parts.forEach((part, index) => {
248
+ if (index == last) {
249
+ part = part.split('#')
250
+ if (part.length > 1) id = part[1]
251
+ part = part[0]
252
+ index == 0 ? tag = part : classes[part] = true
253
+ } else if (!tag) {
254
+ tag = part
255
+ } else {
256
+ classes[part] = true
257
+ }
258
+ })
259
+
260
+ return {
261
+ tag: tag,
262
+ id: id,
263
+ classes: classes,
264
+ }
265
+ }
266
+ end
267
+
268
+ def node_to_s(vnode)
269
+ %x{
270
+ if (!vnode.sel) return self.$escape(vnode.text)
271
+
272
+ const sel = self.$parse_sel(vnode.sel)
273
+
274
+ for (const key in vnode.data.class) {
275
+ vnode.data.class[key] ? sel['classes'][key] = true : delete sel['classes'][key]
276
+ }
277
+
278
+ let attributes = {}
279
+ if (sel['id'].length > 0) attributes['id'] = sel['id']
280
+
281
+ const classes = Object.keys(sel['classes'])
282
+ if (classes.length > 0) attributes['class'] = classes.join(' ')
283
+
284
+ for (const key in vnode.data.attrs) {
285
+ attributes[key] = vnode.data.attrs[key]
286
+ }
287
+
288
+ for (const key in vnode.data.dataset) {
289
+ attributes['data-' + key] = vnode.data.dataset[key]
290
+ }
291
+
292
+ for (const key in vnode.data.props) {
293
+ if (!IGNORE.has(key)) {
294
+ const value = vnode.data.props[key]
295
+
296
+ if (BOOLEAN.has(key)) {
297
+ if (value) attributes[key] = key
298
+ } else {
299
+ attributes[key] = value
300
+ }
301
+ }
302
+ }
303
+
304
+ const styles = []
305
+
306
+ for (let key in vnode.data.style) {
307
+ const value = vnode.data.style[key]
308
+ key = key.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
309
+ styles.push(key + ': ' + value)
310
+ }
311
+
312
+ if (styles.length > 0) attributes['style'] = styles.join('; ')
313
+
314
+ attributes = Object.keys(attributes).map(key =>
315
+ self.$escape(key) + '="' + self.$escape(attributes[key]) + '"'
316
+ )
317
+
318
+ const tag = sel['tag']
319
+ const elements = ['<' + tag]
320
+ if (attributes.length > 0) elements.push(' ' + attributes.join(' '))
321
+ elements.push('>')
322
+
323
+ if (!VOID.has(tag)) {
324
+ if (vnode.data.props && vnode.data.props.innerHTML) {
325
+ elements.push(vnode.data.props.innerHTML)
326
+ } else if (vnode.text) {
327
+ elements.push(self.$escape(vnode.text))
328
+ } else if (vnode.children) {
329
+ vnode.children.forEach(child =>
330
+ elements.push(self.$node_to_s(child))
331
+ )
332
+ }
333
+
334
+ elements.push('</' + tag + '>')
335
+ }
336
+
337
+ return elements.join('')
338
+ }
339
+ end
340
+ # rubocop:enable Lint/UnusedMethodArgument
341
+
342
+ def escape(html)
343
+ ERB::Util.html_escape(html)
344
+ end
154
345
  end
155
346
 
156
347
  # 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", {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snabberb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toby Mao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-13 00:00:00.000000000 Z
11
+ date: 2020-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -146,7 +146,6 @@ files:
146
146
  - lib/snabberb/version.rb
147
147
  - opal/snabberb.rb
148
148
  - opal/snabberb/component.rb
149
- - opal/vendor/snabbdom-to-html.js
150
149
  - opal/vendor/snabbdom.js
151
150
  - snabberb.gemspec
152
151
  homepage: https://github.com/tobymao