snabberb 0.5.0 → 1.0.0

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 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