unpoly-rails 0.56.7 → 0.57.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -1
  3. data/dist/unpoly.js +1569 -793
  4. data/dist/unpoly.min.js +4 -4
  5. data/lib/assets/javascripts/unpoly.coffee +2 -0
  6. data/lib/assets/javascripts/unpoly/browser.coffee.erb +25 -41
  7. data/lib/assets/javascripts/unpoly/bus.coffee.erb +20 -6
  8. data/lib/assets/javascripts/unpoly/classes/cache.coffee +23 -13
  9. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +87 -0
  10. data/lib/assets/javascripts/unpoly/classes/focus_tracker.coffee +29 -0
  11. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +7 -4
  12. data/lib/assets/javascripts/unpoly/classes/record.coffee +1 -1
  13. data/lib/assets/javascripts/unpoly/classes/request.coffee +38 -45
  14. data/lib/assets/javascripts/unpoly/classes/response.coffee +16 -1
  15. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +26 -0
  16. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +59 -0
  17. data/lib/assets/javascripts/unpoly/cookie.coffee +56 -0
  18. data/lib/assets/javascripts/unpoly/dom.coffee.erb +67 -39
  19. data/lib/assets/javascripts/unpoly/feedback.coffee +2 -2
  20. data/lib/assets/javascripts/unpoly/form.coffee.erb +23 -12
  21. data/lib/assets/javascripts/unpoly/history.coffee +2 -2
  22. data/lib/assets/javascripts/unpoly/layout.coffee.erb +118 -99
  23. data/lib/assets/javascripts/unpoly/link.coffee.erb +12 -5
  24. data/lib/assets/javascripts/unpoly/log.coffee +6 -5
  25. data/lib/assets/javascripts/unpoly/modal.coffee.erb +9 -2
  26. data/lib/assets/javascripts/unpoly/motion.coffee.erb +2 -6
  27. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +2 -2
  28. data/lib/assets/javascripts/unpoly/params.coffee.erb +522 -0
  29. data/lib/assets/javascripts/unpoly/popup.coffee.erb +3 -3
  30. data/lib/assets/javascripts/unpoly/proxy.coffee +42 -34
  31. data/lib/assets/javascripts/unpoly/{syntax.coffee → syntax.coffee.erb} +59 -117
  32. data/lib/assets/javascripts/unpoly/{util.coffee → util.coffee.erb} +206 -171
  33. data/lib/unpoly/rails/version.rb +1 -1
  34. data/package.json +1 -1
  35. data/spec_app/Gemfile.lock +1 -1
  36. data/spec_app/app/assets/javascripts/integration_test.coffee +0 -4
  37. data/spec_app/app/assets/stylesheets/integration_test.sass +7 -1
  38. data/spec_app/app/controllers/pages_controller.rb +4 -0
  39. data/spec_app/app/views/form_test/basics/new.erb +34 -5
  40. data/spec_app/app/views/form_test/submission_result.erb +2 -2
  41. data/spec_app/app/views/form_test/uploads/new.erb +15 -2
  42. data/spec_app/app/views/hash_test/unpoly.erb +30 -0
  43. data/spec_app/app/views/pages/start.erb +2 -1
  44. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +17 -2
  45. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +5 -0
  46. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +1 -1
  47. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +5 -0
  48. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +8 -8
  49. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +58 -20
  50. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +78 -0
  51. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +31 -0
  52. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +50 -0
  53. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +67 -0
  54. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +113 -0
  55. data/spec_app/spec/javascripts/up/dom_spec.js.coffee +133 -45
  56. data/spec_app/spec/javascripts/up/form_spec.js.coffee +13 -13
  57. data/spec_app/spec/javascripts/up/layout_spec.js.coffee +110 -26
  58. data/spec_app/spec/javascripts/up/link_spec.js.coffee +1 -1
  59. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +1 -0
  60. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +52 -51
  61. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +2 -2
  62. data/spec_app/spec/javascripts/up/params_spec.coffee +768 -0
  63. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +75 -36
  64. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +48 -15
  65. data/spec_app/spec/javascripts/up/util_spec.js.coffee +148 -131
  66. metadata +17 -5
  67. data/spec_app/spec/javascripts/up/classes/.keep +0 -0
@@ -56,7 +56,7 @@ up.popup = (($) ->
56
56
  @param {string} [config.position='bottom-right']
57
57
  Defines where the popup is attached to the opening element.
58
58
 
59
- Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
59
+ Valid values are `'bottom-right'`, `'bottom-left'`, `'top-right'` and `'top-left'`.
60
60
  @param {string} [config.history=false]
61
61
  Whether opening a popup will add a browser history entry.
62
62
  @param {string} [config.openAnimation='fade-in']
@@ -199,7 +199,7 @@ up.popup = (($) ->
199
199
  @param {string} [options.position='bottom-right']
200
200
  Defines where the popup is attached to the opening element.
201
201
 
202
- Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
202
+ Valid values are `'bottom-right'`, `'bottom-left'`, `'top-right'` and `'top-left'`.
203
203
  @param {string} [options.html]
204
204
  A string of HTML from which to extract the popup contents. No network request will be made.
205
205
  @param {string} [options.confirm]
@@ -405,7 +405,7 @@ up.popup = (($) ->
405
405
  @param [up-position]
406
406
  Defines where the popup is attached to the opening element.
407
407
 
408
- Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
408
+ Valid values are `'bottom-right'`, `'bottom-left'`, `'top-right'` and `'top-left'`.
409
409
  @param {string} [up-confirm]
410
410
  A message that will be displayed in a cancelable confirmation dialog
411
411
  before the popup is opened.
@@ -157,7 +157,7 @@ up.proxy = (($) ->
157
157
 
158
158
  \#\#\# Example
159
159
 
160
- up.request('/search', data: { query: 'sunshine' }).then(function(response) {
160
+ up.request('/search', params: { query: 'sunshine' }).then(function(response) {
161
161
  console.log('The response text is %o', response.text);
162
162
  }).catch(function() {
163
163
  console.error('The request failed');
@@ -192,14 +192,8 @@ up.proxy = (($) ->
192
192
  requests, if available. If set to `false` a network connection will always be attempted.
193
193
  @param {Object} [options.headers={}]
194
194
  An object of additional HTTP headers.
195
- @param {Object|Array|FormData} [options.data={}]
196
- Parameters that should be sent as the request's payload.
197
-
198
- Parameters may be passed as one of the following forms:
199
-
200
- 1. An object where keys are param names and the values are param values
201
- 2. An array of `{ name: 'param-name', value: 'param-value' }` objects
202
- 3. A [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object
195
+ @param {Object|FormData|string|Array} [options.params={}]
196
+ [Parameters](/up.params) that should be sent as the request's payload.
203
197
  @param {string} [options.timeout]
204
198
  A timeout in milliseconds.
205
199
 
@@ -214,23 +208,30 @@ up.proxy = (($) ->
214
208
  @stable
215
209
  ###
216
210
  makeRequest = (args...) ->
217
- options = u.extractOptions(args)
218
- options.url = args[0] if u.isGiven(args[0])
211
+ if u.isString(args[0])
212
+ url = args.shift()
219
213
 
220
- ignoreCache = (options.cache == false)
214
+ # We cannot use u.extractOptions() since sometimes the last argument
215
+ # is an up.Request instead of a basic object.
216
+ requestOrOptions = args.shift() || {}
221
217
 
222
- request = up.Request.wrap(options)
218
+ if url
219
+ requestOrOptions.url = url
220
+
221
+ request = up.Request.wrap(requestOrOptions)
223
222
 
224
223
  # Non-GET requests always touch the network
225
- # unless `options.cache` is explicitly set to `true`.
224
+ # unless `request.cache` is explicitly set to `true`.
226
225
  # These requests are never cached.
227
226
  if !request.isSafe()
228
227
  # We clear the entire cache before an unsafe request, since we
229
228
  # assume the user is writing a change.
230
229
  clear()
231
230
 
231
+ ignoreCache = (request.cache == false)
232
+
232
233
  # If we have an existing promise matching this new request,
233
- # we use it unless `options.cache` is explicitly set to `false`.
234
+ # we use it unless `request.cache` is explicitly set to `false`.
234
235
  if !ignoreCache && (promise = get(request))
235
236
  up.puts 'Re-using cached response for %s %s', request.method, request.url
236
237
  else
@@ -241,7 +242,7 @@ up.proxy = (($) ->
241
242
  promise.catch (e) ->
242
243
  remove(request)
243
244
 
244
- if !options.preload
245
+ if !request.preload
245
246
  # This might actually make `pendingCount` higher than the actual
246
247
  # number of outstanding requests. However, we need to cover the
247
248
  # following case:
@@ -264,7 +265,7 @@ up.proxy = (($) ->
264
265
 
265
266
  \#\#\# Example
266
267
 
267
- up.request('/search', data: { query: 'sunshine' }).then(function(text) {
268
+ up.request('/search', params: { query: 'sunshine' }).then(function(text) {
268
269
  console.log('The response text is %o', text);
269
270
  }).catch(function() {
270
271
  console.error('The request failed');
@@ -286,14 +287,8 @@ up.proxy = (($) ->
286
287
  @param {Object} [request.headers={}]
287
288
  An object of additional header key/value pairs to send along
288
289
  with the request.
289
- @param {Object|Array|FormData} [options.data]
290
- Parameters that should be sent as the request's payload.
291
-
292
- Parameters may be passed as one of the following forms:
293
-
294
- 1. An object where keys are param names and the values are param values
295
- 2. An array of `{ name: 'param-name', value: 'param-value' }` objects
296
- 3. A [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object
290
+ @param {Object|FormData|string|Array} [options.params]
291
+ [Parameters](/up.params) that should be sent as the request's payload.
297
292
  @param {string} [request.timeout]
298
293
  A timeout in milliseconds for the request.
299
294
 
@@ -305,7 +300,7 @@ up.proxy = (($) ->
305
300
  Use [`up.request()`](/up.request) instead.
306
301
  ###
307
302
  ajax = (args...) ->
308
- up.log.warn('up.ajax() has been deprecated. Use up.request() instead.')
303
+ up.warn('up.ajax() has been deprecated. Use up.request() instead.')
309
304
  new Promise (resolve, reject) ->
310
305
  pickResponseText = (response) -> resolve(response.text)
311
306
  makeRequest(args...).then(pickResponseText, reject)
@@ -418,7 +413,6 @@ up.proxy = (($) ->
418
413
  @event up:proxy:recover
419
414
  @stable
420
415
  ###
421
-
422
416
  loadOrQueue = (request) ->
423
417
  if pendingCount < config.maxRequests
424
418
  load(request)
@@ -563,7 +557,7 @@ up.proxy = (($) ->
563
557
  ###
564
558
  clear = cache.clear
565
559
 
566
- up.bus.renamedEvent('up:proxy:received', 'up:proxy:loaded')
560
+ up.bus.deprecateRenamedEvent('up:proxy:received', 'up:proxy:loaded')
567
561
 
568
562
  preloadAfterDelay = ($link) ->
569
563
  delay = parseInt(u.presentAttr($link, 'up-delay')) || config.preloadDelay
@@ -592,20 +586,34 @@ up.proxy = (($) ->
592
586
  @function up.proxy.preload
593
587
  @param {string|Element|jQuery}
594
588
  The element whose destination should be preloaded.
589
+ @param {object} options
590
+ Options that will be passed to the function making the HTTP requests.
595
591
  @return
596
592
  A promise that will be fulfilled when the request was loaded and cached
597
593
  @experimental
598
594
  ###
599
- preload = (linkOrSelector) ->
595
+ preload = (linkOrSelector, options) ->
600
596
  $link = $(linkOrSelector)
601
597
 
602
598
  if up.link.isSafe($link)
603
- up.log.group "Preloading link %o", $link.get(0), ->
599
+ preloadEventAttrs = { message: ['Preloading link %o', $link.get(0)], $element: $link, $link: $link }
600
+ up.bus.whenEmitted('up:link:preload', preloadEventAttrs).then ->
604
601
  variant = up.link.followVariantForLink($link)
605
- variant.preloadLink($link)
602
+ variant.preloadLink($link, options)
606
603
  else
607
604
  Promise.reject(new Error("Won't preload unsafe link"))
608
605
 
606
+ ###**
607
+ This event is [emitted](/up.emit) before a link is [preloaded](/up.preload).
608
+
609
+ @event up:link:preload
610
+ @param {jQuery} event.$link
611
+ The link element that will be preloaded.
612
+ @param event.preventDefault()
613
+ Event listeners may call this method to prevent the link from being preloaded.
614
+ @stable
615
+ ###
616
+
609
617
  ###**
610
618
  @internal
611
619
  ###
@@ -615,11 +623,11 @@ up.proxy = (($) ->
615
623
  ###**
616
624
  @internal
617
625
  ###
618
- wrapMethod = (method, data, appendOpts) ->
626
+ wrapMethod = (method, params) ->
619
627
  if u.contains(config.wrapMethods, method)
620
- data = u.appendRequestData(data, up.protocol.config.methodParam, method, appendOpts)
628
+ params = up.params.add(params, up.protocol.config.methodParam, method)
621
629
  method = 'POST'
622
- [method, data]
630
+ [method, params]
623
631
 
624
632
  ###**
625
633
  Links with an `up-preload` attribute will silently fetch their target
@@ -23,9 +23,6 @@ up.syntax = (($) ->
23
23
 
24
24
  u = up.util
25
25
 
26
- DESTRUCTIBLE_CLASS = 'up-destructible'
27
- DESTRUCTORS_KEY = 'up-destructors'
28
-
29
26
  SYSTEM_MACRO_PRIORITIES = {
30
27
  '[up-back]': -100 # sets [up-href] to previous URL
31
28
  '[up-drawer]': -200 # sets [up-modal] and makes link followable
@@ -213,17 +210,11 @@ up.syntax = (($) ->
213
210
  such as timeouts and event handlers bound to the document.
214
211
  The destructor is *not* expected to remove the element from the DOM, which
215
212
  is already handled by [`up.destroy()`](/up.destroy).
216
-
217
- The function may also return an array of destructor functions.
218
213
  @stable
219
214
  ###
220
- compiler = (selector, args...) ->
221
- # Developer might still call top-level compiler registrations even when we don't boot
222
- # due to an unsupported browser. In that case do no work and exit early.
223
- return unless up.browser.isSupported()
224
- callback = args.pop()
225
- options = u.options(args[0])
226
- insertCompiler(compilers, selector, options, callback)
215
+ registerCompiler = (args...) ->
216
+ compiler = buildCompiler(args...)
217
+ insertCompiler(compilers, compiler)
227
218
 
228
219
  ###**
229
220
  Registers a [compiler](/up.compiler) that is run before all other compilers.
@@ -266,72 +257,36 @@ up.syntax = (($) ->
266
257
  See [`up.compiler()`](/up.compiler) for details.
267
258
  @stable
268
259
  ###
269
- macro = (selector, args...) ->
270
- # Developer might still call top-level compiler registrations even when we don't boot
271
- # due to an unsupported browser. In that case do no work and exit early.
272
- return unless up.browser.isSupported()
273
- callback = args.pop()
274
- options = u.options(args[0])
260
+ registerMacro = (args...) ->
261
+ macro = buildCompiler(args...)
275
262
  if isBooting
276
- options.priority = detectSystemMacroPriority(selector) ||
277
- up.fail('Unregistered priority for system macro %o', selector)
278
- insertCompiler(macros, selector, options, callback)
263
+ macro.priority = detectSystemMacroPriority(macro.selector) ||
264
+ up.fail('Unregistered priority for system macro %o', macro.selector)
265
+ insertCompiler(macros, macro)
279
266
 
280
- detectSystemMacroPriority = (fullMacroSelector) ->
267
+ detectSystemMacroPriority = (macroSelector) ->
281
268
  for substr, priority of SYSTEM_MACRO_PRIORITIES
282
- if fullMacroSelector.indexOf(substr) >= 0
269
+ if macroSelector.indexOf(substr) >= 0
283
270
  return priority
284
271
 
285
- buildCompiler = (selector, options, callback) ->
286
- selector: selector
287
- callback: callback
288
- isSystem: isBooting
289
- priority: options.priority || 0
290
- batch: options.batch
291
- keep: options.keep
292
-
293
- insertCompiler = (queue, selector, options, callback) ->
294
- # Silently discard any compilers that are registered on unsupported browsers
295
- return unless up.browser.isSupported()
296
- newCompiler = buildCompiler(selector, options, callback)
272
+ buildCompiler = (selector, args...) ->
273
+ callback = args.pop()
274
+ options = u.extractOptions(args)
275
+ options = u.options(options,
276
+ selector: selector,
277
+ isSystem: isBooting,
278
+ priority: 0,
279
+ batch: false
280
+ keep: false
281
+ )
282
+ return u.assign(callback, options)
283
+
284
+ insertCompiler = (queue, newCompiler) ->
297
285
  index = 0
298
- while (oldCompiler = queue[index]) && (oldCompiler.priority >= newCompiler.priority)
286
+ while (existingCompiler = queue[index]) && (existingCompiler.priority >= newCompiler.priority)
299
287
  index += 1
300
288
  queue.splice(index, 0, newCompiler)
301
289
 
302
- applyCompiler = (compiler, $jqueryElement, nativeElement) ->
303
- up.puts ("Compiling '%s' on %o" unless compiler.isSystem), compiler.selector, nativeElement
304
- if compiler.keep
305
- value = if u.isString(compiler.keep) then compiler.keep else ''
306
- $jqueryElement.attr('up-keep', value)
307
- returnValue = compiler.callback.apply(nativeElement, [$jqueryElement, data($jqueryElement)])
308
- addDestructor($jqueryElement, returnValue)
309
-
310
- ###**
311
- Tries to find a list of destructors in a compiler's return value.
312
-
313
- @param {Object} returnValue
314
- @return {Function|undefined}
315
- @internal
316
- ###
317
- normalizeDestructor = (returnValue) ->
318
- if u.isFunction(returnValue)
319
- returnValue
320
- else if u.isArray(returnValue) && u.all(returnValue, u.isFunction)
321
- u.sequence(returnValue...)
322
-
323
- addDestructor = ($element, newDestructor) ->
324
- if newDestructor = normalizeDestructor(newDestructor)
325
- $element.addClass(DESTRUCTIBLE_CLASS)
326
- # The initial destructor function is a function that removes the destructor class and data.
327
- elementDestructor = $element.data(DESTRUCTORS_KEY) || -> removeDestructors($element)
328
- elementDestructor = u.sequence(elementDestructor, newDestructor)
329
- $element.data(DESTRUCTORS_KEY, elementDestructor)
330
-
331
- removeDestructors = ($element) ->
332
- $element.removeData(DESTRUCTORS_KEY)
333
- $element.removeClass(DESTRUCTIBLE_CLASS)
334
-
335
290
  ###**
336
291
  Applies all compilers on the given element and its descendants.
337
292
  Unlike [`up.hello()`](/up.hello), this doesn't emit any events.
@@ -342,30 +297,21 @@ up.syntax = (($) ->
342
297
  @internal
343
298
  ###
344
299
  compile = ($fragment, options) ->
345
- options = u.options(options)
346
- $skipSubtrees = $(options.skip)
347
-
348
- up.log.group "Compiling fragment %o", $fragment.get(0), ->
349
- for queue in [macros, compilers]
350
- for compiler in queue
351
- $matches = u.selectInSubtree($fragment, compiler.selector)
352
-
353
- # Exclude all elements that are descendants of the subtrees we want to keep.
354
- # We only do this if `options.skip` was given, since the exclusion
355
- # process below is very expensive (we had a case where compiling 100 slements
356
- # took 1.5s because of this).
357
- if $skipSubtrees.length
358
- $matches = $matches.filter ->
359
- $match = $(this)
360
- u.all $skipSubtrees, (skipSubtree) ->
361
- $match.closest(skipSubtree).length == 0
362
-
363
- if $matches.length
364
- up.log.group ("Compiling '%s' on %d element(s)" unless compiler.isSystem), compiler.selector, $matches.length, ->
365
- if compiler.batch
366
- applyCompiler(compiler, $matches, $matches.get())
367
- else
368
- $matches.each -> applyCompiler(compiler, $(this), this)
300
+ orderedCompilers = macros.concat(compilers)
301
+ compileRun = new up.CompilePass($fragment, orderedCompilers, options)
302
+ compileRun.compile()
303
+
304
+ ###**
305
+ @function up.syntax.destructor
306
+ @internal
307
+ ###
308
+ registerDestructor = (element, destructor) ->
309
+ element = u.element(element)
310
+ unless destructors = element.upDestructors
311
+ destructors = []
312
+ element.upDestructors = destructors
313
+ element.classList.add('up-can-clean')
314
+ destructors.push(destructor)
369
315
 
370
316
  ###**
371
317
  Runs any destroyers on the given fragment and its descendants.
@@ -376,20 +322,18 @@ up.syntax = (($) ->
376
322
  @internal
377
323
  ###
378
324
  clean = ($fragment) ->
379
- $destructibles = u.selectInSubtree($fragment, ".#{DESTRUCTIBLE_CLASS}")
380
- u.each $destructibles, (destructible) ->
381
- # The destructor function may be undefined at this point.
382
- # Although destructible elements should always have an destructor function, we might be
383
- # destroying a clone of such an element. E.g. Unpoly creates a clone when keeping an
384
- # [up-keep] element, and that clone still has the .up-destructible class.
385
- if destructor = $(destructible).data(DESTRUCTORS_KEY)
386
- destructor()
325
+ cleanables = u.selectInSubtree($fragment, '.up-can-clean')
326
+ u.each cleanables, (cleanable) ->
327
+ if destructors = cleanable.upDestructors
328
+ destructor() for destructor in destructors
329
+ # We do not actually remove the #upDestructors property or .up-can-* classes for performance reasons.
330
+ # The element we just cleaned is about to be removed from the DOM.
387
331
 
388
332
  ###**
389
333
  Checks if the given element has an [`up-data`](/up-data) attribute.
390
334
  If yes, parses the attribute value as JSON and returns the parsed object.
391
335
 
392
- Returns an empty object if the element has no `up-data` attribute.
336
+ Returns `undefined` if the element has no `up-data` attribute.
393
337
 
394
338
  \#\#\# Example
395
339
 
@@ -406,8 +350,8 @@ up.syntax = (($) ->
406
350
  @return
407
351
  The JSON-decoded value of the `up-data` attribute.
408
352
 
409
- Returns an empty object (`{}`) if the element has no (or an empty) `up-data` attribute.
410
- @stable
353
+ Returns `undefined` if the element has no (or an empty) `up-data` attribute.
354
+ @experimental
411
355
  ###
412
356
 
413
357
  ###**
@@ -453,13 +397,9 @@ up.syntax = (($) ->
453
397
  A serialized JSON string
454
398
  @stable
455
399
  ###
456
- data = (elementOrSelector) ->
457
- $element = $(elementOrSelector)
458
- json = $element.attr('up-data')
459
- if u.isString(json) && u.trim(json) != ''
460
- JSON.parse(json)
461
- else
462
- {}
400
+ readData = (elementOrSelector) ->
401
+ if element = u.element(elementOrSelector)
402
+ u.jsonAttr(element, 'up-data') || {}
463
403
 
464
404
  ###**
465
405
  Resets the list of registered compiler directives to the
@@ -468,20 +408,22 @@ up.syntax = (($) ->
468
408
  @internal
469
409
  ###
470
410
  reset = ->
471
- isSystem = (compiler) -> compiler.isSystem
472
- compilers = u.select(compilers, isSystem)
473
- macros = u.select(macros, isSystem)
411
+ compilers = u.select(compilers, 'isSystem')
412
+ macros = u.select(macros, 'isSystem')
474
413
 
475
414
  up.on 'up:framework:booted', -> isBooting = false
476
415
  up.on 'up:framework:reset', reset
477
416
 
478
- compiler: compiler
479
- macro: macro
417
+ <% if ENV['JS_KNIFE'] %>knife: eval(Knife.point)<% end %>
418
+ compiler: registerCompiler
419
+ macro: registerMacro
420
+ destructor: registerDestructor
480
421
  compile: compile
481
422
  clean: clean
482
- data: data
423
+ data: readData
483
424
 
484
425
  )(jQuery)
485
426
 
486
427
  up.compiler = up.syntax.compiler
428
+ up.destructor = up.syntax.destructor
487
429
  up.macro = up.syntax.macro