blazer 2.4.2 → 2.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -0
  3. data/README.md +155 -57
  4. data/app/assets/javascripts/blazer/Chart.js +14000 -13979
  5. data/app/assets/javascripts/blazer/bootstrap.js +300 -97
  6. data/app/assets/javascripts/blazer/queries.js +12 -1
  7. data/app/assets/javascripts/blazer/vue.js +10754 -9687
  8. data/app/assets/stylesheets/blazer/application.css +5 -0
  9. data/app/assets/stylesheets/blazer/bootstrap-propshaft.css +10 -0
  10. data/app/assets/stylesheets/blazer/bootstrap-sprockets.css.erb +10 -0
  11. data/app/assets/stylesheets/blazer/{bootstrap.css.erb → bootstrap.css} +527 -455
  12. data/app/controllers/blazer/base_controller.rb +45 -45
  13. data/app/controllers/blazer/dashboards_controller.rb +4 -11
  14. data/app/controllers/blazer/queries_controller.rb +31 -49
  15. data/app/models/blazer/query.rb +9 -3
  16. data/app/views/blazer/_variables.html.erb +5 -4
  17. data/app/views/blazer/dashboards/_form.html.erb +1 -1
  18. data/app/views/blazer/dashboards/show.html.erb +6 -4
  19. data/app/views/blazer/queries/_caching.html.erb +1 -1
  20. data/app/views/blazer/queries/_form.html.erb +3 -3
  21. data/app/views/blazer/queries/run.html.erb +5 -3
  22. data/app/views/blazer/queries/show.html.erb +12 -7
  23. data/app/views/layouts/blazer/application.html.erb +7 -2
  24. data/lib/blazer/adapters/athena_adapter.rb +73 -20
  25. data/lib/blazer/adapters/base_adapter.rb +16 -1
  26. data/lib/blazer/adapters/bigquery_adapter.rb +14 -3
  27. data/lib/blazer/adapters/cassandra_adapter.rb +15 -4
  28. data/lib/blazer/adapters/drill_adapter.rb +10 -0
  29. data/lib/blazer/adapters/druid_adapter.rb +36 -1
  30. data/lib/blazer/adapters/elasticsearch_adapter.rb +19 -4
  31. data/lib/blazer/adapters/hive_adapter.rb +10 -0
  32. data/lib/blazer/adapters/ignite_adapter.rb +12 -2
  33. data/lib/blazer/adapters/influxdb_adapter.rb +22 -10
  34. data/lib/blazer/adapters/mongodb_adapter.rb +4 -0
  35. data/lib/blazer/adapters/neo4j_adapter.rb +17 -2
  36. data/lib/blazer/adapters/opensearch_adapter.rb +52 -0
  37. data/lib/blazer/adapters/presto_adapter.rb +9 -0
  38. data/lib/blazer/adapters/salesforce_adapter.rb +5 -0
  39. data/lib/blazer/adapters/snowflake_adapter.rb +9 -0
  40. data/lib/blazer/adapters/soda_adapter.rb +9 -0
  41. data/lib/blazer/adapters/spark_adapter.rb +5 -0
  42. data/lib/blazer/adapters/sql_adapter.rb +41 -4
  43. data/{app/mailers → lib}/blazer/check_mailer.rb +0 -0
  44. data/lib/blazer/data_source.rb +90 -8
  45. data/lib/blazer/engine.rb +1 -4
  46. data/lib/blazer/result.rb +19 -1
  47. data/lib/blazer/run_statement.rb +7 -3
  48. data/lib/blazer/run_statement_job.rb +4 -2
  49. data/{app/mailers → lib}/blazer/slack_notifier.rb +19 -4
  50. data/lib/blazer/statement.rb +75 -0
  51. data/lib/blazer/version.rb +1 -1
  52. data/lib/blazer.rb +32 -8
  53. data/lib/generators/blazer/templates/config.yml.tt +2 -2
  54. data/lib/tasks/blazer.rake +5 -5
  55. data/licenses/LICENSE-bootstrap.txt +1 -1
  56. metadata +10 -6
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Bootstrap v3.3.7 (http://getbootstrap.com)
3
- * Copyright 2011-2016 Twitter, Inc.
2
+ * Bootstrap v3.4.1 (https://getbootstrap.com/)
3
+ * Copyright 2011-2019 Twitter, Inc.
4
4
  * Licensed under the MIT license
5
5
  */
6
6
 
@@ -17,10 +17,10 @@ if (typeof jQuery === 'undefined') {
17
17
  }(jQuery);
18
18
 
19
19
  /* ========================================================================
20
- * Bootstrap: transition.js v3.3.7
21
- * http://getbootstrap.com/javascript/#transitions
20
+ * Bootstrap: transition.js v3.4.1
21
+ * https://getbootstrap.com/docs/3.4/javascript/#transitions
22
22
  * ========================================================================
23
- * Copyright 2011-2016 Twitter, Inc.
23
+ * Copyright 2011-2019 Twitter, Inc.
24
24
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
25
  * ======================================================================== */
26
26
 
@@ -28,7 +28,7 @@ if (typeof jQuery === 'undefined') {
28
28
  +function ($) {
29
29
  'use strict';
30
30
 
31
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
31
+ // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
32
32
  // ============================================================
33
33
 
34
34
  function transitionEnd() {
@@ -50,7 +50,7 @@ if (typeof jQuery === 'undefined') {
50
50
  return false // explicit for ie8 ( ._.)
51
51
  }
52
52
 
53
- // http://blog.alexmaccaw.com/css-transitions
53
+ // https://blog.alexmaccaw.com/css-transitions
54
54
  $.fn.emulateTransitionEnd = function (duration) {
55
55
  var called = false
56
56
  var $el = this
@@ -77,10 +77,10 @@ if (typeof jQuery === 'undefined') {
77
77
  }(jQuery);
78
78
 
79
79
  /* ========================================================================
80
- * Bootstrap: alert.js v3.3.7
81
- * http://getbootstrap.com/javascript/#alerts
80
+ * Bootstrap: alert.js v3.4.1
81
+ * https://getbootstrap.com/docs/3.4/javascript/#alerts
82
82
  * ========================================================================
83
- * Copyright 2011-2016 Twitter, Inc.
83
+ * Copyright 2011-2019 Twitter, Inc.
84
84
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
85
85
  * ======================================================================== */
86
86
 
@@ -96,7 +96,7 @@ if (typeof jQuery === 'undefined') {
96
96
  $(el).on('click', dismiss, this.close)
97
97
  }
98
98
 
99
- Alert.VERSION = '3.3.7'
99
+ Alert.VERSION = '3.4.1'
100
100
 
101
101
  Alert.TRANSITION_DURATION = 150
102
102
 
@@ -109,7 +109,8 @@ if (typeof jQuery === 'undefined') {
109
109
  selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
110
110
  }
111
111
 
112
- var $parent = $(selector === '#' ? [] : selector)
112
+ selector = selector === '#' ? [] : selector
113
+ var $parent = $(document).find(selector)
113
114
 
114
115
  if (e) e.preventDefault()
115
116
 
@@ -172,10 +173,10 @@ if (typeof jQuery === 'undefined') {
172
173
  }(jQuery);
173
174
 
174
175
  /* ========================================================================
175
- * Bootstrap: button.js v3.3.7
176
- * http://getbootstrap.com/javascript/#buttons
176
+ * Bootstrap: button.js v3.4.1
177
+ * https://getbootstrap.com/docs/3.4/javascript/#buttons
177
178
  * ========================================================================
178
- * Copyright 2011-2016 Twitter, Inc.
179
+ * Copyright 2011-2019 Twitter, Inc.
179
180
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
180
181
  * ======================================================================== */
181
182
 
@@ -192,7 +193,7 @@ if (typeof jQuery === 'undefined') {
192
193
  this.isLoading = false
193
194
  }
194
195
 
195
- Button.VERSION = '3.3.7'
196
+ Button.VERSION = '3.4.1'
196
197
 
197
198
  Button.DEFAULTS = {
198
199
  loadingText: 'loading...'
@@ -298,10 +299,10 @@ if (typeof jQuery === 'undefined') {
298
299
  }(jQuery);
299
300
 
300
301
  /* ========================================================================
301
- * Bootstrap: carousel.js v3.3.7
302
- * http://getbootstrap.com/javascript/#carousel
302
+ * Bootstrap: carousel.js v3.4.1
303
+ * https://getbootstrap.com/docs/3.4/javascript/#carousel
303
304
  * ========================================================================
304
- * Copyright 2011-2016 Twitter, Inc.
305
+ * Copyright 2011-2019 Twitter, Inc.
305
306
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
306
307
  * ======================================================================== */
307
308
 
@@ -329,7 +330,7 @@ if (typeof jQuery === 'undefined') {
329
330
  .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
330
331
  }
331
332
 
332
- Carousel.VERSION = '3.3.7'
333
+ Carousel.VERSION = '3.4.1'
333
334
 
334
335
  Carousel.TRANSITION_DURATION = 600
335
336
 
@@ -443,7 +444,9 @@ if (typeof jQuery === 'undefined') {
443
444
  var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
444
445
  if ($.support.transition && this.$element.hasClass('slide')) {
445
446
  $next.addClass(type)
446
- $next[0].offsetWidth // force reflow
447
+ if (typeof $next === 'object' && $next.length) {
448
+ $next[0].offsetWidth // force reflow
449
+ }
447
450
  $active.addClass(direction)
448
451
  $next.addClass(direction)
449
452
  $active
@@ -505,10 +508,17 @@ if (typeof jQuery === 'undefined') {
505
508
  // =================
506
509
 
507
510
  var clickHandler = function (e) {
508
- var href
509
511
  var $this = $(this)
510
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
512
+ var href = $this.attr('href')
513
+ if (href) {
514
+ href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
515
+ }
516
+
517
+ var target = $this.attr('data-target') || href
518
+ var $target = $(document).find(target)
519
+
511
520
  if (!$target.hasClass('carousel')) return
521
+
512
522
  var options = $.extend({}, $target.data(), $this.data())
513
523
  var slideIndex = $this.attr('data-slide-to')
514
524
  if (slideIndex) options.interval = false
@@ -536,10 +546,10 @@ if (typeof jQuery === 'undefined') {
536
546
  }(jQuery);
537
547
 
538
548
  /* ========================================================================
539
- * Bootstrap: collapse.js v3.3.7
540
- * http://getbootstrap.com/javascript/#collapse
549
+ * Bootstrap: collapse.js v3.4.1
550
+ * https://getbootstrap.com/docs/3.4/javascript/#collapse
541
551
  * ========================================================================
542
- * Copyright 2011-2016 Twitter, Inc.
552
+ * Copyright 2011-2019 Twitter, Inc.
543
553
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
544
554
  * ======================================================================== */
545
555
 
@@ -567,7 +577,7 @@ if (typeof jQuery === 'undefined') {
567
577
  if (this.options.toggle) this.toggle()
568
578
  }
569
579
 
570
- Collapse.VERSION = '3.3.7'
580
+ Collapse.VERSION = '3.4.1'
571
581
 
572
582
  Collapse.TRANSITION_DURATION = 350
573
583
 
@@ -674,7 +684,7 @@ if (typeof jQuery === 'undefined') {
674
684
  }
675
685
 
676
686
  Collapse.prototype.getParent = function () {
677
- return $(this.options.parent)
687
+ return $(document).find(this.options.parent)
678
688
  .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
679
689
  .each($.proxy(function (i, element) {
680
690
  var $element = $(element)
@@ -697,7 +707,7 @@ if (typeof jQuery === 'undefined') {
697
707
  var target = $trigger.attr('data-target')
698
708
  || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
699
709
 
700
- return $(target)
710
+ return $(document).find(target)
701
711
  }
702
712
 
703
713
 
@@ -749,10 +759,10 @@ if (typeof jQuery === 'undefined') {
749
759
  }(jQuery);
750
760
 
751
761
  /* ========================================================================
752
- * Bootstrap: dropdown.js v3.3.7
753
- * http://getbootstrap.com/javascript/#dropdowns
762
+ * Bootstrap: dropdown.js v3.4.1
763
+ * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
754
764
  * ========================================================================
755
- * Copyright 2011-2016 Twitter, Inc.
765
+ * Copyright 2011-2019 Twitter, Inc.
756
766
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
757
767
  * ======================================================================== */
758
768
 
@@ -769,7 +779,7 @@ if (typeof jQuery === 'undefined') {
769
779
  $(element).on('click.bs.dropdown', this.toggle)
770
780
  }
771
781
 
772
- Dropdown.VERSION = '3.3.7'
782
+ Dropdown.VERSION = '3.4.1'
773
783
 
774
784
  function getParent($this) {
775
785
  var selector = $this.attr('data-target')
@@ -779,7 +789,7 @@ if (typeof jQuery === 'undefined') {
779
789
  selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
780
790
  }
781
791
 
782
- var $parent = selector && $(selector)
792
+ var $parent = selector !== '#' ? $(document).find(selector) : null
783
793
 
784
794
  return $parent && $parent.length ? $parent : $this.parent()
785
795
  }
@@ -915,10 +925,10 @@ if (typeof jQuery === 'undefined') {
915
925
  }(jQuery);
916
926
 
917
927
  /* ========================================================================
918
- * Bootstrap: modal.js v3.3.7
919
- * http://getbootstrap.com/javascript/#modals
928
+ * Bootstrap: modal.js v3.4.1
929
+ * https://getbootstrap.com/docs/3.4/javascript/#modals
920
930
  * ========================================================================
921
- * Copyright 2011-2016 Twitter, Inc.
931
+ * Copyright 2011-2019 Twitter, Inc.
922
932
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
923
933
  * ======================================================================== */
924
934
 
@@ -930,15 +940,16 @@ if (typeof jQuery === 'undefined') {
930
940
  // ======================
931
941
 
932
942
  var Modal = function (element, options) {
933
- this.options = options
934
- this.$body = $(document.body)
935
- this.$element = $(element)
936
- this.$dialog = this.$element.find('.modal-dialog')
937
- this.$backdrop = null
938
- this.isShown = null
939
- this.originalBodyPad = null
940
- this.scrollbarWidth = 0
943
+ this.options = options
944
+ this.$body = $(document.body)
945
+ this.$element = $(element)
946
+ this.$dialog = this.$element.find('.modal-dialog')
947
+ this.$backdrop = null
948
+ this.isShown = null
949
+ this.originalBodyPad = null
950
+ this.scrollbarWidth = 0
941
951
  this.ignoreBackdropClick = false
952
+ this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
942
953
 
943
954
  if (this.options.remote) {
944
955
  this.$element
@@ -949,7 +960,7 @@ if (typeof jQuery === 'undefined') {
949
960
  }
950
961
  }
951
962
 
952
- Modal.VERSION = '3.3.7'
963
+ Modal.VERSION = '3.4.1'
953
964
 
954
965
  Modal.TRANSITION_DURATION = 300
955
966
  Modal.BACKDROP_TRANSITION_DURATION = 150
@@ -966,7 +977,7 @@ if (typeof jQuery === 'undefined') {
966
977
 
967
978
  Modal.prototype.show = function (_relatedTarget) {
968
979
  var that = this
969
- var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
980
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
970
981
 
971
982
  this.$element.trigger(e)
972
983
 
@@ -1057,8 +1068,8 @@ if (typeof jQuery === 'undefined') {
1057
1068
  .off('focusin.bs.modal') // guard against infinite focus loop
1058
1069
  .on('focusin.bs.modal', $.proxy(function (e) {
1059
1070
  if (document !== e.target &&
1060
- this.$element[0] !== e.target &&
1061
- !this.$element.has(e.target).length) {
1071
+ this.$element[0] !== e.target &&
1072
+ !this.$element.has(e.target).length) {
1062
1073
  this.$element.trigger('focus')
1063
1074
  }
1064
1075
  }, this))
@@ -1160,7 +1171,7 @@ if (typeof jQuery === 'undefined') {
1160
1171
  var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1161
1172
 
1162
1173
  this.$element.css({
1163
- paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1174
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1164
1175
  paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1165
1176
  })
1166
1177
  }
@@ -1185,11 +1196,26 @@ if (typeof jQuery === 'undefined') {
1185
1196
  Modal.prototype.setScrollbar = function () {
1186
1197
  var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1187
1198
  this.originalBodyPad = document.body.style.paddingRight || ''
1188
- if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1199
+ var scrollbarWidth = this.scrollbarWidth
1200
+ if (this.bodyIsOverflowing) {
1201
+ this.$body.css('padding-right', bodyPad + scrollbarWidth)
1202
+ $(this.fixedContent).each(function (index, element) {
1203
+ var actualPadding = element.style.paddingRight
1204
+ var calculatedPadding = $(element).css('padding-right')
1205
+ $(element)
1206
+ .data('padding-right', actualPadding)
1207
+ .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
1208
+ })
1209
+ }
1189
1210
  }
1190
1211
 
1191
1212
  Modal.prototype.resetScrollbar = function () {
1192
1213
  this.$body.css('padding-right', this.originalBodyPad)
1214
+ $(this.fixedContent).each(function (index, element) {
1215
+ var padding = $(element).data('padding-right')
1216
+ $(element).removeData('padding-right')
1217
+ element.style.paddingRight = padding ? padding : ''
1218
+ })
1193
1219
  }
1194
1220
 
1195
1221
  Modal.prototype.measureScrollbar = function () { // thx walsh
@@ -1207,8 +1233,8 @@ if (typeof jQuery === 'undefined') {
1207
1233
 
1208
1234
  function Plugin(option, _relatedTarget) {
1209
1235
  return this.each(function () {
1210
- var $this = $(this)
1211
- var data = $this.data('bs.modal')
1236
+ var $this = $(this)
1237
+ var data = $this.data('bs.modal')
1212
1238
  var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1213
1239
 
1214
1240
  if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
@@ -1219,7 +1245,7 @@ if (typeof jQuery === 'undefined') {
1219
1245
 
1220
1246
  var old = $.fn.modal
1221
1247
 
1222
- $.fn.modal = Plugin
1248
+ $.fn.modal = Plugin
1223
1249
  $.fn.modal.Constructor = Modal
1224
1250
 
1225
1251
 
@@ -1236,10 +1262,13 @@ if (typeof jQuery === 'undefined') {
1236
1262
  // ==============
1237
1263
 
1238
1264
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1239
- var $this = $(this)
1240
- var href = $this.attr('href')
1241
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1242
- var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1265
+ var $this = $(this)
1266
+ var href = $this.attr('href')
1267
+ var target = $this.attr('data-target') ||
1268
+ (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
1269
+
1270
+ var $target = $(document).find(target)
1271
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1243
1272
 
1244
1273
  if ($this.is('a')) e.preventDefault()
1245
1274
 
@@ -1255,18 +1284,148 @@ if (typeof jQuery === 'undefined') {
1255
1284
  }(jQuery);
1256
1285
 
1257
1286
  /* ========================================================================
1258
- * Bootstrap: tooltip.js v3.3.7
1259
- * http://getbootstrap.com/javascript/#tooltip
1287
+ * Bootstrap: tooltip.js v3.4.1
1288
+ * https://getbootstrap.com/docs/3.4/javascript/#tooltip
1260
1289
  * Inspired by the original jQuery.tipsy by Jason Frame
1261
1290
  * ========================================================================
1262
- * Copyright 2011-2016 Twitter, Inc.
1291
+ * Copyright 2011-2019 Twitter, Inc.
1263
1292
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1264
1293
  * ======================================================================== */
1265
1294
 
1266
-
1267
1295
  +function ($) {
1268
1296
  'use strict';
1269
1297
 
1298
+ var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
1299
+
1300
+ var uriAttrs = [
1301
+ 'background',
1302
+ 'cite',
1303
+ 'href',
1304
+ 'itemtype',
1305
+ 'longdesc',
1306
+ 'poster',
1307
+ 'src',
1308
+ 'xlink:href'
1309
+ ]
1310
+
1311
+ var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
1312
+
1313
+ var DefaultWhitelist = {
1314
+ // Global attributes allowed on any supplied element below.
1315
+ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
1316
+ a: ['target', 'href', 'title', 'rel'],
1317
+ area: [],
1318
+ b: [],
1319
+ br: [],
1320
+ col: [],
1321
+ code: [],
1322
+ div: [],
1323
+ em: [],
1324
+ hr: [],
1325
+ h1: [],
1326
+ h2: [],
1327
+ h3: [],
1328
+ h4: [],
1329
+ h5: [],
1330
+ h6: [],
1331
+ i: [],
1332
+ img: ['src', 'alt', 'title', 'width', 'height'],
1333
+ li: [],
1334
+ ol: [],
1335
+ p: [],
1336
+ pre: [],
1337
+ s: [],
1338
+ small: [],
1339
+ span: [],
1340
+ sub: [],
1341
+ sup: [],
1342
+ strong: [],
1343
+ u: [],
1344
+ ul: []
1345
+ }
1346
+
1347
+ /**
1348
+ * A pattern that recognizes a commonly useful subset of URLs that are safe.
1349
+ *
1350
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
1351
+ */
1352
+ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
1353
+
1354
+ /**
1355
+ * A pattern that matches safe data URLs. Only matches image, video and audio types.
1356
+ *
1357
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
1358
+ */
1359
+ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
1360
+
1361
+ function allowedAttribute(attr, allowedAttributeList) {
1362
+ var attrName = attr.nodeName.toLowerCase()
1363
+
1364
+ if ($.inArray(attrName, allowedAttributeList) !== -1) {
1365
+ if ($.inArray(attrName, uriAttrs) !== -1) {
1366
+ return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
1367
+ }
1368
+
1369
+ return true
1370
+ }
1371
+
1372
+ var regExp = $(allowedAttributeList).filter(function (index, value) {
1373
+ return value instanceof RegExp
1374
+ })
1375
+
1376
+ // Check if a regular expression validates the attribute.
1377
+ for (var i = 0, l = regExp.length; i < l; i++) {
1378
+ if (attrName.match(regExp[i])) {
1379
+ return true
1380
+ }
1381
+ }
1382
+
1383
+ return false
1384
+ }
1385
+
1386
+ function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
1387
+ if (unsafeHtml.length === 0) {
1388
+ return unsafeHtml
1389
+ }
1390
+
1391
+ if (sanitizeFn && typeof sanitizeFn === 'function') {
1392
+ return sanitizeFn(unsafeHtml)
1393
+ }
1394
+
1395
+ // IE 8 and below don't support createHTMLDocument
1396
+ if (!document.implementation || !document.implementation.createHTMLDocument) {
1397
+ return unsafeHtml
1398
+ }
1399
+
1400
+ var createdDocument = document.implementation.createHTMLDocument('sanitization')
1401
+ createdDocument.body.innerHTML = unsafeHtml
1402
+
1403
+ var whitelistKeys = $.map(whiteList, function (el, i) { return i })
1404
+ var elements = $(createdDocument.body).find('*')
1405
+
1406
+ for (var i = 0, len = elements.length; i < len; i++) {
1407
+ var el = elements[i]
1408
+ var elName = el.nodeName.toLowerCase()
1409
+
1410
+ if ($.inArray(elName, whitelistKeys) === -1) {
1411
+ el.parentNode.removeChild(el)
1412
+
1413
+ continue
1414
+ }
1415
+
1416
+ var attributeList = $.map(el.attributes, function (el) { return el })
1417
+ var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
1418
+
1419
+ for (var j = 0, len2 = attributeList.length; j < len2; j++) {
1420
+ if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
1421
+ el.removeAttribute(attributeList[j].nodeName)
1422
+ }
1423
+ }
1424
+ }
1425
+
1426
+ return createdDocument.body.innerHTML
1427
+ }
1428
+
1270
1429
  // TOOLTIP PUBLIC CLASS DEFINITION
1271
1430
  // ===============================
1272
1431
 
@@ -1282,7 +1441,7 @@ if (typeof jQuery === 'undefined') {
1282
1441
  this.init('tooltip', element, options)
1283
1442
  }
1284
1443
 
1285
- Tooltip.VERSION = '3.3.7'
1444
+ Tooltip.VERSION = '3.4.1'
1286
1445
 
1287
1446
  Tooltip.TRANSITION_DURATION = 150
1288
1447
 
@@ -1299,7 +1458,10 @@ if (typeof jQuery === 'undefined') {
1299
1458
  viewport: {
1300
1459
  selector: 'body',
1301
1460
  padding: 0
1302
- }
1461
+ },
1462
+ sanitize : true,
1463
+ sanitizeFn : null,
1464
+ whiteList : DefaultWhitelist
1303
1465
  }
1304
1466
 
1305
1467
  Tooltip.prototype.init = function (type, element, options) {
@@ -1307,7 +1469,7 @@ if (typeof jQuery === 'undefined') {
1307
1469
  this.type = type
1308
1470
  this.$element = $(element)
1309
1471
  this.options = this.getOptions(options)
1310
- this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1472
+ this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1311
1473
  this.inState = { click: false, hover: false, focus: false }
1312
1474
 
1313
1475
  if (this.$element[0] instanceof document.constructor && !this.options.selector) {
@@ -1340,7 +1502,15 @@ if (typeof jQuery === 'undefined') {
1340
1502
  }
1341
1503
 
1342
1504
  Tooltip.prototype.getOptions = function (options) {
1343
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1505
+ var dataAttributes = this.$element.data()
1506
+
1507
+ for (var dataAttr in dataAttributes) {
1508
+ if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
1509
+ delete dataAttributes[dataAttr]
1510
+ }
1511
+ }
1512
+
1513
+ options = $.extend({}, this.getDefaults(), dataAttributes, options)
1344
1514
 
1345
1515
  if (options.delay && typeof options.delay == 'number') {
1346
1516
  options.delay = {
@@ -1349,6 +1519,10 @@ if (typeof jQuery === 'undefined') {
1349
1519
  }
1350
1520
  }
1351
1521
 
1522
+ if (options.sanitize) {
1523
+ options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
1524
+ }
1525
+
1352
1526
  return options
1353
1527
  }
1354
1528
 
@@ -1460,7 +1634,7 @@ if (typeof jQuery === 'undefined') {
1460
1634
  .addClass(placement)
1461
1635
  .data('bs.' + this.type, this)
1462
1636
 
1463
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1637
+ this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
1464
1638
  this.$element.trigger('inserted.bs.' + this.type)
1465
1639
 
1466
1640
  var pos = this.getPosition()
@@ -1562,7 +1736,16 @@ if (typeof jQuery === 'undefined') {
1562
1736
  var $tip = this.tip()
1563
1737
  var title = this.getTitle()
1564
1738
 
1565
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1739
+ if (this.options.html) {
1740
+ if (this.options.sanitize) {
1741
+ title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
1742
+ }
1743
+
1744
+ $tip.find('.tooltip-inner').html(title)
1745
+ } else {
1746
+ $tip.find('.tooltip-inner').text(title)
1747
+ }
1748
+
1566
1749
  $tip.removeClass('fade in top bottom left right')
1567
1750
  }
1568
1751
 
@@ -1743,6 +1926,9 @@ if (typeof jQuery === 'undefined') {
1743
1926
  })
1744
1927
  }
1745
1928
 
1929
+ Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
1930
+ return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
1931
+ }
1746
1932
 
1747
1933
  // TOOLTIP PLUGIN DEFINITION
1748
1934
  // =========================
@@ -1776,10 +1962,10 @@ if (typeof jQuery === 'undefined') {
1776
1962
  }(jQuery);
1777
1963
 
1778
1964
  /* ========================================================================
1779
- * Bootstrap: popover.js v3.3.7
1780
- * http://getbootstrap.com/javascript/#popovers
1965
+ * Bootstrap: popover.js v3.4.1
1966
+ * https://getbootstrap.com/docs/3.4/javascript/#popovers
1781
1967
  * ========================================================================
1782
- * Copyright 2011-2016 Twitter, Inc.
1968
+ * Copyright 2011-2019 Twitter, Inc.
1783
1969
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1784
1970
  * ======================================================================== */
1785
1971
 
@@ -1796,7 +1982,7 @@ if (typeof jQuery === 'undefined') {
1796
1982
 
1797
1983
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1798
1984
 
1799
- Popover.VERSION = '3.3.7'
1985
+ Popover.VERSION = '3.4.1'
1800
1986
 
1801
1987
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1802
1988
  placement: 'right',
@@ -1822,10 +2008,25 @@ if (typeof jQuery === 'undefined') {
1822
2008
  var title = this.getTitle()
1823
2009
  var content = this.getContent()
1824
2010
 
1825
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1826
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1827
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1828
- ](content)
2011
+ if (this.options.html) {
2012
+ var typeContent = typeof content
2013
+
2014
+ if (this.options.sanitize) {
2015
+ title = this.sanitizeHtml(title)
2016
+
2017
+ if (typeContent === 'string') {
2018
+ content = this.sanitizeHtml(content)
2019
+ }
2020
+ }
2021
+
2022
+ $tip.find('.popover-title').html(title)
2023
+ $tip.find('.popover-content').children().detach().end()[
2024
+ typeContent === 'string' ? 'html' : 'append'
2025
+ ](content)
2026
+ } else {
2027
+ $tip.find('.popover-title').text(title)
2028
+ $tip.find('.popover-content').children().detach().end().text(content)
2029
+ }
1829
2030
 
1830
2031
  $tip.removeClass('fade top bottom left right in')
1831
2032
 
@@ -1844,8 +2045,8 @@ if (typeof jQuery === 'undefined') {
1844
2045
 
1845
2046
  return $e.attr('data-content')
1846
2047
  || (typeof o.content == 'function' ?
1847
- o.content.call($e[0]) :
1848
- o.content)
2048
+ o.content.call($e[0]) :
2049
+ o.content)
1849
2050
  }
1850
2051
 
1851
2052
  Popover.prototype.arrow = function () {
@@ -1885,10 +2086,10 @@ if (typeof jQuery === 'undefined') {
1885
2086
  }(jQuery);
1886
2087
 
1887
2088
  /* ========================================================================
1888
- * Bootstrap: scrollspy.js v3.3.7
1889
- * http://getbootstrap.com/javascript/#scrollspy
2089
+ * Bootstrap: scrollspy.js v3.4.1
2090
+ * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
1890
2091
  * ========================================================================
1891
- * Copyright 2011-2016 Twitter, Inc.
2092
+ * Copyright 2011-2019 Twitter, Inc.
1892
2093
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1893
2094
  * ======================================================================== */
1894
2095
 
@@ -1914,7 +2115,7 @@ if (typeof jQuery === 'undefined') {
1914
2115
  this.process()
1915
2116
  }
1916
2117
 
1917
- ScrollSpy.VERSION = '3.3.7'
2118
+ ScrollSpy.VERSION = '3.4.1'
1918
2119
 
1919
2120
  ScrollSpy.DEFAULTS = {
1920
2121
  offset: 10
@@ -2058,10 +2259,10 @@ if (typeof jQuery === 'undefined') {
2058
2259
  }(jQuery);
2059
2260
 
2060
2261
  /* ========================================================================
2061
- * Bootstrap: tab.js v3.3.7
2062
- * http://getbootstrap.com/javascript/#tabs
2262
+ * Bootstrap: tab.js v3.4.1
2263
+ * https://getbootstrap.com/docs/3.4/javascript/#tabs
2063
2264
  * ========================================================================
2064
- * Copyright 2011-2016 Twitter, Inc.
2265
+ * Copyright 2011-2019 Twitter, Inc.
2065
2266
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2066
2267
  * ======================================================================== */
2067
2268
 
@@ -2078,7 +2279,7 @@ if (typeof jQuery === 'undefined') {
2078
2279
  // jscs:enable requireDollarBeforejQueryAssignment
2079
2280
  }
2080
2281
 
2081
- Tab.VERSION = '3.3.7'
2282
+ Tab.VERSION = '3.4.1'
2082
2283
 
2083
2284
  Tab.TRANSITION_DURATION = 150
2084
2285
 
@@ -2107,7 +2308,7 @@ if (typeof jQuery === 'undefined') {
2107
2308
 
2108
2309
  if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2109
2310
 
2110
- var $target = $(selector)
2311
+ var $target = $(document).find(selector)
2111
2312
 
2112
2313
  this.activate($this.closest('li'), $ul)
2113
2314
  this.activate($target, $target.parent(), function () {
@@ -2132,15 +2333,15 @@ if (typeof jQuery === 'undefined') {
2132
2333
  $active
2133
2334
  .removeClass('active')
2134
2335
  .find('> .dropdown-menu > .active')
2135
- .removeClass('active')
2336
+ .removeClass('active')
2136
2337
  .end()
2137
2338
  .find('[data-toggle="tab"]')
2138
- .attr('aria-expanded', false)
2339
+ .attr('aria-expanded', false)
2139
2340
 
2140
2341
  element
2141
2342
  .addClass('active')
2142
2343
  .find('[data-toggle="tab"]')
2143
- .attr('aria-expanded', true)
2344
+ .attr('aria-expanded', true)
2144
2345
 
2145
2346
  if (transition) {
2146
2347
  element[0].offsetWidth // reflow for transition
@@ -2152,10 +2353,10 @@ if (typeof jQuery === 'undefined') {
2152
2353
  if (element.parent('.dropdown-menu').length) {
2153
2354
  element
2154
2355
  .closest('li.dropdown')
2155
- .addClass('active')
2356
+ .addClass('active')
2156
2357
  .end()
2157
2358
  .find('[data-toggle="tab"]')
2158
- .attr('aria-expanded', true)
2359
+ .attr('aria-expanded', true)
2159
2360
  }
2160
2361
 
2161
2362
  callback && callback()
@@ -2214,10 +2415,10 @@ if (typeof jQuery === 'undefined') {
2214
2415
  }(jQuery);
2215
2416
 
2216
2417
  /* ========================================================================
2217
- * Bootstrap: affix.js v3.3.7
2218
- * http://getbootstrap.com/javascript/#affix
2418
+ * Bootstrap: affix.js v3.4.1
2419
+ * https://getbootstrap.com/docs/3.4/javascript/#affix
2219
2420
  * ========================================================================
2220
- * Copyright 2011-2016 Twitter, Inc.
2421
+ * Copyright 2011-2019 Twitter, Inc.
2221
2422
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2222
2423
  * ======================================================================== */
2223
2424
 
@@ -2231,7 +2432,9 @@ if (typeof jQuery === 'undefined') {
2231
2432
  var Affix = function (element, options) {
2232
2433
  this.options = $.extend({}, Affix.DEFAULTS, options)
2233
2434
 
2234
- this.$target = $(this.options.target)
2435
+ var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
2436
+
2437
+ this.$target = target
2235
2438
  .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2236
2439
  .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
2237
2440
 
@@ -2243,7 +2446,7 @@ if (typeof jQuery === 'undefined') {
2243
2446
  this.checkPosition()
2244
2447
  }
2245
2448
 
2246
- Affix.VERSION = '3.3.7'
2449
+ Affix.VERSION = '3.4.1'
2247
2450
 
2248
2451
  Affix.RESET = 'affix affix-top affix-bottom'
2249
2452