Browse Source

Upgrade to Bootstrap 4.5.0 and jQuery 3.5.1 (#331)

Vince Salvino 4 năm trước cách đây
mục cha
commit
fa852ebc9d
100 tập tin đã thay đổi với 2754 bổ sung1924 xóa
  1. 47 23
      coderedcms/project_template/sass/website/static/website/src/_variables.scss
  2. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/LICENSE
  3. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/README.txt
  4. 189 4
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.css
  5. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.css.map
  6. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.min.css
  7. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.min.css.map
  8. 11 17
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.css
  9. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.css.map
  10. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.min.css
  11. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.min.css.map
  12. 327 140
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.css
  13. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.css.map
  14. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.min.css
  15. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.min.css.map
  16. 286 242
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.js
  17. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.js.map
  18. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.min.js
  19. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.min.js.map
  20. 287 243
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.js
  21. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.js.map
  22. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.min.js
  23. 0 0
      coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.min.js.map
  24. 16 22
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/alert.js
  25. 80 44
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/button.js
  26. 88 96
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/carousel.js
  27. 44 55
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/collapse.js
  28. 115 126
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/dropdown.js
  29. 1 19
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/index.js
  30. 105 87
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/modal.js
  31. 9 13
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/popover.js
  32. 44 50
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/scrollspy.js
  33. 44 50
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/tab.js
  34. 43 46
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/toast.js
  35. 5 5
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/tools/sanitizer.js
  36. 82 95
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/tooltip.js
  37. 24 3
      coderedcms/static/coderedcms/vendor/bootstrap/js/src/util.js
  38. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_badge.scss
  39. 4 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_breadcrumb.scss
  40. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_button-group.scss
  41. 13 8
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_buttons.scss
  42. 28 35
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_card.scss
  43. 6 6
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_carousel.scss
  44. 2 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_close.scss
  45. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_code.scss
  46. 24 9
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_custom-forms.scss
  47. 5 4
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_dropdown.scss
  48. 26 9
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_forms.scss
  49. 60 5
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_functions.scss
  50. 33 8
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_grid.scss
  51. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_images.scss
  52. 1 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_input-group.scss
  53. 36 31
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_list-group.scss
  54. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_mixins.scss
  55. 28 16
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_modal.scss
  56. 4 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_nav.scss
  57. 45 15
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_navbar.scss
  58. 3 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_pagination.scss
  59. 8 9
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_popover.scss
  60. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_print.scss
  61. 6 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_progress.scss
  62. 24 27
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_reboot.scss
  63. 1 0
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_root.scss
  64. 1 0
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_spinners.scss
  65. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_tables.scss
  66. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_type.scss
  67. 2 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_utilities.scss
  68. 46 22
      coderedcms/static/coderedcms/vendor/bootstrap/scss/_variables.scss
  69. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap-grid.scss
  70. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap-reboot.scss
  71. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap.scss
  72. 5 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_background-variant.scss
  73. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_badge.scss
  74. 26 13
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_border-radius.scss
  75. 11 8
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_buttons.scss
  76. 8 8
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_caret.scss
  77. 3 3
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_float.scss
  78. 34 49
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_forms.scss
  79. 30 15
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_grid-framework.scss
  80. 18 0
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_grid.scss
  81. 4 4
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_hover.scss
  82. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_image.scss
  83. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_list-group.scss
  84. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_lists.scss
  85. 2 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_nav-divider.scss
  86. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_reset-text.scss
  87. 3 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_screen-reader.scss
  88. 1 1
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_table-row.scss
  89. 3 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_text-emphasis.scss
  90. 17 7
      coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_transition.scss
  91. 2 2
      coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_background.scss
  92. 5 0
      coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_interactions.scss
  93. 3 4
      coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_text.scss
  94. 0 1
      coderedcms/static/coderedcms/vendor/jquery/jquery-3.4.1.min.js
  95. 0 0
      coderedcms/static/coderedcms/vendor/jquery/jquery-3.4.1.min.map
  96. 265 157
      coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.js
  97. 1 0
      coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.min.js
  98. 0 0
      coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.min.map
  99. 1 1
      coderedcms/templates/coderedcms/pages/base.html
  100. 14 0
      docs/contributing/index.rst

+ 47 - 23
coderedcms/project_template/sass/website/static/website/src/_variables.scss

@@ -1,4 +1,4 @@
-// Custom variables for this project (copied from Bootstrap 4.3.1 sources)
+// Custom variables for this project (copied from Bootstrap 4.5.0 sources)
 // Change the variables here to match your brand.
 //
 // Variables should follow the `$component-state-property-size` formula for
@@ -102,6 +102,15 @@ $yiq-contrasted-threshold:  150 !default;
 $yiq-text-dark:             $gray-900 !default;
 $yiq-text-light:            $white !default;
 
+// Characters which are escaped by the escape-svg function
+$escaped-characters: (
+  ("<","%3c"),
+  (">","%3e"),
+  ("#","%23"),
+  ("(","%28"),
+  (")","%29"),
+) !default;
+
 
 // Options
 //
@@ -221,6 +230,7 @@ $container-max-widths: (
 
 $grid-columns:                12 !default;
 $grid-gutter-width:           30px !default;
+$grid-row-columns:            6 !default;
 
 
 // Components
@@ -367,7 +377,6 @@ $table-dark-accent-bg:        rgba($white, .05) !default;
 $table-dark-hover-color:      $table-dark-color !default;
 $table-dark-hover-bg:         rgba($white, .075) !default;
 $table-dark-border-color:     lighten($table-dark-bg, 7.5%) !default;
-$table-dark-color:            $white !default;
 
 $table-striped-order:         odd !default;
 
@@ -413,6 +422,7 @@ $btn-padding-x:               $input-btn-padding-x !default;
 $btn-font-family:             $input-btn-font-family !default;
 $btn-font-size:               $input-btn-font-size !default;
 $btn-line-height:             $input-btn-line-height !default;
+$btn-white-space:             null !default; // Set to `nowrap` to prevent text wrapping
 
 $btn-padding-y-sm:            $input-btn-padding-y-sm !default;
 $btn-padding-x-sm:            $input-btn-padding-x-sm !default;
@@ -489,13 +499,13 @@ $input-plaintext-color:                 $body-color !default;
 
 $input-height-border:                   $input-border-width * 2 !default;
 
-$input-height-inner:                    calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;
-$input-height-inner-half:               calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;
-$input-height-inner-quarter:            calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;
+$input-height-inner:                    add($input-line-height * 1em, $input-padding-y * 2) !default;
+$input-height-inner-half:               add($input-line-height * .5em, $input-padding-y) !default;
+$input-height-inner-quarter:            add($input-line-height * .25em, $input-padding-y / 2) !default;
 
-$input-height:                          calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;
-$input-height-sm:                       calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;
-$input-height-lg:                       calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;
+$input-height:                          add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;
+$input-height-sm:                       add($input-line-height-sm * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;
+$input-height-lg:                       add($input-line-height-lg * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;
 
 $input-transition:                      border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
 
@@ -519,6 +529,7 @@ $custom-forms-transition:               background-color .15s ease-in-out, borde
 
 $custom-control-gutter:                 .5rem !default;
 $custom-control-spacer-x:               1rem !default;
+$custom-control-cursor:                 null !default;
 
 $custom-control-indicator-size:         1rem !default;
 $custom-control-indicator-bg:           $input-bg !default;
@@ -528,6 +539,8 @@ $custom-control-indicator-box-shadow:   $input-box-shadow !default;
 $custom-control-indicator-border-color: $gray-500 !default;
 $custom-control-indicator-border-width: $input-border-width !default;
 
+$custom-control-label-color:            null !default;
+
 $custom-control-indicator-disabled-bg:          $input-disabled-bg !default;
 $custom-control-label-disabled-color:           $gray-600 !default;
 
@@ -546,20 +559,20 @@ $custom-control-indicator-active-box-shadow:    none !default;
 $custom-control-indicator-active-border-color:  $custom-control-indicator-active-bg !default;
 
 $custom-checkbox-indicator-border-radius:       $border-radius !default;
-$custom-checkbox-indicator-icon-checked:        str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-checkbox-indicator-icon-checked:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'><path fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/></svg>") !default;
 
 $custom-checkbox-indicator-indeterminate-bg:           $component-active-bg !default;
 $custom-checkbox-indicator-indeterminate-color:        $custom-control-indicator-checked-color !default;
-$custom-checkbox-indicator-icon-indeterminate:         str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-checkbox-indicator-icon-indeterminate:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'><path stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/></svg>") !default;
 $custom-checkbox-indicator-indeterminate-box-shadow:   none !default;
 $custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;
 
 $custom-radio-indicator-border-radius:          50% !default;
-$custom-radio-indicator-icon-checked:           str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-radio-indicator-icon-checked:           url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'><circle r='3' fill='#{$custom-control-indicator-checked-color}'/></svg>") !default;
 
 $custom-switch-width:                           $custom-control-indicator-size * 1.75 !default;
 $custom-switch-indicator-border-radius:         $custom-control-indicator-size / 2 !default;
-$custom-switch-indicator-size:                  calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;
+$custom-switch-indicator-size:                  subtract($custom-control-indicator-size, $custom-control-indicator-border-width * 4) !default;
 
 $custom-select-padding-y:           $input-padding-y !default;
 $custom-select-padding-x:           $input-padding-x !default;
@@ -575,10 +588,10 @@ $custom-select-bg:                  $input-bg !default;
 $custom-select-disabled-bg:         $gray-200 !default;
 $custom-select-bg-size:             8px 10px !default; // In pixels because image dimensions
 $custom-select-indicator-color:     $gray-800 !default;
-$custom-select-indicator:           str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e"), "#", "%23") !default;
-$custom-select-background:          $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
+$custom-select-indicator:           url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'><path fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/></svg>") !default;
+$custom-select-background:          escape-svg($custom-select-indicator) no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
 
-$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;
+$custom-select-feedback-icon-padding-right: add(1em * .75, (2 * $custom-select-padding-y * .75) + $custom-select-padding-x + $custom-select-indicator-padding) !default;
 $custom-select-feedback-icon-position:      center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;
 $custom-select-feedback-icon-size:          $input-height-inner-half $input-height-inner-half !default;
 
@@ -651,9 +664,9 @@ $form-feedback-valid-color:         theme-color("success") !default;
 $form-feedback-invalid-color:       theme-color("danger") !default;
 
 $form-feedback-icon-valid-color:    $form-feedback-valid-color !default;
-$form-feedback-icon-valid:          str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$form-feedback-icon-valid:          url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>") !default;
 $form-feedback-icon-invalid-color:  $form-feedback-invalid-color !default;
-$form-feedback-icon-invalid:        str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"), "#", "%23") !default;
+$form-feedback-icon-invalid:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='#{$form-feedback-icon-invalid-color}' viewBox='0 0 12 12'><circle cx='6' cy='6' r='4.5'/><path stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/><circle cx='6' cy='8.2' r='.6' fill='#{$form-feedback-icon-invalid-color}' stroke='none'/></svg>") !default;
 
 $form-validation-states: () !default;
 // stylelint-disable-next-line scss/dollar-variable-default
@@ -729,14 +742,14 @@ $navbar-dark-color:                 rgba($white, .5) !default;
 $navbar-dark-hover-color:           rgba($white, .75) !default;
 $navbar-dark-active-color:          $white !default;
 $navbar-dark-disabled-color:        rgba($white, .25) !default;
-$navbar-dark-toggler-icon-bg:       str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
+$navbar-dark-toggler-icon-bg:       url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'><path stroke='#{$navbar-dark-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-dark-toggler-border-color:  rgba($white, .1) !default;
 
 $navbar-light-color:                rgba($black, .5) !default;
 $navbar-light-hover-color:          rgba($black, .7) !default;
 $navbar-light-active-color:         rgba($black, .9) !default;
 $navbar-light-disabled-color:       rgba($black, .3) !default;
-$navbar-light-toggler-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
+$navbar-light-toggler-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'><path stroke='#{$navbar-light-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-light-toggler-border-color: rgba($black, .1) !default;
 
 $navbar-light-brand-color:                $navbar-light-active-color !default;
@@ -758,7 +771,7 @@ $dropdown-bg:                       $white !default;
 $dropdown-border-color:             rgba($black, .15) !default;
 $dropdown-border-radius:            $border-radius !default;
 $dropdown-border-width:             $border-width !default;
-$dropdown-inner-border-radius:      calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;
+$dropdown-inner-border-radius:      subtract($dropdown-border-radius, $dropdown-border-width) !default;
 $dropdown-divider-bg:               $gray-200 !default;
 $dropdown-divider-margin-y:         $nav-divider-margin-y !default;
 $dropdown-box-shadow:               0 .5rem 1rem rgba($black, .175) !default;
@@ -776,6 +789,7 @@ $dropdown-item-padding-y:           .25rem !default;
 $dropdown-item-padding-x:           1.5rem !default;
 
 $dropdown-header-color:             $gray-600 !default;
+$dropdown-header-padding:           $dropdown-padding-y $dropdown-item-padding-x !default;
 
 
 // Pagination
@@ -823,9 +837,10 @@ $card-spacer-x:                     1.25rem !default;
 $card-border-width:                 $border-width !default;
 $card-border-radius:                $border-radius !default;
 $card-border-color:                 rgba($black, .125) !default;
-$card-inner-border-radius:          calc(#{$card-border-radius} - #{$card-border-width}) !default;
+$card-inner-border-radius:          subtract($card-border-radius, $card-border-width) !default;
 $card-cap-bg:                       rgba($black, .03) !default;
 $card-cap-color:                    null !default;
+$card-height:                       null !default;
 $card-color:                        null !default;
 $card-bg:                           $white !default;
 
@@ -872,6 +887,7 @@ $popover-max-width:                 276px !default;
 $popover-border-width:              $border-width !default;
 $popover-border-color:              rgba($black, .2) !default;
 $popover-border-radius:             $border-radius-lg !default;
+$popover-inner-border-radius:       subtract($popover-border-radius, $popover-border-width) !default;
 $popover-box-shadow:                0 .25rem .5rem rgba($black, .2) !default;
 
 $popover-header-bg:                 darken($popover-bg, 3%) !default;
@@ -930,6 +946,9 @@ $badge-pill-border-radius:          10rem !default;
 // Padding applied to the modal body
 $modal-inner-padding:               1rem !default;
 
+// Margin between elements in footer, must be lower than or equal to 2 * $modal-inner-padding
+$modal-footer-margin-between:       .5rem !default;
+
 $modal-dialog-margin:               .5rem !default;
 $modal-dialog-margin-y-sm-up:       1.75rem !default;
 
@@ -940,6 +959,7 @@ $modal-content-bg:                  $white !default;
 $modal-content-border-color:        rgba($black, .2) !default;
 $modal-content-border-width:        $border-width !default;
 $modal-content-border-radius:       $border-radius-lg !default;
+$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default;
 $modal-content-box-shadow-xs:       0 .25rem .5rem rgba($black, .5) !default;
 $modal-content-box-shadow-sm-up:    0 .5rem 1rem rgba($black, .5) !default;
 
@@ -961,6 +981,7 @@ $modal-sm:                          300px !default;
 $modal-fade-transform:              translate(0, -50px) !default;
 $modal-show-transform:              none !default;
 $modal-transition:                  transform .3s ease-out !default;
+$modal-scale-transform:             scale(1.02) !default;
 
 
 // Alerts
@@ -1036,6 +1057,8 @@ $figure-caption-color:              $gray-600 !default;
 
 // Breadcrumbs
 
+$breadcrumb-font-size:              null !default;
+
 $breadcrumb-padding-y:              .75rem !default;
 $breadcrumb-padding-x:              1rem !default;
 $breadcrumb-item-padding:           .5rem !default;
@@ -1070,8 +1093,8 @@ $carousel-caption-color:             $white !default;
 
 $carousel-control-icon-width:        20px !default;
 
-$carousel-control-prev-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"), "#", "%23") !default;
-$carousel-control-next-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$carousel-control-prev-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' width='8' height='8' viewBox='0 0 8 8'><path d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/></svg>") !default;
+$carousel-control-next-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' width='8' height='8' viewBox='0 0 8 8'><path d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/></svg>") !default;
 
 $carousel-transition-duration:       .6s !default;
 $carousel-transition:                transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
@@ -1116,6 +1139,7 @@ $pre-scrollable-max-height:         340px !default;
 $displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;
 $overflows: auto, hidden !default;
 $positions: static, relative, absolute, fixed, sticky !default;
+$user-selects: all, auto, none !default;
 
 
 // Printing

+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/LICENSE

@@ -1,7 +1,7 @@
 The MIT License (MIT)
 
-Copyright (c) 2011-2019 Twitter, Inc.
-Copyright (c) 2011-2019 The Bootstrap Authors
+Copyright (c) 2011-2020 Twitter, Inc.
+Copyright (c) 2011-2020 The Bootstrap Authors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/README.txt

@@ -1,3 +1,3 @@
-Minimal redistribution of Bootstrap 4.3.1 for CodeRed CMS.
+Minimal redistribution of Bootstrap 4.5.0 for CodeRed CMS.
 Full source and documentation available at: https://getbootstrap.com/.
 

+ 189 - 4
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.css

@@ -1,7 +1,7 @@
 /*!
- * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
 html {
@@ -47,7 +47,7 @@ html {
   }
 }
 
-.container-fluid {
+.container-fluid, .container-sm, .container-md, .container-lg, .container-xl {
   width: 100%;
   padding-right: 15px;
   padding-left: 15px;
@@ -55,6 +55,30 @@ html {
   margin-left: auto;
 }
 
+@media (min-width: 576px) {
+  .container, .container-sm {
+    max-width: 540px;
+  }
+}
+
+@media (min-width: 768px) {
+  .container, .container-sm, .container-md {
+    max-width: 720px;
+  }
+}
+
+@media (min-width: 992px) {
+  .container, .container-sm, .container-md, .container-lg {
+    max-width: 960px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container, .container-sm, .container-md, .container-lg, .container-xl {
+    max-width: 1140px;
+  }
+}
+
 .row {
   display: -ms-flexbox;
   display: flex;
@@ -92,9 +116,46 @@ html {
   flex-basis: 0;
   -ms-flex-positive: 1;
   flex-grow: 1;
+  min-width: 0;
+  max-width: 100%;
+}
+
+.row-cols-1 > * {
+  -ms-flex: 0 0 100%;
+  flex: 0 0 100%;
   max-width: 100%;
 }
 
+.row-cols-2 > * {
+  -ms-flex: 0 0 50%;
+  flex: 0 0 50%;
+  max-width: 50%;
+}
+
+.row-cols-3 > * {
+  -ms-flex: 0 0 33.333333%;
+  flex: 0 0 33.333333%;
+  max-width: 33.333333%;
+}
+
+.row-cols-4 > * {
+  -ms-flex: 0 0 25%;
+  flex: 0 0 25%;
+  max-width: 25%;
+}
+
+.row-cols-5 > * {
+  -ms-flex: 0 0 20%;
+  flex: 0 0 20%;
+  max-width: 20%;
+}
+
+.row-cols-6 > * {
+  -ms-flex: 0 0 16.666667%;
+  flex: 0 0 16.666667%;
+  max-width: 16.666667%;
+}
+
 .col-auto {
   -ms-flex: 0 0 auto;
   flex: 0 0 auto;
@@ -299,8 +360,39 @@ html {
     flex-basis: 0;
     -ms-flex-positive: 1;
     flex-grow: 1;
+    min-width: 0;
     max-width: 100%;
   }
+  .row-cols-sm-1 > * {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .row-cols-sm-2 > * {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .row-cols-sm-3 > * {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .row-cols-sm-4 > * {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .row-cols-sm-5 > * {
+    -ms-flex: 0 0 20%;
+    flex: 0 0 20%;
+    max-width: 20%;
+  }
+  .row-cols-sm-6 > * {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
   .col-sm-auto {
     -ms-flex: 0 0 auto;
     flex: 0 0 auto;
@@ -471,8 +563,39 @@ html {
     flex-basis: 0;
     -ms-flex-positive: 1;
     flex-grow: 1;
+    min-width: 0;
     max-width: 100%;
   }
+  .row-cols-md-1 > * {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .row-cols-md-2 > * {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .row-cols-md-3 > * {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .row-cols-md-4 > * {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .row-cols-md-5 > * {
+    -ms-flex: 0 0 20%;
+    flex: 0 0 20%;
+    max-width: 20%;
+  }
+  .row-cols-md-6 > * {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
   .col-md-auto {
     -ms-flex: 0 0 auto;
     flex: 0 0 auto;
@@ -643,8 +766,39 @@ html {
     flex-basis: 0;
     -ms-flex-positive: 1;
     flex-grow: 1;
+    min-width: 0;
+    max-width: 100%;
+  }
+  .row-cols-lg-1 > * {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
     max-width: 100%;
   }
+  .row-cols-lg-2 > * {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .row-cols-lg-3 > * {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .row-cols-lg-4 > * {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .row-cols-lg-5 > * {
+    -ms-flex: 0 0 20%;
+    flex: 0 0 20%;
+    max-width: 20%;
+  }
+  .row-cols-lg-6 > * {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
   .col-lg-auto {
     -ms-flex: 0 0 auto;
     flex: 0 0 auto;
@@ -815,8 +969,39 @@ html {
     flex-basis: 0;
     -ms-flex-positive: 1;
     flex-grow: 1;
+    min-width: 0;
+    max-width: 100%;
+  }
+  .row-cols-xl-1 > * {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
     max-width: 100%;
   }
+  .row-cols-xl-2 > * {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .row-cols-xl-3 > * {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .row-cols-xl-4 > * {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .row-cols-xl-5 > * {
+    -ms-flex: 0 0 20%;
+    flex: 0 0 20%;
+    max-width: 20%;
+  }
+  .row-cols-xl-6 > * {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
   .col-xl-auto {
     -ms-flex: 0 0 auto;
     flex: 0 0 auto;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.min.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-grid.min.css.map


+ 11 - 17
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.css

@@ -1,7 +1,7 @@
 /*!
- * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
  */
@@ -33,7 +33,7 @@ body {
   background-color: #fff;
 }
 
-[tabindex="-1"]:focus {
+[tabindex="-1"]:focus:not(:focus-visible) {
   outline: 0 !important;
 }
 
@@ -133,20 +133,16 @@ a:hover {
   text-decoration: underline;
 }
 
-a:not([href]):not([tabindex]) {
+a:not([href]) {
   color: inherit;
   text-decoration: none;
 }
 
-a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
+a:not([href]):hover {
   color: inherit;
   text-decoration: none;
 }
 
-a:not([href]):not([tabindex]):focus {
-  outline: 0;
-}
-
 pre,
 code,
 kbd,
@@ -159,6 +155,7 @@ pre {
   margin-top: 0;
   margin-bottom: 1rem;
   overflow: auto;
+  -ms-overflow-style: scrollbar;
 }
 
 figure {
@@ -226,6 +223,10 @@ select {
   text-transform: none;
 }
 
+[role="button"] {
+  cursor: pointer;
+}
+
 select {
   word-wrap: normal;
 }
@@ -258,13 +259,6 @@ input[type="checkbox"] {
   padding: 0;
 }
 
-input[type="date"],
-input[type="time"],
-input[type="datetime-local"],
-input[type="month"] {
-  -webkit-appearance: listbox;
-}
-
 textarea {
   overflow: auto;
   resize: vertical;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.min.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap-reboot.min.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 327 - 140
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.min.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/css/bootstrap.min.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 286 - 242
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.bundle.min.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 287 - 243
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/bootstrap/dist/js/bootstrap.min.js.map


+ 16 - 22
coderedcms/static/coderedcms/vendor/bootstrap/js/src/alert.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): alert.js
+ * Bootstrap (v4.5.0): alert.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,27 +15,21 @@ import Util from './util'
  */
 
 const NAME                = 'alert'
-const VERSION             = '4.3.1'
+const VERSION             = '4.5.0'
 const DATA_KEY            = 'bs.alert'
 const EVENT_KEY           = `.${DATA_KEY}`
 const DATA_API_KEY        = '.data-api'
 const JQUERY_NO_CONFLICT  = $.fn[NAME]
 
-const Selector = {
-  DISMISS : '[data-dismiss="alert"]'
-}
+const SELECTOR_DISMISS = '[data-dismiss="alert"]'
 
-const Event = {
-  CLOSE          : `close${EVENT_KEY}`,
-  CLOSED         : `closed${EVENT_KEY}`,
-  CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
-}
+const EVENT_CLOSE          = `close${EVENT_KEY}`
+const EVENT_CLOSED         = `closed${EVENT_KEY}`
+const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
 
-const ClassName = {
-  ALERT : 'alert',
-  FADE  : 'fade',
-  SHOW  : 'show'
-}
+const CLASS_NAME_ALERT = 'alert'
+const CLASS_NAME_FADE  = 'fade'
+const CLASS_NAME_SHOW  = 'show'
 
 /**
  * ------------------------------------------------------------------------
@@ -87,23 +81,23 @@ class Alert {
     }
 
     if (!parent) {
-      parent = $(element).closest(`.${ClassName.ALERT}`)[0]
+      parent = $(element).closest(`.${CLASS_NAME_ALERT}`)[0]
     }
 
     return parent
   }
 
   _triggerCloseEvent(element) {
-    const closeEvent = $.Event(Event.CLOSE)
+    const closeEvent = $.Event(EVENT_CLOSE)
 
     $(element).trigger(closeEvent)
     return closeEvent
   }
 
   _removeElement(element) {
-    $(element).removeClass(ClassName.SHOW)
+    $(element).removeClass(CLASS_NAME_SHOW)
 
-    if (!$(element).hasClass(ClassName.FADE)) {
+    if (!$(element).hasClass(CLASS_NAME_FADE)) {
       this._destroyElement(element)
       return
     }
@@ -118,7 +112,7 @@ class Alert {
   _destroyElement(element) {
     $(element)
       .detach()
-      .trigger(Event.CLOSED)
+      .trigger(EVENT_CLOSED)
       .remove()
   }
 
@@ -158,8 +152,8 @@ class Alert {
  */
 
 $(document).on(
-  Event.CLICK_DATA_API,
-  Selector.DISMISS,
+  EVENT_CLICK_DATA_API,
+  SELECTOR_DISMISS,
   Alert._handleDismiss(new Alert())
 )
 

+ 80 - 44
coderedcms/static/coderedcms/vendor/bootstrap/js/src/button.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): button.js
+ * Bootstrap (v4.5.0): button.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -14,31 +14,28 @@ import $ from 'jquery'
  */
 
 const NAME                = 'button'
-const VERSION             = '4.3.1'
+const VERSION             = '4.5.0'
 const DATA_KEY            = 'bs.button'
 const EVENT_KEY           = `.${DATA_KEY}`
 const DATA_API_KEY        = '.data-api'
 const JQUERY_NO_CONFLICT  = $.fn[NAME]
 
-const ClassName = {
-  ACTIVE : 'active',
-  BUTTON : 'btn',
-  FOCUS  : 'focus'
-}
+const CLASS_NAME_ACTIVE = 'active'
+const CLASS_NAME_BUTTON = 'btn'
+const CLASS_NAME_FOCUS  = 'focus'
 
-const Selector = {
-  DATA_TOGGLE_CARROT : '[data-toggle^="button"]',
-  DATA_TOGGLE        : '[data-toggle="buttons"]',
-  INPUT              : 'input:not([type="hidden"])',
-  ACTIVE             : '.active',
-  BUTTON             : '.btn'
-}
+const SELECTOR_DATA_TOGGLE_CARROT   = '[data-toggle^="button"]'
+const SELECTOR_DATA_TOGGLES         = '[data-toggle="buttons"]'
+const SELECTOR_DATA_TOGGLE          = '[data-toggle="button"]'
+const SELECTOR_DATA_TOGGLES_BUTTONS = '[data-toggle="buttons"] .btn'
+const SELECTOR_INPUT                = 'input:not([type="hidden"])'
+const SELECTOR_ACTIVE               = '.active'
+const SELECTOR_BUTTON               = '.btn'
 
-const Event = {
-  CLICK_DATA_API      : `click${EVENT_KEY}${DATA_API_KEY}`,
-  FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +
+const EVENT_CLICK_DATA_API      = `click${EVENT_KEY}${DATA_API_KEY}`
+const EVENT_FOCUS_BLUR_DATA_API = `focus${EVENT_KEY}${DATA_API_KEY} ` +
                           `blur${EVENT_KEY}${DATA_API_KEY}`
-}
+const EVENT_LOAD_DATA_API       = `load${EVENT_KEY}${DATA_API_KEY}`
 
 /**
  * ------------------------------------------------------------------------
@@ -63,34 +60,31 @@ class Button {
     let triggerChangeEvent = true
     let addAriaPressed = true
     const rootElement = $(this._element).closest(
-      Selector.DATA_TOGGLE
+      SELECTOR_DATA_TOGGLES
     )[0]
 
     if (rootElement) {
-      const input = this._element.querySelector(Selector.INPUT)
+      const input = this._element.querySelector(SELECTOR_INPUT)
 
       if (input) {
         if (input.type === 'radio') {
           if (input.checked &&
-            this._element.classList.contains(ClassName.ACTIVE)) {
+            this._element.classList.contains(CLASS_NAME_ACTIVE)) {
             triggerChangeEvent = false
           } else {
-            const activeElement = rootElement.querySelector(Selector.ACTIVE)
+            const activeElement = rootElement.querySelector(SELECTOR_ACTIVE)
 
             if (activeElement) {
-              $(activeElement).removeClass(ClassName.ACTIVE)
+              $(activeElement).removeClass(CLASS_NAME_ACTIVE)
             }
           }
         }
 
         if (triggerChangeEvent) {
-          if (input.hasAttribute('disabled') ||
-            rootElement.hasAttribute('disabled') ||
-            input.classList.contains('disabled') ||
-            rootElement.classList.contains('disabled')) {
-            return
+          // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input
+          if (input.type === 'checkbox' || input.type === 'radio') {
+            input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE)
           }
-          input.checked = !this._element.classList.contains(ClassName.ACTIVE)
           $(input).trigger('change')
         }
 
@@ -99,13 +93,15 @@ class Button {
       }
     }
 
-    if (addAriaPressed) {
-      this._element.setAttribute('aria-pressed',
-        !this._element.classList.contains(ClassName.ACTIVE))
-    }
+    if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {
+      if (addAriaPressed) {
+        this._element.setAttribute('aria-pressed',
+          !this._element.classList.contains(CLASS_NAME_ACTIVE))
+      }
 
-    if (triggerChangeEvent) {
-      $(this._element).toggleClass(ClassName.ACTIVE)
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(CLASS_NAME_ACTIVE)
+      }
     }
   }
 
@@ -139,22 +135,62 @@ class Button {
  */
 
 $(document)
-  .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {
-    event.preventDefault()
-
+  .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, (event) => {
     let button = event.target
+    const initialButton = button
 
-    if (!$(button).hasClass(ClassName.BUTTON)) {
-      button = $(button).closest(Selector.BUTTON)
+    if (!$(button).hasClass(CLASS_NAME_BUTTON)) {
+      button = $(button).closest(SELECTOR_BUTTON)[0]
     }
 
-    Button._jQueryInterface.call($(button), 'toggle')
+    if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) {
+      event.preventDefault() // work around Firefox bug #1540995
+    } else {
+      const inputBtn = button.querySelector(SELECTOR_INPUT)
+
+      if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) {
+        event.preventDefault() // work around Firefox bug #1540995
+        return
+      }
+
+      if (initialButton.tagName === 'LABEL' && inputBtn && inputBtn.type === 'checkbox') {
+        event.preventDefault() // work around event sent to label and input
+      }
+      Button._jQueryInterface.call($(button), 'toggle')
+    }
   })
-  .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {
-    const button = $(event.target).closest(Selector.BUTTON)[0]
-    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))
+  .on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, (event) => {
+    const button = $(event.target).closest(SELECTOR_BUTTON)[0]
+    $(button).toggleClass(CLASS_NAME_FOCUS, /^focus(in)?$/.test(event.type))
   })
 
+$(window).on(EVENT_LOAD_DATA_API, () => {
+  // ensure correct active class is set to match the controls' actual values/states
+
+  // find all checkboxes/readio buttons inside data-toggle groups
+  let buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLES_BUTTONS))
+  for (let i = 0, len = buttons.length; i < len; i++) {
+    const button = buttons[i]
+    const input = button.querySelector(SELECTOR_INPUT)
+    if (input.checked || input.hasAttribute('checked')) {
+      button.classList.add(CLASS_NAME_ACTIVE)
+    } else {
+      button.classList.remove(CLASS_NAME_ACTIVE)
+    }
+  }
+
+  // find all button toggles
+  buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))
+  for (let i = 0, len = buttons.length; i < len; i++) {
+    const button = buttons[i]
+    if (button.getAttribute('aria-pressed') === 'true') {
+      button.classList.add(CLASS_NAME_ACTIVE)
+    } else {
+      button.classList.remove(CLASS_NAME_ACTIVE)
+    }
+  }
+})
+
 /**
  * ------------------------------------------------------------------------
  * jQuery

+ 88 - 96
coderedcms/static/coderedcms/vendor/bootstrap/js/src/carousel.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): carousel.js
+ * Bootstrap (v4.5.0): carousel.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@ import Util from './util'
  */
 
 const NAME                   = 'carousel'
-const VERSION                = '4.3.1'
+const VERSION                = '4.5.0'
 const DATA_KEY               = 'bs.carousel'
 const EVENT_KEY              = `.${DATA_KEY}`
 const DATA_API_KEY           = '.data-api'
@@ -43,51 +43,42 @@ const DefaultType = {
   touch    : 'boolean'
 }
 
-const Direction = {
-  NEXT     : 'next',
-  PREV     : 'prev',
-  LEFT     : 'left',
-  RIGHT    : 'right'
-}
-
-const Event = {
-  SLIDE          : `slide${EVENT_KEY}`,
-  SLID           : `slid${EVENT_KEY}`,
-  KEYDOWN        : `keydown${EVENT_KEY}`,
-  MOUSEENTER     : `mouseenter${EVENT_KEY}`,
-  MOUSELEAVE     : `mouseleave${EVENT_KEY}`,
-  TOUCHSTART     : `touchstart${EVENT_KEY}`,
-  TOUCHMOVE      : `touchmove${EVENT_KEY}`,
-  TOUCHEND       : `touchend${EVENT_KEY}`,
-  POINTERDOWN    : `pointerdown${EVENT_KEY}`,
-  POINTERUP      : `pointerup${EVENT_KEY}`,
-  DRAG_START     : `dragstart${EVENT_KEY}`,
-  LOAD_DATA_API  : `load${EVENT_KEY}${DATA_API_KEY}`,
-  CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
-}
-
-const ClassName = {
-  CAROUSEL      : 'carousel',
-  ACTIVE        : 'active',
-  SLIDE         : 'slide',
-  RIGHT         : 'carousel-item-right',
-  LEFT          : 'carousel-item-left',
-  NEXT          : 'carousel-item-next',
-  PREV          : 'carousel-item-prev',
-  ITEM          : 'carousel-item',
-  POINTER_EVENT : 'pointer-event'
-}
-
-const Selector = {
-  ACTIVE      : '.active',
-  ACTIVE_ITEM : '.active.carousel-item',
-  ITEM        : '.carousel-item',
-  ITEM_IMG    : '.carousel-item img',
-  NEXT_PREV   : '.carousel-item-next, .carousel-item-prev',
-  INDICATORS  : '.carousel-indicators',
-  DATA_SLIDE  : '[data-slide], [data-slide-to]',
-  DATA_RIDE   : '[data-ride="carousel"]'
-}
+const DIRECTION_NEXT     = 'next'
+const DIRECTION_PREV     = 'prev'
+const DIRECTION_LEFT     = 'left'
+const DIRECTION_RIGHT    = 'right'
+
+const EVENT_SLIDE          = `slide${EVENT_KEY}`
+const EVENT_SLID           = `slid${EVENT_KEY}`
+const EVENT_KEYDOWN        = `keydown${EVENT_KEY}`
+const EVENT_MOUSEENTER     = `mouseenter${EVENT_KEY}`
+const EVENT_MOUSELEAVE     = `mouseleave${EVENT_KEY}`
+const EVENT_TOUCHSTART     = `touchstart${EVENT_KEY}`
+const EVENT_TOUCHMOVE      = `touchmove${EVENT_KEY}`
+const EVENT_TOUCHEND       = `touchend${EVENT_KEY}`
+const EVENT_POINTERDOWN    = `pointerdown${EVENT_KEY}`
+const EVENT_POINTERUP      = `pointerup${EVENT_KEY}`
+const EVENT_DRAG_START     = `dragstart${EVENT_KEY}`
+const EVENT_LOAD_DATA_API  = `load${EVENT_KEY}${DATA_API_KEY}`
+const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
+
+const CLASS_NAME_CAROUSEL      = 'carousel'
+const CLASS_NAME_ACTIVE        = 'active'
+const CLASS_NAME_SLIDE         = 'slide'
+const CLASS_NAME_RIGHT         = 'carousel-item-right'
+const CLASS_NAME_LEFT          = 'carousel-item-left'
+const CLASS_NAME_NEXT          = 'carousel-item-next'
+const CLASS_NAME_PREV          = 'carousel-item-prev'
+const CLASS_NAME_POINTER_EVENT = 'pointer-event'
+
+const SELECTOR_ACTIVE      = '.active'
+const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'
+const SELECTOR_ITEM        = '.carousel-item'
+const SELECTOR_ITEM_IMG    = '.carousel-item img'
+const SELECTOR_NEXT_PREV   = '.carousel-item-next, .carousel-item-prev'
+const SELECTOR_INDICATORS  = '.carousel-indicators'
+const SELECTOR_DATA_SLIDE  = '[data-slide], [data-slide-to]'
+const SELECTOR_DATA_RIDE   = '[data-ride="carousel"]'
 
 const PointerType = {
   TOUCH : 'touch',
@@ -112,7 +103,7 @@ class Carousel {
 
     this._config            = this._getConfig(config)
     this._element           = element
-    this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)
+    this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS)
     this._touchSupported    = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
     this._pointerEvent      = Boolean(window.PointerEvent || window.MSPointerEvent)
 
@@ -133,7 +124,7 @@ class Carousel {
 
   next() {
     if (!this._isSliding) {
-      this._slide(Direction.NEXT)
+      this._slide(DIRECTION_NEXT)
     }
   }
 
@@ -148,7 +139,7 @@ class Carousel {
 
   prev() {
     if (!this._isSliding) {
-      this._slide(Direction.PREV)
+      this._slide(DIRECTION_PREV)
     }
   }
 
@@ -157,7 +148,7 @@ class Carousel {
       this._isPaused = true
     }
 
-    if (this._element.querySelector(Selector.NEXT_PREV)) {
+    if (this._element.querySelector(SELECTOR_NEXT_PREV)) {
       Util.triggerTransitionEnd(this._element)
       this.cycle(true)
     }
@@ -185,7 +176,7 @@ class Carousel {
   }
 
   to(index) {
-    this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)
+    this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)
 
     const activeIndex = this._getItemIndex(this._activeElement)
 
@@ -194,7 +185,7 @@ class Carousel {
     }
 
     if (this._isSliding) {
-      $(this._element).one(Event.SLID, () => this.to(index))
+      $(this._element).one(EVENT_SLID, () => this.to(index))
       return
     }
 
@@ -205,8 +196,8 @@ class Carousel {
     }
 
     const direction = index > activeIndex
-      ? Direction.NEXT
-      : Direction.PREV
+      ? DIRECTION_NEXT
+      : DIRECTION_PREV
 
     this._slide(direction, this._items[index])
   }
@@ -245,6 +236,8 @@ class Carousel {
 
     const direction = absDeltax / this.touchDeltaX
 
+    this.touchDeltaX = 0
+
     // swipe left
     if (direction > 0) {
       this.prev()
@@ -258,14 +251,13 @@ class Carousel {
 
   _addEventListeners() {
     if (this._config.keyboard) {
-      $(this._element)
-        .on(Event.KEYDOWN, (event) => this._keydown(event))
+      $(this._element).on(EVENT_KEYDOWN, (event) => this._keydown(event))
     }
 
     if (this._config.pause === 'hover') {
       $(this._element)
-        .on(Event.MOUSEENTER, (event) => this.pause(event))
-        .on(Event.MOUSELEAVE, (event) => this.cycle(event))
+        .on(EVENT_MOUSEENTER, (event) => this.pause(event))
+        .on(EVENT_MOUSELEAVE, (event) => this.cycle(event))
     }
 
     if (this._config.touch) {
@@ -318,16 +310,18 @@ class Carousel {
       }
     }
 
-    $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, (e) => e.preventDefault())
+    $(this._element.querySelectorAll(SELECTOR_ITEM_IMG))
+      .on(EVENT_DRAG_START, (e) => e.preventDefault())
+
     if (this._pointerEvent) {
-      $(this._element).on(Event.POINTERDOWN, (event) => start(event))
-      $(this._element).on(Event.POINTERUP, (event) => end(event))
+      $(this._element).on(EVENT_POINTERDOWN, (event) => start(event))
+      $(this._element).on(EVENT_POINTERUP, (event) => end(event))
 
-      this._element.classList.add(ClassName.POINTER_EVENT)
+      this._element.classList.add(CLASS_NAME_POINTER_EVENT)
     } else {
-      $(this._element).on(Event.TOUCHSTART, (event) => start(event))
-      $(this._element).on(Event.TOUCHMOVE, (event) => move(event))
-      $(this._element).on(Event.TOUCHEND, (event) => end(event))
+      $(this._element).on(EVENT_TOUCHSTART, (event) => start(event))
+      $(this._element).on(EVENT_TOUCHMOVE, (event) => move(event))
+      $(this._element).on(EVENT_TOUCHEND, (event) => end(event))
     }
   }
 
@@ -351,14 +345,14 @@ class Carousel {
 
   _getItemIndex(element) {
     this._items = element && element.parentNode
-      ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))
+      ? [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM))
       : []
     return this._items.indexOf(element)
   }
 
   _getItemByDirection(direction, activeElement) {
-    const isNextDirection = direction === Direction.NEXT
-    const isPrevDirection = direction === Direction.PREV
+    const isNextDirection = direction === DIRECTION_NEXT
+    const isPrevDirection = direction === DIRECTION_PREV
     const activeIndex     = this._getItemIndex(activeElement)
     const lastItemIndex   = this._items.length - 1
     const isGoingToWrap   = isPrevDirection && activeIndex === 0 ||
@@ -368,7 +362,7 @@ class Carousel {
       return activeElement
     }
 
-    const delta     = direction === Direction.PREV ? -1 : 1
+    const delta     = direction === DIRECTION_PREV ? -1 : 1
     const itemIndex = (activeIndex + delta) % this._items.length
 
     return itemIndex === -1
@@ -377,8 +371,8 @@ class Carousel {
 
   _triggerSlideEvent(relatedTarget, eventDirectionName) {
     const targetIndex = this._getItemIndex(relatedTarget)
-    const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))
-    const slideEvent = $.Event(Event.SLIDE, {
+    const fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM))
+    const slideEvent = $.Event(EVENT_SLIDE, {
       relatedTarget,
       direction: eventDirectionName,
       from: fromIndex,
@@ -392,22 +386,21 @@ class Carousel {
 
   _setActiveIndicatorElement(element) {
     if (this._indicatorsElement) {
-      const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))
-      $(indicators)
-        .removeClass(ClassName.ACTIVE)
+      const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE))
+      $(indicators).removeClass(CLASS_NAME_ACTIVE)
 
       const nextIndicator = this._indicatorsElement.children[
         this._getItemIndex(element)
       ]
 
       if (nextIndicator) {
-        $(nextIndicator).addClass(ClassName.ACTIVE)
+        $(nextIndicator).addClass(CLASS_NAME_ACTIVE)
       }
     }
   }
 
   _slide(direction, element) {
-    const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)
+    const activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)
     const activeElementIndex = this._getItemIndex(activeElement)
     const nextElement   = element || activeElement &&
       this._getItemByDirection(direction, activeElement)
@@ -418,17 +411,17 @@ class Carousel {
     let orderClassName
     let eventDirectionName
 
-    if (direction === Direction.NEXT) {
-      directionalClassName = ClassName.LEFT
-      orderClassName = ClassName.NEXT
-      eventDirectionName = Direction.LEFT
+    if (direction === DIRECTION_NEXT) {
+      directionalClassName = CLASS_NAME_LEFT
+      orderClassName = CLASS_NAME_NEXT
+      eventDirectionName = DIRECTION_LEFT
     } else {
-      directionalClassName = ClassName.RIGHT
-      orderClassName = ClassName.PREV
-      eventDirectionName = Direction.RIGHT
+      directionalClassName = CLASS_NAME_RIGHT
+      orderClassName = CLASS_NAME_PREV
+      eventDirectionName = DIRECTION_RIGHT
     }
 
-    if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+    if (nextElement && $(nextElement).hasClass(CLASS_NAME_ACTIVE)) {
       this._isSliding = false
       return
     }
@@ -451,14 +444,14 @@ class Carousel {
 
     this._setActiveIndicatorElement(nextElement)
 
-    const slidEvent = $.Event(Event.SLID, {
+    const slidEvent = $.Event(EVENT_SLID, {
       relatedTarget: nextElement,
       direction: eventDirectionName,
       from: activeElementIndex,
       to: nextElementIndex
     })
 
-    if ($(this._element).hasClass(ClassName.SLIDE)) {
+    if ($(this._element).hasClass(CLASS_NAME_SLIDE)) {
       $(nextElement).addClass(orderClassName)
 
       Util.reflow(nextElement)
@@ -480,9 +473,9 @@ class Carousel {
         .one(Util.TRANSITION_END, () => {
           $(nextElement)
             .removeClass(`${directionalClassName} ${orderClassName}`)
-            .addClass(ClassName.ACTIVE)
+            .addClass(CLASS_NAME_ACTIVE)
 
-          $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)
+          $(activeElement).removeClass(`${CLASS_NAME_ACTIVE} ${orderClassName} ${directionalClassName}`)
 
           this._isSliding = false
 
@@ -490,8 +483,8 @@ class Carousel {
         })
         .emulateTransitionEnd(transitionDuration)
     } else {
-      $(activeElement).removeClass(ClassName.ACTIVE)
-      $(nextElement).addClass(ClassName.ACTIVE)
+      $(activeElement).removeClass(CLASS_NAME_ACTIVE)
+      $(nextElement).addClass(CLASS_NAME_ACTIVE)
 
       this._isSliding = false
       $(this._element).trigger(slidEvent)
@@ -549,7 +542,7 @@ class Carousel {
 
     const target = $(selector)[0]
 
-    if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+    if (!target || !$(target).hasClass(CLASS_NAME_CAROUSEL)) {
       return
     }
 
@@ -579,11 +572,10 @@ class Carousel {
  * ------------------------------------------------------------------------
  */
 
-$(document)
-  .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)
+$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler)
 
-$(window).on(Event.LOAD_DATA_API, () => {
-  const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))
+$(window).on(EVENT_LOAD_DATA_API, () => {
+  const carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE))
   for (let i = 0, len = carousels.length; i < len; i++) {
     const $carousel = $(carousels[i])
     Carousel._jQueryInterface.call($carousel, $carousel.data())

+ 44 - 55
coderedcms/static/coderedcms/vendor/bootstrap/js/src/collapse.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): collapse.js
+ * Bootstrap (v4.5.0): collapse.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@ import Util from './util'
  */
 
 const NAME                = 'collapse'
-const VERSION             = '4.3.1'
+const VERSION             = '4.5.0'
 const DATA_KEY            = 'bs.collapse'
 const EVENT_KEY           = `.${DATA_KEY}`
 const DATA_API_KEY        = '.data-api'
@@ -31,30 +31,22 @@ const DefaultType = {
   parent : '(string|element)'
 }
 
-const Event = {
-  SHOW           : `show${EVENT_KEY}`,
-  SHOWN          : `shown${EVENT_KEY}`,
-  HIDE           : `hide${EVENT_KEY}`,
-  HIDDEN         : `hidden${EVENT_KEY}`,
-  CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
-}
+const EVENT_SHOW           = `show${EVENT_KEY}`
+const EVENT_SHOWN          = `shown${EVENT_KEY}`
+const EVENT_HIDE           = `hide${EVENT_KEY}`
+const EVENT_HIDDEN         = `hidden${EVENT_KEY}`
+const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
 
-const ClassName = {
-  SHOW       : 'show',
-  COLLAPSE   : 'collapse',
-  COLLAPSING : 'collapsing',
-  COLLAPSED  : 'collapsed'
-}
+const CLASS_NAME_SHOW       = 'show'
+const CLASS_NAME_COLLAPSE   = 'collapse'
+const CLASS_NAME_COLLAPSING = 'collapsing'
+const CLASS_NAME_COLLAPSED  = 'collapsed'
 
-const Dimension = {
-  WIDTH  : 'width',
-  HEIGHT : 'height'
-}
+const DIMENSION_WIDTH  = 'width'
+const DIMENSION_HEIGHT = 'height'
 
-const Selector = {
-  ACTIVES     : '.show, .collapsing',
-  DATA_TOGGLE : '[data-toggle="collapse"]'
-}
+const SELECTOR_ACTIVES     = '.show, .collapsing'
+const SELECTOR_DATA_TOGGLE = '[data-toggle="collapse"]'
 
 /**
  * ------------------------------------------------------------------------
@@ -72,7 +64,7 @@ class Collapse {
       `[data-toggle="collapse"][data-target="#${element.id}"]`
     ))
 
-    const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))
+    const toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))
     for (let i = 0, len = toggleList.length; i < len; i++) {
       const elem = toggleList[i]
       const selector = Util.getSelectorFromElement(elem)
@@ -109,7 +101,7 @@ class Collapse {
   // Public
 
   toggle() {
-    if ($(this._element).hasClass(ClassName.SHOW)) {
+    if ($(this._element).hasClass(CLASS_NAME_SHOW)) {
       this.hide()
     } else {
       this.show()
@@ -118,7 +110,7 @@ class Collapse {
 
   show() {
     if (this._isTransitioning ||
-      $(this._element).hasClass(ClassName.SHOW)) {
+      $(this._element).hasClass(CLASS_NAME_SHOW)) {
       return
     }
 
@@ -126,13 +118,13 @@ class Collapse {
     let activesData
 
     if (this._parent) {
-      actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))
+      actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES))
         .filter((elem) => {
           if (typeof this._config.parent === 'string') {
             return elem.getAttribute('data-parent') === this._config.parent
           }
 
-          return elem.classList.contains(ClassName.COLLAPSE)
+          return elem.classList.contains(CLASS_NAME_COLLAPSE)
         })
 
       if (actives.length === 0) {
@@ -147,7 +139,7 @@ class Collapse {
       }
     }
 
-    const startEvent = $.Event(Event.SHOW)
+    const startEvent = $.Event(EVENT_SHOW)
     $(this._element).trigger(startEvent)
     if (startEvent.isDefaultPrevented()) {
       return
@@ -163,14 +155,14 @@ class Collapse {
     const dimension = this._getDimension()
 
     $(this._element)
-      .removeClass(ClassName.COLLAPSE)
-      .addClass(ClassName.COLLAPSING)
+      .removeClass(CLASS_NAME_COLLAPSE)
+      .addClass(CLASS_NAME_COLLAPSING)
 
     this._element.style[dimension] = 0
 
     if (this._triggerArray.length) {
       $(this._triggerArray)
-        .removeClass(ClassName.COLLAPSED)
+        .removeClass(CLASS_NAME_COLLAPSED)
         .attr('aria-expanded', true)
     }
 
@@ -178,15 +170,14 @@ class Collapse {
 
     const complete = () => {
       $(this._element)
-        .removeClass(ClassName.COLLAPSING)
-        .addClass(ClassName.COLLAPSE)
-        .addClass(ClassName.SHOW)
+        .removeClass(CLASS_NAME_COLLAPSING)
+        .addClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)
 
       this._element.style[dimension] = ''
 
       this.setTransitioning(false)
 
-      $(this._element).trigger(Event.SHOWN)
+      $(this._element).trigger(EVENT_SHOWN)
     }
 
     const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)
@@ -202,11 +193,11 @@ class Collapse {
 
   hide() {
     if (this._isTransitioning ||
-      !$(this._element).hasClass(ClassName.SHOW)) {
+      !$(this._element).hasClass(CLASS_NAME_SHOW)) {
       return
     }
 
-    const startEvent = $.Event(Event.HIDE)
+    const startEvent = $.Event(EVENT_HIDE)
     $(this._element).trigger(startEvent)
     if (startEvent.isDefaultPrevented()) {
       return
@@ -219,9 +210,8 @@ class Collapse {
     Util.reflow(this._element)
 
     $(this._element)
-      .addClass(ClassName.COLLAPSING)
-      .removeClass(ClassName.COLLAPSE)
-      .removeClass(ClassName.SHOW)
+      .addClass(CLASS_NAME_COLLAPSING)
+      .removeClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)
 
     const triggerArrayLength = this._triggerArray.length
     if (triggerArrayLength > 0) {
@@ -231,8 +221,8 @@ class Collapse {
 
         if (selector !== null) {
           const $elem = $([].slice.call(document.querySelectorAll(selector)))
-          if (!$elem.hasClass(ClassName.SHOW)) {
-            $(trigger).addClass(ClassName.COLLAPSED)
+          if (!$elem.hasClass(CLASS_NAME_SHOW)) {
+            $(trigger).addClass(CLASS_NAME_COLLAPSED)
               .attr('aria-expanded', false)
           }
         }
@@ -244,9 +234,9 @@ class Collapse {
     const complete = () => {
       this.setTransitioning(false)
       $(this._element)
-        .removeClass(ClassName.COLLAPSING)
-        .addClass(ClassName.COLLAPSE)
-        .trigger(Event.HIDDEN)
+        .removeClass(CLASS_NAME_COLLAPSING)
+        .addClass(CLASS_NAME_COLLAPSE)
+        .trigger(EVENT_HIDDEN)
     }
 
     this._element.style[dimension] = ''
@@ -284,8 +274,8 @@ class Collapse {
   }
 
   _getDimension() {
-    const hasWidth = $(this._element).hasClass(Dimension.WIDTH)
-    return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT
+    const hasWidth = $(this._element).hasClass(DIMENSION_WIDTH)
+    return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT
   }
 
   _getParent() {
@@ -302,10 +292,9 @@ class Collapse {
       parent = document.querySelector(this._config.parent)
     }
 
-    const selector =
-      `[data-toggle="collapse"][data-parent="${this._config.parent}"]`
-
+    const selector = `[data-toggle="collapse"][data-parent="${this._config.parent}"]`
     const children = [].slice.call(parent.querySelectorAll(selector))
+
     $(children).each((i, element) => {
       this._addAriaAndCollapsedClass(
         Collapse._getTargetFromElement(element),
@@ -317,11 +306,11 @@ class Collapse {
   }
 
   _addAriaAndCollapsedClass(element, triggerArray) {
-    const isOpen = $(element).hasClass(ClassName.SHOW)
+    const isOpen = $(element).hasClass(CLASS_NAME_SHOW)
 
     if (triggerArray.length) {
       $(triggerArray)
-        .toggleClass(ClassName.COLLAPSED, !isOpen)
+        .toggleClass(CLASS_NAME_COLLAPSED, !isOpen)
         .attr('aria-expanded', isOpen)
     }
   }
@@ -343,7 +332,7 @@ class Collapse {
         ...typeof config === 'object' && config ? config : {}
       }
 
-      if (!data && _config.toggle && /show|hide/.test(config)) {
+      if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
         _config.toggle = false
       }
 
@@ -368,7 +357,7 @@ class Collapse {
  * ------------------------------------------------------------------------
  */
 
-$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
   // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
   if (event.currentTarget.tagName === 'A') {
     event.preventDefault()

+ 115 - 126
coderedcms/static/coderedcms/vendor/bootstrap/js/src/dropdown.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): dropdown.js
+ * Bootstrap (v4.5.0): dropdown.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -16,7 +16,7 @@ import Util from './util'
  */
 
 const NAME                     = 'dropdown'
-const VERSION                  = '4.3.1'
+const VERSION                  = '4.5.0'
 const DATA_KEY                 = 'bs.dropdown'
 const EVENT_KEY                = `.${DATA_KEY}`
 const DATA_API_KEY             = '.data-api'
@@ -29,61 +29,52 @@ const ARROW_DOWN_KEYCODE       = 40 // KeyboardEvent.which value for down arrow
 const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)
 const REGEXP_KEYDOWN           = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)
 
-const Event = {
-  HIDE             : `hide${EVENT_KEY}`,
-  HIDDEN           : `hidden${EVENT_KEY}`,
-  SHOW             : `show${EVENT_KEY}`,
-  SHOWN            : `shown${EVENT_KEY}`,
-  CLICK            : `click${EVENT_KEY}`,
-  CLICK_DATA_API   : `click${EVENT_KEY}${DATA_API_KEY}`,
-  KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,
-  KEYUP_DATA_API   : `keyup${EVENT_KEY}${DATA_API_KEY}`
-}
-
-const ClassName = {
-  DISABLED        : 'disabled',
-  SHOW            : 'show',
-  DROPUP          : 'dropup',
-  DROPRIGHT       : 'dropright',
-  DROPLEFT        : 'dropleft',
-  MENURIGHT       : 'dropdown-menu-right',
-  MENULEFT        : 'dropdown-menu-left',
-  POSITION_STATIC : 'position-static'
-}
-
-const Selector = {
-  DATA_TOGGLE   : '[data-toggle="dropdown"]',
-  FORM_CHILD    : '.dropdown form',
-  MENU          : '.dropdown-menu',
-  NAVBAR_NAV    : '.navbar-nav',
-  VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
-}
-
-const AttachmentMap = {
-  TOP       : 'top-start',
-  TOPEND    : 'top-end',
-  BOTTOM    : 'bottom-start',
-  BOTTOMEND : 'bottom-end',
-  RIGHT     : 'right-start',
-  RIGHTEND  : 'right-end',
-  LEFT      : 'left-start',
-  LEFTEND   : 'left-end'
-}
+const EVENT_HIDE             = `hide${EVENT_KEY}`
+const EVENT_HIDDEN           = `hidden${EVENT_KEY}`
+const EVENT_SHOW             = `show${EVENT_KEY}`
+const EVENT_SHOWN            = `shown${EVENT_KEY}`
+const EVENT_CLICK            = `click${EVENT_KEY}`
+const EVENT_CLICK_DATA_API   = `click${EVENT_KEY}${DATA_API_KEY}`
+const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`
+const EVENT_KEYUP_DATA_API   = `keyup${EVENT_KEY}${DATA_API_KEY}`
+
+const CLASS_NAME_DISABLED        = 'disabled'
+const CLASS_NAME_SHOW            = 'show'
+const CLASS_NAME_DROPUP          = 'dropup'
+const CLASS_NAME_DROPRIGHT       = 'dropright'
+const CLASS_NAME_DROPLEFT        = 'dropleft'
+const CLASS_NAME_MENURIGHT       = 'dropdown-menu-right'
+const CLASS_NAME_POSITION_STATIC = 'position-static'
+
+const SELECTOR_DATA_TOGGLE   = '[data-toggle="dropdown"]'
+const SELECTOR_FORM_CHILD    = '.dropdown form'
+const SELECTOR_MENU          = '.dropdown-menu'
+const SELECTOR_NAVBAR_NAV    = '.navbar-nav'
+const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
+
+const PLACEMENT_TOP       = 'top-start'
+const PLACEMENT_TOPEND    = 'top-end'
+const PLACEMENT_BOTTOM    = 'bottom-start'
+const PLACEMENT_BOTTOMEND = 'bottom-end'
+const PLACEMENT_RIGHT     = 'right-start'
+const PLACEMENT_LEFT      = 'left-start'
 
 const Default = {
-  offset    : 0,
-  flip      : true,
-  boundary  : 'scrollParent',
-  reference : 'toggle',
-  display   : 'dynamic'
+  offset       : 0,
+  flip         : true,
+  boundary     : 'scrollParent',
+  reference    : 'toggle',
+  display      : 'dynamic',
+  popperConfig : null
 }
 
 const DefaultType = {
-  offset    : '(number|string|function)',
-  flip      : 'boolean',
-  boundary  : '(string|element)',
-  reference : '(string|element)',
-  display   : 'string'
+  offset       : '(number|string|function)',
+  flip         : 'boolean',
+  boundary     : '(string|element)',
+  reference    : '(string|element)',
+  display      : 'string',
+  popperConfig : '(null|object)'
 }
 
 /**
@@ -120,12 +111,11 @@ class Dropdown {
   // Public
 
   toggle() {
-    if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {
+    if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED)) {
       return
     }
 
-    const parent   = Dropdown._getParentFromElement(this._element)
-    const isActive = $(this._menu).hasClass(ClassName.SHOW)
+    const isActive = $(this._menu).hasClass(CLASS_NAME_SHOW)
 
     Dropdown._clearMenus()
 
@@ -133,10 +123,19 @@ class Dropdown {
       return
     }
 
+    this.show(true)
+  }
+
+  show(usePopper = false) {
+    if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED) || $(this._menu).hasClass(CLASS_NAME_SHOW)) {
+      return
+    }
+
     const relatedTarget = {
       relatedTarget: this._element
     }
-    const showEvent = $.Event(Event.SHOW, relatedTarget)
+    const showEvent = $.Event(EVENT_SHOW, relatedTarget)
+    const parent = Dropdown._getParentFromElement(this._element)
 
     $(parent).trigger(showEvent)
 
@@ -145,7 +144,7 @@ class Dropdown {
     }
 
     // Disable totally Popper.js for Dropdown in Navbar
-    if (!this._inNavbar) {
+    if (!this._inNavbar && usePopper) {
       /**
        * Check for Popper dependency
        * Popper - https://popper.js.org
@@ -171,7 +170,7 @@ class Dropdown {
       // to allow the menu to "escape" the scroll parent's boundaries
       // https://github.com/twbs/bootstrap/issues/24251
       if (this._config.boundary !== 'scrollParent') {
-        $(parent).addClass(ClassName.POSITION_STATIC)
+        $(parent).addClass(CLASS_NAME_POSITION_STATIC)
       }
       this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())
     }
@@ -181,51 +180,28 @@ class Dropdown {
     // only needed because of broken event delegation on iOS
     // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
     if ('ontouchstart' in document.documentElement &&
-        $(parent).closest(Selector.NAVBAR_NAV).length === 0) {
+        $(parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {
       $(document.body).children().on('mouseover', null, $.noop)
     }
 
     this._element.focus()
     this._element.setAttribute('aria-expanded', true)
 
-    $(this._menu).toggleClass(ClassName.SHOW)
+    $(this._menu).toggleClass(CLASS_NAME_SHOW)
     $(parent)
-      .toggleClass(ClassName.SHOW)
-      .trigger($.Event(Event.SHOWN, relatedTarget))
-  }
-
-  show() {
-    if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) {
-      return
-    }
-
-    const relatedTarget = {
-      relatedTarget: this._element
-    }
-    const showEvent = $.Event(Event.SHOW, relatedTarget)
-    const parent = Dropdown._getParentFromElement(this._element)
-
-    $(parent).trigger(showEvent)
-
-    if (showEvent.isDefaultPrevented()) {
-      return
-    }
-
-    $(this._menu).toggleClass(ClassName.SHOW)
-    $(parent)
-      .toggleClass(ClassName.SHOW)
-      .trigger($.Event(Event.SHOWN, relatedTarget))
+      .toggleClass(CLASS_NAME_SHOW)
+      .trigger($.Event(EVENT_SHOWN, relatedTarget))
   }
 
   hide() {
-    if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) {
+    if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED) || !$(this._menu).hasClass(CLASS_NAME_SHOW)) {
       return
     }
 
     const relatedTarget = {
       relatedTarget: this._element
     }
-    const hideEvent = $.Event(Event.HIDE, relatedTarget)
+    const hideEvent = $.Event(EVENT_HIDE, relatedTarget)
     const parent = Dropdown._getParentFromElement(this._element)
 
     $(parent).trigger(hideEvent)
@@ -234,10 +210,14 @@ class Dropdown {
       return
     }
 
-    $(this._menu).toggleClass(ClassName.SHOW)
+    if (this._popper) {
+      this._popper.destroy()
+    }
+
+    $(this._menu).toggleClass(CLASS_NAME_SHOW)
     $(parent)
-      .toggleClass(ClassName.SHOW)
-      .trigger($.Event(Event.HIDDEN, relatedTarget))
+      .toggleClass(CLASS_NAME_SHOW)
+      .trigger($.Event(EVENT_HIDDEN, relatedTarget))
   }
 
   dispose() {
@@ -261,7 +241,7 @@ class Dropdown {
   // Private
 
   _addEventListeners() {
-    $(this._element).on(Event.CLICK, (event) => {
+    $(this._element).on(EVENT_CLICK, (event) => {
       event.preventDefault()
       event.stopPropagation()
       this.toggle()
@@ -289,7 +269,7 @@ class Dropdown {
       const parent = Dropdown._getParentFromElement(this._element)
 
       if (parent) {
-        this._menu = parent.querySelector(Selector.MENU)
+        this._menu = parent.querySelector(SELECTOR_MENU)
       }
     }
     return this._menu
@@ -297,20 +277,19 @@ class Dropdown {
 
   _getPlacement() {
     const $parentDropdown = $(this._element.parentNode)
-    let placement = AttachmentMap.BOTTOM
+    let placement = PLACEMENT_BOTTOM
 
     // Handle dropup
-    if ($parentDropdown.hasClass(ClassName.DROPUP)) {
-      placement = AttachmentMap.TOP
-      if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
-        placement = AttachmentMap.TOPEND
-      }
-    } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {
-      placement = AttachmentMap.RIGHT
-    } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {
-      placement = AttachmentMap.LEFT
-    } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
-      placement = AttachmentMap.BOTTOMEND
+    if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {
+      placement = $(this._menu).hasClass(CLASS_NAME_MENURIGHT)
+        ? PLACEMENT_TOPEND
+        : PLACEMENT_TOP
+    } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {
+      placement = PLACEMENT_RIGHT
+    } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {
+      placement = PLACEMENT_LEFT
+    } else if ($(this._menu).hasClass(CLASS_NAME_MENURIGHT)) {
+      placement = PLACEMENT_BOTTOMEND
     }
     return placement
   }
@@ -359,7 +338,10 @@ class Dropdown {
       }
     }
 
-    return popperConfig
+    return {
+      ...popperConfig,
+      ...this._config.popperConfig
+    }
   }
 
   // Static
@@ -389,7 +371,7 @@ class Dropdown {
       return
     }
 
-    const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))
+    const toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))
 
     for (let i = 0, len = toggles.length; i < len; i++) {
       const parent = Dropdown._getParentFromElement(toggles[i])
@@ -407,7 +389,7 @@ class Dropdown {
       }
 
       const dropdownMenu = context._menu
-      if (!$(parent).hasClass(ClassName.SHOW)) {
+      if (!$(parent).hasClass(CLASS_NAME_SHOW)) {
         continue
       }
 
@@ -417,7 +399,7 @@ class Dropdown {
         continue
       }
 
-      const hideEvent = $.Event(Event.HIDE, relatedTarget)
+      const hideEvent = $.Event(EVENT_HIDE, relatedTarget)
       $(parent).trigger(hideEvent)
       if (hideEvent.isDefaultPrevented()) {
         continue
@@ -431,10 +413,14 @@ class Dropdown {
 
       toggles[i].setAttribute('aria-expanded', 'false')
 
-      $(dropdownMenu).removeClass(ClassName.SHOW)
+      if (context._popper) {
+        context._popper.destroy()
+      }
+
+      $(dropdownMenu).removeClass(CLASS_NAME_SHOW)
       $(parent)
-        .removeClass(ClassName.SHOW)
-        .trigger($.Event(Event.HIDDEN, relatedTarget))
+        .removeClass(CLASS_NAME_SHOW)
+        .trigger($.Event(EVENT_HIDDEN, relatedTarget))
     }
   }
 
@@ -461,31 +447,35 @@ class Dropdown {
     if (/input|textarea/i.test(event.target.tagName)
       ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&
       (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||
-        $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
+        $(event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
       return
     }
 
-    event.preventDefault()
-    event.stopPropagation()
-
-    if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+    if (this.disabled || $(this).hasClass(CLASS_NAME_DISABLED)) {
       return
     }
 
     const parent   = Dropdown._getParentFromElement(this)
-    const isActive = $(parent).hasClass(ClassName.SHOW)
+    const isActive = $(parent).hasClass(CLASS_NAME_SHOW)
+
+    if (!isActive && event.which === ESCAPE_KEYCODE) {
+      return
+    }
+
+    event.preventDefault()
+    event.stopPropagation()
 
     if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
       if (event.which === ESCAPE_KEYCODE) {
-        const toggle = parent.querySelector(Selector.DATA_TOGGLE)
-        $(toggle).trigger('focus')
+        $(parent.querySelector(SELECTOR_DATA_TOGGLE)).trigger('focus')
       }
 
       $(this).trigger('click')
       return
     }
 
-    const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))
+    const items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS))
+      .filter((item) => $(item).is(':visible'))
 
     if (items.length === 0) {
       return
@@ -516,15 +506,15 @@ class Dropdown {
  */
 
 $(document)
-  .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
-  .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)
-  .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)
-  .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+  .on(EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
+  .on(EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown._dataApiKeydownHandler)
+  .on(`${EVENT_CLICK_DATA_API} ${EVENT_KEYUP_DATA_API}`, Dropdown._clearMenus)
+  .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
     event.preventDefault()
     event.stopPropagation()
     Dropdown._jQueryInterface.call($(this), 'toggle')
   })
-  .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {
+  .on(EVENT_CLICK_DATA_API, SELECTOR_FORM_CHILD, (e) => {
     e.stopPropagation()
   })
 
@@ -541,5 +531,4 @@ $.fn[NAME].noConflict = () => {
   return Dropdown._jQueryInterface
 }
 
-
 export default Dropdown

+ 1 - 19
coderedcms/static/coderedcms/vendor/bootstrap/js/src/index.js

@@ -1,4 +1,3 @@
-import $ from 'jquery'
 import Alert from './alert'
 import Button from './button'
 import Carousel from './carousel'
@@ -14,28 +13,11 @@ import Util from './util'
 
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): index.js
+ * Bootstrap (v4.5.0): index.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
 
-(() => {
-  if (typeof $ === 'undefined') {
-    throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.')
-  }
-
-  const version = $.fn.jquery.split(' ')[0].split('.')
-  const minMajor = 1
-  const ltMajor = 2
-  const minMinor = 9
-  const minPatch = 1
-  const maxMajor = 4
-
-  if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
-    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
-  }
-})()
-
 export {
   Util,
   Alert,

+ 105 - 87
coderedcms/static/coderedcms/vendor/bootstrap/js/src/modal.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): modal.js
+ * Bootstrap (v4.5.0): modal.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@ import Util from './util'
  */
 
 const NAME               = 'modal'
-const VERSION            = '4.3.1'
+const VERSION            = '4.5.0'
 const DATA_KEY           = 'bs.modal'
 const EVENT_KEY          = `.${DATA_KEY}`
 const DATA_API_KEY       = '.data-api'
@@ -36,37 +36,33 @@ const DefaultType = {
   show     : 'boolean'
 }
 
-const Event = {
-  HIDE              : `hide${EVENT_KEY}`,
-  HIDDEN            : `hidden${EVENT_KEY}`,
-  SHOW              : `show${EVENT_KEY}`,
-  SHOWN             : `shown${EVENT_KEY}`,
-  FOCUSIN           : `focusin${EVENT_KEY}`,
-  RESIZE            : `resize${EVENT_KEY}`,
-  CLICK_DISMISS     : `click.dismiss${EVENT_KEY}`,
-  KEYDOWN_DISMISS   : `keydown.dismiss${EVENT_KEY}`,
-  MOUSEUP_DISMISS   : `mouseup.dismiss${EVENT_KEY}`,
-  MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,
-  CLICK_DATA_API    : `click${EVENT_KEY}${DATA_API_KEY}`
-}
-
-const ClassName = {
-  SCROLLABLE         : 'modal-dialog-scrollable',
-  SCROLLBAR_MEASURER : 'modal-scrollbar-measure',
-  BACKDROP           : 'modal-backdrop',
-  OPEN               : 'modal-open',
-  FADE               : 'fade',
-  SHOW               : 'show'
-}
-
-const Selector = {
-  DIALOG         : '.modal-dialog',
-  MODAL_BODY     : '.modal-body',
-  DATA_TOGGLE    : '[data-toggle="modal"]',
-  DATA_DISMISS   : '[data-dismiss="modal"]',
-  FIXED_CONTENT  : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
-  STICKY_CONTENT : '.sticky-top'
-}
+const EVENT_HIDE              = `hide${EVENT_KEY}`
+const EVENT_HIDE_PREVENTED    = `hidePrevented${EVENT_KEY}`
+const EVENT_HIDDEN            = `hidden${EVENT_KEY}`
+const EVENT_SHOW              = `show${EVENT_KEY}`
+const EVENT_SHOWN             = `shown${EVENT_KEY}`
+const EVENT_FOCUSIN           = `focusin${EVENT_KEY}`
+const EVENT_RESIZE            = `resize${EVENT_KEY}`
+const EVENT_CLICK_DISMISS     = `click.dismiss${EVENT_KEY}`
+const EVENT_KEYDOWN_DISMISS   = `keydown.dismiss${EVENT_KEY}`
+const EVENT_MOUSEUP_DISMISS   = `mouseup.dismiss${EVENT_KEY}`
+const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}`
+const EVENT_CLICK_DATA_API    = `click${EVENT_KEY}${DATA_API_KEY}`
+
+const CLASS_NAME_SCROLLABLE         = 'modal-dialog-scrollable'
+const CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure'
+const CLASS_NAME_BACKDROP           = 'modal-backdrop'
+const CLASS_NAME_OPEN               = 'modal-open'
+const CLASS_NAME_FADE               = 'fade'
+const CLASS_NAME_SHOW               = 'show'
+const CLASS_NAME_STATIC             = 'modal-static'
+
+const SELECTOR_DIALOG         = '.modal-dialog'
+const SELECTOR_MODAL_BODY     = '.modal-body'
+const SELECTOR_DATA_TOGGLE    = '[data-toggle="modal"]'
+const SELECTOR_DATA_DISMISS   = '[data-dismiss="modal"]'
+const SELECTOR_FIXED_CONTENT  = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'
+const SELECTOR_STICKY_CONTENT = '.sticky-top'
 
 /**
  * ------------------------------------------------------------------------
@@ -78,7 +74,7 @@ class Modal {
   constructor(element, config) {
     this._config              = this._getConfig(config)
     this._element             = element
-    this._dialog              = element.querySelector(Selector.DIALOG)
+    this._dialog              = element.querySelector(SELECTOR_DIALOG)
     this._backdrop            = null
     this._isShown             = false
     this._isBodyOverflowing   = false
@@ -108,11 +104,11 @@ class Modal {
       return
     }
 
-    if ($(this._element).hasClass(ClassName.FADE)) {
+    if ($(this._element).hasClass(CLASS_NAME_FADE)) {
       this._isTransitioning = true
     }
 
-    const showEvent = $.Event(Event.SHOW, {
+    const showEvent = $.Event(EVENT_SHOW, {
       relatedTarget
     })
 
@@ -133,13 +129,13 @@ class Modal {
     this._setResizeEvent()
 
     $(this._element).on(
-      Event.CLICK_DISMISS,
-      Selector.DATA_DISMISS,
+      EVENT_CLICK_DISMISS,
+      SELECTOR_DATA_DISMISS,
       (event) => this.hide(event)
     )
 
-    $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {
-      $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {
+    $(this._dialog).on(EVENT_MOUSEDOWN_DISMISS, () => {
+      $(this._element).one(EVENT_MOUSEUP_DISMISS, (event) => {
         if ($(event.target).is(this._element)) {
           this._ignoreBackdropClick = true
         }
@@ -158,7 +154,7 @@ class Modal {
       return
     }
 
-    const hideEvent = $.Event(Event.HIDE)
+    const hideEvent = $.Event(EVENT_HIDE)
 
     $(this._element).trigger(hideEvent)
 
@@ -167,7 +163,7 @@ class Modal {
     }
 
     this._isShown = false
-    const transition = $(this._element).hasClass(ClassName.FADE)
+    const transition = $(this._element).hasClass(CLASS_NAME_FADE)
 
     if (transition) {
       this._isTransitioning = true
@@ -176,13 +172,12 @@ class Modal {
     this._setEscapeEvent()
     this._setResizeEvent()
 
-    $(document).off(Event.FOCUSIN)
-
-    $(this._element).removeClass(ClassName.SHOW)
+    $(document).off(EVENT_FOCUSIN)
 
-    $(this._element).off(Event.CLICK_DISMISS)
-    $(this._dialog).off(Event.MOUSEDOWN_DISMISS)
+    $(this._element).removeClass(CLASS_NAME_SHOW)
 
+    $(this._element).off(EVENT_CLICK_DISMISS)
+    $(this._dialog).off(EVENT_MOUSEDOWN_DISMISS)
 
     if (transition) {
       const transitionDuration  = Util.getTransitionDurationFromElement(this._element)
@@ -200,11 +195,11 @@ class Modal {
       .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY))
 
     /**
-     * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`
+     * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`
      * Do not move `document` in `htmlElements` array
-     * It will remove `Event.CLICK_DATA_API` event that should remain
+     * It will remove `EVENT_CLICK_DATA_API` event that should remain
      */
-    $(document).off(Event.FOCUSIN)
+    $(document).off(EVENT_FOCUSIN)
 
     $.removeData(this._element, DATA_KEY)
 
@@ -234,8 +229,32 @@ class Modal {
     return config
   }
 
+  _triggerBackdropTransition() {
+    if (this._config.backdrop === 'static') {
+      const hideEventPrevented = $.Event(EVENT_HIDE_PREVENTED)
+
+      $(this._element).trigger(hideEventPrevented)
+      if (hideEventPrevented.defaultPrevented) {
+        return
+      }
+
+      this._element.classList.add(CLASS_NAME_STATIC)
+
+      const modalTransitionDuration = Util.getTransitionDurationFromElement(this._element)
+
+      $(this._element).one(Util.TRANSITION_END, () => {
+        this._element.classList.remove(CLASS_NAME_STATIC)
+      })
+        .emulateTransitionEnd(modalTransitionDuration)
+      this._element.focus()
+    } else {
+      this.hide()
+    }
+  }
+
   _showElement(relatedTarget) {
-    const transition = $(this._element).hasClass(ClassName.FADE)
+    const transition = $(this._element).hasClass(CLASS_NAME_FADE)
+    const modalBody = this._dialog ? this._dialog.querySelector(SELECTOR_MODAL_BODY) : null
 
     if (!this._element.parentNode ||
         this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
@@ -247,8 +266,8 @@ class Modal {
     this._element.removeAttribute('aria-hidden')
     this._element.setAttribute('aria-modal', true)
 
-    if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {
-      this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0
+    if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
+      modalBody.scrollTop = 0
     } else {
       this._element.scrollTop = 0
     }
@@ -257,13 +276,13 @@ class Modal {
       Util.reflow(this._element)
     }
 
-    $(this._element).addClass(ClassName.SHOW)
+    $(this._element).addClass(CLASS_NAME_SHOW)
 
     if (this._config.focus) {
       this._enforceFocus()
     }
 
-    const shownEvent = $.Event(Event.SHOWN, {
+    const shownEvent = $.Event(EVENT_SHOWN, {
       relatedTarget
     })
 
@@ -288,8 +307,8 @@ class Modal {
 
   _enforceFocus() {
     $(document)
-      .off(Event.FOCUSIN) // Guard against infinite focus loop
-      .on(Event.FOCUSIN, (event) => {
+      .off(EVENT_FOCUSIN) // Guard against infinite focus loop
+      .on(EVENT_FOCUSIN, (event) => {
         if (document !== event.target &&
             this._element !== event.target &&
             $(this._element).has(event.target).length === 0) {
@@ -299,23 +318,25 @@ class Modal {
   }
 
   _setEscapeEvent() {
-    if (this._isShown && this._config.keyboard) {
-      $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
-        if (event.which === ESCAPE_KEYCODE) {
+    if (this._isShown) {
+      $(this._element).on(EVENT_KEYDOWN_DISMISS, (event) => {
+        if (this._config.keyboard && event.which === ESCAPE_KEYCODE) {
           event.preventDefault()
           this.hide()
+        } else if (!this._config.keyboard && event.which === ESCAPE_KEYCODE) {
+          this._triggerBackdropTransition()
         }
       })
     } else if (!this._isShown) {
-      $(this._element).off(Event.KEYDOWN_DISMISS)
+      $(this._element).off(EVENT_KEYDOWN_DISMISS)
     }
   }
 
   _setResizeEvent() {
     if (this._isShown) {
-      $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))
+      $(window).on(EVENT_RESIZE, (event) => this.handleUpdate(event))
     } else {
-      $(window).off(Event.RESIZE)
+      $(window).off(EVENT_RESIZE)
     }
   }
 
@@ -325,10 +346,10 @@ class Modal {
     this._element.removeAttribute('aria-modal')
     this._isTransitioning = false
     this._showBackdrop(() => {
-      $(document.body).removeClass(ClassName.OPEN)
+      $(document.body).removeClass(CLASS_NAME_OPEN)
       this._resetAdjustments()
       this._resetScrollbar()
-      $(this._element).trigger(Event.HIDDEN)
+      $(this._element).trigger(EVENT_HIDDEN)
     })
   }
 
@@ -340,12 +361,12 @@ class Modal {
   }
 
   _showBackdrop(callback) {
-    const animate = $(this._element).hasClass(ClassName.FADE)
-      ? ClassName.FADE : ''
+    const animate = $(this._element).hasClass(CLASS_NAME_FADE)
+      ? CLASS_NAME_FADE : ''
 
     if (this._isShown && this._config.backdrop) {
       this._backdrop = document.createElement('div')
-      this._backdrop.className = ClassName.BACKDROP
+      this._backdrop.className = CLASS_NAME_BACKDROP
 
       if (animate) {
         this._backdrop.classList.add(animate)
@@ -353,7 +374,7 @@ class Modal {
 
       $(this._backdrop).appendTo(document.body)
 
-      $(this._element).on(Event.CLICK_DISMISS, (event) => {
+      $(this._element).on(EVENT_CLICK_DISMISS, (event) => {
         if (this._ignoreBackdropClick) {
           this._ignoreBackdropClick = false
           return
@@ -361,18 +382,15 @@ class Modal {
         if (event.target !== event.currentTarget) {
           return
         }
-        if (this._config.backdrop === 'static') {
-          this._element.focus()
-        } else {
-          this.hide()
-        }
+
+        this._triggerBackdropTransition()
       })
 
       if (animate) {
         Util.reflow(this._backdrop)
       }
 
-      $(this._backdrop).addClass(ClassName.SHOW)
+      $(this._backdrop).addClass(CLASS_NAME_SHOW)
 
       if (!callback) {
         return
@@ -389,7 +407,7 @@ class Modal {
         .one(Util.TRANSITION_END, callback)
         .emulateTransitionEnd(backdropTransitionDuration)
     } else if (!this._isShown && this._backdrop) {
-      $(this._backdrop).removeClass(ClassName.SHOW)
+      $(this._backdrop).removeClass(CLASS_NAME_SHOW)
 
       const callbackRemove = () => {
         this._removeBackdrop()
@@ -398,7 +416,7 @@ class Modal {
         }
       }
 
-      if ($(this._element).hasClass(ClassName.FADE)) {
+      if ($(this._element).hasClass(CLASS_NAME_FADE)) {
         const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
 
         $(this._backdrop)
@@ -437,7 +455,7 @@ class Modal {
 
   _checkScrollbar() {
     const rect = document.body.getBoundingClientRect()
-    this._isBodyOverflowing = rect.left + rect.right < window.innerWidth
+    this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth
     this._scrollbarWidth = this._getScrollbarWidth()
   }
 
@@ -445,8 +463,8 @@ class Modal {
     if (this._isBodyOverflowing) {
       // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
       //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
-      const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))
-      const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))
+      const fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT))
+      const stickyContent = [].slice.call(document.querySelectorAll(SELECTOR_STICKY_CONTENT))
 
       // Adjust fixed content padding
       $(fixedContent).each((index, element) => {
@@ -474,12 +492,12 @@ class Modal {
         .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)
     }
 
-    $(document.body).addClass(ClassName.OPEN)
+    $(document.body).addClass(CLASS_NAME_OPEN)
   }
 
   _resetScrollbar() {
     // Restore fixed content padding
-    const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))
+    const fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT))
     $(fixedContent).each((index, element) => {
       const padding = $(element).data('padding-right')
       $(element).removeData('padding-right')
@@ -487,7 +505,7 @@ class Modal {
     })
 
     // Restore sticky content
-    const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))
+    const elements = [].slice.call(document.querySelectorAll(`${SELECTOR_STICKY_CONTENT}`))
     $(elements).each((index, element) => {
       const margin = $(element).data('margin-right')
       if (typeof margin !== 'undefined') {
@@ -503,7 +521,7 @@ class Modal {
 
   _getScrollbarWidth() { // thx d.walsh
     const scrollDiv = document.createElement('div')
-    scrollDiv.className = ClassName.SCROLLBAR_MEASURER
+    scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER
     document.body.appendChild(scrollDiv)
     const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth
     document.body.removeChild(scrollDiv)
@@ -544,7 +562,7 @@ class Modal {
  * ------------------------------------------------------------------------
  */
 
-$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
   let target
   const selector = Util.getSelectorFromElement(this)
 
@@ -562,13 +580,13 @@ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
     event.preventDefault()
   }
 
-  const $target = $(target).one(Event.SHOW, (showEvent) => {
+  const $target = $(target).one(EVENT_SHOW, (showEvent) => {
     if (showEvent.isDefaultPrevented()) {
       // Only register focus restorer if modal will actually get shown
       return
     }
 
-    $target.one(Event.HIDDEN, () => {
+    $target.one(EVENT_HIDDEN, () => {
       if ($(this).is(':visible')) {
         this.focus()
       }

+ 9 - 13
coderedcms/static/coderedcms/vendor/bootstrap/js/src/popover.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): popover.js
+ * Bootstrap (v4.5.0): popover.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@ import Tooltip from './tooltip'
  */
 
 const NAME                = 'popover'
-const VERSION             = '4.3.1'
+const VERSION             = '4.5.0'
 const DATA_KEY            = 'bs.popover'
 const EVENT_KEY           = `.${DATA_KEY}`
 const JQUERY_NO_CONFLICT  = $.fn[NAME]
@@ -38,15 +38,11 @@ const DefaultType = {
   content : '(string|element|function)'
 }
 
-const ClassName = {
-  FADE : 'fade',
-  SHOW : 'show'
-}
+const CLASS_NAME_FADE = 'fade'
+const CLASS_NAME_SHOW = 'show'
 
-const Selector = {
-  TITLE   : '.popover-header',
-  CONTENT : '.popover-body'
-}
+const SELECTOR_TITLE   = '.popover-header'
+const SELECTOR_CONTENT = '.popover-body'
 
 const Event = {
   HIDE       : `hide${EVENT_KEY}`,
@@ -117,14 +113,14 @@ class Popover extends Tooltip {
     const $tip = $(this.getTipElement())
 
     // We use append for html objects to maintain js events
-    this.setElementContent($tip.find(Selector.TITLE), this.getTitle())
+    this.setElementContent($tip.find(SELECTOR_TITLE), this.getTitle())
     let content = this._getContent()
     if (typeof content === 'function') {
       content = content.call(this.element)
     }
-    this.setElementContent($tip.find(Selector.CONTENT), content)
+    this.setElementContent($tip.find(SELECTOR_CONTENT), content)
 
-    $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)
+    $tip.removeClass(`${CLASS_NAME_FADE} ${CLASS_NAME_SHOW}`)
   }
 
   // Private

+ 44 - 50
coderedcms/static/coderedcms/vendor/bootstrap/js/src/scrollspy.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): scrollspy.js
+ * Bootstrap (v4.5.0): scrollspy.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@ import Util from './util'
  */
 
 const NAME               = 'scrollspy'
-const VERSION            = '4.3.1'
+const VERSION            = '4.5.0'
 const DATA_KEY           = 'bs.scrollspy'
 const EVENT_KEY          = `.${DATA_KEY}`
 const DATA_API_KEY       = '.data-api'
@@ -33,34 +33,24 @@ const DefaultType = {
   target : '(string|element)'
 }
 
-const Event = {
-  ACTIVATE      : `activate${EVENT_KEY}`,
-  SCROLL        : `scroll${EVENT_KEY}`,
-  LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`
-}
+const EVENT_ACTIVATE      = `activate${EVENT_KEY}`
+const EVENT_SCROLL        = `scroll${EVENT_KEY}`
+const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
 
-const ClassName = {
-  DROPDOWN_ITEM : 'dropdown-item',
-  DROPDOWN_MENU : 'dropdown-menu',
-  ACTIVE        : 'active'
-}
+const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'
+const CLASS_NAME_ACTIVE        = 'active'
 
-const Selector = {
-  DATA_SPY        : '[data-spy="scroll"]',
-  ACTIVE          : '.active',
-  NAV_LIST_GROUP  : '.nav, .list-group',
-  NAV_LINKS       : '.nav-link',
-  NAV_ITEMS       : '.nav-item',
-  LIST_ITEMS      : '.list-group-item',
-  DROPDOWN        : '.dropdown',
-  DROPDOWN_ITEMS  : '.dropdown-item',
-  DROPDOWN_TOGGLE : '.dropdown-toggle'
-}
+const SELECTOR_DATA_SPY        = '[data-spy="scroll"]'
+const SELECTOR_NAV_LIST_GROUP  = '.nav, .list-group'
+const SELECTOR_NAV_LINKS       = '.nav-link'
+const SELECTOR_NAV_ITEMS       = '.nav-item'
+const SELECTOR_LIST_ITEMS      = '.list-group-item'
+const SELECTOR_DROPDOWN        = '.dropdown'
+const SELECTOR_DROPDOWN_ITEMS  = '.dropdown-item'
+const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
 
-const OffsetMethod = {
-  OFFSET   : 'offset',
-  POSITION : 'position'
-}
+const METHOD_OFFSET   = 'offset'
+const METHOD_POSITION = 'position'
 
 /**
  * ------------------------------------------------------------------------
@@ -73,15 +63,15 @@ class ScrollSpy {
     this._element       = element
     this._scrollElement = element.tagName === 'BODY' ? window : element
     this._config        = this._getConfig(config)
-    this._selector      = `${this._config.target} ${Selector.NAV_LINKS},` +
-                          `${this._config.target} ${Selector.LIST_ITEMS},` +
-                          `${this._config.target} ${Selector.DROPDOWN_ITEMS}`
+    this._selector      = `${this._config.target} ${SELECTOR_NAV_LINKS},` +
+                          `${this._config.target} ${SELECTOR_LIST_ITEMS},` +
+                          `${this._config.target} ${SELECTOR_DROPDOWN_ITEMS}`
     this._offsets       = []
     this._targets       = []
     this._activeTarget  = null
     this._scrollHeight  = 0
 
-    $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))
+    $(this._scrollElement).on(EVENT_SCROLL, (event) => this._process(event))
 
     this.refresh()
     this._process()
@@ -101,12 +91,12 @@ class ScrollSpy {
 
   refresh() {
     const autoMethod = this._scrollElement === this._scrollElement.window
-      ? OffsetMethod.OFFSET : OffsetMethod.POSITION
+      ? METHOD_OFFSET : METHOD_POSITION
 
     const offsetMethod = this._config.method === 'auto'
       ? autoMethod : this._config.method
 
-    const offsetBase = offsetMethod === OffsetMethod.POSITION
+    const offsetBase = offsetMethod === METHOD_POSITION
       ? this._getScrollTop() : 0
 
     this._offsets = []
@@ -167,7 +157,7 @@ class ScrollSpy {
       ...typeof config === 'object' && config ? config : {}
     }
 
-    if (typeof config.target !== 'string') {
+    if (typeof config.target !== 'string' && Util.isElement(config.target)) {
       let id = $(config.target).attr('id')
       if (!id) {
         id = Util.getUID(NAME)
@@ -201,9 +191,7 @@ class ScrollSpy {
   _process() {
     const scrollTop    = this._getScrollTop() + this._config.offset
     const scrollHeight = this._getScrollHeight()
-    const maxScroll    = this._config.offset +
-      scrollHeight -
-      this._getOffsetHeight()
+    const maxScroll    = this._config.offset + scrollHeight - this._getOffsetHeight()
 
     if (this._scrollHeight !== scrollHeight) {
       this.refresh()
@@ -224,8 +212,7 @@ class ScrollSpy {
       return
     }
 
-    const offsetLength = this._offsets.length
-    for (let i = offsetLength; i--;) {
+    for (let i = this._offsets.length; i--;) {
       const isActiveTarget = this._activeTarget !== this._targets[i] &&
           scrollTop >= this._offsets[i] &&
           (typeof this._offsets[i + 1] === 'undefined' ||
@@ -248,28 +235,35 @@ class ScrollSpy {
 
     const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))
 
-    if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
-      $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)
-      $link.addClass(ClassName.ACTIVE)
+    if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {
+      $link.closest(SELECTOR_DROPDOWN)
+        .find(SELECTOR_DROPDOWN_TOGGLE)
+        .addClass(CLASS_NAME_ACTIVE)
+      $link.addClass(CLASS_NAME_ACTIVE)
     } else {
       // Set triggered link as active
-      $link.addClass(ClassName.ACTIVE)
+      $link.addClass(CLASS_NAME_ACTIVE)
       // Set triggered links parents as active
       // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
-      $link.parents(Selector.NAV_LIST_GROUP).prev(`${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`).addClass(ClassName.ACTIVE)
+      $link.parents(SELECTOR_NAV_LIST_GROUP)
+        .prev(`${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`)
+        .addClass(CLASS_NAME_ACTIVE)
       // Handle special case when .nav-link is inside .nav-item
-      $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE)
+      $link.parents(SELECTOR_NAV_LIST_GROUP)
+        .prev(SELECTOR_NAV_ITEMS)
+        .children(SELECTOR_NAV_LINKS)
+        .addClass(CLASS_NAME_ACTIVE)
     }
 
-    $(this._scrollElement).trigger(Event.ACTIVATE, {
+    $(this._scrollElement).trigger(EVENT_ACTIVATE, {
       relatedTarget: target
     })
   }
 
   _clear() {
     [].slice.call(document.querySelectorAll(this._selector))
-      .filter((node) => node.classList.contains(ClassName.ACTIVE))
-      .forEach((node) => node.classList.remove(ClassName.ACTIVE))
+      .filter((node) => node.classList.contains(CLASS_NAME_ACTIVE))
+      .forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE))
   }
 
   // Static
@@ -300,8 +294,8 @@ class ScrollSpy {
  * ------------------------------------------------------------------------
  */
 
-$(window).on(Event.LOAD_DATA_API, () => {
-  const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY))
+$(window).on(EVENT_LOAD_DATA_API, () => {
+  const scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY))
   const scrollSpysLength = scrollSpys.length
 
   for (let i = scrollSpysLength; i--;) {

+ 44 - 50
coderedcms/static/coderedcms/vendor/bootstrap/js/src/tab.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): tab.js
+ * Bootstrap (v4.5.0): tab.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,37 +15,31 @@ import Util from './util'
  */
 
 const NAME               = 'tab'
-const VERSION            = '4.3.1'
+const VERSION            = '4.5.0'
 const DATA_KEY           = 'bs.tab'
 const EVENT_KEY          = `.${DATA_KEY}`
 const DATA_API_KEY       = '.data-api'
 const JQUERY_NO_CONFLICT = $.fn[NAME]
 
-const Event = {
-  HIDE           : `hide${EVENT_KEY}`,
-  HIDDEN         : `hidden${EVENT_KEY}`,
-  SHOW           : `show${EVENT_KEY}`,
-  SHOWN          : `shown${EVENT_KEY}`,
-  CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
-}
-
-const ClassName = {
-  DROPDOWN_MENU : 'dropdown-menu',
-  ACTIVE        : 'active',
-  DISABLED      : 'disabled',
-  FADE          : 'fade',
-  SHOW          : 'show'
-}
-
-const Selector = {
-  DROPDOWN              : '.dropdown',
-  NAV_LIST_GROUP        : '.nav, .list-group',
-  ACTIVE                : '.active',
-  ACTIVE_UL             : '> li > .active',
-  DATA_TOGGLE           : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
-  DROPDOWN_TOGGLE       : '.dropdown-toggle',
-  DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active'
-}
+const EVENT_HIDE           = `hide${EVENT_KEY}`
+const EVENT_HIDDEN         = `hidden${EVENT_KEY}`
+const EVENT_SHOW           = `show${EVENT_KEY}`
+const EVENT_SHOWN          = `shown${EVENT_KEY}`
+const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
+
+const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu'
+const CLASS_NAME_ACTIVE        = 'active'
+const CLASS_NAME_DISABLED      = 'disabled'
+const CLASS_NAME_FADE          = 'fade'
+const CLASS_NAME_SHOW          = 'show'
+
+const SELECTOR_DROPDOWN              = '.dropdown'
+const SELECTOR_NAV_LIST_GROUP        = '.nav, .list-group'
+const SELECTOR_ACTIVE                = '.active'
+const SELECTOR_ACTIVE_UL             = '> li > .active'
+const SELECTOR_DATA_TOGGLE           = '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]'
+const SELECTOR_DROPDOWN_TOGGLE       = '.dropdown-toggle'
+const SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active'
 
 /**
  * ------------------------------------------------------------------------
@@ -69,27 +63,27 @@ class Tab {
   show() {
     if (this._element.parentNode &&
         this._element.parentNode.nodeType === Node.ELEMENT_NODE &&
-        $(this._element).hasClass(ClassName.ACTIVE) ||
-        $(this._element).hasClass(ClassName.DISABLED)) {
+        $(this._element).hasClass(CLASS_NAME_ACTIVE) ||
+        $(this._element).hasClass(CLASS_NAME_DISABLED)) {
       return
     }
 
     let target
     let previous
-    const listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0]
+    const listElement = $(this._element).closest(SELECTOR_NAV_LIST_GROUP)[0]
     const selector = Util.getSelectorFromElement(this._element)
 
     if (listElement) {
-      const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE
+      const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE
       previous = $.makeArray($(listElement).find(itemSelector))
       previous = previous[previous.length - 1]
     }
 
-    const hideEvent = $.Event(Event.HIDE, {
+    const hideEvent = $.Event(EVENT_HIDE, {
       relatedTarget: this._element
     })
 
-    const showEvent = $.Event(Event.SHOW, {
+    const showEvent = $.Event(EVENT_SHOW, {
       relatedTarget: previous
     })
 
@@ -114,11 +108,11 @@ class Tab {
     )
 
     const complete = () => {
-      const hiddenEvent = $.Event(Event.HIDDEN, {
+      const hiddenEvent = $.Event(EVENT_HIDDEN, {
         relatedTarget: this._element
       })
 
-      const shownEvent = $.Event(Event.SHOWN, {
+      const shownEvent = $.Event(EVENT_SHOWN, {
         relatedTarget: previous
       })
 
@@ -142,11 +136,11 @@ class Tab {
 
   _activate(element, container, callback) {
     const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL')
-      ? $(container).find(Selector.ACTIVE_UL)
-      : $(container).children(Selector.ACTIVE)
+      ? $(container).find(SELECTOR_ACTIVE_UL)
+      : $(container).children(SELECTOR_ACTIVE)
 
     const active = activeElements[0]
-    const isTransitioning = callback && (active && $(active).hasClass(ClassName.FADE))
+    const isTransitioning = callback && (active && $(active).hasClass(CLASS_NAME_FADE))
     const complete = () => this._transitionComplete(
       element,
       active,
@@ -157,7 +151,7 @@ class Tab {
       const transitionDuration = Util.getTransitionDurationFromElement(active)
 
       $(active)
-        .removeClass(ClassName.SHOW)
+        .removeClass(CLASS_NAME_SHOW)
         .one(Util.TRANSITION_END, complete)
         .emulateTransitionEnd(transitionDuration)
     } else {
@@ -167,14 +161,14 @@ class Tab {
 
   _transitionComplete(element, active, callback) {
     if (active) {
-      $(active).removeClass(ClassName.ACTIVE)
+      $(active).removeClass(CLASS_NAME_ACTIVE)
 
       const dropdownChild = $(active.parentNode).find(
-        Selector.DROPDOWN_ACTIVE_CHILD
+        SELECTOR_DROPDOWN_ACTIVE_CHILD
       )[0]
 
       if (dropdownChild) {
-        $(dropdownChild).removeClass(ClassName.ACTIVE)
+        $(dropdownChild).removeClass(CLASS_NAME_ACTIVE)
       }
 
       if (active.getAttribute('role') === 'tab') {
@@ -182,24 +176,24 @@ class Tab {
       }
     }
 
-    $(element).addClass(ClassName.ACTIVE)
+    $(element).addClass(CLASS_NAME_ACTIVE)
     if (element.getAttribute('role') === 'tab') {
       element.setAttribute('aria-selected', true)
     }
 
     Util.reflow(element)
 
-    if (element.classList.contains(ClassName.FADE)) {
-      element.classList.add(ClassName.SHOW)
+    if (element.classList.contains(CLASS_NAME_FADE)) {
+      element.classList.add(CLASS_NAME_SHOW)
     }
 
-    if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
-      const dropdownElement = $(element).closest(Selector.DROPDOWN)[0]
+    if (element.parentNode && $(element.parentNode).hasClass(CLASS_NAME_DROPDOWN_MENU)) {
+      const dropdownElement = $(element).closest(SELECTOR_DROPDOWN)[0]
 
       if (dropdownElement) {
-        const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE))
+        const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE))
 
-        $(dropdownToggleList).addClass(ClassName.ACTIVE)
+        $(dropdownToggleList).addClass(CLASS_NAME_ACTIVE)
       }
 
       element.setAttribute('aria-expanded', true)
@@ -239,7 +233,7 @@ class Tab {
  */
 
 $(document)
-  .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+  .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
     event.preventDefault()
     Tab._jQueryInterface.call($(this), 'show')
   })

+ 43 - 46
coderedcms/static/coderedcms/vendor/bootstrap/js/src/toast.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): toast.js
+ * Bootstrap (v4.5.0): toast.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -15,25 +15,21 @@ import Util from './util'
  */
 
 const NAME               = 'toast'
-const VERSION            = '4.3.1'
+const VERSION            = '4.5.0'
 const DATA_KEY           = 'bs.toast'
 const EVENT_KEY          = `.${DATA_KEY}`
 const JQUERY_NO_CONFLICT = $.fn[NAME]
 
-const Event = {
-  CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,
-  HIDE          : `hide${EVENT_KEY}`,
-  HIDDEN        : `hidden${EVENT_KEY}`,
-  SHOW          : `show${EVENT_KEY}`,
-  SHOWN         : `shown${EVENT_KEY}`
-}
+const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`
+const EVENT_HIDE          = `hide${EVENT_KEY}`
+const EVENT_HIDDEN        = `hidden${EVENT_KEY}`
+const EVENT_SHOW          = `show${EVENT_KEY}`
+const EVENT_SHOWN         = `shown${EVENT_KEY}`
 
-const ClassName = {
-  FADE    : 'fade',
-  HIDE    : 'hide',
-  SHOW    : 'show',
-  SHOWING : 'showing'
-}
+const CLASS_NAME_FADE    = 'fade'
+const CLASS_NAME_HIDE    = 'hide'
+const CLASS_NAME_SHOW    = 'show'
+const CLASS_NAME_SHOWING = 'showing'
 
 const DefaultType = {
   animation : 'boolean',
@@ -47,9 +43,7 @@ const Default = {
   delay     : 500
 }
 
-const Selector = {
-  DATA_DISMISS : '[data-dismiss="toast"]'
-}
+const SELECTOR_DATA_DISMISS = '[data-dismiss="toast"]'
 
 /**
  * ------------------------------------------------------------------------
@@ -82,25 +76,33 @@ class Toast {
   // Public
 
   show() {
-    $(this._element).trigger(Event.SHOW)
+    const showEvent = $.Event(EVENT_SHOW)
+
+    $(this._element).trigger(showEvent)
+    if (showEvent.isDefaultPrevented()) {
+      return
+    }
 
     if (this._config.animation) {
-      this._element.classList.add(ClassName.FADE)
+      this._element.classList.add(CLASS_NAME_FADE)
     }
 
     const complete = () => {
-      this._element.classList.remove(ClassName.SHOWING)
-      this._element.classList.add(ClassName.SHOW)
+      this._element.classList.remove(CLASS_NAME_SHOWING)
+      this._element.classList.add(CLASS_NAME_SHOW)
 
-      $(this._element).trigger(Event.SHOWN)
+      $(this._element).trigger(EVENT_SHOWN)
 
       if (this._config.autohide) {
-        this.hide()
+        this._timeout = setTimeout(() => {
+          this.hide()
+        }, this._config.delay)
       }
     }
 
-    this._element.classList.remove(ClassName.HIDE)
-    this._element.classList.add(ClassName.SHOWING)
+    this._element.classList.remove(CLASS_NAME_HIDE)
+    Util.reflow(this._element)
+    this._element.classList.add(CLASS_NAME_SHOWING)
     if (this._config.animation) {
       const transitionDuration = Util.getTransitionDurationFromElement(this._element)
 
@@ -112,31 +114,30 @@ class Toast {
     }
   }
 
-  hide(withoutTimeout) {
-    if (!this._element.classList.contains(ClassName.SHOW)) {
+  hide() {
+    if (!this._element.classList.contains(CLASS_NAME_SHOW)) {
       return
     }
 
-    $(this._element).trigger(Event.HIDE)
+    const hideEvent = $.Event(EVENT_HIDE)
 
-    if (withoutTimeout) {
-      this._close()
-    } else {
-      this._timeout = setTimeout(() => {
-        this._close()
-      }, this._config.delay)
+    $(this._element).trigger(hideEvent)
+    if (hideEvent.isDefaultPrevented()) {
+      return
     }
+
+    this._close()
   }
 
   dispose() {
     clearTimeout(this._timeout)
     this._timeout = null
 
-    if (this._element.classList.contains(ClassName.SHOW)) {
-      this._element.classList.remove(ClassName.SHOW)
+    if (this._element.classList.contains(CLASS_NAME_SHOW)) {
+      this._element.classList.remove(CLASS_NAME_SHOW)
     }
 
-    $(this._element).off(Event.CLICK_DISMISS)
+    $(this._element).off(EVENT_CLICK_DISMISS)
 
     $.removeData(this._element, DATA_KEY)
     this._element = null
@@ -162,20 +163,16 @@ class Toast {
   }
 
   _setListeners() {
-    $(this._element).on(
-      Event.CLICK_DISMISS,
-      Selector.DATA_DISMISS,
-      () => this.hide(true)
-    )
+    $(this._element).on(EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide())
   }
 
   _close() {
     const complete = () => {
-      this._element.classList.add(ClassName.HIDE)
-      $(this._element).trigger(Event.HIDDEN)
+      this._element.classList.add(CLASS_NAME_HIDE)
+      $(this._element).trigger(EVENT_HIDDEN)
     }
 
-    this._element.classList.remove(ClassName.SHOW)
+    this._element.classList.remove(CLASS_NAME_SHOW)
     if (this._config.animation) {
       const transitionDuration = Util.getTransitionDurationFromElement(this._element)
 

+ 5 - 5
coderedcms/static/coderedcms/vendor/bootstrap/js/src/tools/sanitizer.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): tools/sanitizer.js
+ * Bootstrap (v4.5.0): tools/sanitizer.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -37,7 +37,7 @@ export const DefaultWhitelist = {
   h5: [],
   h6: [],
   i: [],
-  img: ['src', 'alt', 'title', 'width', 'height'],
+  img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
   li: [],
   ol: [],
   p: [],
@@ -57,14 +57,14 @@ export const DefaultWhitelist = {
  *
  * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
  */
-const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
+const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi
 
 /**
  * A pattern that matches safe data URLs. Only matches image, video and audio types.
  *
  * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
  */
-const 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
+const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i
 
 function allowedAttribute(attr, allowedAttributeList) {
   const attrName = attr.nodeName.toLowerCase()
@@ -80,7 +80,7 @@ function allowedAttribute(attr, allowedAttributeList) {
   const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp)
 
   // Check if a regular expression validates the attribute.
-  for (let i = 0, l = regExp.length; i < l; i++) {
+  for (let i = 0, len = regExp.length; i < len; i++) {
     if (attrName.match(regExp[i])) {
       return true
     }

+ 82 - 95
coderedcms/static/coderedcms/vendor/bootstrap/js/src/tooltip.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): tooltip.js
+ * Bootstrap (v4.5.0): tooltip.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -20,7 +20,7 @@ import Util from './util'
  */
 
 const NAME                  = 'tooltip'
-const VERSION               = '4.3.1'
+const VERSION               = '4.5.0'
 const DATA_KEY              = 'bs.tooltip'
 const EVENT_KEY             = `.${DATA_KEY}`
 const JQUERY_NO_CONFLICT    = $.fn[NAME]
@@ -43,7 +43,8 @@ const DefaultType = {
   boundary          : '(string|element)',
   sanitize          : 'boolean',
   sanitizeFn        : '(null|function)',
-  whiteList         : 'object'
+  whiteList         : 'object',
+  popperConfig      : '(null|object)'
 }
 
 const AttachmentMap = {
@@ -71,13 +72,12 @@ const Default = {
   boundary          : 'scrollParent',
   sanitize          : true,
   sanitizeFn        : null,
-  whiteList         : DefaultWhitelist
+  whiteList         : DefaultWhitelist,
+  popperConfig      : null
 }
 
-const HoverState = {
-  SHOW : 'show',
-  OUT  : 'out'
-}
+const HOVER_STATE_SHOW = 'show'
+const HOVER_STATE_OUT  = 'out'
 
 const Event = {
   HIDE       : `hide${EVENT_KEY}`,
@@ -92,24 +92,16 @@ const Event = {
   MOUSELEAVE : `mouseleave${EVENT_KEY}`
 }
 
-const ClassName = {
-  FADE : 'fade',
-  SHOW : 'show'
-}
-
-const Selector = {
-  TOOLTIP       : '.tooltip',
-  TOOLTIP_INNER : '.tooltip-inner',
-  ARROW         : '.arrow'
-}
+const CLASS_NAME_FADE = 'fade'
+const CLASS_NAME_SHOW = 'show'
 
-const Trigger = {
-  HOVER  : 'hover',
-  FOCUS  : 'focus',
-  CLICK  : 'click',
-  MANUAL : 'manual'
-}
+const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'
+const SELECTOR_ARROW         = '.arrow'
 
+const TRIGGER_HOVER  = 'hover'
+const TRIGGER_FOCUS  = 'focus'
+const TRIGGER_CLICK  = 'click'
+const TRIGGER_MANUAL = 'manual'
 
 /**
  * ------------------------------------------------------------------------
@@ -119,10 +111,6 @@ const Trigger = {
 
 class Tooltip {
   constructor(element, config) {
-    /**
-     * Check for Popper dependency
-     * Popper - https://popper.js.org
-     */
     if (typeof Popper === 'undefined') {
       throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)')
     }
@@ -211,7 +199,7 @@ class Tooltip {
         context._leave(null, context)
       }
     } else {
-      if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {
+      if ($(this.getTipElement()).hasClass(CLASS_NAME_SHOW)) {
         this._leave(null, this)
         return
       }
@@ -226,7 +214,7 @@ class Tooltip {
     $.removeData(this.element, this.constructor.DATA_KEY)
 
     $(this.element).off(this.constructor.EVENT_KEY)
-    $(this.element).closest('.modal').off('hide.bs.modal')
+    $(this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler)
 
     if (this.tip) {
       $(this.tip).remove()
@@ -236,7 +224,7 @@ class Tooltip {
     this._timeout       = null
     this._hoverState    = null
     this._activeTrigger = null
-    if (this._popper !== null) {
+    if (this._popper) {
       this._popper.destroy()
     }
 
@@ -274,7 +262,7 @@ class Tooltip {
       this.setContent()
 
       if (this.config.animation) {
-        $(tip).addClass(ClassName.FADE)
+        $(tip).addClass(CLASS_NAME_FADE)
       }
 
       const placement  = typeof this.config.placement === 'function'
@@ -293,29 +281,9 @@ class Tooltip {
 
       $(this.element).trigger(this.constructor.Event.INSERTED)
 
-      this._popper = new Popper(this.element, tip, {
-        placement: attachment,
-        modifiers: {
-          offset: this._getOffset(),
-          flip: {
-            behavior: this.config.fallbackPlacement
-          },
-          arrow: {
-            element: Selector.ARROW
-          },
-          preventOverflow: {
-            boundariesElement: this.config.boundary
-          }
-        },
-        onCreate: (data) => {
-          if (data.originalPlacement !== data.placement) {
-            this._handlePopperPlacementChange(data)
-          }
-        },
-        onUpdate: (data) => this._handlePopperPlacementChange(data)
-      })
+      this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment))
 
-      $(tip).addClass(ClassName.SHOW)
+      $(tip).addClass(CLASS_NAME_SHOW)
 
       // If this is a touch-enabled device we add extra
       // empty mouseover listeners to the body's immediate children;
@@ -334,12 +302,12 @@ class Tooltip {
 
         $(this.element).trigger(this.constructor.Event.SHOWN)
 
-        if (prevHoverState === HoverState.OUT) {
+        if (prevHoverState === HOVER_STATE_OUT) {
           this._leave(null, this)
         }
       }
 
-      if ($(this.tip).hasClass(ClassName.FADE)) {
+      if ($(this.tip).hasClass(CLASS_NAME_FADE)) {
         const transitionDuration = Util.getTransitionDurationFromElement(this.tip)
 
         $(this.tip)
@@ -355,7 +323,7 @@ class Tooltip {
     const tip       = this.getTipElement()
     const hideEvent = $.Event(this.constructor.Event.HIDE)
     const complete = () => {
-      if (this._hoverState !== HoverState.SHOW && tip.parentNode) {
+      if (this._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {
         tip.parentNode.removeChild(tip)
       }
 
@@ -377,7 +345,7 @@ class Tooltip {
       return
     }
 
-    $(tip).removeClass(ClassName.SHOW)
+    $(tip).removeClass(CLASS_NAME_SHOW)
 
     // If this is a touch-enabled device we remove the extra
     // empty mouseover listeners we added for iOS support
@@ -385,11 +353,11 @@ class Tooltip {
       $(document.body).children().off('mouseover', null, $.noop)
     }
 
-    this._activeTrigger[Trigger.CLICK] = false
-    this._activeTrigger[Trigger.FOCUS] = false
-    this._activeTrigger[Trigger.HOVER] = false
+    this._activeTrigger[TRIGGER_CLICK] = false
+    this._activeTrigger[TRIGGER_FOCUS] = false
+    this._activeTrigger[TRIGGER_HOVER] = false
 
-    if ($(this.tip).hasClass(ClassName.FADE)) {
+    if ($(this.tip).hasClass(CLASS_NAME_FADE)) {
       const transitionDuration = Util.getTransitionDurationFromElement(tip)
 
       $(tip)
@@ -425,8 +393,8 @@ class Tooltip {
 
   setContent() {
     const tip = this.getTipElement()
-    this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())
-    $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)
+    this.setElementContent($(tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle())
+    $(tip).removeClass(`${CLASS_NAME_FADE} ${CLASS_NAME_SHOW}`)
   }
 
   setElementContent($element, content) {
@@ -468,6 +436,35 @@ class Tooltip {
 
   // Private
 
+  _getPopperConfig(attachment) {
+    const defaultBsConfig = {
+      placement: attachment,
+      modifiers: {
+        offset: this._getOffset(),
+        flip: {
+          behavior: this.config.fallbackPlacement
+        },
+        arrow: {
+          element: SELECTOR_ARROW
+        },
+        preventOverflow: {
+          boundariesElement: this.config.boundary
+        }
+      },
+      onCreate: (data) => {
+        if (data.originalPlacement !== data.placement) {
+          this._handlePopperPlacementChange(data)
+        }
+      },
+      onUpdate: (data) => this._handlePopperPlacementChange(data)
+    }
+
+    return {
+      ...defaultBsConfig,
+      ...this.config.popperConfig
+    }
+  }
+
   _getOffset() {
     const offset = {}
 
@@ -513,36 +510,27 @@ class Tooltip {
           this.config.selector,
           (event) => this.toggle(event)
         )
-      } else if (trigger !== Trigger.MANUAL) {
-        const eventIn = trigger === Trigger.HOVER
+      } else if (trigger !== TRIGGER_MANUAL) {
+        const eventIn = trigger === TRIGGER_HOVER
           ? this.constructor.Event.MOUSEENTER
           : this.constructor.Event.FOCUSIN
-        const eventOut = trigger === Trigger.HOVER
+        const eventOut = trigger === TRIGGER_HOVER
           ? this.constructor.Event.MOUSELEAVE
           : this.constructor.Event.FOCUSOUT
 
         $(this.element)
-          .on(
-            eventIn,
-            this.config.selector,
-            (event) => this._enter(event)
-          )
-          .on(
-            eventOut,
-            this.config.selector,
-            (event) => this._leave(event)
-          )
+          .on(eventIn, this.config.selector, (event) => this._enter(event))
+          .on(eventOut, this.config.selector, (event) => this._leave(event))
       }
     })
 
-    $(this.element).closest('.modal').on(
-      'hide.bs.modal',
-      () => {
-        if (this.element) {
-          this.hide()
-        }
+    this._hideModalHandler = () => {
+      if (this.element) {
+        this.hide()
       }
-    )
+    }
+
+    $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler)
 
     if (this.config.selector) {
       this.config = {
@@ -582,18 +570,18 @@ class Tooltip {
 
     if (event) {
       context._activeTrigger[
-        event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER
+        event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER
       ] = true
     }
 
-    if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {
-      context._hoverState = HoverState.SHOW
+    if ($(context.getTipElement()).hasClass(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
+      context._hoverState = HOVER_STATE_SHOW
       return
     }
 
     clearTimeout(context._timeout)
 
-    context._hoverState = HoverState.SHOW
+    context._hoverState = HOVER_STATE_SHOW
 
     if (!context.config.delay || !context.config.delay.show) {
       context.show()
@@ -601,7 +589,7 @@ class Tooltip {
     }
 
     context._timeout = setTimeout(() => {
-      if (context._hoverState === HoverState.SHOW) {
+      if (context._hoverState === HOVER_STATE_SHOW) {
         context.show()
       }
     }, context.config.delay.show)
@@ -621,7 +609,7 @@ class Tooltip {
 
     if (event) {
       context._activeTrigger[
-        event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER
+        event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER
       ] = false
     }
 
@@ -631,7 +619,7 @@ class Tooltip {
 
     clearTimeout(context._timeout)
 
-    context._hoverState = HoverState.OUT
+    context._hoverState = HOVER_STATE_OUT
 
     if (!context.config.delay || !context.config.delay.hide) {
       context.hide()
@@ -639,7 +627,7 @@ class Tooltip {
     }
 
     context._timeout = setTimeout(() => {
-      if (context._hoverState === HoverState.OUT) {
+      if (context._hoverState === HOVER_STATE_OUT) {
         context.hide()
       }
     }, context.config.delay.hide)
@@ -722,8 +710,7 @@ class Tooltip {
   }
 
   _handlePopperPlacementChange(popperData) {
-    const popperInstance = popperData.instance
-    this.tip = popperInstance.popper
+    this.tip = popperData.instance.popper
     this._cleanTipClass()
     this.addAttachmentClass(this._getAttachment(popperData.placement))
   }
@@ -736,7 +723,7 @@ class Tooltip {
       return
     }
 
-    $(tip).removeClass(ClassName.FADE)
+    $(tip).removeClass(CLASS_NAME_FADE)
     this.config.animation = false
     this.hide()
     this.show()

+ 24 - 3
coderedcms/static/coderedcms/vendor/bootstrap/js/src/util.js

@@ -1,6 +1,6 @@
 /**
  * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): util.js
+ * Bootstrap (v4.5.0): util.js
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * --------------------------------------------------------------------------
  */
@@ -19,6 +19,10 @@ const MILLISECONDS_MULTIPLIER = 1000
 
 // Shoutout AngusCroll (https://goo.gl/pxwQGp)
 function toType(obj) {
+  if (obj === null || typeof obj === 'undefined') {
+    return `${obj}`
+  }
+
   return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
 }
 
@@ -30,7 +34,7 @@ function getSpecialTransitionEndEvent() {
       if ($(event.target).is(this)) {
         return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
       }
-      return undefined // eslint-disable-line no-undefined
+      return undefined
     }
   }
 }
@@ -63,7 +67,6 @@ function setTransitionEndSupport() {
  */
 
 const Util = {
-
   TRANSITION_END: 'bsTransitionEnd',
 
   getUID(prefix) {
@@ -169,9 +172,27 @@ const Util = {
     }
 
     return Util.findShadowRoot(element.parentNode)
+  },
+
+  jQueryDetection() {
+    if (typeof $ === 'undefined') {
+      throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.')
+    }
+
+    const version = $.fn.jquery.split(' ')[0].split('.')
+    const minMajor = 1
+    const ltMajor = 2
+    const minMinor = 9
+    const minPatch = 1
+    const maxMajor = 4
+
+    if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
+      throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+    }
   }
 }
 
+Util.jQueryDetection()
 setTransitionEndSupport()
 
 export default Util

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/_badge.scss

@@ -16,7 +16,7 @@
   @include transition($badge-transition);
 
   @at-root a#{&} {
-    @include hover-focus {
+    @include hover-focus() {
       text-decoration: none;
     }
   }

+ 4 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/_breadcrumb.scss

@@ -3,12 +3,15 @@
   flex-wrap: wrap;
   padding: $breadcrumb-padding-y $breadcrumb-padding-x;
   margin-bottom: $breadcrumb-margin-bottom;
+  @include font-size($breadcrumb-font-size);
   list-style: none;
   background-color: $breadcrumb-bg;
   @include border-radius($breadcrumb-border-radius);
 }
 
 .breadcrumb-item {
+  display: flex;
+
   // The separator between breadcrumbs (by default, a forward-slash: "/")
   + .breadcrumb-item {
     padding-left: $breadcrumb-item-padding;
@@ -17,7 +20,7 @@
       display: inline-block; // Suppress underlining of the separator in modern browsers
       padding-right: $breadcrumb-item-padding;
       color: $breadcrumb-divider-color;
-      content: $breadcrumb-divider;
+      content: escape-svg($breadcrumb-divider);
     }
   }
 

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/_button-group.scss

@@ -13,7 +13,7 @@
 
     // Bring the hover, focused, and "active" buttons to the front to overlay
     // the borders properly
-    @include hover {
+    @include hover() {
       z-index: 1;
     }
     &:focus,

+ 13 - 8
coderedcms/static/coderedcms/vendor/bootstrap/scss/_buttons.scss

@@ -10,6 +10,8 @@
   font-weight: $btn-font-weight;
   color: $body-color;
   text-align: center;
+  text-decoration: if($link-decoration == none, null, none);
+  white-space: $btn-white-space;
   vertical-align: middle;
   user-select: none;
   background-color: transparent;
@@ -17,7 +19,7 @@
   @include button-size($btn-padding-y, $btn-padding-x, $btn-font-size, $btn-line-height, $btn-border-radius);
   @include transition($btn-transition);
 
-  @include hover {
+  @include hover() {
     color: $body-color;
     text-decoration: none;
   }
@@ -35,12 +37,16 @@
     @include box-shadow(none);
   }
 
-  &:not(:disabled):not(.disabled):active,
-  &:not(:disabled):not(.disabled).active {
-    @include box-shadow($btn-active-box-shadow);
+  &:not(:disabled):not(.disabled) {
+    cursor: if($enable-pointer-cursor-for-buttons, pointer, null);
 
-    &:focus {
-      @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
+    &:active,
+    &.active {
+      @include box-shadow($btn-active-box-shadow);
+
+      &:focus {
+        @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
+      }
     }
   }
 }
@@ -79,7 +85,7 @@ fieldset:disabled a.btn {
   color: $link-color;
   text-decoration: $link-decoration;
 
-  @include hover {
+  @include hover() {
     color: $link-hover-color;
     text-decoration: $link-hover-decoration;
   }
@@ -87,7 +93,6 @@ fieldset:disabled a.btn {
   &:focus,
   &.focus {
     text-decoration: $link-hover-decoration;
-    box-shadow: none;
   }
 
   &:disabled,

+ 28 - 35
coderedcms/static/coderedcms/vendor/bootstrap/scss/_card.scss

@@ -7,6 +7,7 @@
   display: flex;
   flex-direction: column;
   min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
+  height: $card-height;
   word-wrap: break-word;
   background-color: $card-bg;
   background-clip: border-box;
@@ -18,15 +19,18 @@
     margin-left: 0;
   }
 
-  > .list-group:first-child {
-    .list-group-item:first-child {
-      @include border-top-radius($card-border-radius);
+  > .list-group {
+    border-top: inherit;
+    border-bottom: inherit;
+
+    &:first-child {
+      border-top-width: 0;
+      @include border-top-radius($card-inner-border-radius);
     }
-  }
 
-  > .list-group:last-child {
-    .list-group-item:last-child {
-      @include border-bottom-radius($card-border-radius);
+    &:last-child  {
+      border-bottom-width: 0;
+      @include border-bottom-radius($card-inner-border-radius);
     }
   }
 }
@@ -35,6 +39,9 @@
   // Enable `flex-grow: 1` for decks and groups so that card blocks take up
   // as much space as possible, ensuring footers are aligned to the bottom.
   flex: 1 1 auto;
+  // Workaround for the image size bug in IE
+  // See: https://github.com/twbs/bootstrap/pull/28855
+  min-height: 1px;
   padding: $card-spacer-x;
   color: $card-color;
 }
@@ -53,7 +60,7 @@
 }
 
 .card-link {
-  @include hover {
+  @include hover() {
     text-decoration: none;
   }
 
@@ -86,6 +93,7 @@
 
 .card-footer {
   padding: $card-spacer-y $card-spacer-x;
+  color: $card-cap-color;
   background-color: $card-cap-bg;
   border-top: $card-border-width solid $card-border-color;
 
@@ -121,19 +129,20 @@
   padding: $card-img-overlay-padding;
 }
 
-.card-img {
+.card-img,
+.card-img-top,
+.card-img-bottom {
+  flex-shrink: 0; // For IE: https://github.com/twbs/bootstrap/issues/29396
   width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
-  @include border-radius($card-inner-border-radius);
 }
 
-// Card image caps
+.card-img,
 .card-img-top {
-  width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
   @include border-top-radius($card-inner-border-radius);
 }
 
+.card-img,
 .card-img-bottom {
-  width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
   @include border-bottom-radius($card-inner-border-radius);
 }
 
@@ -141,23 +150,19 @@
 // Card deck
 
 .card-deck {
-  display: flex;
-  flex-direction: column;
-
   .card {
     margin-bottom: $card-deck-margin;
   }
 
   @include media-breakpoint-up(sm) {
+    display: flex;
     flex-flow: row wrap;
     margin-right: -$card-deck-margin;
     margin-left: -$card-deck-margin;
 
     .card {
-      display: flex;
       // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
       flex: 1 0 0%;
-      flex-direction: column;
       margin-right: $card-deck-margin;
       margin-bottom: 0; // Override the default
       margin-left: $card-deck-margin;
@@ -171,9 +176,6 @@
 //
 
 .card-group {
-  display: flex;
-  flex-direction: column;
-
   // The child selector allows nested `.card` within `.card-group`
   // to display properly.
   > .card {
@@ -181,6 +183,7 @@
   }
 
   @include media-breakpoint-up(sm) {
+    display: flex;
     flex-flow: row wrap;
     // The child selector allows nested `.card` within `.card-group`
     // to display properly.
@@ -262,27 +265,17 @@
   > .card {
     overflow: hidden;
 
-    &:not(:first-of-type) {
-      .card-header:first-child {
-        @include border-radius(0);
-      }
-
-      &:not(:last-of-type) {
-        border-bottom: 0;
-        @include border-radius(0);
-      }
-    }
-
-    &:first-of-type {
+    &:not(:last-of-type) {
       border-bottom: 0;
       @include border-bottom-radius(0);
     }
 
-    &:last-of-type {
+    &:not(:first-of-type) {
       @include border-top-radius(0);
     }
 
-    .card-header {
+    > .card-header {
+      @include border-radius(0);
       margin-bottom: -$card-border-width;
     }
   }

+ 6 - 6
coderedcms/static/coderedcms/vendor/bootstrap/scss/_carousel.scss

@@ -75,7 +75,7 @@
   .active.carousel-item-right {
     z-index: 0;
     opacity: 0;
-    @include transition(0s $carousel-transition-duration opacity);
+    @include transition(opacity 0s $carousel-transition-duration);
   }
 }
 
@@ -101,7 +101,7 @@
   @include transition($carousel-control-transition);
 
   // Hover/focus state
-  @include hover-focus {
+  @include hover-focus() {
     color: $carousel-control-color;
     text-decoration: none;
     outline: 0;
@@ -111,13 +111,13 @@
 .carousel-control-prev {
   left: 0;
   @if $enable-gradients {
-    background: linear-gradient(90deg, rgba($black, .25), rgba($black, .001));
+    background-image: linear-gradient(90deg, rgba($black, .25), rgba($black, .001));
   }
 }
 .carousel-control-next {
   right: 0;
   @if $enable-gradients {
-    background: linear-gradient(270deg, rgba($black, .25), rgba($black, .001));
+    background-image: linear-gradient(270deg, rgba($black, .25), rgba($black, .001));
   }
 }
 
@@ -130,10 +130,10 @@
   background: no-repeat 50% / 100% 100%;
 }
 .carousel-control-prev-icon {
-  background-image: $carousel-control-prev-icon-bg;
+  background-image: escape-svg($carousel-control-prev-icon-bg);
 }
 .carousel-control-next-icon {
-  background-image: $carousel-control-next-icon-bg;
+  background-image: escape-svg($carousel-control-next-icon-bg);
 }
 
 

+ 2 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/_close.scss

@@ -8,13 +8,13 @@
   opacity: .5;
 
   // Override <a>'s hover style
-  @include hover {
+  @include hover() {
     color: $close-color;
     text-decoration: none;
   }
 
   &:not(:disabled):not(.disabled) {
-    @include hover-focus {
+    @include hover-focus() {
       opacity: .75;
     }
   }
@@ -30,7 +30,6 @@ button.close {
   padding: 0;
   background-color: transparent;
   border: 0;
-  appearance: none;
 }
 
 // Future-proof disabling of clicks on `<a>` elements

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/_code.scss

@@ -2,7 +2,7 @@
 code {
   @include font-size($code-font-size);
   color: $code-color;
-  word-break: break-word;
+  word-wrap: break-word;
 
   // Streamline the style when inside anchors to avoid broken underline and more
   a > & {

+ 24 - 9
coderedcms/static/coderedcms/vendor/bootstrap/scss/_custom-forms.scss

@@ -21,7 +21,10 @@
 
 .custom-control-input {
   position: absolute;
+  left: 0;
   z-index: -1; // Put the input behind the label so it doesn't overlay text
+  width: $custom-control-indicator-size;
+  height: ($font-size-base * $line-height-base + $custom-control-indicator-size) / 2;
   opacity: 0;
 
   &:checked ~ .custom-control-label::before {
@@ -51,6 +54,8 @@
     @include box-shadow($custom-control-indicator-active-box-shadow);
   }
 
+  // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247
+  &[disabled],
   &:disabled {
     ~ .custom-control-label {
       color: $custom-control-label-disabled-color;
@@ -69,7 +74,9 @@
 .custom-control-label {
   position: relative;
   margin-bottom: 0;
+  color: $custom-control-label-color;
   vertical-align: top;
+  cursor: $custom-control-cursor;
 
   // Background-color and (when enabled) gradient
   &::before {
@@ -111,7 +118,7 @@
 
   .custom-control-input:checked ~ .custom-control-label {
     &::after {
-      background-image: $custom-checkbox-indicator-icon-checked;
+      background-image: escape-svg($custom-checkbox-indicator-icon-checked);
     }
   }
 
@@ -122,7 +129,7 @@
       @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);
     }
     &::after {
-      background-image: $custom-checkbox-indicator-icon-indeterminate;
+      background-image: escape-svg($custom-checkbox-indicator-icon-indeterminate);
     }
   }
 
@@ -148,7 +155,7 @@
 
   .custom-control-input:checked ~ .custom-control-label {
     &::after {
-      background-image: $custom-radio-indicator-icon-checked;
+      background-image: escape-svg($custom-radio-indicator-icon-checked);
     }
   }
 
@@ -177,8 +184,8 @@
     }
 
     &::after {
-      top: calc(#{(($font-size-base * $line-height-base - $custom-control-indicator-size) / 2)} + #{$custom-control-indicator-border-width * 2});
-      left: calc(#{-($custom-switch-width + $custom-control-gutter)} + #{$custom-control-indicator-border-width * 2});
+      top: add(($font-size-base * $line-height-base - $custom-control-indicator-size) / 2, $custom-control-indicator-border-width * 2);
+      left: add(-($custom-switch-width + $custom-control-gutter), $custom-control-indicator-border-width * 2);
       width: $custom-switch-indicator-size;
       height: $custom-switch-indicator-size;
       background-color: $custom-control-indicator-border-color;
@@ -220,8 +227,7 @@
   line-height: $custom-select-line-height;
   color: $custom-select-color;
   vertical-align: middle;
-  background: $custom-select-background;
-  background-color: $custom-select-bg;
+  background: $custom-select-bg $custom-select-background;
   border: $custom-select-border-width solid $custom-select-border-color;
   @include border-radius($custom-select-border-radius, 0);
   @include box-shadow($custom-select-box-shadow);
@@ -231,8 +237,9 @@
     border-color: $custom-select-focus-border-color;
     outline: 0;
     @if $enable-shadows {
-      box-shadow: $custom-select-box-shadow, $custom-select-focus-box-shadow;
+      @include box-shadow($custom-select-box-shadow, $custom-select-focus-box-shadow);
     } @else {
+      // Avoid using mixin so we can pass custom focus shadow properly
       box-shadow: $custom-select-focus-box-shadow;
     }
 
@@ -263,6 +270,12 @@
   &::-ms-expand {
     display: none;
   }
+
+  // Remove outline from select box in FF
+  &:-moz-focusring {
+    color: transparent;
+    text-shadow: 0 0 0 $custom-select-color;
+  }
 }
 
 .custom-select-sm {
@@ -307,6 +320,8 @@
     box-shadow: $custom-file-focus-box-shadow;
   }
 
+  // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247
+  &[disabled] ~ .custom-file-label,
   &:disabled ~ .custom-file-label {
     background-color: $custom-file-disabled-bg;
   }
@@ -365,7 +380,7 @@
 
 .custom-range {
   width: 100%;
-  height: calc(#{$custom-range-thumb-height} + #{$custom-range-thumb-focus-box-shadow-width * 2});
+  height: add($custom-range-thumb-height, $custom-range-thumb-focus-box-shadow-width * 2);
   padding: 0; // Need to reset padding
   background-color: transparent;
   appearance: none;

+ 5 - 4
coderedcms/static/coderedcms/vendor/bootstrap/scss/_dropdown.scss

@@ -10,7 +10,7 @@
   white-space: nowrap;
 
   // Generate the caret automatically
-  @include caret;
+  @include caret();
 }
 
 // The dropdown menu
@@ -114,7 +114,7 @@
 
 // Dividers (basically an `<hr>`) within the dropdown
 .dropdown-divider {
-  @include nav-divider($dropdown-divider-bg, $dropdown-divider-margin-y);
+  @include nav-divider($dropdown-divider-bg, $dropdown-divider-margin-y, true);
 }
 
 // Links, buttons, and more within the dropdown menu
@@ -128,6 +128,7 @@
   font-weight: $font-weight-normal;
   color: $dropdown-link-color;
   text-align: inherit; // For `<button>`s
+  text-decoration: if($link-decoration == none, null, none);
   white-space: nowrap; // prevent links from randomly breaking onto new lines
   background-color: transparent; // For `<button>`s
   border: 0; // For `<button>`s
@@ -144,7 +145,7 @@
     }
   }
 
-  @include hover-focus {
+  @include hover-focus() {
     color: $dropdown-link-hover-color;
     text-decoration: none;
     @include gradient-bg($dropdown-link-hover-bg);
@@ -176,7 +177,7 @@
 // Dropdown section headers
 .dropdown-header {
   display: block;
-  padding: $dropdown-padding-y $dropdown-item-padding-x;
+  padding: $dropdown-header-padding;
   margin-bottom: 0; // for use with heading elements
   @include font-size($font-size-sm);
   color: $dropdown-header-color;

+ 26 - 9
coderedcms/static/coderedcms/vendor/bootstrap/scss/_forms.scss

@@ -30,8 +30,14 @@
     border: 0;
   }
 
+  // Remove select outline from select box in FF
+  &:-moz-focusring {
+    color: transparent;
+    text-shadow: 0 0 0 $input-color;
+  }
+
   // Customize the `:focus` state to imitate native WebKit styles.
-  @include form-control-focus();
+  @include form-control-focus($ignore-warning: true);
 
   // Placeholder
   &::placeholder {
@@ -53,6 +59,15 @@
   }
 }
 
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  &.form-control {
+    appearance: none; // Fix appearance for date inputs in Safari
+  }
+}
+
 select.form-control {
   &:focus::-ms-value {
     // Suppress the nested default white text on blue background highlight given to
@@ -80,23 +95,23 @@ select.form-control {
 // For use with horizontal and inline forms, when you need the label (or legend)
 // text to align with the form controls.
 .col-form-label {
-  padding-top: calc(#{$input-padding-y} + #{$input-border-width});
-  padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});
+  padding-top: add($input-padding-y, $input-border-width);
+  padding-bottom: add($input-padding-y, $input-border-width);
   margin-bottom: 0; // Override the `<label>/<legend>` default
   @include font-size(inherit); // Override the `<legend>` default
   line-height: $input-line-height;
 }
 
 .col-form-label-lg {
-  padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width});
-  padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width});
+  padding-top: add($input-padding-y-lg, $input-border-width);
+  padding-bottom: add($input-padding-y-lg, $input-border-width);
   @include font-size($input-font-size-lg);
   line-height: $input-line-height-lg;
 }
 
 .col-form-label-sm {
-  padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width});
-  padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width});
+  padding-top: add($input-padding-y-sm, $input-border-width);
+  padding-bottom: add($input-padding-y-sm, $input-border-width);
   @include font-size($input-font-size-sm);
   line-height: $input-line-height-sm;
 }
@@ -110,9 +125,9 @@ select.form-control {
 .form-control-plaintext {
   display: block;
   width: 100%;
-  padding-top: $input-padding-y;
-  padding-bottom: $input-padding-y;
+  padding: $input-padding-y 0;
   margin-bottom: 0; // match inputs if this class comes on inputs with default margins
+  @include font-size($input-font-size);
   line-height: $input-line-height;
   color: $input-plaintext-color;
   background-color: transparent;
@@ -210,6 +225,8 @@ textarea.form-control {
   margin-top: $form-check-input-margin-y;
   margin-left: -$form-check-input-gutter;
 
+  // Use [disabled] and :disabled for workaround https://github.com/twbs/bootstrap/issues/28247
+  &[disabled] ~ .form-check-label,
   &:disabled ~ .form-check-label {
     color: $text-muted;
   }

+ 60 - 5
coderedcms/static/coderedcms/vendor/bootstrap/scss/_functions.scss

@@ -8,7 +8,7 @@
   $prev-key: null;
   $prev-num: null;
   @each $key, $num in $map {
-    @if $prev-num == null or unit($num) == "%" {
+    @if $prev-num == null or unit($num) == "%" or unit($prev-num) == "%" {
       // Do nothing
     } @else if not comparable($prev-num, $num) {
       @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
@@ -23,10 +23,12 @@
 // Starts at zero
 // Used to ensure the min-width of the lowest breakpoint starts at 0.
 @mixin _assert-starts-at-zero($map, $map-name: "$grid-breakpoints") {
-  $values: map-values($map);
-  $first-value: nth($values, 1);
-  @if $first-value != 0 {
-    @warn "First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.";
+  @if length($map) > 0 {
+    $values: map-values($map);
+    $first-value: nth($values, 1);
+    @if $first-value != 0 {
+      @warn "First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.";
+    }
   }
 }
 
@@ -48,6 +50,22 @@
   @return $string;
 }
 
+// See https://codepen.io/kevinweber/pen/dXWoRw
+@function escape-svg($string) {
+  @if str-index($string, "data:image/svg+xml") {
+    @each $char, $encoded in $escaped-characters {
+      // Do not escape the url brackets
+      @if str-index($string, "url(") == 1 {
+        $string: url("#{str-replace(str-slice($string, 6, -3), $char, $encoded)}");
+      } @else {
+        $string: str-replace($string, $char, $encoded);
+      }
+    }
+  }
+
+  @return $string;
+}
+
 // Color contrast
 @function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {
   $r: red($color);
@@ -84,3 +102,40 @@
 
   @return mix($color-base, $color, $level * $theme-color-interval);
 }
+
+// Return valid calc
+@function add($value1, $value2, $return-calc: true) {
+  @if $value1 == null {
+    @return $value2;
+  }
+
+  @if $value2 == null {
+    @return $value1;
+  }
+
+  @if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) {
+    @return $value1 + $value2;
+  }
+
+  @return if($return-calc == true, calc(#{$value1} + #{$value2}), $value1 + unquote(" + ") + $value2);
+}
+
+@function subtract($value1, $value2, $return-calc: true) {
+  @if $value1 == null and $value2 == null {
+    @return null;
+  }
+
+  @if $value1 == null {
+    @return -$value2;
+  }
+
+  @if $value2 == null {
+    @return $value1;
+  }
+
+  @if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) {
+    @return $value1 - $value2;
+  }
+
+  @return if($return-calc == true, calc(#{$value1} - #{$value2}), $value1 + unquote(" - ") + $value2);
+}

+ 33 - 8
coderedcms/static/coderedcms/vendor/bootstrap/scss/_grid.scss

@@ -3,26 +3,51 @@
 // Set the container width, and override it for fixed navbars in media queries.
 
 @if $enable-grid-classes {
+  // Single container class with breakpoint max-widths
   .container {
     @include make-container();
     @include make-container-max-widths();
   }
-}
-
-// Fluid container
-//
-// Utilizes the mixin meant for fixed width containers, but with 100% width for
-// fluid, full width layouts.
 
-@if $enable-grid-classes {
+  // 100% wide container at all breakpoints
   .container-fluid {
     @include make-container();
   }
+
+  // Responsive containers that are 100% wide until a breakpoint
+  @each $breakpoint, $container-max-width in $container-max-widths {
+    .container-#{$breakpoint} {
+      @extend .container-fluid;
+    }
+
+    @include media-breakpoint-up($breakpoint, $grid-breakpoints) {
+      %responsive-container-#{$breakpoint} {
+        max-width: $container-max-width;
+      }
+
+      // Extend each breakpoint which is smaller or equal to the current breakpoint
+      $extend-breakpoint: true;
+
+      @each $name, $width in $grid-breakpoints {
+        @if ($extend-breakpoint) {
+          .container#{breakpoint-infix($name, $grid-breakpoints)} {
+            @extend %responsive-container-#{$breakpoint};
+          }
+
+          // Once the current breakpoint is reached, stop extending
+          @if ($breakpoint == $name) {
+            $extend-breakpoint: false;
+          }
+        }
+      }
+    }
+  }
 }
 
+
 // Row
 //
-// Rows contain and clear the floats of your columns.
+// Rows contain your columns.
 
 @if $enable-grid-classes {
   .row {

+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_images.scss

@@ -6,7 +6,7 @@
 // which weren't expecting the images within themselves to be involuntarily resized.
 // See also https://github.com/twbs/bootstrap/issues/18178
 .img-fluid {
-  @include img-fluid;
+  @include img-fluid();
 }
 
 
@@ -19,7 +19,7 @@
   @include box-shadow($thumbnail-box-shadow);
 
   // Keep them at most 100% wide
-  @include img-fluid;
+  @include img-fluid();
 }
 
 //

+ 1 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_input-group.scss

@@ -17,9 +17,8 @@
   > .custom-file {
     position: relative; // For focus state's z-index
     flex: 1 1 auto;
-    // Add width 1% and flex-basis auto to ensure that button will not wrap out
-    // the column. Applies to IE Edge+ and Firefox. Chrome does not require this.
     width: 1%;
+    min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size
     margin-bottom: 0;
 
     + .form-control,

+ 36 - 31
coderedcms/static/coderedcms/vendor/bootstrap/scss/_list-group.scss

@@ -9,6 +9,7 @@
   // No need to set list-style: none; since .list-group-item is block level
   padding-left: 0; // reset padding because ul and ol
   margin-bottom: 0;
+  @include border-radius($list-group-border-radius);
 }
 
 
@@ -23,7 +24,7 @@
   text-align: inherit; // For `<button>`s (anchors inherit)
 
   // Hover state
-  @include hover-focus {
+  @include hover-focus() {
     z-index: 1; // Place hover/focus items above their siblings for proper border styling
     color: $list-group-action-hover-color;
     text-decoration: none;
@@ -45,19 +46,17 @@
   position: relative;
   display: block;
   padding: $list-group-item-padding-y $list-group-item-padding-x;
-  // Place the border on the list items and negative margin up for better styling
-  margin-bottom: -$list-group-border-width;
   color: $list-group-color;
+  text-decoration: if($link-decoration == none, null, none);
   background-color: $list-group-bg;
   border: $list-group-border-width solid $list-group-border-color;
 
   &:first-child {
-    @include border-top-radius($list-group-border-radius);
+    @include border-top-radius(inherit);
   }
 
   &:last-child {
-    margin-bottom: 0;
-    @include border-bottom-radius($list-group-border-radius);
+    @include border-bottom-radius(inherit);
   }
 
   &.disabled,
@@ -74,6 +73,15 @@
     background-color: $list-group-active-bg;
     border-color: $list-group-active-border-color;
   }
+
+  & + & {
+    border-top-width: 0;
+
+    &.active {
+      margin-top: -$list-group-border-width;
+      border-top-width: $list-group-border-width;
+    }
+  }
 }
 
 
@@ -88,20 +96,30 @@
     .list-group-horizontal#{$infix} {
       flex-direction: row;
 
-      .list-group-item {
-        margin-right: -$list-group-border-width;
-        margin-bottom: 0;
-
+      > .list-group-item {
         &:first-child {
-          @include border-left-radius($list-group-border-radius);
+          @include border-bottom-left-radius($list-group-border-radius);
           @include border-top-right-radius(0);
         }
 
         &:last-child {
-          margin-right: 0;
-          @include border-right-radius($list-group-border-radius);
+          @include border-top-right-radius($list-group-border-radius);
           @include border-bottom-left-radius(0);
         }
+
+        &.active {
+          margin-top: 0;
+        }
+
+        & + .list-group-item {
+          border-top-width: $list-group-border-width;
+          border-left-width: 0;
+
+          &.active {
+            margin-left: -$list-group-border-width;
+            border-left-width: $list-group-border-width;
+          }
+        }
       }
     }
   }
@@ -114,26 +132,13 @@
 // useful within other components (e.g., cards).
 
 .list-group-flush {
-  .list-group-item {
-    border-right: 0;
-    border-left: 0;
-    @include border-radius(0);
+  @include border-radius(0);
 
-    &:last-child {
-      margin-bottom: -$list-group-border-width;
-    }
-  }
+  > .list-group-item {
+    border-width: 0 0 $list-group-border-width;
 
-  &:first-child {
-    .list-group-item:first-child {
-      border-top: 0;
-    }
-  }
-
-  &:last-child {
-    .list-group-item:last-child {
-      margin-bottom: 0;
-      border-bottom: 0;
+    &:last-child {
+      border-bottom-width: 0;
     }
   }
 }

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/_mixins.scss

@@ -22,7 +22,7 @@
 @import "mixins/text-truncate";
 @import "mixins/visibility";
 
-// // Components
+// Components
 @import "mixins/alert";
 @import "mixins/buttons";
 @import "mixins/caret";
@@ -33,14 +33,14 @@
 @import "mixins/forms";
 @import "mixins/table-row";
 
-// // Skins
+// Skins
 @import "mixins/background-variant";
 @import "mixins/border-radius";
 @import "mixins/box-shadow";
 @import "mixins/gradients";
 @import "mixins/transition";
 
-// // Layout
+// Layout
 @import "mixins/clearfix";
 @import "mixins/grid-framework";
 @import "mixins/grid";

+ 28 - 16
coderedcms/static/coderedcms/vendor/bootstrap/scss/_modal.scss

@@ -48,14 +48,19 @@
   .modal.show & {
     transform: $modal-show-transform;
   }
+
+  // When trying to close, animate focus to scale
+  .modal.modal-static & {
+    transform: $modal-scale-transform;
+  }
 }
 
 .modal-dialog-scrollable {
   display: flex; // IE10/11
-  max-height: calc(100% - #{$modal-dialog-margin * 2});
+  max-height: subtract(100%, $modal-dialog-margin * 2);
 
   .modal-content {
-    max-height: calc(100vh - #{$modal-dialog-margin * 2}); // IE10/11
+    max-height: subtract(100vh, $modal-dialog-margin * 2); // IE10/11
     overflow: hidden;
   }
 
@@ -72,12 +77,13 @@
 .modal-dialog-centered {
   display: flex;
   align-items: center;
-  min-height: calc(100% - #{$modal-dialog-margin * 2});
+  min-height: subtract(100%, $modal-dialog-margin * 2);
 
   // Ensure `modal-dialog-centered` extends the full height of the view (IE10/11)
   &::before {
     display: block; // IE10
-    height: calc(100vh - #{$modal-dialog-margin * 2});
+    height: subtract(100vh, $modal-dialog-margin * 2);
+    height: min-content; // Reset height to 0 except on IE
     content: "";
   }
 
@@ -138,7 +144,7 @@
   justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
   padding: $modal-header-padding;
   border-bottom: $modal-header-border-width solid $modal-header-border-color;
-  @include border-top-radius($modal-content-border-radius);
+  @include border-top-radius($modal-content-inner-border-radius);
 
   .close {
     padding: $modal-header-padding;
@@ -158,7 +164,7 @@
 .modal-body {
   position: relative;
   // Enable `flex-grow: 1` so that the body take up as much space as possible
-  // when should there be a fixed height on `.modal-dialog`.
+  // when there should be a fixed height on `.modal-dialog`.
   flex: 1 1 auto;
   padding: $modal-inner-padding;
 }
@@ -166,15 +172,20 @@
 // Footer (for actions)
 .modal-footer {
   display: flex;
+  flex-wrap: wrap;
   align-items: center; // vertically center
   justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
-  padding: $modal-inner-padding;
+  padding: $modal-inner-padding - $modal-footer-margin-between / 2;
   border-top: $modal-footer-border-width solid $modal-footer-border-color;
-  @include border-bottom-radius($modal-content-border-radius);
-
-  // Easily place margin between footer elements
-  > :not(:first-child) { margin-left: .25rem; }
-  > :not(:last-child) { margin-right: .25rem; }
+  @include border-bottom-radius($modal-content-inner-border-radius);
+
+  // Place margin between footer elements
+  // This solution is far from ideal because of the universal selector usage,
+  // but is needed to fix https://github.com/twbs/bootstrap/issues/24800
+  // stylelint-disable-next-line selector-max-universal
+  > * {
+    margin: $modal-footer-margin-between / 2;
+  }
 }
 
 // Measure scrollbar width for padding body during modal show/hide
@@ -195,18 +206,19 @@
   }
 
   .modal-dialog-scrollable {
-    max-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});
+    max-height: subtract(100%, $modal-dialog-margin-y-sm-up * 2);
 
     .modal-content {
-      max-height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});
+      max-height: subtract(100vh, $modal-dialog-margin-y-sm-up * 2);
     }
   }
 
   .modal-dialog-centered {
-    min-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});
+    min-height: subtract(100%, $modal-dialog-margin-y-sm-up * 2);
 
     &::before {
-      height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});
+      height: subtract(100vh, $modal-dialog-margin-y-sm-up * 2);
+      height: min-content;
     }
   }
 

+ 4 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/_nav.scss

@@ -1,7 +1,7 @@
 // Base class
 //
 // Kickstart any navigation component with a set of style resets. Works with
-// `<nav>`s or `<ul>`s.
+// `<nav>`s, `<ul>`s or `<ol>`s.
 
 .nav {
   display: flex;
@@ -14,8 +14,9 @@
 .nav-link {
   display: block;
   padding: $nav-link-padding-y $nav-link-padding-x;
+  text-decoration: if($link-decoration == none, null, none);
 
-  @include hover-focus {
+  @include hover-focus() {
     text-decoration: none;
   }
 
@@ -42,7 +43,7 @@
     border: $nav-tabs-border-width solid transparent;
     @include border-top-radius($nav-tabs-border-radius);
 
-    @include hover-focus {
+    @include hover-focus() {
       border-color: $nav-tabs-link-hover-border-color;
     }
 

+ 45 - 15
coderedcms/static/coderedcms/vendor/bootstrap/scss/_navbar.scss

@@ -25,13 +25,23 @@
 
   // Because flex properties aren't inherited, we need to redeclare these first
   // few properties so that content nested within behave properly.
-  > .container,
-  > .container-fluid {
+  %container-flex-properties {
     display: flex;
     flex-wrap: wrap;
     align-items: center;
     justify-content: space-between;
   }
+
+  .container,
+  .container-fluid {
+    @extend %container-flex-properties;
+  }
+
+  @each $breakpoint, $container-max-width in $container-max-widths {
+    > .container#{breakpoint-infix($breakpoint, $container-max-widths)} {
+      @extend %container-flex-properties;
+    }
+  }
 }
 
 
@@ -48,7 +58,7 @@
   line-height: inherit;
   white-space: nowrap;
 
-  @include hover-focus {
+  @include hover-focus() {
     text-decoration: none;
   }
 }
@@ -113,7 +123,7 @@
   border: $border-width solid transparent; // remove default button style
   @include border-radius($navbar-toggler-border-radius);
 
-  @include hover-focus {
+  @include hover-focus() {
     text-decoration: none;
   }
 }
@@ -139,11 +149,21 @@
 
     &#{$infix} {
       @include media-breakpoint-down($breakpoint) {
-        > .container,
-        > .container-fluid {
+        %container-navbar-expand-#{$breakpoint} {
           padding-right: 0;
           padding-left: 0;
         }
+
+        > .container,
+        > .container-fluid {
+          @extend %container-navbar-expand-#{$breakpoint};
+        }
+
+        @each $size, $container-max-width in $container-max-widths {
+          > .container#{breakpoint-infix($size, $container-max-widths)} {
+            @extend %container-navbar-expand-#{$breakpoint};
+          }
+        }
       }
 
       @include media-breakpoint-up($next) {
@@ -164,9 +184,19 @@
         }
 
         // For nesting containers, have to redeclare for alignment purposes
+        %container-nesting-#{$breakpoint} {
+          flex-wrap: nowrap;
+        }
+
         > .container,
         > .container-fluid {
-          flex-wrap: nowrap;
+          @extend %container-nesting-#{$breakpoint};
+        }
+
+        @each $size, $container-max-width in $container-max-widths {
+          > .container#{breakpoint-infix($size, $container-max-widths)} {
+            @extend %container-nesting-#{$breakpoint};
+          }
         }
 
         .navbar-collapse {
@@ -194,7 +224,7 @@
   .navbar-brand {
     color: $navbar-light-brand-color;
 
-    @include hover-focus {
+    @include hover-focus() {
       color: $navbar-light-brand-hover-color;
     }
   }
@@ -203,7 +233,7 @@
     .nav-link {
       color: $navbar-light-color;
 
-      @include hover-focus {
+      @include hover-focus() {
         color: $navbar-light-hover-color;
       }
 
@@ -226,7 +256,7 @@
   }
 
   .navbar-toggler-icon {
-    background-image: $navbar-light-toggler-icon-bg;
+    background-image: escape-svg($navbar-light-toggler-icon-bg);
   }
 
   .navbar-text {
@@ -234,7 +264,7 @@
     a {
       color: $navbar-light-active-color;
 
-      @include hover-focus {
+      @include hover-focus() {
         color: $navbar-light-active-color;
       }
     }
@@ -246,7 +276,7 @@
   .navbar-brand {
     color: $navbar-dark-brand-color;
 
-    @include hover-focus {
+    @include hover-focus() {
       color: $navbar-dark-brand-hover-color;
     }
   }
@@ -255,7 +285,7 @@
     .nav-link {
       color: $navbar-dark-color;
 
-      @include hover-focus {
+      @include hover-focus() {
         color: $navbar-dark-hover-color;
       }
 
@@ -278,7 +308,7 @@
   }
 
   .navbar-toggler-icon {
-    background-image: $navbar-dark-toggler-icon-bg;
+    background-image: escape-svg($navbar-dark-toggler-icon-bg);
   }
 
   .navbar-text {
@@ -286,7 +316,7 @@
     a {
       color: $navbar-dark-active-color;
 
-      @include hover-focus {
+      @include hover-focus() {
         color: $navbar-dark-active-color;
       }
     }

+ 3 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_pagination.scss

@@ -11,6 +11,7 @@
   margin-left: -$pagination-border-width;
   line-height: $pagination-line-height;
   color: $pagination-color;
+  text-decoration: if($link-decoration == none, null, none);
   background-color: $pagination-bg;
   border: $pagination-border-width solid $pagination-border-color;
 
@@ -23,7 +24,7 @@
   }
 
   &:focus {
-    z-index: 2;
+    z-index: 3;
     outline: $pagination-focus-outline;
     box-shadow: $pagination-focus-box-shadow;
   }
@@ -43,7 +44,7 @@
   }
 
   &.active .page-link {
-    z-index: 1;
+    z-index: 3;
     color: $pagination-active-color;
     background-color: $pagination-active-bg;
     border-color: $pagination-active-border-color;

+ 8 - 9
coderedcms/static/coderedcms/vendor/bootstrap/scss/_popover.scss

@@ -22,7 +22,7 @@
     display: block;
     width: $popover-arrow-width;
     height: $popover-arrow-height;
-    margin: 0 $border-radius-lg;
+    margin: 0 $popover-border-radius;
 
     &::before,
     &::after {
@@ -39,7 +39,7 @@
   margin-bottom: $popover-arrow-height;
 
   > .arrow {
-    bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    bottom: subtract(-$popover-arrow-height, $popover-border-width);
 
     &::before {
       bottom: 0;
@@ -59,10 +59,10 @@
   margin-left: $popover-arrow-height;
 
   > .arrow {
-    left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    left: subtract(-$popover-arrow-height, $popover-border-width);
     width: $popover-arrow-height;
     height: $popover-arrow-width;
-    margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
+    margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners
 
     &::before {
       left: 0;
@@ -82,7 +82,7 @@
   margin-top: $popover-arrow-height;
 
   > .arrow {
-    top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    top: subtract(-$popover-arrow-height, $popover-border-width);
 
     &::before {
       top: 0;
@@ -114,10 +114,10 @@
   margin-right: $popover-arrow-height;
 
   > .arrow {
-    right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    right: subtract(-$popover-arrow-height, $popover-border-width);
     width: $popover-arrow-height;
     height: $popover-arrow-width;
-    margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
+    margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners
 
     &::before {
       right: 0;
@@ -157,8 +157,7 @@
   color: $popover-header-color;
   background-color: $popover-header-bg;
   border-bottom: $popover-border-width solid darken($popover-header-bg, 5%);
-  $offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width});
-  @include border-top-radius($offset-border-width);
+  @include border-top-radius($popover-inner-border-radius);
 
   &:empty {
     display: none;

+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_print.scss

@@ -1,6 +1,6 @@
 // stylelint-disable declaration-no-important, selector-no-qualifying-type
 
-// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
+// Source: https://github.com/h5bp/main.css/blob/master/src/_print.css
 
 // ==========================================================================
 // Print styles.
@@ -57,7 +57,7 @@
 
     //
     // Printing Tables:
-    // http://css-discuss.incutio.com/wiki/Printing_Tables
+    // https://web.archive.org/web/20180815150934/http://css-discuss.incutio.com/wiki/Printing_Tables
     //
 
     thead {

+ 6 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_progress.scss

@@ -10,6 +10,7 @@
   display: flex;
   height: $progress-height;
   overflow: hidden; // force rounded corners by cropping it
+  line-height: 0;
   @include font-size($progress-font-size);
   background-color: $progress-bg;
   @include border-radius($progress-border-radius);
@@ -20,6 +21,7 @@
   display: flex;
   flex-direction: column;
   justify-content: center;
+  overflow: hidden;
   color: $progress-bar-color;
   text-align: center;
   white-space: nowrap;
@@ -36,8 +38,10 @@
   .progress-bar-animated {
     animation: progress-bar-stripes $progress-bar-animation-timing;
 
-    @media (prefers-reduced-motion: reduce) {
-      animation: none;
+    @if $enable-prefers-reduced-motion-media-query {
+      @media (prefers-reduced-motion: reduce) {
+        animation: none;
+      }
     }
   }
 }

+ 24 - 27
coderedcms/static/coderedcms/vendor/bootstrap/scss/_reboot.scss

@@ -54,12 +54,16 @@ body {
   background-color: $body-bg; // 2
 }
 
-// Suppress the focus outline on elements that cannot be accessed via keyboard.
-// This prevents an unwanted focus outline from appearing around elements that
-// might still respond to pointer events.
-//
-// Credit: https://github.com/suitcss/base
-[tabindex="-1"]:focus {
+// Future-proof rule: in browsers that support :focus-visible, suppress the focus outline
+// on elements that programmatically receive focus but wouldn't normally show a visible
+// focus outline. In general, this would mean that the outline is only applied if the
+// interaction that led to the element receiving programmatic focus was a keyboard interaction,
+// or the browser has somehow determined that the user is primarily a keyboard user and/or
+// wants focus outlines to always be presented.
+//
+// See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible
+// and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/
+[tabindex="-1"]:focus:not(:focus-visible) {
   outline: 0 !important;
 }
 
@@ -184,30 +188,25 @@ a {
   text-decoration: $link-decoration;
   background-color: transparent; // Remove the gray background on active links in IE 10.
 
-  @include hover {
+  @include hover() {
     color: $link-hover-color;
     text-decoration: $link-hover-decoration;
   }
 }
 
-// And undo these styles for placeholder links/named anchors (without href)
-// which have not been made explicitly keyboard-focusable (without tabindex).
+// And undo these styles for placeholder links/named anchors (without href).
 // It would be more straightforward to just use a[href] in previous block, but that
 // causes specificity issues in many other styles that are too complex to fix.
 // See https://github.com/twbs/bootstrap/issues/19402
 
-a:not([href]):not([tabindex]) {
+a:not([href]) {
   color: inherit;
   text-decoration: none;
 
-  @include hover-focus {
+  @include hover() {
     color: inherit;
     text-decoration: none;
   }
-
-  &:focus {
-    outline: 0;
-  }
 }
 
 
@@ -230,6 +229,9 @@ pre {
   margin-bottom: 1rem;
   // Don't allow content to break outside
   overflow: auto;
+  // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,
+  // making it impossible to interact with the content
+  -ms-overflow-style: scrollbar;
 }
 
 
@@ -331,6 +333,13 @@ select {
   text-transform: none; // Remove the inheritance of text transform in Firefox
 }
 
+// Set the cursor for non-`<button>` buttons
+//
+// Details at https://github.com/twbs/bootstrap/pull/30562
+[role="button"] {
+  cursor: pointer;
+}
+
 // Remove the inheritance of word-wrap in Safari.
 //
 // Details at https://github.com/twbs/bootstrap/issues/24990
@@ -377,18 +386,6 @@ input[type="checkbox"] {
 }
 
 
-input[type="date"],
-input[type="time"],
-input[type="datetime-local"],
-input[type="month"] {
-  // Remove the default appearance of temporal inputs to avoid a Mobile Safari
-  // bug where setting a custom line-height prevents text from being vertically
-  // centered within the input.
-  // See https://bugs.webkit.org/show_bug.cgi?id=139848
-  // and https://github.com/twbs/bootstrap/issues/11266
-  -webkit-appearance: listbox;
-}
-
 textarea {
   overflow: auto; // Remove the default vertical scrollbar in IE.
   // Textareas should really only resize vertically so they don't break their (horizontal) containers.

+ 1 - 0
coderedcms/static/coderedcms/vendor/bootstrap/scss/_root.scss

@@ -1,3 +1,4 @@
+// Do not forget to update getting-started/theming.md!
 :root {
   // Custom variable values only support SassScript inside `#{}`.
   @each $color, $value in $colors {

+ 1 - 0
coderedcms/static/coderedcms/vendor/bootstrap/scss/_spinners.scss

@@ -34,6 +34,7 @@
   }
   50% {
     opacity: 1;
+    transform: none;
   }
 }
 

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/_tables.scss

@@ -84,7 +84,7 @@
 
 .table-hover {
   tbody tr {
-    @include hover {
+    @include hover() {
       color: $table-hover-color;
       background-color: $table-hover-bg;
     }
@@ -142,14 +142,14 @@
   }
 
   &.table-striped {
-    tbody tr:nth-of-type(odd) {
+    tbody tr:nth-of-type(#{$table-striped-order}) {
       background-color: $table-dark-accent-bg;
     }
   }
 
   &.table-hover {
     tbody tr {
-      @include hover {
+      @include hover() {
         color: $table-dark-hover-color;
         background-color: $table-dark-hover-bg;
       }

+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/_type.scss

@@ -82,12 +82,12 @@ mark,
 //
 
 .list-unstyled {
-  @include list-unstyled;
+  @include list-unstyled();
 }
 
 // Inline turns list items into inline-block
 .list-inline {
-  @include list-unstyled;
+  @include list-unstyled();
 }
 .list-inline-item {
   display: inline-block;

+ 2 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/_utilities.scss

@@ -6,12 +6,13 @@
 @import "utilities/embed";
 @import "utilities/flex";
 @import "utilities/float";
+@import "utilities/interactions";
 @import "utilities/overflow";
 @import "utilities/position";
 @import "utilities/screenreaders";
 @import "utilities/shadows";
 @import "utilities/sizing";
-@import "utilities/stretched-link";
 @import "utilities/spacing";
+@import "utilities/stretched-link";
 @import "utilities/text";
 @import "utilities/visibility";

+ 46 - 22
coderedcms/static/coderedcms/vendor/bootstrap/scss/_variables.scss

@@ -101,6 +101,15 @@ $yiq-contrasted-threshold:  150 !default;
 $yiq-text-dark:             $gray-900 !default;
 $yiq-text-light:            $white !default;
 
+// Characters which are escaped by the escape-svg function
+$escaped-characters: (
+  ("<","%3c"),
+  (">","%3e"),
+  ("#","%23"),
+  ("(","%28"),
+  (")","%29"),
+) !default;
+
 
 // Options
 //
@@ -220,6 +229,7 @@ $container-max-widths: (
 
 $grid-columns:                12 !default;
 $grid-gutter-width:           30px !default;
+$grid-row-columns:            6 !default;
 
 
 // Components
@@ -366,7 +376,6 @@ $table-dark-accent-bg:        rgba($white, .05) !default;
 $table-dark-hover-color:      $table-dark-color !default;
 $table-dark-hover-bg:         rgba($white, .075) !default;
 $table-dark-border-color:     lighten($table-dark-bg, 7.5%) !default;
-$table-dark-color:            $white !default;
 
 $table-striped-order:         odd !default;
 
@@ -412,6 +421,7 @@ $btn-padding-x:               $input-btn-padding-x !default;
 $btn-font-family:             $input-btn-font-family !default;
 $btn-font-size:               $input-btn-font-size !default;
 $btn-line-height:             $input-btn-line-height !default;
+$btn-white-space:             null !default; // Set to `nowrap` to prevent text wrapping
 
 $btn-padding-y-sm:            $input-btn-padding-y-sm !default;
 $btn-padding-x-sm:            $input-btn-padding-x-sm !default;
@@ -488,13 +498,13 @@ $input-plaintext-color:                 $body-color !default;
 
 $input-height-border:                   $input-border-width * 2 !default;
 
-$input-height-inner:                    calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;
-$input-height-inner-half:               calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;
-$input-height-inner-quarter:            calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;
+$input-height-inner:                    add($input-line-height * 1em, $input-padding-y * 2) !default;
+$input-height-inner-half:               add($input-line-height * .5em, $input-padding-y) !default;
+$input-height-inner-quarter:            add($input-line-height * .25em, $input-padding-y / 2) !default;
 
-$input-height:                          calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;
-$input-height-sm:                       calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;
-$input-height-lg:                       calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;
+$input-height:                          add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;
+$input-height-sm:                       add($input-line-height-sm * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;
+$input-height-lg:                       add($input-line-height-lg * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;
 
 $input-transition:                      border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
 
@@ -518,6 +528,7 @@ $custom-forms-transition:               background-color .15s ease-in-out, borde
 
 $custom-control-gutter:                 .5rem !default;
 $custom-control-spacer-x:               1rem !default;
+$custom-control-cursor:                 null !default;
 
 $custom-control-indicator-size:         1rem !default;
 $custom-control-indicator-bg:           $input-bg !default;
@@ -527,6 +538,8 @@ $custom-control-indicator-box-shadow:   $input-box-shadow !default;
 $custom-control-indicator-border-color: $gray-500 !default;
 $custom-control-indicator-border-width: $input-border-width !default;
 
+$custom-control-label-color:            null !default;
+
 $custom-control-indicator-disabled-bg:          $input-disabled-bg !default;
 $custom-control-label-disabled-color:           $gray-600 !default;
 
@@ -545,20 +558,20 @@ $custom-control-indicator-active-box-shadow:    none !default;
 $custom-control-indicator-active-border-color:  $custom-control-indicator-active-bg !default;
 
 $custom-checkbox-indicator-border-radius:       $border-radius !default;
-$custom-checkbox-indicator-icon-checked:        str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-checkbox-indicator-icon-checked:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'><path fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/></svg>") !default;
 
 $custom-checkbox-indicator-indeterminate-bg:           $component-active-bg !default;
 $custom-checkbox-indicator-indeterminate-color:        $custom-control-indicator-checked-color !default;
-$custom-checkbox-indicator-icon-indeterminate:         str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-checkbox-indicator-icon-indeterminate:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'><path stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/></svg>") !default;
 $custom-checkbox-indicator-indeterminate-box-shadow:   none !default;
 $custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;
 
 $custom-radio-indicator-border-radius:          50% !default;
-$custom-radio-indicator-icon-checked:           str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
+$custom-radio-indicator-icon-checked:           url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'><circle r='3' fill='#{$custom-control-indicator-checked-color}'/></svg>") !default;
 
 $custom-switch-width:                           $custom-control-indicator-size * 1.75 !default;
 $custom-switch-indicator-border-radius:         $custom-control-indicator-size / 2 !default;
-$custom-switch-indicator-size:                  calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;
+$custom-switch-indicator-size:                  subtract($custom-control-indicator-size, $custom-control-indicator-border-width * 4) !default;
 
 $custom-select-padding-y:           $input-padding-y !default;
 $custom-select-padding-x:           $input-padding-x !default;
@@ -574,10 +587,10 @@ $custom-select-bg:                  $input-bg !default;
 $custom-select-disabled-bg:         $gray-200 !default;
 $custom-select-bg-size:             8px 10px !default; // In pixels because image dimensions
 $custom-select-indicator-color:     $gray-800 !default;
-$custom-select-indicator:           str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e"), "#", "%23") !default;
-$custom-select-background:          $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
+$custom-select-indicator:           url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'><path fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/></svg>") !default;
+$custom-select-background:          escape-svg($custom-select-indicator) no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
 
-$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;
+$custom-select-feedback-icon-padding-right: add(1em * .75, (2 * $custom-select-padding-y * .75) + $custom-select-padding-x + $custom-select-indicator-padding) !default;
 $custom-select-feedback-icon-position:      center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;
 $custom-select-feedback-icon-size:          $input-height-inner-half $input-height-inner-half !default;
 
@@ -650,9 +663,9 @@ $form-feedback-valid-color:         theme-color("success") !default;
 $form-feedback-invalid-color:       theme-color("danger") !default;
 
 $form-feedback-icon-valid-color:    $form-feedback-valid-color !default;
-$form-feedback-icon-valid:          str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$form-feedback-icon-valid:          url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>") !default;
 $form-feedback-icon-invalid-color:  $form-feedback-invalid-color !default;
-$form-feedback-icon-invalid:        str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"), "#", "%23") !default;
+$form-feedback-icon-invalid:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='#{$form-feedback-icon-invalid-color}' viewBox='0 0 12 12'><circle cx='6' cy='6' r='4.5'/><path stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/><circle cx='6' cy='8.2' r='.6' fill='#{$form-feedback-icon-invalid-color}' stroke='none'/></svg>") !default;
 
 $form-validation-states: () !default;
 // stylelint-disable-next-line scss/dollar-variable-default
@@ -728,14 +741,14 @@ $navbar-dark-color:                 rgba($white, .5) !default;
 $navbar-dark-hover-color:           rgba($white, .75) !default;
 $navbar-dark-active-color:          $white !default;
 $navbar-dark-disabled-color:        rgba($white, .25) !default;
-$navbar-dark-toggler-icon-bg:       str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
+$navbar-dark-toggler-icon-bg:       url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'><path stroke='#{$navbar-dark-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-dark-toggler-border-color:  rgba($white, .1) !default;
 
 $navbar-light-color:                rgba($black, .5) !default;
 $navbar-light-hover-color:          rgba($black, .7) !default;
 $navbar-light-active-color:         rgba($black, .9) !default;
 $navbar-light-disabled-color:       rgba($black, .3) !default;
-$navbar-light-toggler-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
+$navbar-light-toggler-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'><path stroke='#{$navbar-light-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-light-toggler-border-color: rgba($black, .1) !default;
 
 $navbar-light-brand-color:                $navbar-light-active-color !default;
@@ -757,7 +770,7 @@ $dropdown-bg:                       $white !default;
 $dropdown-border-color:             rgba($black, .15) !default;
 $dropdown-border-radius:            $border-radius !default;
 $dropdown-border-width:             $border-width !default;
-$dropdown-inner-border-radius:      calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;
+$dropdown-inner-border-radius:      subtract($dropdown-border-radius, $dropdown-border-width) !default;
 $dropdown-divider-bg:               $gray-200 !default;
 $dropdown-divider-margin-y:         $nav-divider-margin-y !default;
 $dropdown-box-shadow:               0 .5rem 1rem rgba($black, .175) !default;
@@ -775,6 +788,7 @@ $dropdown-item-padding-y:           .25rem !default;
 $dropdown-item-padding-x:           1.5rem !default;
 
 $dropdown-header-color:             $gray-600 !default;
+$dropdown-header-padding:           $dropdown-padding-y $dropdown-item-padding-x !default;
 
 
 // Pagination
@@ -822,9 +836,10 @@ $card-spacer-x:                     1.25rem !default;
 $card-border-width:                 $border-width !default;
 $card-border-radius:                $border-radius !default;
 $card-border-color:                 rgba($black, .125) !default;
-$card-inner-border-radius:          calc(#{$card-border-radius} - #{$card-border-width}) !default;
+$card-inner-border-radius:          subtract($card-border-radius, $card-border-width) !default;
 $card-cap-bg:                       rgba($black, .03) !default;
 $card-cap-color:                    null !default;
+$card-height:                       null !default;
 $card-color:                        null !default;
 $card-bg:                           $white !default;
 
@@ -871,6 +886,7 @@ $popover-max-width:                 276px !default;
 $popover-border-width:              $border-width !default;
 $popover-border-color:              rgba($black, .2) !default;
 $popover-border-radius:             $border-radius-lg !default;
+$popover-inner-border-radius:       subtract($popover-border-radius, $popover-border-width) !default;
 $popover-box-shadow:                0 .25rem .5rem rgba($black, .2) !default;
 
 $popover-header-bg:                 darken($popover-bg, 3%) !default;
@@ -929,6 +945,9 @@ $badge-pill-border-radius:          10rem !default;
 // Padding applied to the modal body
 $modal-inner-padding:               1rem !default;
 
+// Margin between elements in footer, must be lower than or equal to 2 * $modal-inner-padding
+$modal-footer-margin-between:       .5rem !default;
+
 $modal-dialog-margin:               .5rem !default;
 $modal-dialog-margin-y-sm-up:       1.75rem !default;
 
@@ -939,6 +958,7 @@ $modal-content-bg:                  $white !default;
 $modal-content-border-color:        rgba($black, .2) !default;
 $modal-content-border-width:        $border-width !default;
 $modal-content-border-radius:       $border-radius-lg !default;
+$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default;
 $modal-content-box-shadow-xs:       0 .25rem .5rem rgba($black, .5) !default;
 $modal-content-box-shadow-sm-up:    0 .5rem 1rem rgba($black, .5) !default;
 
@@ -960,6 +980,7 @@ $modal-sm:                          300px !default;
 $modal-fade-transform:              translate(0, -50px) !default;
 $modal-show-transform:              none !default;
 $modal-transition:                  transform .3s ease-out !default;
+$modal-scale-transform:             scale(1.02) !default;
 
 
 // Alerts
@@ -1035,6 +1056,8 @@ $figure-caption-color:              $gray-600 !default;
 
 // Breadcrumbs
 
+$breadcrumb-font-size:              null !default;
+
 $breadcrumb-padding-y:              .75rem !default;
 $breadcrumb-padding-x:              1rem !default;
 $breadcrumb-item-padding:           .5rem !default;
@@ -1069,8 +1092,8 @@ $carousel-caption-color:             $white !default;
 
 $carousel-control-icon-width:        20px !default;
 
-$carousel-control-prev-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"), "#", "%23") !default;
-$carousel-control-next-icon-bg:      str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"), "#", "%23") !default;
+$carousel-control-prev-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' width='8' height='8' viewBox='0 0 8 8'><path d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/></svg>") !default;
+$carousel-control-next-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' width='8' height='8' viewBox='0 0 8 8'><path d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/></svg>") !default;
 
 $carousel-transition-duration:       .6s !default;
 $carousel-transition:                transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
@@ -1115,6 +1138,7 @@ $pre-scrollable-max-height:         340px !default;
 $displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;
 $overflows: auto, hidden !default;
 $positions: static, relative, absolute, fixed, sticky !default;
+$user-selects: all, auto, none !default;
 
 
 // Printing

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap-grid.scss

@@ -1,7 +1,7 @@
 /*!
- * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
 

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap-reboot.scss

@@ -1,7 +1,7 @@
 /*!
- * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
  */

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/bootstrap.scss

@@ -1,7 +1,7 @@
 /*!
- * Bootstrap v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
 

+ 5 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_background-variant.scss

@@ -2,20 +2,22 @@
 
 // Contextual backgrounds
 
-@mixin bg-variant($parent, $color) {
+@mixin bg-variant($parent, $color, $ignore-warning: false) {
   #{$parent} {
     background-color: $color !important;
   }
   a#{$parent},
   button#{$parent} {
-    @include hover-focus {
+    @include hover-focus() {
       background-color: darken($color, 10%) !important;
     }
   }
+  @include deprecate("The `bg-variant` mixin", "v4.4.0", "v5", $ignore-warning);
 }
 
-@mixin bg-gradient-variant($parent, $color) {
+@mixin bg-gradient-variant($parent, $color, $ignore-warning: false) {
   #{$parent} {
     background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;
   }
+  @include deprecate("The `bg-gradient-variant` mixin", "v4.5.0", "v5", $ignore-warning);
 }

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_badge.scss

@@ -3,7 +3,7 @@
   background-color: $bg;
 
   @at-root a#{&} {
-    @include hover-focus {
+    @include hover-focus() {
       color: color-yiq($bg);
       background-color: darken($bg, 10%);
     }

+ 26 - 13
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_border-radius.scss

@@ -1,9 +1,22 @@
 // stylelint-disable property-blacklist
 // Single side border-radius
 
+// Helper function to replace negative values with 0
+@function valid-radius($radius) {
+  $return: ();
+  @each $value in $radius {
+    @if type-of($value) == number {
+      $return: append($return, max($value, 0));
+    } @else {
+      $return: append($return, $value);
+    }
+  }
+  @return $return;
+}
+
 @mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {
   @if $enable-rounded {
-    border-radius: $radius;
+    border-radius: valid-radius($radius);
   }
   @else if $fallback-border-radius != false {
     border-radius: $fallback-border-radius;
@@ -12,52 +25,52 @@
 
 @mixin border-top-radius($radius) {
   @if $enable-rounded {
-    border-top-left-radius: $radius;
-    border-top-right-radius: $radius;
+    border-top-left-radius: valid-radius($radius);
+    border-top-right-radius: valid-radius($radius);
   }
 }
 
 @mixin border-right-radius($radius) {
   @if $enable-rounded {
-    border-top-right-radius: $radius;
-    border-bottom-right-radius: $radius;
+    border-top-right-radius: valid-radius($radius);
+    border-bottom-right-radius: valid-radius($radius);
   }
 }
 
 @mixin border-bottom-radius($radius) {
   @if $enable-rounded {
-    border-bottom-right-radius: $radius;
-    border-bottom-left-radius: $radius;
+    border-bottom-right-radius: valid-radius($radius);
+    border-bottom-left-radius: valid-radius($radius);
   }
 }
 
 @mixin border-left-radius($radius) {
   @if $enable-rounded {
-    border-top-left-radius: $radius;
-    border-bottom-left-radius: $radius;
+    border-top-left-radius: valid-radius($radius);
+    border-bottom-left-radius: valid-radius($radius);
   }
 }
 
 @mixin border-top-left-radius($radius) {
   @if $enable-rounded {
-    border-top-left-radius: $radius;
+    border-top-left-radius: valid-radius($radius);
   }
 }
 
 @mixin border-top-right-radius($radius) {
   @if $enable-rounded {
-    border-top-right-radius: $radius;
+    border-top-right-radius: valid-radius($radius);
   }
 }
 
 @mixin border-bottom-right-radius($radius) {
   @if $enable-rounded {
-    border-bottom-right-radius: $radius;
+    border-bottom-right-radius: valid-radius($radius);
   }
 }
 
 @mixin border-bottom-left-radius($radius) {
   @if $enable-rounded {
-    border-bottom-left-radius: $radius;
+    border-bottom-left-radius: valid-radius($radius);
   }
 }

+ 11 - 8
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_buttons.scss

@@ -9,7 +9,7 @@
   border-color: $border;
   @include box-shadow($btn-box-shadow);
 
-  @include hover {
+  @include hover() {
     color: color-yiq($hover-background);
     @include gradient-bg($hover-background);
     border-color: $hover-border;
@@ -17,10 +17,13 @@
 
   &:focus,
   &.focus {
-    // Avoid using mixin so we can pass custom focus shadow properly
+    color: color-yiq($hover-background);
+    @include gradient-bg($hover-background);
+    border-color: $hover-border;
     @if $enable-shadows {
-      box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
+      @include box-shadow($btn-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5));
     } @else {
+      // Avoid using mixin so we can pass custom focus shadow properly
       box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
     }
   }
@@ -48,10 +51,10 @@
     border-color: $active-border;
 
     &:focus {
-      // Avoid using mixin so we can pass custom focus shadow properly
       @if $enable-shadows and $btn-active-box-shadow != none {
-        box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
+        @include box-shadow($btn-active-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5));
       } @else {
+        // Avoid using mixin so we can pass custom focus shadow properly
         box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
       }
     }
@@ -62,7 +65,7 @@
   color: $color;
   border-color: $color;
 
-  @include hover {
+  @include hover() {
     color: $color-hover;
     background-color: $active-background;
     border-color: $active-border;
@@ -87,10 +90,10 @@
     border-color: $active-border;
 
     &:focus {
-      // Avoid using mixin so we can pass custom focus shadow properly
       @if $enable-shadows and $btn-active-box-shadow != none {
-        box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5);
+        @include box-shadow($btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5));
       } @else {
+        // Avoid using mixin so we can pass custom focus shadow properly
         box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
       }
     }

+ 8 - 8
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_caret.scss

@@ -1,25 +1,25 @@
-@mixin caret-down {
+@mixin caret-down() {
   border-top: $caret-width solid;
   border-right: $caret-width solid transparent;
   border-bottom: 0;
   border-left: $caret-width solid transparent;
 }
 
-@mixin caret-up {
+@mixin caret-up() {
   border-top: 0;
   border-right: $caret-width solid transparent;
   border-bottom: $caret-width solid;
   border-left: $caret-width solid transparent;
 }
 
-@mixin caret-right {
+@mixin caret-right() {
   border-top: $caret-width solid transparent;
   border-right: 0;
   border-bottom: $caret-width solid transparent;
   border-left: $caret-width solid;
 }
 
-@mixin caret-left {
+@mixin caret-left() {
   border-top: $caret-width solid transparent;
   border-right: $caret-width solid;
   border-bottom: $caret-width solid transparent;
@@ -33,11 +33,11 @@
       vertical-align: $caret-vertical-align;
       content: "";
       @if $direction == down {
-        @include caret-down;
+        @include caret-down();
       } @else if $direction == up {
-        @include caret-up;
+        @include caret-up();
       } @else if $direction == right {
-        @include caret-right;
+        @include caret-right();
       }
     }
 
@@ -51,7 +51,7 @@
         margin-right: $caret-spacing;
         vertical-align: $caret-vertical-align;
         content: "";
-        @include caret-left;
+        @include caret-left();
       }
     }
 

+ 3 - 3
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_float.scss

@@ -1,14 +1,14 @@
 // stylelint-disable declaration-no-important
 
-@mixin float-left {
+@mixin float-left() {
   float: left !important;
   @include deprecate("The `float-left` mixin", "v4.3.0", "v5");
 }
-@mixin float-right {
+@mixin float-right() {
   float: right !important;
   @include deprecate("The `float-right` mixin", "v4.3.0", "v5");
 }
-@mixin float-none {
+@mixin float-none() {
   float: none !important;
   @include deprecate("The `float-none` mixin", "v4.3.0", "v5");
 }

+ 34 - 49
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_forms.scss

@@ -10,21 +10,36 @@
 //
 // Example usage: change the default blue border and shadow to white for better
 // contrast against a dark gray background.
-@mixin form-control-focus() {
+@mixin form-control-focus($ignore-warning: false) {
   &:focus {
     color: $input-focus-color;
     background-color: $input-focus-bg;
     border-color: $input-focus-border-color;
     outline: 0;
-    // Avoid using mixin so we can pass custom focus shadow properly
     @if $enable-shadows {
-      box-shadow: $input-box-shadow, $input-focus-box-shadow;
+      @include box-shadow($input-box-shadow, $input-focus-box-shadow);
     } @else {
+      // Avoid using mixin so we can pass custom focus shadow properly
       box-shadow: $input-focus-box-shadow;
     }
   }
+  @include deprecate("The `form-control-focus()` mixin", "v4.4.0", "v5", $ignore-warning);
 }
 
+// This mixin uses an `if()` technique to be compatible with Dart Sass
+// See https://github.com/sass/sass/issues/1873#issuecomment-152293725 for more details
+@mixin form-validation-state-selector($state) {
+  @if ($state == "valid" or $state == "invalid") {
+    .was-validated #{if(&, "&", "")}:#{$state},
+    #{if(&, "&", "")}.is-#{$state} {
+      @content;
+    }
+  } @else {
+    #{if(&, "&", "")}.is-#{$state} {
+      @content;
+    }
+  }
+}
 
 @mixin form-validation-state($state, $color, $icon) {
   .#{$state}-feedback {
@@ -50,16 +65,22 @@
     @include border-radius($form-feedback-tooltip-border-radius);
   }
 
+  @include form-validation-state-selector($state) {
+    ~ .#{$state}-feedback,
+    ~ .#{$state}-tooltip {
+      display: block;
+    }
+  }
+
   .form-control {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       border-color: $color;
 
       @if $enable-validation-icons {
         padding-right: $input-height-inner;
-        background-image: $icon;
+        background-image: escape-svg($icon);
         background-repeat: no-repeat;
-        background-position: center right $input-height-inner-quarter;
+        background-position: right $input-height-inner-quarter center;
         background-size: $input-height-inner-half $input-height-inner-half;
       }
 
@@ -67,18 +88,12 @@
         border-color: $color;
         box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
       }
-
-      ~ .#{$state}-feedback,
-      ~ .#{$state}-tooltip {
-        display: block;
-      }
     }
   }
 
   // stylelint-disable-next-line selector-no-qualifying-type
   textarea.form-control {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       @if $enable-validation-icons {
         padding-right: $input-height-inner;
         background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
@@ -87,41 +102,23 @@
   }
 
   .custom-select {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       border-color: $color;
 
       @if $enable-validation-icons {
         padding-right: $custom-select-feedback-icon-padding-right;
-        background: $custom-select-background, $icon $custom-select-bg no-repeat $custom-select-feedback-icon-position / $custom-select-feedback-icon-size;
+        background: $custom-select-background, escape-svg($icon) $custom-select-bg no-repeat $custom-select-feedback-icon-position / $custom-select-feedback-icon-size;
       }
 
       &:focus {
         border-color: $color;
         box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
       }
-
-      ~ .#{$state}-feedback,
-      ~ .#{$state}-tooltip {
-        display: block;
-      }
-    }
-  }
-
-
-  .form-control-file {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
-      ~ .#{$state}-feedback,
-      ~ .#{$state}-tooltip {
-        display: block;
-      }
     }
   }
 
   .form-check-input {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       ~ .form-check-label {
         color: $color;
       }
@@ -134,8 +131,7 @@
   }
 
   .custom-control-input {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       ~ .custom-control-label {
         color: $color;
 
@@ -144,11 +140,6 @@
         }
       }
 
-      ~ .#{$state}-feedback,
-      ~ .#{$state}-tooltip {
-        display: block;
-      }
-
       &:checked {
         ~ .custom-control-label::before {
           border-color: lighten($color, 10%);
@@ -170,17 +161,11 @@
 
   // custom file
   .custom-file-input {
-    .was-validated &:#{$state},
-    &.is-#{$state} {
+    @include form-validation-state-selector($state) {
       ~ .custom-file-label {
         border-color: $color;
       }
 
-      ~ .#{$state}-feedback,
-      ~ .#{$state}-tooltip {
-        display: block;
-      }
-
       &:focus {
         ~ .custom-file-label {
           border-color: $color;

+ 30 - 15
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_grid-framework.scss

@@ -15,12 +15,15 @@
   @each $breakpoint in map-keys($breakpoints) {
     $infix: breakpoint-infix($breakpoint, $breakpoints);
 
-    // Allow columns to stretch full width below their breakpoints
-    @for $i from 1 through $columns {
-      .col#{$infix}-#{$i} {
-        @extend %grid-column;
+    @if $columns > 0 {
+      // Allow columns to stretch full width below their breakpoints
+      @for $i from 1 through $columns {
+        .col#{$infix}-#{$i} {
+          @extend %grid-column;
+        }
       }
     }
+
     .col#{$infix},
     .col#{$infix}-auto {
       @extend %grid-column;
@@ -31,17 +34,27 @@
       .col#{$infix} {
         flex-basis: 0;
         flex-grow: 1;
+        min-width: 0; // See https://github.com/twbs/bootstrap/issues/25410
         max-width: 100%;
       }
+
+      @if $grid-row-columns > 0 {
+        @for $i from 1 through $grid-row-columns {
+          .row-cols#{$infix}-#{$i} {
+            @include row-cols($i);
+          }
+        }
+      }
+
       .col#{$infix}-auto {
-        flex: 0 0 auto;
-        width: auto;
-        max-width: 100%; // Reset earlier grid tiers
+        @include make-col-auto();
       }
 
-      @for $i from 1 through $columns {
-        .col#{$infix}-#{$i} {
-          @include make-col($i, $columns);
+      @if $columns > 0 {
+        @for $i from 1 through $columns {
+          .col#{$infix}-#{$i} {
+            @include make-col($i, $columns);
+          }
         }
       }
 
@@ -53,11 +66,13 @@
         .order#{$infix}-#{$i} { order: $i; }
       }
 
-      // `$columns - 1` because offsetting by the width of an entire row isn't possible
-      @for $i from 0 through ($columns - 1) {
-        @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
-          .offset#{$infix}-#{$i} {
-            @include make-col-offset($i, $columns);
+      @if $columns > 0 {
+        // `$columns - 1` because offsetting by the width of an entire row isn't possible
+        @for $i from 0 through ($columns - 1) {
+          @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
+            .offset#{$infix}-#{$i} {
+              @include make-col-offset($i, $columns);
+            }
           }
         }
       }

+ 18 - 0
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_grid.scss

@@ -45,7 +45,25 @@
   max-width: percentage($size / $columns);
 }
 
+@mixin make-col-auto() {
+  flex: 0 0 auto;
+  width: auto;
+  max-width: 100%; // Reset earlier grid tiers
+}
+
 @mixin make-col-offset($size, $columns: $grid-columns) {
   $num: $size / $columns;
   margin-left: if($num == 0, 0, percentage($num));
 }
+
+// Row columns
+//
+// Specify on a parent element(e.g., .row) to force immediate children into NN
+// numberof columns. Supports wrapping to new lines, but does not do a Masonry
+// style grid.
+@mixin row-cols($count) {
+  & > * {
+    flex: 0 0 100% / $count;
+    max-width: 100% / $count;
+  }
+}

+ 4 - 4
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_hover.scss

@@ -9,18 +9,18 @@
 //
 // Issue: https://github.com/twbs/bootstrap/issues/25195
 
-@mixin hover {
+@mixin hover() {
   &:hover { @content; }
 }
 
-@mixin hover-focus {
+@mixin hover-focus() {
   &:hover,
   &:focus {
     @content;
   }
 }
 
-@mixin plain-hover-focus {
+@mixin plain-hover-focus() {
   &,
   &:hover,
   &:focus {
@@ -28,7 +28,7 @@
   }
 }
 
-@mixin hover-focus-active {
+@mixin hover-focus-active() {
   &:hover,
   &:focus,
   &:active {

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_image.scss

@@ -7,7 +7,7 @@
 //
 // Keep images from scaling beyond the width of their parents.
 
-@mixin img-fluid {
+@mixin img-fluid() {
   // Part 1: Set a maximum relative to the parent
   max-width: 100%;
   // Part 2: Override the height to auto, otherwise images will be stretched

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_list-group.scss

@@ -6,7 +6,7 @@
     background-color: $background;
 
     &.list-group-item-action {
-      @include hover-focus {
+      @include hover-focus() {
         color: $color;
         background-color: darken($background, 5%);
       }

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_lists.scss

@@ -1,7 +1,7 @@
 // Lists
 
 // Unstyled keeps list items block level, just removes default browser padding and list-style
-@mixin list-unstyled {
+@mixin list-unstyled() {
   padding-left: 0;
   list-style: none;
 }

+ 2 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_nav-divider.scss

@@ -2,9 +2,10 @@
 //
 // Dividers (basically an hr) within dropdowns and nav lists
 
-@mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y) {
+@mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y, $ignore-warning: false) {
   height: 0;
   margin: $margin-y 0;
   overflow: hidden;
   border-top: 1px solid $color;
+  @include deprecate("The `nav-divider()` mixin", "v4.4.0", "v5", $ignore-warning);
 }

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_reset-text.scss

@@ -1,4 +1,4 @@
-@mixin reset-text {
+@mixin reset-text() {
   font-family: $font-family-base;
   // We deliberately do NOT reset font-size or word-wrap.
   font-style: normal;

+ 3 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_screen-reader.scss

@@ -3,11 +3,12 @@
 // See: https://a11yproject.com/posts/how-to-hide-content/
 // See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
 
-@mixin sr-only {
+@mixin sr-only() {
   position: absolute;
   width: 1px;
   height: 1px;
   padding: 0;
+  margin: -1px; // Fix for https://github.com/twbs/bootstrap/issues/25686
   overflow: hidden;
   clip: rect(0, 0, 0, 0);
   white-space: nowrap;
@@ -20,7 +21,7 @@
 //
 // Credit: HTML5 Boilerplate
 
-@mixin sr-only-focusable {
+@mixin sr-only-focusable() {
   &:active,
   &:focus {
     position: static;

+ 1 - 1
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_table-row.scss

@@ -26,7 +26,7 @@
     $hover-background: darken($background, 5%);
 
     .table-#{$state} {
-      @include hover {
+      @include hover() {
         background-color: $hover-background;
 
         > td,

+ 3 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_text-emphasis.scss

@@ -2,15 +2,16 @@
 
 // Typography
 
-@mixin text-emphasis-variant($parent, $color) {
+@mixin text-emphasis-variant($parent, $color, $ignore-warning: false) {
   #{$parent} {
     color: $color !important;
   }
   @if $emphasized-link-hover-darken-percentage != 0 {
     a#{$parent} {
-      @include hover-focus {
+      @include hover-focus() {
         color: darken($color, $emphasized-link-hover-darken-percentage) !important;
       }
     }
   }
+  @include deprecate("`text-emphasis-variant()`", "v4.4.0", "v5", $ignore-warning);
 }

+ 17 - 7
coderedcms/static/coderedcms/vendor/bootstrap/scss/mixins/_transition.scss

@@ -1,16 +1,26 @@
 // stylelint-disable property-blacklist
 @mixin transition($transition...) {
+  @if length($transition) == 0 {
+    $transition: $transition-base;
+  }
+
+  @if length($transition) > 1 {
+    @each $value in $transition {
+      @if $value == null or $value == none {
+        @warn "The keyword 'none' or 'null' must be used as a single argument.";
+      }
+    }
+  }
+
   @if $enable-transitions {
-    @if length($transition) == 0 {
-      transition: $transition-base;
-    } @else {
+    @if nth($transition, 1) != null {
       transition: $transition;
     }
-  }
 
-  @if $enable-prefers-reduced-motion-media-query {
-    @media (prefers-reduced-motion: reduce) {
-      transition: none;
+    @if $enable-prefers-reduced-motion-media-query and nth($transition, 1) != null and nth($transition, 1) != none {
+      @media (prefers-reduced-motion: reduce) {
+        transition: none;
+      }
     }
   }
 }

+ 2 - 2
coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_background.scss

@@ -1,12 +1,12 @@
 // stylelint-disable declaration-no-important
 
 @each $color, $value in $theme-colors {
-  @include bg-variant(".bg-#{$color}", $value);
+  @include bg-variant(".bg-#{$color}", $value, true);
 }
 
 @if $enable-gradients {
   @each $color, $value in $theme-colors {
-    @include bg-gradient-variant(".bg-gradient-#{$color}", $value);
+    @include bg-gradient-variant(".bg-gradient-#{$color}", $value, true);
   }
 }
 

+ 5 - 0
coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_interactions.scss

@@ -0,0 +1,5 @@
+// stylelint-disable declaration-no-important
+
+@each $value in $user-selects {
+  .user-select-#{$value} { user-select: $value !important; }
+}

+ 3 - 4
coderedcms/static/coderedcms/vendor/bootstrap/scss/utilities/_text.scss

@@ -11,7 +11,7 @@
 .text-justify  { text-align: justify !important; }
 .text-wrap     { white-space: normal !important; }
 .text-nowrap   { white-space: nowrap !important; }
-.text-truncate { @include text-truncate; }
+.text-truncate { @include text-truncate(); }
 
 // Responsive alignment
 
@@ -45,7 +45,7 @@
 .text-white { color: $white !important; }
 
 @each $color, $value in $theme-colors {
-  @include text-emphasis-variant(".text-#{$color}", $value);
+  @include text-emphasis-variant(".text-#{$color}", $value, true);
 }
 
 .text-body { color: $body-color !important; }
@@ -63,8 +63,7 @@
 .text-decoration-none { text-decoration: none !important; }
 
 .text-break {
-  word-break: break-word !important; // IE & < Edge 18
-  overflow-wrap: break-word !important;
+  word-wrap: break-word !important;
 }
 
 // Reset

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 1
coderedcms/static/coderedcms/vendor/jquery/jquery-3.4.1.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/jquery/jquery-3.4.1.min.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 265 - 157
coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
coderedcms/static/coderedcms/vendor/jquery/jquery-3.5.1.min.map


+ 1 - 1
coderedcms/templates/coderedcms/pages/base.html

@@ -168,7 +168,7 @@
         {% block footer %}{% endblock %}
 
         {% block required_scripts %}
-        <script src="{% static 'coderedcms/vendor/jquery/jquery-3.4.1.min.js' %}" ></script>
+        <script src="{% static 'coderedcms/vendor/jquery/jquery-3.5.1.min.js' %}" ></script>
         {% endblock %}
 
         {% block frontend_scripts %}

+ 14 - 0
docs/contributing/index.rst

@@ -112,6 +112,20 @@ license header comment states copyright, ownership, license, and also provides c
     /* @license-end */
 
 
+Upgrading 3rd-Party CSS/JavaScript Libraries
+--------------------------------------------
+
+External front-end libraries are included in two places:
+* Source or distributables are in ``coderedcms/static/coderedcms/vendor/``.
+* Referenced via a CDN in ``coderedcms/static/coderedcms/codered-front.js``.
+
+To upgrade, replace the relevant files or links in these two sources. Then be
+sure to change any URLs if applicable within the ``base.html`` template.
+
+If changing SASS sources, be sure to test ``.scss`` files in
+``coderedcms/project_template/sass/`` which may require changes.
+
+
 Testing CodeRed CMS
 -------------------
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác