clearwater 0.1.0 → 0.1.1
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 +4 -4
- data/lib/clearwater/version.rb +1 -1
- data/lib/clearwater.rb +1 -0
- data/opal/clearwater/cached_render.rb +1 -1
- data/opal/clearwater/component.rb +30 -16
- data/opal/clearwater/link.rb +3 -1
- data/opal/clearwater/virtual_dom/js/virtual_dom.js +80 -167
- data/opal/clearwater/virtual_dom.rb +41 -69
- metadata +5 -6
- data/opal/clearwater/model.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11ea030584d8c9bbc61d8d81690140cc88fa6a6b
|
4
|
+
data.tar.gz: 7a2dc906feb4e2c005f0521c1e842592466edd18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b166c268e598a8f5179c05d33200ac7656ed153f49bb0da56e1a7f3e0e5a6d06c79e3e47ecd10b1c0f7be84136e74b7aa2e88490568aa5fb4cf54f1007d13bb
|
7
|
+
data.tar.gz: 65fa07556d0afacd3a63bfce7e49cb1d992fd31860afa1dbf8a61a4841a31bb0aa8bc203a7ffe900f36daa3dfc38ba56979b73eb8bd69561ee26fab8f164fff0
|
data/lib/clearwater/version.rb
CHANGED
data/lib/clearwater.rb
CHANGED
@@ -141,6 +141,12 @@ module Clearwater
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def tag tag_name, attributes=nil, content=nil
|
144
|
+
case attributes
|
145
|
+
when Array, Component, Numeric, String
|
146
|
+
content = attributes
|
147
|
+
attributes = nil
|
148
|
+
end
|
149
|
+
|
144
150
|
VirtualDOM.node(
|
145
151
|
tag_name,
|
146
152
|
sanitize_attributes(attributes),
|
@@ -157,7 +163,7 @@ module Clearwater
|
|
157
163
|
end
|
158
164
|
|
159
165
|
def sanitize_attributes attributes
|
160
|
-
return
|
166
|
+
return attributes unless attributes.is_a? Hash
|
161
167
|
|
162
168
|
# Allow specifying `class` instead of `class_name`.
|
163
169
|
# Note: `class_name` is still allowed
|
@@ -171,7 +177,7 @@ module Clearwater
|
|
171
177
|
end
|
172
178
|
|
173
179
|
attributes.each do |key, handler|
|
174
|
-
if key
|
180
|
+
if key[0, 2] == 'on'
|
175
181
|
attributes[key] = proc do |event|
|
176
182
|
handler.call(Browser::Event.new(event))
|
177
183
|
end
|
@@ -182,20 +188,28 @@ module Clearwater
|
|
182
188
|
end
|
183
189
|
|
184
190
|
def sanitize_content content
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
191
|
+
%x{
|
192
|
+
if(content.$$class) {
|
193
|
+
if(content.$$class === Opal.Array) {
|
194
|
+
return #{content.map { |c| `self.$sanitize_content(c)` }};
|
195
|
+
} else if(content === Opal.nil) {
|
196
|
+
return '';
|
197
|
+
} else {
|
198
|
+
var cached_render = content.$cached_render;
|
199
|
+
var render = content.$render;
|
200
|
+
|
201
|
+
if(cached_render && !cached_render.$$stub) {
|
202
|
+
return content.$cached_render();
|
203
|
+
} else if(render && !render.$$stub) {
|
204
|
+
return self.$sanitize_content(content.$render());
|
205
|
+
} else {
|
206
|
+
return content;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
} else {
|
210
|
+
return content;
|
211
|
+
}
|
212
|
+
}
|
199
213
|
end
|
200
214
|
|
201
215
|
def call &block
|
data/opal/clearwater/link.rb
CHANGED
@@ -86,7 +86,9 @@ class Link
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def navigate event
|
89
|
-
|
89
|
+
# Don't handle middle-button clicks and clicks with modifier keys. Let them
|
90
|
+
# pass through to the browser's default handling or the user's modified handling.
|
91
|
+
unless event.meta? || event.shift? || event.ctrl? || event.alt? || (event.respond_to?(:button) && event.button == 1)
|
90
92
|
event.prevent
|
91
93
|
if href != $window.location.path
|
92
94
|
$window.history.push href
|
@@ -3,17 +3,17 @@ var createElement = require("./vdom/create-element.js")
|
|
3
3
|
|
4
4
|
module.exports = createElement
|
5
5
|
|
6
|
-
},{"./vdom/create-element.js":
|
6
|
+
},{"./vdom/create-element.js":13}],2:[function(require,module,exports){
|
7
7
|
var diff = require("./vtree/diff.js")
|
8
8
|
|
9
9
|
module.exports = diff
|
10
10
|
|
11
|
-
},{"./vtree/diff.js":
|
11
|
+
},{"./vtree/diff.js":33}],3:[function(require,module,exports){
|
12
12
|
var h = require("./virtual-hyperscript/index.js")
|
13
13
|
|
14
14
|
module.exports = h
|
15
15
|
|
16
|
-
},{"./virtual-hyperscript/index.js":
|
16
|
+
},{"./virtual-hyperscript/index.js":20}],4:[function(require,module,exports){
|
17
17
|
var diff = require("./diff.js")
|
18
18
|
var patch = require("./patch.js")
|
19
19
|
var h = require("./h.js")
|
@@ -30,115 +30,7 @@ module.exports = {
|
|
30
30
|
VText: VText
|
31
31
|
}
|
32
32
|
|
33
|
-
},{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":
|
34
|
-
/*!
|
35
|
-
* Cross-Browser Split 1.1.1
|
36
|
-
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
|
37
|
-
* Available under the MIT License
|
38
|
-
* ECMAScript compliant, uniform cross-browser split method
|
39
|
-
*/
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Splits a string into an array of strings using a regex or string separator. Matches of the
|
43
|
-
* separator are not included in the result array. However, if `separator` is a regex that contains
|
44
|
-
* capturing groups, backreferences are spliced into the result each time `separator` is matched.
|
45
|
-
* Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
|
46
|
-
* cross-browser.
|
47
|
-
* @param {String} str String to split.
|
48
|
-
* @param {RegExp|String} separator Regex or string to use for separating the string.
|
49
|
-
* @param {Number} [limit] Maximum number of items to include in the result array.
|
50
|
-
* @returns {Array} Array of substrings.
|
51
|
-
* @example
|
52
|
-
*
|
53
|
-
* // Basic use
|
54
|
-
* split('a b c d', ' ');
|
55
|
-
* // -> ['a', 'b', 'c', 'd']
|
56
|
-
*
|
57
|
-
* // With limit
|
58
|
-
* split('a b c d', ' ', 2);
|
59
|
-
* // -> ['a', 'b']
|
60
|
-
*
|
61
|
-
* // Backreferences in result array
|
62
|
-
* split('..word1 word2..', /([a-z]+)(\d+)/i);
|
63
|
-
* // -> ['..', 'word', '1', ' ', 'word', '2', '..']
|
64
|
-
*/
|
65
|
-
module.exports = (function split(undef) {
|
66
|
-
|
67
|
-
var nativeSplit = String.prototype.split,
|
68
|
-
compliantExecNpcg = /()??/.exec("")[1] === undef,
|
69
|
-
// NPCG: nonparticipating capturing group
|
70
|
-
self;
|
71
|
-
|
72
|
-
self = function(str, separator, limit) {
|
73
|
-
// If `separator` is not a regex, use `nativeSplit`
|
74
|
-
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
|
75
|
-
return nativeSplit.call(str, separator, limit);
|
76
|
-
}
|
77
|
-
var output = [],
|
78
|
-
flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
|
79
|
-
(separator.sticky ? "y" : ""),
|
80
|
-
// Firefox 3+
|
81
|
-
lastLastIndex = 0,
|
82
|
-
// Make `global` and avoid `lastIndex` issues by working with a copy
|
83
|
-
separator = new RegExp(separator.source, flags + "g"),
|
84
|
-
separator2, match, lastIndex, lastLength;
|
85
|
-
str += ""; // Type-convert
|
86
|
-
if (!compliantExecNpcg) {
|
87
|
-
// Doesn't need flags gy, but they don't hurt
|
88
|
-
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
|
89
|
-
}
|
90
|
-
/* Values for `limit`, per the spec:
|
91
|
-
* If undefined: 4294967295 // Math.pow(2, 32) - 1
|
92
|
-
* If 0, Infinity, or NaN: 0
|
93
|
-
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
|
94
|
-
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
|
95
|
-
* If other: Type-convert, then use the above rules
|
96
|
-
*/
|
97
|
-
limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
|
98
|
-
limit >>> 0; // ToUint32(limit)
|
99
|
-
while (match = separator.exec(str)) {
|
100
|
-
// `separator.lastIndex` is not reliable cross-browser
|
101
|
-
lastIndex = match.index + match[0].length;
|
102
|
-
if (lastIndex > lastLastIndex) {
|
103
|
-
output.push(str.slice(lastLastIndex, match.index));
|
104
|
-
// Fix browsers whose `exec` methods don't consistently return `undefined` for
|
105
|
-
// nonparticipating capturing groups
|
106
|
-
if (!compliantExecNpcg && match.length > 1) {
|
107
|
-
match[0].replace(separator2, function() {
|
108
|
-
for (var i = 1; i < arguments.length - 2; i++) {
|
109
|
-
if (arguments[i] === undef) {
|
110
|
-
match[i] = undef;
|
111
|
-
}
|
112
|
-
}
|
113
|
-
});
|
114
|
-
}
|
115
|
-
if (match.length > 1 && match.index < str.length) {
|
116
|
-
Array.prototype.push.apply(output, match.slice(1));
|
117
|
-
}
|
118
|
-
lastLength = match[0].length;
|
119
|
-
lastLastIndex = lastIndex;
|
120
|
-
if (output.length >= limit) {
|
121
|
-
break;
|
122
|
-
}
|
123
|
-
}
|
124
|
-
if (separator.lastIndex === match.index) {
|
125
|
-
separator.lastIndex++; // Avoid an infinite loop
|
126
|
-
}
|
127
|
-
}
|
128
|
-
if (lastLastIndex === str.length) {
|
129
|
-
if (lastLength || !separator.test("")) {
|
130
|
-
output.push("");
|
131
|
-
}
|
132
|
-
} else {
|
133
|
-
output.push(str.slice(lastLastIndex));
|
134
|
-
}
|
135
|
-
return output.length > limit ? output.slice(0, limit) : output;
|
136
|
-
};
|
137
|
-
|
138
|
-
return self;
|
139
|
-
})();
|
140
|
-
|
141
|
-
},{}],6:[function(require,module,exports){
|
33
|
+
},{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":11,"./vnode/vnode.js":29,"./vnode/vtext.js":31}],5:[function(require,module,exports){
|
142
34
|
'use strict';
|
143
35
|
|
144
36
|
var OneVersionConstraint = require('individual/one-version');
|
@@ -160,7 +52,7 @@ function EvStore(elem) {
|
|
160
52
|
return hash;
|
161
53
|
}
|
162
54
|
|
163
|
-
},{"individual/one-version":
|
55
|
+
},{"individual/one-version":7}],6:[function(require,module,exports){
|
164
56
|
(function (global){
|
165
57
|
'use strict';
|
166
58
|
|
@@ -183,7 +75,7 @@ function Individual(key, value) {
|
|
183
75
|
}
|
184
76
|
|
185
77
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
186
|
-
},{}],
|
78
|
+
},{}],7:[function(require,module,exports){
|
187
79
|
'use strict';
|
188
80
|
|
189
81
|
var Individual = require('./index.js');
|
@@ -207,7 +99,7 @@ function OneVersion(moduleName, version, defaultValue) {
|
|
207
99
|
return Individual(key, defaultValue);
|
208
100
|
}
|
209
101
|
|
210
|
-
},{"./index.js":
|
102
|
+
},{"./index.js":6}],8:[function(require,module,exports){
|
211
103
|
(function (global){
|
212
104
|
var topLevel = typeof global !== 'undefined' ? global :
|
213
105
|
typeof window !== 'undefined' ? window : {}
|
@@ -226,14 +118,14 @@ if (typeof document !== 'undefined') {
|
|
226
118
|
}
|
227
119
|
|
228
120
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
229
|
-
},{"min-document":
|
121
|
+
},{"min-document":34}],9:[function(require,module,exports){
|
230
122
|
"use strict";
|
231
123
|
|
232
124
|
module.exports = function isObject(x) {
|
233
125
|
return typeof x === "object" && x !== null;
|
234
126
|
};
|
235
127
|
|
236
|
-
},{}],
|
128
|
+
},{}],10:[function(require,module,exports){
|
237
129
|
var nativeIsArray = Array.isArray
|
238
130
|
var toString = Object.prototype.toString
|
239
131
|
|
@@ -243,12 +135,12 @@ function isArray(obj) {
|
|
243
135
|
return toString.call(obj) === "[object Array]"
|
244
136
|
}
|
245
137
|
|
246
|
-
},{}],
|
138
|
+
},{}],11:[function(require,module,exports){
|
247
139
|
var patch = require("./vdom/patch.js")
|
248
140
|
|
249
141
|
module.exports = patch
|
250
142
|
|
251
|
-
},{"./vdom/patch.js":
|
143
|
+
},{"./vdom/patch.js":16}],12:[function(require,module,exports){
|
252
144
|
var isObject = require("is-object")
|
253
145
|
var isHook = require("../vnode/is-vhook.js")
|
254
146
|
|
@@ -347,7 +239,7 @@ function getPrototype(value) {
|
|
347
239
|
}
|
348
240
|
}
|
349
241
|
|
350
|
-
},{"../vnode/is-vhook.js":
|
242
|
+
},{"../vnode/is-vhook.js":24,"is-object":9}],13:[function(require,module,exports){
|
351
243
|
var document = require("global/document")
|
352
244
|
|
353
245
|
var applyProperties = require("./apply-properties")
|
@@ -395,7 +287,7 @@ function createElement(vnode, opts) {
|
|
395
287
|
return node
|
396
288
|
}
|
397
289
|
|
398
|
-
},{"../vnode/handle-thunk.js":
|
290
|
+
},{"../vnode/handle-thunk.js":22,"../vnode/is-vnode.js":25,"../vnode/is-vtext.js":26,"../vnode/is-widget.js":27,"./apply-properties":12,"global/document":8}],14:[function(require,module,exports){
|
399
291
|
// Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
|
400
292
|
// We don't want to read all of the DOM nodes in the tree so we use
|
401
293
|
// the in-order tree indexing to eliminate recursion down certain branches.
|
@@ -482,13 +374,12 @@ function ascending(a, b) {
|
|
482
374
|
return a > b ? 1 : -1
|
483
375
|
}
|
484
376
|
|
485
|
-
},{}],
|
377
|
+
},{}],15:[function(require,module,exports){
|
486
378
|
var applyProperties = require("./apply-properties")
|
487
379
|
|
488
380
|
var isWidget = require("../vnode/is-widget.js")
|
489
381
|
var VPatch = require("../vnode/vpatch.js")
|
490
382
|
|
491
|
-
var render = require("./create-element")
|
492
383
|
var updateWidget = require("./update-widget")
|
493
384
|
|
494
385
|
module.exports = applyPatch
|
@@ -536,7 +427,7 @@ function removeNode(domNode, vNode) {
|
|
536
427
|
}
|
537
428
|
|
538
429
|
function insertNode(parentNode, vNode, renderOptions) {
|
539
|
-
var newNode = render(vNode, renderOptions)
|
430
|
+
var newNode = renderOptions.render(vNode, renderOptions)
|
540
431
|
|
541
432
|
if (parentNode) {
|
542
433
|
parentNode.appendChild(newNode)
|
@@ -553,7 +444,7 @@ function stringPatch(domNode, leftVNode, vText, renderOptions) {
|
|
553
444
|
newNode = domNode
|
554
445
|
} else {
|
555
446
|
var parentNode = domNode.parentNode
|
556
|
-
newNode = render(vText, renderOptions)
|
447
|
+
newNode = renderOptions.render(vText, renderOptions)
|
557
448
|
|
558
449
|
if (parentNode && newNode !== domNode) {
|
559
450
|
parentNode.replaceChild(newNode, domNode)
|
@@ -570,7 +461,7 @@ function widgetPatch(domNode, leftVNode, widget, renderOptions) {
|
|
570
461
|
if (updating) {
|
571
462
|
newNode = widget.update(leftVNode, domNode) || domNode
|
572
463
|
} else {
|
573
|
-
newNode = render(widget, renderOptions)
|
464
|
+
newNode = renderOptions.render(widget, renderOptions)
|
574
465
|
}
|
575
466
|
|
576
467
|
var parentNode = domNode.parentNode
|
@@ -588,7 +479,7 @@ function widgetPatch(domNode, leftVNode, widget, renderOptions) {
|
|
588
479
|
|
589
480
|
function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
|
590
481
|
var parentNode = domNode.parentNode
|
591
|
-
var newNode = render(vNode, renderOptions)
|
482
|
+
var newNode = renderOptions.render(vNode, renderOptions)
|
592
483
|
|
593
484
|
if (parentNode && newNode !== domNode) {
|
594
485
|
parentNode.replaceChild(newNode, domNode)
|
@@ -636,16 +527,21 @@ function replaceRoot(oldRoot, newRoot) {
|
|
636
527
|
return newRoot;
|
637
528
|
}
|
638
529
|
|
639
|
-
},{"../vnode/is-widget.js":
|
530
|
+
},{"../vnode/is-widget.js":27,"../vnode/vpatch.js":30,"./apply-properties":12,"./update-widget":17}],16:[function(require,module,exports){
|
640
531
|
var document = require("global/document")
|
641
532
|
var isArray = require("x-is-array")
|
642
533
|
|
534
|
+
var render = require("./create-element")
|
643
535
|
var domIndex = require("./dom-index")
|
644
536
|
var patchOp = require("./patch-op")
|
645
537
|
module.exports = patch
|
646
538
|
|
647
|
-
function patch(rootNode, patches) {
|
648
|
-
|
539
|
+
function patch(rootNode, patches, renderOptions) {
|
540
|
+
renderOptions = renderOptions || {}
|
541
|
+
renderOptions.patch = renderOptions.patch || patchRecursive
|
542
|
+
renderOptions.render = renderOptions.render || render
|
543
|
+
|
544
|
+
return renderOptions.patch(rootNode, patches, renderOptions)
|
649
545
|
}
|
650
546
|
|
651
547
|
function patchRecursive(rootNode, patches, renderOptions) {
|
@@ -658,11 +554,8 @@ function patchRecursive(rootNode, patches, renderOptions) {
|
|
658
554
|
var index = domIndex(rootNode, patches.a, indices)
|
659
555
|
var ownerDocument = rootNode.ownerDocument
|
660
556
|
|
661
|
-
if (!renderOptions) {
|
662
|
-
renderOptions =
|
663
|
-
if (ownerDocument !== document) {
|
664
|
-
renderOptions.document = ownerDocument
|
665
|
-
}
|
557
|
+
if (!renderOptions.document && ownerDocument !== document) {
|
558
|
+
renderOptions.document = ownerDocument
|
666
559
|
}
|
667
560
|
|
668
561
|
for (var i = 0; i < indices.length; i++) {
|
@@ -714,7 +607,7 @@ function patchIndices(patches) {
|
|
714
607
|
return indices
|
715
608
|
}
|
716
609
|
|
717
|
-
},{"./dom-index":
|
610
|
+
},{"./create-element":13,"./dom-index":14,"./patch-op":15,"global/document":8,"x-is-array":10}],17:[function(require,module,exports){
|
718
611
|
var isWidget = require("../vnode/is-widget.js")
|
719
612
|
|
720
613
|
module.exports = updateWidget
|
@@ -731,7 +624,7 @@ function updateWidget(a, b) {
|
|
731
624
|
return false
|
732
625
|
}
|
733
626
|
|
734
|
-
},{"../vnode/is-widget.js":
|
627
|
+
},{"../vnode/is-widget.js":27}],18:[function(require,module,exports){
|
735
628
|
'use strict';
|
736
629
|
|
737
630
|
var EvStore = require('ev-store');
|
@@ -760,7 +653,7 @@ EvHook.prototype.unhook = function(node, propertyName) {
|
|
760
653
|
es[propName] = undefined;
|
761
654
|
};
|
762
655
|
|
763
|
-
},{"ev-store":
|
656
|
+
},{"ev-store":5}],19:[function(require,module,exports){
|
764
657
|
'use strict';
|
765
658
|
|
766
659
|
module.exports = SoftSetHook;
|
@@ -779,7 +672,7 @@ SoftSetHook.prototype.hook = function (node, propertyName) {
|
|
779
672
|
}
|
780
673
|
};
|
781
674
|
|
782
|
-
},{}],
|
675
|
+
},{}],20:[function(require,module,exports){
|
783
676
|
'use strict';
|
784
677
|
|
785
678
|
var isArray = require('x-is-array');
|
@@ -845,6 +738,8 @@ function h(tagName, properties, children) {
|
|
845
738
|
function addChild(c, childNodes, tag, props) {
|
846
739
|
if (typeof c === 'string') {
|
847
740
|
childNodes.push(new VText(c));
|
741
|
+
} else if (typeof c === 'number') {
|
742
|
+
childNodes.push(new VText(String(c)));
|
848
743
|
} else if (isChild(c)) {
|
849
744
|
childNodes.push(c);
|
850
745
|
} else if (isArray(c)) {
|
@@ -916,14 +811,9 @@ function errorString(obj) {
|
|
916
811
|
}
|
917
812
|
}
|
918
813
|
|
919
|
-
},{"../vnode/is-thunk":
|
814
|
+
},{"../vnode/is-thunk":23,"../vnode/is-vhook":24,"../vnode/is-vnode":25,"../vnode/is-vtext":26,"../vnode/is-widget":27,"../vnode/vnode.js":29,"../vnode/vtext.js":31,"./hooks/ev-hook.js":18,"./hooks/soft-set-hook.js":19,"./parse-tag.js":21,"x-is-array":10}],21:[function(require,module,exports){
|
920
815
|
'use strict';
|
921
816
|
|
922
|
-
var split = require('browser-split');
|
923
|
-
|
924
|
-
var classIdSplit = /([\.#]?[a-zA-Z0-9_:-]+)/;
|
925
|
-
var notClassId = /^\.|#/;
|
926
|
-
|
927
817
|
module.exports = parseTag;
|
928
818
|
|
929
819
|
function parseTag(tag, props) {
|
@@ -933,16 +823,13 @@ function parseTag(tag, props) {
|
|
933
823
|
|
934
824
|
var noId = !(props.hasOwnProperty('id'));
|
935
825
|
|
936
|
-
var tagParts =
|
937
|
-
var tagName = null;
|
826
|
+
var tagParts = splitTag(tag);
|
938
827
|
|
939
|
-
|
940
|
-
tagName = 'DIV';
|
941
|
-
}
|
828
|
+
var tagName = tagParts[0] || 'DIV';
|
942
829
|
|
943
830
|
var classes, part, type, i;
|
944
831
|
|
945
|
-
for (i =
|
832
|
+
for (i = 1; i < tagParts.length; i++) {
|
946
833
|
part = tagParts[i];
|
947
834
|
|
948
835
|
if (!part) {
|
@@ -951,9 +838,7 @@ function parseTag(tag, props) {
|
|
951
838
|
|
952
839
|
type = part.charAt(0);
|
953
840
|
|
954
|
-
if (
|
955
|
-
tagName = part;
|
956
|
-
} else if (type === '.') {
|
841
|
+
if (type === '.') {
|
957
842
|
classes = classes || [];
|
958
843
|
classes.push(part.substring(1, part.length));
|
959
844
|
} else if (type === '#' && noId) {
|
@@ -972,7 +857,35 @@ function parseTag(tag, props) {
|
|
972
857
|
return props.namespace ? tagName : tagName.toUpperCase();
|
973
858
|
}
|
974
859
|
|
975
|
-
|
860
|
+
|
861
|
+
function splitTag(tag) {
|
862
|
+
|
863
|
+
var classIndex, idIndex,
|
864
|
+
remaining = tag,
|
865
|
+
parts = [],
|
866
|
+
last = '';
|
867
|
+
|
868
|
+
do {
|
869
|
+
idIndex = remaining.indexOf('#');
|
870
|
+
classIndex = remaining.indexOf('.');
|
871
|
+
if ((idIndex === -1 || idIndex > classIndex) && classIndex !== -1) {
|
872
|
+
parts.push(last + remaining.substr(0, classIndex));
|
873
|
+
last = '.';
|
874
|
+
remaining = remaining.substr(classIndex + 1);
|
875
|
+
} else if (idIndex !== -1){
|
876
|
+
parts.push(last + remaining.substr(0, idIndex));
|
877
|
+
last = '#';
|
878
|
+
remaining = remaining.substr(idIndex + 1);
|
879
|
+
}
|
880
|
+
|
881
|
+
} while(idIndex !== -1 || classIndex !== -1)
|
882
|
+
|
883
|
+
parts.push(last + remaining);
|
884
|
+
|
885
|
+
return parts;
|
886
|
+
}
|
887
|
+
|
888
|
+
},{}],22:[function(require,module,exports){
|
976
889
|
var isVNode = require("./is-vnode")
|
977
890
|
var isVText = require("./is-vtext")
|
978
891
|
var isWidget = require("./is-widget")
|
@@ -1014,14 +927,14 @@ function renderThunk(thunk, previous) {
|
|
1014
927
|
return renderedThunk
|
1015
928
|
}
|
1016
929
|
|
1017
|
-
},{"./is-thunk":
|
930
|
+
},{"./is-thunk":23,"./is-vnode":25,"./is-vtext":26,"./is-widget":27}],23:[function(require,module,exports){
|
1018
931
|
module.exports = isThunk
|
1019
932
|
|
1020
933
|
function isThunk(t) {
|
1021
934
|
return t && t.type === "Thunk"
|
1022
935
|
}
|
1023
936
|
|
1024
|
-
},{}],
|
937
|
+
},{}],24:[function(require,module,exports){
|
1025
938
|
module.exports = isHook
|
1026
939
|
|
1027
940
|
function isHook(hook) {
|
@@ -1030,7 +943,7 @@ function isHook(hook) {
|
|
1030
943
|
typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
|
1031
944
|
}
|
1032
945
|
|
1033
|
-
},{}],
|
946
|
+
},{}],25:[function(require,module,exports){
|
1034
947
|
var version = require("./version")
|
1035
948
|
|
1036
949
|
module.exports = isVirtualNode
|
@@ -1039,7 +952,7 @@ function isVirtualNode(x) {
|
|
1039
952
|
return x && x.type === "VirtualNode" && x.version === version
|
1040
953
|
}
|
1041
954
|
|
1042
|
-
},{"./version":
|
955
|
+
},{"./version":28}],26:[function(require,module,exports){
|
1043
956
|
var version = require("./version")
|
1044
957
|
|
1045
958
|
module.exports = isVirtualText
|
@@ -1048,17 +961,17 @@ function isVirtualText(x) {
|
|
1048
961
|
return x && x.type === "VirtualText" && x.version === version
|
1049
962
|
}
|
1050
963
|
|
1051
|
-
},{"./version":
|
964
|
+
},{"./version":28}],27:[function(require,module,exports){
|
1052
965
|
module.exports = isWidget
|
1053
966
|
|
1054
967
|
function isWidget(w) {
|
1055
968
|
return w && w.type === "Widget"
|
1056
969
|
}
|
1057
970
|
|
1058
|
-
},{}],
|
971
|
+
},{}],28:[function(require,module,exports){
|
1059
972
|
module.exports = "2"
|
1060
973
|
|
1061
|
-
},{}],
|
974
|
+
},{}],29:[function(require,module,exports){
|
1062
975
|
var version = require("./version")
|
1063
976
|
var isVNode = require("./is-vnode")
|
1064
977
|
var isWidget = require("./is-widget")
|
@@ -1132,7 +1045,7 @@ function VirtualNode(tagName, properties, children, key, namespace) {
|
|
1132
1045
|
VirtualNode.prototype.version = version
|
1133
1046
|
VirtualNode.prototype.type = "VirtualNode"
|
1134
1047
|
|
1135
|
-
},{"./is-thunk":
|
1048
|
+
},{"./is-thunk":23,"./is-vhook":24,"./is-vnode":25,"./is-widget":27,"./version":28}],30:[function(require,module,exports){
|
1136
1049
|
var version = require("./version")
|
1137
1050
|
|
1138
1051
|
VirtualPatch.NONE = 0
|
@@ -1156,7 +1069,7 @@ function VirtualPatch(type, vNode, patch) {
|
|
1156
1069
|
VirtualPatch.prototype.version = version
|
1157
1070
|
VirtualPatch.prototype.type = "VirtualPatch"
|
1158
1071
|
|
1159
|
-
},{"./version":
|
1072
|
+
},{"./version":28}],31:[function(require,module,exports){
|
1160
1073
|
var version = require("./version")
|
1161
1074
|
|
1162
1075
|
module.exports = VirtualText
|
@@ -1168,7 +1081,7 @@ function VirtualText(text) {
|
|
1168
1081
|
VirtualText.prototype.version = version
|
1169
1082
|
VirtualText.prototype.type = "VirtualText"
|
1170
1083
|
|
1171
|
-
},{"./version":
|
1084
|
+
},{"./version":28}],32:[function(require,module,exports){
|
1172
1085
|
var isObject = require("is-object")
|
1173
1086
|
var isHook = require("../vnode/is-vhook")
|
1174
1087
|
|
@@ -1228,7 +1141,7 @@ function getPrototype(value) {
|
|
1228
1141
|
}
|
1229
1142
|
}
|
1230
1143
|
|
1231
|
-
},{"../vnode/is-vhook":
|
1144
|
+
},{"../vnode/is-vhook":24,"is-object":9}],33:[function(require,module,exports){
|
1232
1145
|
var isArray = require("x-is-array")
|
1233
1146
|
|
1234
1147
|
var VPatch = require("../vnode/vpatch")
|
@@ -1657,7 +1570,7 @@ function appendPatch(apply, patch) {
|
|
1657
1570
|
}
|
1658
1571
|
}
|
1659
1572
|
|
1660
|
-
},{"../vnode/handle-thunk":
|
1573
|
+
},{"../vnode/handle-thunk":22,"../vnode/is-thunk":23,"../vnode/is-vnode":25,"../vnode/is-vtext":26,"../vnode/is-widget":27,"../vnode/vpatch":30,"./diff-props":32,"x-is-array":10}],34:[function(require,module,exports){
|
1661
1574
|
|
1662
1575
|
},{}]},{},[4])(4)
|
1663
1576
|
});
|
@@ -1,108 +1,80 @@
|
|
1
1
|
require 'browser'
|
2
2
|
require 'clearwater/virtual_dom/js/virtual_dom.js'
|
3
3
|
|
4
|
-
module
|
5
|
-
def self.
|
6
|
-
|
4
|
+
module VirtualDOM
|
5
|
+
def self.node(tag_name, attributes, content)
|
6
|
+
content = sanitize_content(content)
|
7
|
+
attributes = HashUtils.camelize_keys(attributes).to_n
|
8
|
+
`virtualDom.h(tag_name, attributes, content)`
|
7
9
|
end
|
8
|
-
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
return nil if hash.nil?
|
13
|
-
|
14
|
-
Hash[hash.map { |k,v|
|
15
|
-
key = StringUtils.camelize(k)
|
16
|
-
value = if Hash === v
|
17
|
-
camelize_keys(v)
|
18
|
-
else
|
19
|
-
v
|
20
|
-
end
|
21
|
-
|
22
|
-
[key, value]
|
23
|
-
}]
|
11
|
+
def self.diff first, second
|
12
|
+
`virtualDom.diff(first, second)`
|
24
13
|
end
|
25
|
-
end
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
content = Array(content).map { |node|
|
30
|
-
case node
|
31
|
-
when Node
|
32
|
-
node.node
|
33
|
-
else
|
34
|
-
node
|
35
|
-
end
|
36
|
-
}
|
37
|
-
attributes = HashUtils.camelize_keys(attributes).to_n
|
38
|
-
Node.new(`virtualDom.h(tag_name, attributes, content)`)
|
15
|
+
def self.patch node, diff
|
16
|
+
`virtualDom.patch(node, diff)`
|
39
17
|
end
|
40
18
|
|
41
|
-
def self.
|
42
|
-
|
19
|
+
def self.sanitize_content content
|
20
|
+
%x{
|
21
|
+
if(content === Opal.nil) return Opal.nil;
|
22
|
+
if(content.$$class === Opal.Array)
|
23
|
+
return #{content.map!{ |c| sanitize_content c }};
|
24
|
+
return content;
|
25
|
+
}
|
43
26
|
end
|
44
27
|
|
45
28
|
class Document
|
46
29
|
def initialize(root=$document.create_element('div'))
|
47
30
|
@root = root
|
48
|
-
@rendered_nodes = {}
|
49
31
|
end
|
50
32
|
|
51
33
|
def render node
|
52
34
|
if rendered?
|
53
|
-
diff =
|
54
|
-
@tree
|
35
|
+
diff = VirtualDOM.diff @node, node
|
36
|
+
VirtualDOM.patch @tree, diff
|
55
37
|
@node = node
|
56
38
|
else
|
57
39
|
@node = node
|
58
|
-
@tree = node
|
59
|
-
@root.inner_dom = @tree
|
40
|
+
@tree = create_element(node)
|
41
|
+
@root.inner_dom = @tree
|
60
42
|
@rendered = true
|
61
43
|
end
|
62
44
|
end
|
63
45
|
|
46
|
+
def create_element node
|
47
|
+
`virtualDom.create(node)`
|
48
|
+
end
|
49
|
+
|
64
50
|
def rendered?
|
65
51
|
@rendered
|
66
52
|
end
|
67
53
|
end
|
68
54
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def initialize(node)
|
73
|
-
@node = node
|
74
|
-
end
|
75
|
-
|
76
|
-
def method_missing *args, &block
|
77
|
-
node.send *args, &block
|
78
|
-
end
|
79
|
-
|
80
|
-
def to_element
|
81
|
-
Element.new(VirtualDOM.create_element(node))
|
82
|
-
end
|
83
|
-
|
84
|
-
def diff other
|
85
|
-
`virtualDom.diff(self.node, other.node)`
|
86
|
-
end
|
87
|
-
|
88
|
-
def patch diff
|
89
|
-
`virtualDom.patch(#{to_element.to_n}, diff)`
|
55
|
+
module StringUtils
|
56
|
+
def self.camelize string
|
57
|
+
string.gsub(/_(\w)/) { |match| match.gsub(/_/, '').upcase }
|
90
58
|
end
|
91
59
|
end
|
92
60
|
|
93
|
-
|
94
|
-
|
61
|
+
module HashUtils
|
62
|
+
def self.camelize_keys(hash)
|
63
|
+
return hash unless hash.is_a? Hash
|
95
64
|
|
96
|
-
|
97
|
-
|
98
|
-
|
65
|
+
camelized = {}
|
66
|
+
hash.each do |k, v|
|
67
|
+
key = StringUtils.camelize(k)
|
68
|
+
value = if v.class == Hash
|
69
|
+
camelize_keys(v)
|
70
|
+
else
|
71
|
+
v
|
72
|
+
end
|
99
73
|
|
100
|
-
|
101
|
-
|
102
|
-
end
|
74
|
+
camelized[key] = value
|
75
|
+
end
|
103
76
|
|
104
|
-
|
105
|
-
@element
|
77
|
+
camelized
|
106
78
|
end
|
107
79
|
end
|
108
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clearwater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Gaskins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.7
|
19
|
+
version: '0.7'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.7
|
26
|
+
version: '0.7'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: opal-browser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,7 +139,6 @@ files:
|
|
139
139
|
- opal/clearwater/cgi.rb
|
140
140
|
- opal/clearwater/component.rb
|
141
141
|
- opal/clearwater/link.rb
|
142
|
-
- opal/clearwater/model.rb
|
143
142
|
- opal/clearwater/router.rb
|
144
143
|
- opal/clearwater/router/route.rb
|
145
144
|
- opal/clearwater/router/route_collection.rb
|
@@ -166,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
165
|
version: '0'
|
167
166
|
requirements: []
|
168
167
|
rubyforge_project:
|
169
|
-
rubygems_version: 2.4.
|
168
|
+
rubygems_version: 2.4.8
|
170
169
|
signing_key:
|
171
170
|
specification_version: 4
|
172
171
|
summary: Front-end web framework built on Opal
|
data/opal/clearwater/model.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require "clearwater/binding"
|
2
|
-
|
3
|
-
module Clearwater
|
4
|
-
class Model
|
5
|
-
def initialize attributes={}
|
6
|
-
@_bindings = Hash.new { |h,k| h[k] = [] }
|
7
|
-
self.class.attributes.each do |attr|
|
8
|
-
public_send "#{attr}=", attributes[attr]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def add_binding attribute, &block
|
13
|
-
binding = Binding.new(self, attribute, &block)
|
14
|
-
@_bindings[attribute].delete_if(&:dead?)
|
15
|
-
@_bindings[attribute] << binding
|
16
|
-
binding
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.attributes *args
|
20
|
-
@attributes ||= []
|
21
|
-
args.each do |attr|
|
22
|
-
attr_reader attr
|
23
|
-
|
24
|
-
define_method "#{attr}=" do |value|
|
25
|
-
instance_variable_set "@#{attr}", value
|
26
|
-
@_bindings[attr].each(&:call)
|
27
|
-
@_bindings[attr].delete_if(&:dead?)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
@attributes.concat args
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|