Quellcode durchsuchen

Merge https://github.com/gcushen/hugo-academic

Xℹ Ruoyao vor 5 Jahren
Ursprung
Commit
6cb70207b8
100 geänderte Dateien mit 1309 neuen und 712 gelöschten Zeilen
  1. 1 1
      .editorconfig
  2. 43 0
      .github/contributing.md
  3. 3 1
      .gitignore
  4. 4 5
      README.md
  5. 68 0
      archetypes/authors/_index.md
  6. BIN
      archetypes/authors/avatar.jpg
  7. 0 0
      assets/images/icon.png
  8. 314 160
      assets/js/academic.js
  9. 1 1
      assets/js/vendor/bootstrap.min.js
  10. 1 4
      assets/scss/academic/_content.scss
  11. 0 5
      assets/scss/academic/_dark.scss
  12. 2 1
      assets/scss/academic/_docs.scss
  13. 158 154
      assets/scss/academic/_nav.scss
  14. 7 2
      assets/scss/academic/_root.scss
  15. 20 5
      assets/scss/academic/_widgets.scss
  16. 10 0
      assets/scss/bootstrap_variables.scss
  17. 4 4
      assets/scss/main.scss
  18. 1 1
      assets/scss/vendor/bootstrap/_badge.scss
  19. 2 1
      assets/scss/vendor/bootstrap/_breadcrumb.scss
  20. 1 1
      assets/scss/vendor/bootstrap/_button-group.scss
  21. 4 2
      assets/scss/vendor/bootstrap/_buttons.scss
  22. 17 28
      assets/scss/vendor/bootstrap/_card.scss
  23. 6 6
      assets/scss/vendor/bootstrap/_carousel.scss
  24. 2 2
      assets/scss/vendor/bootstrap/_close.scss
  25. 1 1
      assets/scss/vendor/bootstrap/_code.scss
  26. 22 8
      assets/scss/vendor/bootstrap/_custom-forms.scss
  27. 3 3
      assets/scss/vendor/bootstrap/_dropdown.scss
  28. 17 9
      assets/scss/vendor/bootstrap/_forms.scss
  29. 49 1
      assets/scss/vendor/bootstrap/_functions.scss
  30. 25 8
      assets/scss/vendor/bootstrap/_grid.scss
  31. 2 2
      assets/scss/vendor/bootstrap/_images.scss
  32. 2 4
      assets/scss/vendor/bootstrap/_input-group.scss
  33. 31 22
      assets/scss/vendor/bootstrap/_list-group.scss
  34. 3 3
      assets/scss/vendor/bootstrap/_mixins.scss
  35. 26 16
      assets/scss/vendor/bootstrap/_modal.scss
  36. 3 3
      assets/scss/vendor/bootstrap/_nav.scss
  37. 45 15
      assets/scss/vendor/bootstrap/_navbar.scss
  38. 2 2
      assets/scss/vendor/bootstrap/_pagination.scss
  39. 8 9
      assets/scss/vendor/bootstrap/_popover.scss
  40. 2 2
      assets/scss/vendor/bootstrap/_print.scss
  41. 5 2
      assets/scss/vendor/bootstrap/_progress.scss
  42. 14 15
      assets/scss/vendor/bootstrap/_reboot.scss
  43. 1 0
      assets/scss/vendor/bootstrap/_root.scss
  44. 3 3
      assets/scss/vendor/bootstrap/_tables.scss
  45. 2 2
      assets/scss/vendor/bootstrap/_type.scss
  46. 42 22
      assets/scss/vendor/bootstrap/_variables.scss
  47. 1 1
      assets/scss/vendor/bootstrap/bootstrap-grid.scss
  48. 1 1
      assets/scss/vendor/bootstrap/bootstrap-reboot.scss
  49. 1 1
      assets/scss/vendor/bootstrap/bootstrap.scss
  50. 3 2
      assets/scss/vendor/bootstrap/mixins/_background-variant.scss
  51. 1 1
      assets/scss/vendor/bootstrap/mixins/_badge.scss
  52. 5 2
      assets/scss/vendor/bootstrap/mixins/_buttons.scss
  53. 8 8
      assets/scss/vendor/bootstrap/mixins/_caret.scss
  54. 3 3
      assets/scss/vendor/bootstrap/mixins/_float.scss
  55. 32 47
      assets/scss/vendor/bootstrap/mixins/_forms.scss
  56. 8 3
      assets/scss/vendor/bootstrap/mixins/_grid-framework.scss
  57. 18 0
      assets/scss/vendor/bootstrap/mixins/_grid.scss
  58. 4 4
      assets/scss/vendor/bootstrap/mixins/_hover.scss
  59. 1 1
      assets/scss/vendor/bootstrap/mixins/_image.scss
  60. 1 1
      assets/scss/vendor/bootstrap/mixins/_list-group.scss
  61. 1 1
      assets/scss/vendor/bootstrap/mixins/_lists.scss
  62. 2 1
      assets/scss/vendor/bootstrap/mixins/_nav-divider.scss
  63. 1 1
      assets/scss/vendor/bootstrap/mixins/_reset-text.scss
  64. 3 2
      assets/scss/vendor/bootstrap/mixins/_screen-reader.scss
  65. 1 1
      assets/scss/vendor/bootstrap/mixins/_table-row.scss
  66. 3 2
      assets/scss/vendor/bootstrap/mixins/_text-emphasis.scss
  67. 1 1
      assets/scss/vendor/bootstrap/utilities/_background.scss
  68. 2 2
      assets/scss/vendor/bootstrap/utilities/_text.scss
  69. 1 1
      data/academic.toml
  70. 21 7
      data/assets.toml
  71. 6 0
      data/i18n/languages.yaml
  72. 11 7
      exampleSite/config/_default/config.toml
  73. 31 13
      exampleSite/config/_default/params.toml
  74. 5 5
      exampleSite/content/authors/admin/_index.md
  75. 4 0
      exampleSite/content/home/featured.md
  76. 4 1
      exampleSite/content/home/hero.md
  77. 1 0
      exampleSite/content/home/posts.md
  78. 1 0
      exampleSite/content/home/publications.md
  79. 1 1
      exampleSite/content/home/skills.md
  80. 1 0
      exampleSite/content/home/talks.md
  81. 134 51
      exampleSite/content/post/writing-technical-content/index.md
  82. 4 4
      exampleSite/content/slides/example/index.md
  83. 5 0
      exampleSite/resources/_gen/assets/scss/scss/main.scss_6c95cc1249b26b124274204dbf970c34.content
  84. 1 0
      exampleSite/resources/_gen/assets/scss/scss/main.scss_6c95cc1249b26b124274204dbf970c34.json
  85. BIN
      exampleSite/resources/_gen/images/authors/admin/avatar_hu52a603635ecebd45650b162dadabb4e5_12861_270x270_fill_q90_lanczos_center.jpg
  86. BIN
      exampleSite/resources/_gen/images/authors/admin2/avatar_hu52a603635ecebd45650b162dadabb4e5_12861_270x270_fill_q90_lanczos_center.jpg
  87. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-1950s_huaf5482f8cea0c5a703a328640e3b7509_21614_0x190_resize_lanczos_2.png
  88. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-apogee_hu4b45d99db97150df01464c393bfd17d4_24119_0x190_resize_lanczos_2.png
  89. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-coffee-playfair_hu446a8f670cc5622adcc77b97ba95f6c5_22462_0x190_resize_lanczos_2.png
  90. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-dark_hu1e8601ecc47f58eada7743fdcd709d3d_21456_0x190_resize_lanczos_2.png
  91. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-default_huba6228b7bdf30e2f03f12ea91b2cba0d_21751_0x190_resize_lanczos_2.png
  92. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-forest_hu4f093a1c683134431456584193ea41ee_21797_0x190_resize_lanczos_2.png
  93. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-ocean_hu14831ccafc2219f30a7a096fa7617e01_21760_0x190_resize_lanczos_2.png
  94. BIN
      exampleSite/resources/_gen/images/home/gallery/gallery/theme-strawberry_hu36b0b347fcca08bd39e2df22dcedbdfb_39532_0x190_resize_lanczos_2.png
  95. BIN
      exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_192x192_fill_lanczos_center_2.png
  96. BIN
      exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_32x32_fill_lanczos_center_2.png
  97. BIN
      exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_512x512_fill_lanczos_center_2.png
  98. BIN
      exampleSite/resources/_gen/images/post/getting-started/featured_hub9ee31969f44a6711206a2baf9f065b4_241861_1200x0_resize_q90_lanczos.jpg
  99. BIN
      exampleSite/resources/_gen/images/post/getting-started/featured_hub9ee31969f44a6711206a2baf9f065b4_241861_150x0_resize_q90_lanczos.jpg
  100. BIN
      exampleSite/resources/_gen/images/post/jupyter/featured_hub1daa031c2af6888ff37bd93eb033a1a_71549_150x0_resize_lanczos_2.png

+ 1 - 1
.editorconfig

@@ -16,5 +16,5 @@ max_line_length = 100
 [*.md]
 trim_trailing_whitespace = false
 
-[layouts/shortcodes/*.html]
+[{layouts/shortcodes/*.html, layouts/_default/_markup/*.html}]
 insert_final_newline = false

+ 43 - 0
.github/contributing.md

@@ -0,0 +1,43 @@
+# Contributing to Academic
+
+For **help**, **support**, and **questions** please use our **[community chat](https://spectrum.chat/academic)**  🚑.
+
+---
+
+## Where to Start
+
+Learn [how to contribute code on Github](https://codeburst.io/a-step-by-step-guide-to-making-your-first-github-contribution-5302260a2940).
+
+If you're a developer looking to contribute, but you're not sure where to begin, check out the [good first issue](https://github.com/gcushen/hugo-academic/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) label on Github, which contains small tasks that have been specifically flagged as being friendly to new contributors.
+
+After that, if you're looking for something a little more challenging to sink your teeth into, there's a broader [help wanted](https://github.com/gcushen/hugo-academic/labels/help%20wanted) label encompassing issues which need some love.
+
+If you have a straightforward bug fix or improvement, feel free to contribute it in a [Pull Request](https://github.com/gcushen/hugo-academic/pulls).
+
+If you have an idea for a new feature, please start by [searching the issues](https://github.com/gcushen/hugo-academic/issues) to check that the feature has not already been suggested and then suggest it by [opening a new issue](https://github.com/gcushen/hugo-academic/issues/new/choose), as adding new features to Academic first requires some analysis around the design and spec.
+
+To contribute a **new language pack**, refer to the [language pack guide](https://sourcethemes.com/academic/docs/language/#create-or-modify-a-language-pack). Once created, place you language pack in `academic/i18n/`, add the name of the language to `academic/data/i18n/language.yaml`, and open a Pull Request on Github with these two files.
+
+To contribute to **Academic Admin**, the automatic publication importer, refer to [its dedicated Github repository](https://github.com/sourcethemes/academic-admin).
+
+## Stickers
+
+🖼️ [Decorate your laptop or journal with an Academic **sticker**](https://www.redbubble.com/people/neutreno/works/34387919-academic)
+
+## Donations
+
+As a pure community-driven open source project, we welcome your support:
+
+  - ☕️ [**Donate a coffee**](https://paypal.me/cushen)
+  - 💵 [Become a backer on **Patreon**](https://www.patreon.com/cushen)
+
+## Other ways to help
+
+If you're not a developer there are still plenty of ways that you can help. We always need help with:
+
+- Helping our Academic community on the [chat](https://spectrum.chat/academic)
+- Improving the [documentation](https://sourcethemes.com/academic/docs/) and writing tutorials
+  - Just click the _Edit_ button at the bottom of pages or contribute to the [documentation repository](https://github.com/sourcethemes/academic-www)
+- Testing and quality assurance
+- Hosting local Academic themed events or meetups
+- Promoting Academic to others by blogging, vlogging, code streaming, talking etc.

+ 3 - 1
.gitignore

@@ -1,7 +1,9 @@
 # IDE specific
 .idea/
 .vscode/
-resources/
+
+# Hugo
+exampleSite/public/
 
 # Jupyter
 .ipynb_checkpoints/

+ 4 - 5
README.md

@@ -4,14 +4,13 @@
 
 ### The Page Builder to Easily Create Professional Websites :pencil2: :newspaper: :rocket:
 
-**Create a free website with Academic using Markdown, Jupyter, or RStudio. Choose a beautiful color theme and build anything with the Page Builder - over 40 _widgets_, _themes_, and _language packs_ included!**
+**Create a free website with Academic using Markdown, Jupyter, or RStudio. Choose a beautiful color theme and build anything with the Page Builder - over 50 _widgets_, _themes_, and _language packs_ included!**
 
 [Check out the latest **demo**](https://academic-demo.netlify.com/) of what you'll get in less than 10 minutes, or [view the **showcase**](https://sourcethemes.com/academic/#expo) of personal, project, and business sites.
 
 - 👉 [**Get Started**](https://sourcethemes.com/academic/docs/install/)
 - 📚 [View the **documentation**](https://sourcethemes.com/academic/docs/)
-- 💬 [**Ask a question** on the forum](https://discourse.gohugo.io)
-- 👥 [Chat with the **community**](https://spectrum.chat/academic)
+- 💬 [Chat with the **Academic community**](https://spectrum.chat/academic) or [**Hugo community**](https://discourse.gohugo.io)
 - 🐦 Twitter: [@source_themes](https://twitter.com/source_themes) [@GeorgeCushen](https://twitter.com/GeorgeCushen) [#MadeWithAcademic](https://twitter.com/search?q=%23MadeWithAcademic&src=typd)
 - 💡 [Request a **feature** or report a **bug**](https://github.com/gcushen/hugo-academic/issues)
 - ⬆️ **Updating?** View the [Update Guide](https://sourcethemes.com/academic/docs/update/) and [Release Notes](https://sourcethemes.com/academic/updates/)
@@ -83,7 +82,7 @@ You can choose from one of the following four methods to install:
 Prerequisites:
 
 * [Download and install Git](https://git-scm.com/downloads)
-* [Download and install Hugo Extended v0.58.3+](https://gohugo.io/getting-started/installing/#quick-install)
+* [Download and install Hugo Extended v0.63.1+](https://gohugo.io/getting-started/installing/#quick-install)
 
 Install:
 
@@ -106,7 +105,7 @@ Install:
 
 Prerequisites:
 
-* [Download and install Hugo Extended v0.58.3+](https://gohugo.io/getting-started/installing/#quick-install)
+* [Download and install Hugo Extended v0.63.1+](https://gohugo.io/getting-started/installing/#quick-install)
 
 Install:
 

+ 68 - 0
archetypes/authors/_index.md

@@ -0,0 +1,68 @@
+---
+# Display name
+name: "{{ replace .Name "-" " " | title }}"
+
+# Username (this should match the folder name and the name on publications)
+authors:
+- Name "{{ replace .Name "-" " " | title }}"
+
+# Is this the primary user of the site?
+superuser: false
+
+# Role/position (e.g., Professor of Artificial Intelligence)
+role:
+
+# Organizations/Affiliations
+organizations:
+- name: 
+  url: ""
+
+# Short bio (displayed in user profile at end of posts)
+bio: 
+
+# List each interest with a dash
+interests:
+- Interest 1
+- Interest 2
+
+education:
+  courses:
+  - course: Title course 1
+    institution: Name of Institution
+    year: 2012
+  - course: Title course 1
+    institution: Name of Institution
+    year: 2012
+
+# Social/Academic Networking
+# For available icons, see: https://sourcethemes.com/academic/docs/page-builder/#icons
+#   For an email link, use "fas" icon pack, "envelope" icon, and a link in the
+#   form "mailto:your-email@example.com" or "#contact" for contact widget.
+social:
+- icon: envelope
+  icon_pack: fas
+  link: '#contact'  # For a direct email link, use "mailto:test@example.org".
+- icon: twitter
+  icon_pack: fab
+  link: https://twitter.com/USERNAME
+- icon: google-scholar
+  icon_pack: ai
+  link: https://scholar.google.com/citations?user=PERSON-ID
+- icon: github
+  icon_pack: fab
+  link: https://github.com/USERNAME
+# Link to a PDF of your resume/CV from the About widget.
+# To enable, copy your resume/CV to `static/files/cv.pdf` and uncomment the lines below.
+# - icon: cv
+#   icon_pack: ai
+#   link: files/cv.pdf
+
+# Enter email to display Gravatar (if Gravatar enabled in Config)
+email: ""
+
+# Organizational groups that you belong to (for People widget)
+#   Set this to `[]` or comment out if you are not using People widget.
+user_groups:
+- Group 1
+- Group 2
+---

BIN
archetypes/authors/avatar.jpg


+ 0 - 0
static/img/icon-512.png → assets/images/icon.png


+ 314 - 160
assets/js/academic.js

@@ -5,7 +5,7 @@
  *  Core JS functions and initialization.
  **************************************************/
 
-(function($){
+(function ($) {
 
   /* ---------------------------------------------------------------------------
    * Responsive scrolling for URL hashes.
@@ -14,11 +14,7 @@
   // Dynamically get responsive navigation bar height for offsetting Scrollspy.
   function getNavBarHeight() {
     let $navbar = $('#navbar-main');
-    let $navbar_collapse_show = $('#navbar-main .navbar-collapse.collapse.show');
-    let navbar_offset = $navbar.innerHeight();
-    if ($navbar_collapse_show.length){
-      navbar_offset -= $navbar_collapse_show.innerHeight();
-    }
+    let navbar_offset = $navbar.outerHeight();
     console.debug('Navbar height: ' + navbar_offset);
     return navbar_offset;
   }
@@ -35,7 +31,7 @@
     target = (typeof target === 'undefined' || typeof target === 'object') ? decodeURIComponent(window.location.hash) : target;
 
     // If target element exists, scroll to it taking into account fixed navigation bar offset.
-    if($(target).length) {
+    if ($(target).length) {
       // Escape special chars from IDs, such as colons found in Markdown footnote links.
       target = '#' + $.escapeSelector(target.substring(1));  // Previously, `target = target.replace(/:/g, '\\:');`
 
@@ -46,8 +42,8 @@
       }, 600, function () {
         $('body').removeClass('scrolling');
       });
-    }else{
-      console.debug('Cannot scroll to target `#'+target+'`. ID not found!');
+    } else {
+      console.debug('Cannot scroll to target `#' + target + '`. ID not found!');
     }
   }
 
@@ -65,7 +61,7 @@
   function removeQueryParamsFromUrl() {
     if (window.history.replaceState) {
       let urlWithoutSearchParams = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.hash;
-      window.history.replaceState({path:urlWithoutSearchParams}, '', urlWithoutSearchParams);
+      window.history.replaceState({path: urlWithoutSearchParams}, '', urlWithoutSearchParams);
     }
   }
 
@@ -76,12 +72,12 @@
    * Add smooth scrolling to all links inside the main navbar.
    * --------------------------------------------------------------------------- */
 
-  $('#navbar-main li.nav-item a.nav-link').on('click', function(event) {
+  $('#navbar-main li.nav-item a.nav-link').on('click', function (event) {
     // Store requested URL hash.
     let hash = this.hash;
 
     // If we are on a widget page and the navbar link is to a section on the same page.
-    if ( this.pathname === window.location.pathname && hash && $(hash).length && ($(".js-widget-page").length > 0)) {
+    if (this.pathname === window.location.pathname && hash && $(hash).length && ($(".js-widget-page").length > 0)) {
       // Prevent default click behavior.
       event.preventDefault();
 
@@ -104,7 +100,7 @@
    * Hide mobile collapsable menu on clicking a link.
    * --------------------------------------------------------------------------- */
 
-  $(document).on('click', '.navbar-collapse.show', function(e) {
+  $(document).on('click', '.navbar-collapse.show', function (e) {
     //get the <a> element that was clicked, even if the <span> element that is inside the <a> element is e.target
     let targetElement = $(e.target).is('a') ? $(e.target) : $(e.target).parent();
 
@@ -137,55 +133,57 @@
       // Use Bootstrap compatible grid layout.
       columnWidth: '.grid-sizer'
     },
-    filter: function() {
+    filter: function () {
       let $this = $(this);
-      let searchResults = searchRegex ? $this.text().match( searchRegex ) : true;
-      let filterResults = filterValues ? $this.is( filterValues ) : true;
+      let searchResults = searchRegex ? $this.text().match(searchRegex) : true;
+      let filterResults = filterValues ? $this.is(filterValues) : true;
       return searchResults && filterResults;
     }
   });
 
   // Filter by search term.
-  let $quickSearch = $('.filter-search').keyup( debounce( function() {
-    searchRegex = new RegExp( $quickSearch.val(), 'gi' );
+  let $quickSearch = $('.filter-search').keyup(debounce(function () {
+    searchRegex = new RegExp($quickSearch.val(), 'gi');
     $grid_pubs.isotope();
-  }) );
+  }));
 
   // Debounce input to prevent spamming filter requests.
-  function debounce( fn, threshold ) {
+  function debounce(fn, threshold) {
     let timeout;
     threshold = threshold || 100;
     return function debounced() {
-      clearTimeout( timeout );
+      clearTimeout(timeout);
       let args = arguments;
       let _this = this;
+
       function delayed() {
-        fn.apply( _this, args );
+        fn.apply(_this, args);
       }
-      timeout = setTimeout( delayed, threshold );
+
+      timeout = setTimeout(delayed, threshold);
     };
   }
 
   // Flatten object by concatenating values.
-  function concatValues( obj ) {
+  function concatValues(obj) {
     let value = '';
-    for ( let prop in obj ) {
-      value += obj[ prop ];
+    for (let prop in obj) {
+      value += obj[prop];
     }
     return value;
   }
 
-  $('.pub-filters').on( 'change', function() {
+  $('.pub-filters').on('change', function () {
     let $this = $(this);
 
     // Get group key.
     let filterGroup = $this[0].getAttribute('data-filter-group');
 
     // Set filter for group.
-    pubFilters[ filterGroup ] = this.value;
+    pubFilters[filterGroup] = this.value;
 
     // Combine filters.
-    filterValues = concatValues( pubFilters );
+    filterValues = concatValues(pubFilters);
 
     // Activate filters.
     $grid_pubs.isotope();
@@ -204,7 +202,7 @@
 
   // Filter publications according to hash in URL.
   function filter_publications() {
-    let urlHash = window.location.hash.replace('#','');
+    let urlHash = window.location.hash.replace('#', '');
     let filterValue = '*';
 
     // Check if hash is numeric.
@@ -214,8 +212,8 @@
 
     // Set filter.
     let filterGroup = 'pubtype';
-    pubFilters[ filterGroup ] = filterValue;
-    filterValues = concatValues( pubFilters );
+    pubFilters[filterGroup] = filterValue;
+    filterValues = concatValues(pubFilters);
 
     // Activate filters.
     $grid_pubs.isotope();
@@ -228,7 +226,7 @@
   * Google Maps or OpenStreetMap via Leaflet.
   * --------------------------------------------------------------------------- */
 
-  function initMap () {
+  function initMap() {
     if ($('#map').length) {
       let map_provider = $('#map-provider').val();
       let lat = $('#map-lat').val();
@@ -237,7 +235,7 @@
       let address = $('#map-dir').val();
       let api_key = $('#map-api-key').val();
 
-      if ( map_provider == 1 ) {
+      if (map_provider == 1) {
         let map = new GMaps({
           div: '#map',
           lat: lat,
@@ -260,29 +258,29 @@
           lat: lat,
           lng: lng,
           click: function (e) {
-            let url = 'https://www.google.com/maps/place/' + encodeURIComponent(address) + '/@' + lat + ',' + lng +'/';
+            let url = 'https://www.google.com/maps/place/' + encodeURIComponent(address) + '/@' + lat + ',' + lng + '/';
             window.open(url, '_blank')
           },
           title: address
         })
       } else {
-          let map = new L.map('map').setView([lat, lng], zoom);
-          if ( map_provider == 3 && api_key.length ) {
-            L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
-              attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
-              maxZoom: 18,
-              id: 'mapbox.streets',
-              accessToken: api_key
-            }).addTo(map);
-          } else {
-            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
-              maxZoom: 19,
-              attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
-            }).addTo(map);
-          }
-          let marker = L.marker([lat, lng]).addTo(map);
-          let url = lat + ',' + lng +'#map='+ zoom +'/'+ lat +'/'+ lng +'&layers=N';
-          marker.bindPopup(address + '<p><a href="https://www.openstreetmap.org/directions?engine=osrm_car&route='+ url +'">Routing via OpenStreetMap</a></p>');
+        let map = new L.map('map').setView([lat, lng], zoom);
+        if (map_provider == 3 && api_key.length) {
+          L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
+            attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
+            maxZoom: 18,
+            id: 'mapbox.streets',
+            accessToken: api_key
+          }).addTo(map);
+        } else {
+          L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+            maxZoom: 19,
+            attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
+          }).addTo(map);
+        }
+        let marker = L.marker([lat, lng]).addTo(map);
+        let url = lat + ',' + lng + '#map=' + zoom + '/' + lat + '/' + lng + '&layers=N';
+        marker.bindPopup(address + '<p><a href="https://www.openstreetmap.org/directions?engine=osrm_car&route=' + url + '">Routing via OpenStreetMap</a></p>');
       }
     }
   }
@@ -294,10 +292,10 @@
   function printLatestRelease(selector, repo) {
     $.getJSON('https://api.github.com/repos/' + repo + '/tags').done(function (json) {
       let release = json[0];
-      $(selector).append(' '+release.name);
-    }).fail(function( jqxhr, textStatus, error ) {
+      $(selector).append(' ' + release.name);
+    }).fail(function (jqxhr, textStatus, error) {
       let err = textStatus + ", " + error;
-      console.log( "Request Failed: " + err );
+      console.log("Request Failed: " + err);
     });
   }
 
@@ -318,7 +316,7 @@
       $('#fancybox-style-noscroll').remove();
     } else {
       // Prevent fixed positioned elements (e.g. navbar) moving due to scrollbars.
-      if ( !$('#fancybox-style-noscroll').length && document.body.scrollHeight > window.innerHeight ) {
+      if (!$('#fancybox-style-noscroll').length && document.body.scrollHeight > window.innerHeight) {
         $('head').append(
           '<style id="fancybox-style-noscroll">.compensate-for-scrollbar{margin-right:' +
           (window.innerWidth - document.documentElement.clientWidth) +
@@ -335,37 +333,169 @@
   }
 
   /* ---------------------------------------------------------------------------
-  * Toggle day/night mode.
+  * Change Theme Mode (0: Day, 1: Night, 2: Auto).
   * --------------------------------------------------------------------------- */
 
-  function toggleDarkMode(codeHlEnabled, codeHlLight, codeHlDark, diagramEnabled) {
-    if ($('body').hasClass('dark')) {
-      $('body').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 500);
+  function canChangeTheme() {
+    // If the theme changer component is present, then user is allowed to change the theme variation.
+    return $('.js-dark-toggle').length;
+  }
+
+  function getThemeMode() {
+    return parseInt(localStorage.getItem('dark_mode') || 2);
+  }
+
+  function changeThemeModeClick() {
+    if (!canChangeTheme()) {
+      return;
+    }
+    let $themeChanger = $('.js-dark-toggle i');
+    let currentThemeMode = getThemeMode();
+    let isDarkTheme;
+    switch (currentThemeMode) {
+      case 0:
+        localStorage.setItem('dark_mode', '1');
+        isDarkTheme = 1;
+        console.info('User changed theme variation to Dark.');
+        $themeChanger.removeClass('fa-moon fa-sun').addClass('fa-palette');
+        break;
+      case 1:
+        localStorage.setItem('dark_mode', '2');
+        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+          // The visitor prefers dark themes and switching to the dark variation is allowed by admin.
+          isDarkTheme = 1;
+        } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
+          // The visitor prefers light themes and switching to the dark variation is allowed by admin.
+          isDarkTheme = 0;
+        } else {
+          isDarkTheme = isSiteThemeDark;  // Use the site's default theme variation based on `light` in the theme file.
+        }
+        console.info('User changed theme variation to Auto.');
+        $themeChanger.removeClass('fa-moon fa-palette').addClass('fa-sun');
+        break;
+      default:
+        localStorage.setItem('dark_mode', '0');
+        isDarkTheme = 0;
+        console.info('User changed theme variation to Light.');
+        $themeChanger.removeClass('fa-sun fa-palette').addClass('fa-moon');
+        break;
+    }
+    renderThemeVariation(isDarkTheme);
+  }
+
+  function getThemeVariation() {
+    if (!canChangeTheme()) {
+      return isSiteThemeDark;  // Use the site's default theme variation based on `light` in the theme file.
+    }
+    let currentThemeMode = getThemeMode();
+    let isDarkTheme;
+    switch (currentThemeMode) {
+      case 0:
+        isDarkTheme = 0;
+        break;
+      case 1:
+        isDarkTheme = 1;
+        break;
+      default:
+        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+          // The visitor prefers dark themes and switching to the dark variation is allowed by admin.
+          isDarkTheme = 1;
+        } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
+          // The visitor prefers light themes and switching to the dark variation is allowed by admin.
+          isDarkTheme = 0;
+        } else {
+          isDarkTheme = isSiteThemeDark;  // Use the site's default theme variation based on `light` in the theme file.
+        }
+        break;
+    }
+    return isDarkTheme;
+  }
+
+  /**
+   * Render theme variation (day or night).
+   *
+   * @param {int} isDarkTheme - TODO: convert to boolean.
+   * @param {boolean} init
+   * @returns {undefined}
+   */
+  function renderThemeVariation(isDarkTheme, init = false) {
+    // Is code highlighting enabled in site config?
+    const codeHlEnabled = $('link[title=hl-light]').length > 0;
+    const codeHlLight = $('link[title=hl-light]')[0];
+    const codeHlDark = $('link[title=hl-dark]')[0];
+    const diagramEnabled = $('script[title=mermaid]').length > 0;
+
+    // Check if re-render required.
+    if (!init) {
+      // If request to render light when light variation already rendered, return.
+      // If request to render dark when dark variation already rendered, return.
+      if ((isDarkTheme === 0 && !$('body').hasClass('dark')) || (isDarkTheme === 1 && $('body').hasClass('dark'))) {
+        return;
+      }
+    }
+
+    if (isDarkTheme === 0) {
+      if (!init) {
+        // Only fade in the page when changing the theme variation.
+        $('body').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 500);
+      }
       $('body').removeClass('dark');
       if (codeHlEnabled) {
         codeHlLight.disabled = false;
         codeHlDark.disabled = true;
       }
-      $('.js-dark-toggle i').removeClass('fa-sun').addClass('fa-moon');
-      localStorage.setItem('dark_mode', '0');
       if (diagramEnabled) {
-        // TODO: Investigate Mermaid.js approach to re-render diagrams with new theme without reloading.
-        location.reload();
+        if (init) {
+          mermaid.initialize({theme: 'default', securityLevel: 'loose'});
+        } else {
+          // Have to reload to re-initialise Mermaid with the new theme and re-parse the Mermaid code blocks.
+          location.reload();
+        }
+      }
+    } else if (isDarkTheme === 1) {
+      if (!init) {
+        // Only fade in the page when changing the theme variation.
+        $('body').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 500);
       }
-    } else {
-      $('body').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 500);
       $('body').addClass('dark');
       if (codeHlEnabled) {
         codeHlLight.disabled = true;
         codeHlDark.disabled = false;
       }
-      $('.js-dark-toggle i').removeClass('fa-moon').addClass('fa-sun');
-      localStorage.setItem('dark_mode', '1');
       if (diagramEnabled) {
-        // TODO: Investigate Mermaid.js approach to re-render diagrams with new theme without reloading.
-        location.reload();
+        if (init) {
+          mermaid.initialize({theme: 'dark', securityLevel: 'loose'});
+        } else {
+          // Have to reload to re-initialise Mermaid with the new theme and re-parse the Mermaid code blocks.
+          location.reload();
+        }
+      }
+    }
+  }
+
+  function initThemeVariation() {
+    // If theme changer component present, set its icon according to the theme mode (day, night, or auto).
+    if (canChangeTheme) {
+      let themeMode = getThemeMode();
+      let $themeChanger = $('.js-dark-toggle i');
+      switch (themeMode) {
+        case 0:
+          $themeChanger.removeClass('fa-sun fa-palette').addClass('fa-moon');
+          console.info('Initialize theme variation to Light.');
+          break;
+        case 1:
+          $themeChanger.removeClass('fa-moon fa-sun').addClass('fa-palette');
+          console.info('Initialize theme variation to Dark.');
+          break;
+        default:
+          $themeChanger.removeClass('fa-moon fa-palette').addClass('fa-sun');
+          console.info('Initialize theme variation to Auto.');
+          break;
       }
     }
+    // Render the day or night theme.
+    let isDarkTheme = getThemeVariation();
+    renderThemeVariation(isDarkTheme, true);
   }
 
   /* ---------------------------------------------------------------------------
@@ -373,89 +503,101 @@
   * --------------------------------------------------------------------------- */
 
   function normalizeCarouselSlideHeights() {
-    $('.carousel').each(function(){
+    $('.carousel').each(function () {
       // Get carousel slides.
       let items = $('.carousel-item', this);
       // Reset all slide heights.
       items.css('min-height', 0);
       // Normalize all slide heights.
-      let maxHeight = Math.max.apply(null, items.map(function(){return $(this).outerHeight()}).get());
+      let maxHeight = Math.max.apply(null, items.map(function () {
+        return $(this).outerHeight()
+      }).get());
       items.css('min-height', maxHeight + 'px');
     })
   }
 
   /* ---------------------------------------------------------------------------
-   * On document ready.
-   * --------------------------------------------------------------------------- */
+ * Fix Hugo's Goldmark output and Mermaid code blocks.
+ * --------------------------------------------------------------------------- */
 
-  $(document).ready(function() {
-    // Fix Hugo's auto-generated Table of Contents.
-    //   Must be performed prior to initializing ScrollSpy.
-    $('#TableOfContents > ul > li > ul').unwrap().unwrap();
+  /**
+   * Fix Hugo's Goldmark output.
+   */
+  function fixHugoOutput() {
+    // Fix Goldmark table of contents.
+    // - Must be performed prior to initializing ScrollSpy.
     $('#TableOfContents').addClass('nav flex-column');
     $('#TableOfContents li').addClass('nav-item');
     $('#TableOfContents li a').addClass('nav-link');
 
-    // Fix Mmark task lists (remove bullet points).
+    // Fix Goldmark task lists (remove bullet points).
     $("input[type='checkbox'][disabled]").parents('ul').addClass('task-list');
+  }
 
-    // Fix Mermaid.js clash with Highlight.js.
+  /**
+   * Fix Mermaid.js clash with Highlight.js.
+   * Refactor Mermaid code blocks as divs to prevent Highlight parsing them and enable Mermaid to parse them.
+   */
+  function fixMermaid() {
     let mermaids = [];
     [].push.apply(mermaids, document.getElementsByClassName('language-mermaid'));
-    for (i = 0; i < mermaids.length; i++) {
+    for (let i = 0; i < mermaids.length; i++) {
       $(mermaids[i]).unwrap('pre');  // Remove <pre> wrapper.
-      $(mermaids[i]).replaceWith(function(){
+      $(mermaids[i]).replaceWith(function () {
         // Convert <code> block to <div> and add `mermaid` class so that Mermaid will parse it.
         return $("<div />").append($(this).contents()).addClass('mermaid');
       });
     }
+  }
 
-    // Get theme variation (day/night).
-    let defaultThemeVariation;
-    if ($('body').hasClass('dark')) {
-      // The `color_theme` of the site is dark.
-      defaultThemeVariation = 1;
-    } else if ($('.js-dark-toggle').length && window.matchMedia('(prefers-color-scheme: dark)').matches) {
-      // The visitor prefers dark themes and switching to the dark variation is allowed by admin.
-      defaultThemeVariation = 1;
-    } else {
-      // Default to day (light) theme.
-      defaultThemeVariation = 0;
-    }
-    let dark_mode = parseInt(localStorage.getItem('dark_mode') || defaultThemeVariation);
+  /* ---------------------------------------------------------------------------
+   * On document ready.
+   * --------------------------------------------------------------------------- */
 
-    // Is code highlighting enabled in site config?
-    const codeHlEnabled = $('link[title=hl-light]').length > 0;
-    const codeHlLight = $('link[title=hl-light]')[0];
-    const codeHlDark = $('link[title=hl-dark]')[0];
-    const diagramEnabled = $('script[title=mermaid]').length > 0;
+  $(document).ready(function () {
+    fixHugoOutput();
+    fixMermaid();
 
-    if (dark_mode) {
-      $('body').addClass('dark');
-      if (codeHlEnabled) {
-        codeHlLight.disabled = true;
-        codeHlDark.disabled = false;
-      }
-      if (diagramEnabled) {
-        mermaid.initialize({ theme: 'dark' });
-      }
-      $('.js-dark-toggle i').removeClass('fa-moon').addClass('fa-sun');
-    } else {
-      $('body').removeClass('dark');
-      if (codeHlEnabled) {
-        codeHlLight.disabled = false;
-        codeHlDark.disabled = true;
-      }
-      if (diagramEnabled) {
-        mermaid.initialize({ theme: 'default' });
-      }
-      $('.js-dark-toggle i').removeClass('fa-sun').addClass('fa-moon');
+    // Initialise code highlighting if enabled for this page.
+    // Note: this block should be processed after the Mermaid code-->div conversion.
+    if (code_highlighting) {
+      hljs.initHighlighting();
     }
 
-    // Toggle day/night mode.
-    $('.js-dark-toggle').click(function(e) {
+    // Initialize theme variation.
+    initThemeVariation();
+
+    // Change theme mode.
+    $('.js-dark-toggle').click(function (e) {
       e.preventDefault();
-      toggleDarkMode(codeHlEnabled, codeHlLight, codeHlDark, diagramEnabled);
+      changeThemeModeClick();
+    });
+
+    // Live update of day/night mode on system preferences update (no refresh required).
+    // Note: since we listen only for *dark* events, we won't detect other scheme changes such as light to no-preference.
+    const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+    darkModeMediaQuery.addListener((e) => {
+      if (!canChangeTheme()) {
+        // Changing theme variation is not allowed by admin.
+        return;
+      }
+      const darkModeOn = e.matches;
+      console.log(`OS dark mode preference changed to ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
+      let currentThemeVariation = parseInt(localStorage.getItem('dark_mode') || 2);
+      let isDarkTheme;
+      if (currentThemeVariation === 2) {
+        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+          // The visitor prefers dark themes.
+          isDarkTheme = 1;
+        } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
+          // The visitor prefers light themes.
+          isDarkTheme = 0;
+        } else {
+          // The visitor does not have a day or night preference, so use the theme's default setting.
+          isDarkTheme = isSiteThemeDark;
+        }
+        renderThemeVariation(isDarkTheme);
+      }
     });
   });
 
@@ -463,32 +605,9 @@
    * On window loaded.
    * --------------------------------------------------------------------------- */
 
-  $(window).on('load', function() {
-    // Re-initialize Scrollspy with dynamic navbar height offset.
-    fixScrollspy();
-
-    if (window.location.hash) {
-      // When accessing homepage from another page and `#top` hash is set, show top of page (no hash).
-      if (window.location.hash == "#top") {
-        window.location.hash = ""
-      } else if (!$('.projects-container').length) {
-        // If URL contains a hash and there are no dynamically loaded images on the page,
-        // immediately scroll to target ID taking into account responsive offset.
-        // Otherwise, wait for `imagesLoaded()` to complete before scrolling to hash to prevent scrolling to wrong
-        // location.
-        scrollToAnchor();
-      }
-    }
-
-    // Call `fixScrollspy` when window is resized.
-    let resizeTimer;
-    $(window).resize(function() {
-      clearTimeout(resizeTimer);
-      resizeTimer = setTimeout(fixScrollspy, 200);
-    });
-
+  $(window).on('load', function () {
     // Filter projects.
-    $('.projects-container').each(function(index, container) {
+    $('.projects-container').each(function (index, container) {
       let $container = $(container);
       let $section = $container.closest('section');
       let layout;
@@ -498,7 +617,7 @@
         layout = 'masonry';
       }
 
-      $container.imagesLoaded(function() {
+      $container.imagesLoaded(function () {
         // Initialize Isotope after all images have loaded.
         $container.isotope({
           itemSelector: '.isotope-item',
@@ -510,7 +629,7 @@
         });
 
         // Filter items when filter link is clicked.
-        $section.find('.project-filters a').click(function() {
+        $section.find('.project-filters a').click(function () {
           let selector = $(this).attr('data-filter');
           $container.isotope({filter: selector});
           $(this).removeClass('active').addClass('active').siblings().removeClass('active all');
@@ -536,24 +655,24 @@
     }
 
     // Scroll to top of page.
-    $('.back-to-top').click( function(event) {
+    $('.back-to-top').click(function (event) {
       event.preventDefault();
       $('html, body').animate({
         'scrollTop': 0
-      }, 800, function() {
+      }, 800, function () {
         window.location.hash = "";
       });
     });
 
     // Load citation modal on 'Cite' click.
-    $('.js-cite-modal').click(function(e) {
+    $('.js-cite-modal').click(function (e) {
       e.preventDefault();
       let filename = $(this).attr('data-filename');
       let modal = $('#modal');
-      modal.find('.modal-body code').load( filename , function( response, status, xhr ) {
-        if ( status == 'error' ) {
+      modal.find('.modal-body code').load(filename, function (response, status, xhr) {
+        if (status == 'error') {
           let msg = "Error: ";
-          $('#modal-error').html( msg + xhr.status + " " + xhr.statusText );
+          $('#modal-error').html(msg + xhr.status + " " + xhr.statusText);
         } else {
           $('.js-download-cite').attr('href', filename);
         }
@@ -562,7 +681,7 @@
     });
 
     // Copy citation text on 'Copy' click.
-    $('.js-copy-cite').click(function(e) {
+    $('.js-copy-cite').click(function (e) {
       e.preventDefault();
       // Get selection.
       let range = document.createRange();
@@ -572,7 +691,7 @@
       try {
         // Execute the copy command.
         document.execCommand('copy');
-      } catch(e) {
+      } catch (e) {
         console.log('Error: citation copy failed.');
       }
       // Remove selection.
@@ -588,11 +707,11 @@
       printLatestRelease(githubReleaseSelector, $(githubReleaseSelector).data('repo'));
 
     // On search icon click toggle search dialog.
-    $('.js-search').click(function(e) {
+    $('.js-search').click(function (e) {
       e.preventDefault();
       toggleSearchDialog();
     });
-    $(document).on('keydown', function(e){
+    $(document).on('keydown', function (e) {
       if (e.which == 27) {
         // `Esc` key pressed.
         if ($('body').hasClass('searching')) {
@@ -610,4 +729,39 @@
   // Normalize Bootstrap carousel slide heights.
   $(window).on('load resize orientationchange', normalizeCarouselSlideHeights);
 
+  // Automatic main menu dropdowns on mouse over.
+  $('body').on('mouseenter mouseleave', '.dropdown', function (e) {
+    var dropdown = $(e.target).closest('.dropdown');
+    var menu = $('.dropdown-menu', dropdown);
+    dropdown.addClass('show');
+    menu.addClass('show');
+    setTimeout(function () {
+      dropdown[dropdown.is(':hover') ? 'addClass' : 'removeClass']('show');
+      menu[dropdown.is(':hover') ? 'addClass' : 'removeClass']('show');
+    }, 300);
+
+    // Re-initialize Scrollspy with dynamic navbar height offset.
+    fixScrollspy();
+
+    if (window.location.hash) {
+      // When accessing homepage from another page and `#top` hash is set, show top of page (no hash).
+      if (window.location.hash == "#top") {
+        window.location.hash = ""
+      } else if (!$('.projects-container').length) {
+        // If URL contains a hash and there are no dynamically loaded images on the page,
+        // immediately scroll to target ID taking into account responsive offset.
+        // Otherwise, wait for `imagesLoaded()` to complete before scrolling to hash to prevent scrolling to wrong
+        // location.
+        scrollToAnchor();
+      }
+    }
+
+    // Call `fixScrollspy` when window is resized.
+    let resizeTimer;
+    $(window).resize(function () {
+      clearTimeout(resizeTimer);
+      resizeTimer = setTimeout(fixScrollspy, 200);
+    });
+  });
+
 })(jQuery);

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
assets/js/vendor/bootstrap.min.js


+ 1 - 4
assets/scss/academic/_content.scss

@@ -267,12 +267,9 @@ ul.share li:hover i {
  *  Author profile card
  **************************************************/
 
-.author-card .portrait {
+.author-card .avatar {
   width: 60px;
   height: 60px;
-  margin: 0 auto;
-  border-radius: 50%;
-  object-fit: cover;
 }
 
 .author-card .card-title {

+ 0 - 5
assets/scss/academic/_dark.scss

@@ -113,11 +113,6 @@ body.dark,
   color: #fff;
 }
 
-.dark .navbar-light {
-  box-shadow: 0 0.125rem 0.25rem 0 rgba(255, 255, 255, .11);
-  border-color: #070707;
-}
-
 .dark select {
   background: rgb(40, 42, 54);
   color: rgb(248, 248, 242);

+ 2 - 1
assets/scss/academic/_docs.scss

@@ -218,8 +218,9 @@ ul.toc-top {
   padding-left: 0;
 }
 
+// TOC indentation for each level.
 #TableOfContents ul ul {
-  display: none;
+  padding-left: 0.8rem;
 }
 
 #TableOfContents li {

+ 158 - 154
assets/scss/academic/_nav.scss

@@ -3,196 +3,200 @@
  **************************************************/
 
 .navbar {
-  min-height: 70px !important;
-}
-
-.navbar-light {
-  background: $sta-menu-primary !important;
-  box-shadow: 0 0.125rem 0.25rem 0 rgba(0,0,0,.11)
-}
-
-.navbar-light .navbar-toggler {
-  border-color: transparent;
-}
-
-.navbar-toggler {
-  color: $sta-menu-text !important;
-}
-
-.navbar-light .navbar-toggler:focus,
-.navbar-light .navbar-toggler:hover {
-  background-color: transparent;
-}
-
-.dropdown-menu,
-nav#navbar-main li.nav-item {
+  height: 70px;
+  background: $sta-menu-primary;
+  box-shadow: 0 0.125rem 0.25rem 0 rgba(0,0,0,.11);
   font-size: #{$sta-font-size-small}px;
-}
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+
+  // Remove Bootstrap's navbar v-padding and assign v-padding to logo separately to maximise logo size.
+  // Otherwise, Bootstrap's navbar v-padding causes issue with logo fitting within fixed 50px height bar in md-lg sizes.
+  padding: 0 1rem;
+
+  .nav-item {
+    // For z-index compatibility with logo on mobile layout, otherwise nav-item can't be clicked when logo present.
+    position: relative;
+  }
+  @include media-breakpoint-down(md) {
+    height: 50px;
+
+    .navbar-nav-scroll {
+      width: 100%;
+      overflow: hidden;
+
+      .navbar-nav {
+        overflow-x: auto;
+        white-space: nowrap;
+        -webkit-overflow-scrolling: touch;
+      }
+    }
+  }
 
-.navbar-light .navbar-nav>.nav-item>.nav-link,
-.navbar-light .navbar-nav>.nav-item>.nav-link:focus,
-.navbar-light .navbar-nav>.nav-item>.nav-link:hover {
-  white-space: nowrap;
-  -webkit-transition: 0.2s ease;
-  transition: 0.2s ease;
-  color: $sta-menu-text;
-}
+  .navbar-nav {
+    display: flex;
 
-.navbar-light .navbar-nav>.nav-item>.nav-link:focus {
-  color: $sta-menu-text;
-  background-color: transparent;
-}
+    .nav-link {
+      color: rgba($sta-menu-text, .85);
 
-.navbar-light .navbar-nav>.nav-item>.nav-link:hover {
-  color: $sta-menu-text-active;
-  background-color: transparent;
-}
+      &.active,
+      &:hover,
+      &:focus {
+        color: $sta-menu-text;
+      }
 
-.navbar-light .navbar-nav>li.nav-item>a.active,
-.navbar-light .navbar-nav>li.nav-item>a.active:focus,
-.navbar-light .navbar-nav>li.nav-item>a.active:hover {
-  color: $sta-menu-text-active;
-  font-weight: 700;
-  background-color: transparent !important; /* Override Bootstrap. */
-}
+      &.active {
+        font-weight: bold !important;
+        color: $sta-menu-text-active !important;
+      }
+    }
+  }
 
-.navbar-brand,
-.navbar-nav li.nav-item a.nav-link {
-  height: inherit;
-  line-height: 50px;
-  padding-top: 10px;
-  padding-bottom: 10px;
-}
+  .dropdown-menu {
+    font-size: #{$sta-font-size-small}px;
+  }
 
-.navbar-brand img {
-  max-height: 50px;
-}
+  // Note: dedicated `i18n-active` class to prevent ScrollSpy removing `active` class from language chooser.
+  .dropdown-item.active,
+  .i18n-active {
+    font-weight: bold;
+    color: $sta-menu-text-active !important;
+  }
 
-.navbar-light .navbar-toggler .icon-bar {
-  background-color: $sta-menu-text !important;
 }
 
-.dropdown-menu {
-  background-color: $sta-menu-primary !important;
+.dark .navbar {
+  box-shadow: 0 0.125rem 0.25rem 0 rgba(255, 255, 255, .11);
 }
 
-.dropdown-menu > li > a {
-  display: block;
-  padding: 3px 20px;
-  clear: both;
-  font-weight: 400;
-  line-height: 1.42857143;
-  color: $sta-menu-text;
-  white-space: nowrap;
+// Remove Bootstrap's border from Toggle button.
+.navbar-toggler {
+  border: 0 !important;
+  position: relative;  // For z-index clickable mobile logo.
+  z-index: 1030;
 }
-
-.dropdown-menu>li>a:focus,
-.dropdown-menu>li>a:hover {
-  color: $sta-menu-text-active;
-  text-decoration: none;
-  background-color: $sta-menu-primary;
+.navbar-toggler:focus,
+.navbar-toggler:active {
+  outline: none !important;
+  box-shadow: none !important;
 }
 
-.dropdown-menu > .active,
-.dropdown-menu > .active:focus,
-.dropdown-menu > .active:hover {
-  color: $sta-menu-primary;
-  text-decoration: none;
-  background-color: $sta-menu-text-active;
-  outline: 0;
+@include media-breakpoint-down(md) {  /* Match breakpoint for i18n dropdown in navbar.html. */
+  .i18n-dropdown .nav-link::after {
+    content: none;
+  }
+  .i18n-dropdown .dropdown-menu {
+    /* Use style from uncollapsable dropdowns to prevent dropdown going off page. */
+    position: absolute;
+    /* Below style from .dropdown-menu-right to prevent dropdown going off page. */
+    right: 0;
+    left: auto;
+  }
 }
 
-.navbar-light .navbar-nav>.open>a,
-.navbar-light .navbar-nav>.open>a:focus,
-.navbar-light .navbar-nav>.open>a:hover,
-.navbar-light .navbar-nav>.open>a:visited {
-  color: $sta-menu-text !important;
-  background-color: $sta-menu-primary !important;
+// Allow user to horizontally scroll.
+// Commented out this feature as it causes dropdowns to appear within the menu bar.
+// TODO: re-enable in a way that doesn't break dropdowns.
+/*
+.navbar .collapse {
+  overflow-x: auto;
 }
+*/
 
-.navbar-light .navbar-brand {
+.navbar-brand {
+  // Set v-padding to 5px to align with 50/70px responsive max navbar heights.
+  padding-top: 5px;
+  padding-bottom: 5px;
   font-weight: bold;
-  font-size: 1.2em;
-  color: $sta-menu-title;
+  position: relative;
+  z-index: 1030;  // For z-index clickable mobile logo.
 }
 
-.navbar-light .navbar-brand:focus,
-.navbar-light .navbar-brand:hover {
-  color: $sta-menu-title;
-  background-color: transparent;
+// Dynamically fit logo image to space available.
+// No need to explicitly set a size for each breakpoint.
+// See https://caniuse.com/#feat=mdn-css_properties_width_stretch .
+.navbar-brand img {
+  width: auto;
+  height: -moz-available;
+  height: -webkit-fill-available;
+  height: -webkit-stretch;
+  height: stretch;
+  max-height: 60px;  // For lg+ responsive sizing. 60px height +10px v-padding = 70px
+  max-width: fit-content;  // Must override default responsive image style.
 }
 
-@media screen and (max-width: 1200px) {
-  .navbar {
-    min-height: 50px !important;
-  }
+#navbar-main .main-menu-item ul li .nav-link {
+  color: $sta-menu-text;
+}
 
-  .navbar-brand,
-  .navbar-nav li.nav-item a.nav-link {
-    height: inherit;
-    line-height: 40px;
-    padding-top: 5px;
-    padding-bottom: 5px;
+@include media-breakpoint-down(md) {
+  // Used in conjunction with mobile .navbar-brand to center logo on mobile.
+  .navbar-brand-mobile-wrapper {
+    position: absolute;
+    left: 0;
+    right: 0;
+  }
+  .navbar-brand {
+    // Center logo in mobile navbar.
+    margin: 0 auto;
   }
-
   .navbar-brand img {
-    max-height: 40px;
+    max-height: 40px;  // 40px height + 10px v-padding = 50px.
   }
-
   .navbar-toggler {
-    display: block;
+    border-color: transparent;  // Remove Bootstrap's border from Toggle button.
   }
-
-  .fixed-top {
-    top: 0;
-    border-width: 0 0 1px;
+  #navbar-main .main-menu-item {
+    text-align: left !important;
+    padding-left: 0;
   }
-
-  .navbar-nav > li.nav-item > a.nav-link {
-    padding-top: 10px;
-    padding-bottom: 10px;
-    line-height: normal;
+  .navbar-collapse {
+    z-index: 1031 !important;  // Appear just over navbar.
+    position: absolute;
+    left: 0;
+    top: 50px;
+    width: 100%;
+    background-color: $sta-menu-primary;
+    text-align: center !important;
   }
-
-  .dropdown-menu > li > a {
-    display: block;
-    padding: 3px 20px;
-    clear: both;
-    font-weight: 400;
-    line-height: 1.42857143;
-    color: $sta-menu-text;
-    white-space: nowrap;
+  #navbar-main .main-menu-item .nav-item {
+    padding: 10px 15px !important;
   }
-
-  .navbar-light .navbar-nav .open .dropdown-menu {
-    position: static;
-    width: auto;
-    margin-top: 0;
-    background-color: transparent;
-    border: 0;
-    box-shadow: none;
+  #navbar-main .main-menu-item .nav-item .nav-link {
+    padding: 5px 15px !important;
   }
+}
 
-  .navbar-light .navbar-nav .open .dropdown-menu > li > a {
-    padding: 5px 15px 5px 25px;
-    line-height: 20px;
-    color: $sta-menu-text;
-  }
+ul.nav-icons {
+  list-style-type: none;
+  font-size: 18px;
+  padding: 0.5rem 0 0.5rem 0;
+  margin: 0;
+}
 
-  .navbar-light .navbar-nav .open .dropdown-menu > li > a:focus,
-  .navbar-light .navbar-nav .open .dropdown-menu > li > a:hover {
-    color: inherit;
-    background-color: transparent;
-  }
+ul.nav-icons li {
+  display: inline;
+  padding-right: 1rem;
+}
 
-  .navbar-light .navbar-nav .open .dropdown-menu >.nav-item> .active,
-  .navbar-light .navbar-nav .open .dropdown-menu >.nav-item> .active:focus,
-  .navbar-light .navbar-nav .open .dropdown-menu >.nav-item> .active:hover {
-    color: $sta-menu-text-active;
-    background-color: transparent;
-  }
+ul.nav-icons li:last-of-type {
+  padding-right: 0;
+}
 
-  .collapse.in {
-    display: block !important;
-  }
+ul.nav-icons li.nav-item a.nav-link {
+  padding: 0;
+}
+
+.dropdown-menu {
+  background-color: $sta-menu-primary !important;
+  color: $sta-menu-text !important;
+  z-index: 1032;  // I18n dropdown over mobile expanded menu.
+}
+
+.dropdown-item {
+  background-color: $sta-menu-primary !important;
+  color: $sta-menu-text !important;
 }

+ 7 - 2
assets/scss/academic/_root.scss

@@ -24,7 +24,7 @@ body {
   padding-top: 0;
   counter-reset: captions;
 }
-@media screen and (max-width: 1200px) { /* Match max-width of .nav-bar query. */
+@include media-breakpoint-down(md) { /* Match max-width of .nav-bar query. */
   body {
     margin-top: 50px; /* Offset body content by navbar height. */
   }
@@ -59,6 +59,10 @@ ul.task-list {
   list-style: none;
 }
 
+ul.task-list li input[type="checkbox"] {
+  margin-right: 0.5rem;
+}
+
 /* Navigation bar text */
 .navbar-light {
   font-family: $sta-font-nav, sans-serif;
@@ -286,6 +290,7 @@ a[data-fancybox] {
 
 .gallery a[data-fancybox] img {
   height: 250px;
+  width: auto;
   max-width: inherit;
   display: inherit;
   margin: 0;
@@ -354,7 +359,7 @@ footer a.back-to-top i {
 }
 
 .dark site-footer,
-.dark footer a#back_to_top i,
+.dark footer a.back-to-top i,
 .dark .docs .body-footer {
   color: rgba(255,255,255,0.54);
 }

+ 20 - 5
assets/scss/academic/_widgets.scss

@@ -265,14 +265,29 @@ a.hero-cta-alt:hover {
   position: relative;
 }
 
-.portrait {
-  width: 200px;
-  height: 200px;
+.avatar {
+  width: 270px;
+  height: 270px;
   margin: 0 auto;
-  border-radius: 50%;
   object-fit: cover;
 }
 
+// Use smaller avatar size in About widget on small devices.
+@include media-breakpoint-down(sm) {
+  .wg-about .avatar {
+    width: 200px;
+    height: 200px;
+  }
+}
+
+.avatar-circle {
+  border-radius: 50%;
+}
+
+.avatar-square {
+  border-radius: 3px;
+}
+
 .portrait-title h2 {
   font-size: 1.75em;
   font-weight: 300;
@@ -511,7 +526,7 @@ ul.ul-edu li .description p.institution {
   font-size: 0.7rem;
 }
 
-.people-widget .portrait {
+.people-widget .avatar {
   width: 80%;
   max-width: 150px;
   height: auto;

+ 10 - 0
assets/scss/bootstrap_variables.scss

@@ -11,3 +11,13 @@ $container-max-widths: (
   lg: 960px,
   xl: 1200px
 );
+
+$navbar-toggler-padding-x: 0;
+$navbar-toggler-font-size: 18px;
+$navbar-brand-font-size: 1.2rem;
+
+$navbar-light-color: $sta-menu-text;
+$navbar-light-active-color: $sta-menu-text-active;
+$navbar-light-brand-color: $sta-menu-title;
+$navbar-light-brand-hover-color: $navbar-light-active-color;
+$navbar-light-toggler-border-color: transparent;

+ 4 - 4
assets/scss/main.scss

@@ -9,10 +9,10 @@ $sta-lighten-percentage: 10%;
 $sta-font-size: {{ $scr.Get "font_size" }};
 $sta-font-size-small: {{ $scr.Get "font_size_small" }};
 
-$sta-font-body: {{ $scr.Get "body_font" }};
-$sta-font-heading: {{ $scr.Get "heading_font" }};
-$sta-font-nav: {{ $scr.Get "nav_font" }};
-$sta-font-mono: {{ $scr.Get "mono_font" }};
+$sta-font-body: "{{ $scr.Get "body_font" }}";
+$sta-font-heading: "{{ $scr.Get "heading_font" }}";
+$sta-font-nav: "{{ $scr.Get "nav_font" }}";
+$sta-font-mono: "{{ $scr.Get "mono_font" }}";
 
 $sta-primary: {{ $scr.Get "primary" }};
 $sta-primary-light: lighten($sta-primary, $sta-lighten-percentage);

+ 1 - 1
assets/scss/vendor/bootstrap/_badge.scss

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

+ 2 - 1
assets/scss/vendor/bootstrap/_breadcrumb.scss

@@ -3,6 +3,7 @@
   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);
@@ -17,7 +18,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
assets/scss/vendor/bootstrap/_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,

+ 4 - 2
assets/scss/vendor/bootstrap/_buttons.scss

@@ -10,14 +10,16 @@
   font-weight: $btn-font-weight;
   color: $body-color;
   text-align: center;
+  white-space: $btn-white-space;
   vertical-align: middle;
+  cursor: if($enable-pointer-cursor-for-buttons, pointer, null);
   user-select: none;
   background-color: transparent;
   border: $btn-border-width solid transparent;
   @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;
   }
@@ -79,7 +81,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;
   }

+ 17 - 28
assets/scss/vendor/bootstrap/_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;
@@ -35,6 +36,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 +57,7 @@
 }
 
 .card-link {
-  @include hover {
+  @include hover() {
     text-decoration: none;
   }
 
@@ -121,19 +125,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 +146,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 +172,6 @@
 //
 
 .card-group {
-  display: flex;
-  flex-direction: column;
-
   // The child selector allows nested `.card` within `.card-group`
   // to display properly.
   > .card {
@@ -181,6 +179,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 +261,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
assets/scss/vendor/bootstrap/_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 - 2
assets/scss/vendor/bootstrap/_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;
     }
   }

+ 1 - 1
assets/scss/vendor/bootstrap/_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 > & {

+ 22 - 8
assets/scss/vendor/bootstrap/_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);
@@ -263,6 +269,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 +319,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 +379,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;

+ 3 - 3
assets/scss/vendor/bootstrap/_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
@@ -144,7 +144,7 @@
     }
   }
 
-  @include hover-focus {
+  @include hover-focus() {
     color: $dropdown-link-hover-color;
     text-decoration: none;
     @include gradient-bg($dropdown-link-hover-bg);

+ 17 - 9
assets/scss/vendor/bootstrap/_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 {
@@ -80,23 +86,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 +116,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 +216,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;
   }

+ 49 - 1
assets/scss/vendor/bootstrap/_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}' !";
@@ -48,6 +48,17 @@
   @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 {
+      $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 +95,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);
+}

+ 25 - 8
assets/scss/vendor/bootstrap/_grid.scss

@@ -3,26 +3,43 @@
 // 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;
+      }
+
+      @each $name, $width in $grid-breakpoints {
+        @if ($container-max-width > $width or $breakpoint == $name) {
+          .container#{breakpoint-infix($name, $grid-breakpoints)} {
+            @extend %responsive-container-#{$breakpoint};
+          }
+        }
+      }
+    }
+  }
 }
 
+
 // Row
 //
-// Rows contain and clear the floats of your columns.
+// Rows contain your columns.
 
 @if $enable-grid-classes {
   .row {

+ 2 - 2
assets/scss/vendor/bootstrap/_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();
 }
 
 //

+ 2 - 4
assets/scss/vendor/bootstrap/_input-group.scss

@@ -16,10 +16,8 @@
   > .custom-select,
   > .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%;
+    flex: 1 1 0%;
+    min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size
     margin-bottom: 0;
 
     + .form-control,

+ 31 - 22
assets/scss/vendor/bootstrap/_list-group.scss

@@ -23,7 +23,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,8 +45,6 @@
   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;
   background-color: $list-group-bg;
   border: $list-group-border-width solid $list-group-border-color;
@@ -56,7 +54,6 @@
   }
 
   &:last-child {
-    margin-bottom: 0;
     @include border-bottom-radius($list-group-border-radius);
   }
 
@@ -74,6 +71,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;
+    }
+  }
 }
 
 
@@ -89,19 +95,29 @@
       flex-direction: row;
 
       .list-group-item {
-        margin-right: -$list-group-border-width;
-        margin-bottom: 0;
-
         &: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;
+          }
+        }
       }
     }
   }
@@ -115,25 +131,18 @@
 
 .list-group-flush {
   .list-group-item {
-    border-right: 0;
-    border-left: 0;
+    border-right-width: 0;
+    border-left-width: 0;
     @include border-radius(0);
 
-    &:last-child {
-      margin-bottom: -$list-group-border-width;
-    }
-  }
-
-  &:first-child {
-    .list-group-item:first-child {
-      border-top: 0;
+    &:first-child {
+      border-top-width: 0;
     }
   }
 
   &:last-child {
     .list-group-item:last-child {
-      margin-bottom: 0;
-      border-bottom: 0;
+      border-bottom-width: 0;
     }
   }
 }

+ 3 - 3
assets/scss/vendor/bootstrap/_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";

+ 26 - 16
assets/scss/vendor/bootstrap/_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,12 @@
 .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);
     content: "";
   }
 
@@ -138,7 +143,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 +163,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 +171,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 +205,18 @@
   }
 
   .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);
     }
   }
 

+ 3 - 3
assets/scss/vendor/bootstrap/_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;
@@ -15,7 +15,7 @@
   display: block;
   padding: $nav-link-padding-y $nav-link-padding-x;
 
-  @include hover-focus {
+  @include hover-focus() {
     text-decoration: none;
   }
 
@@ -42,7 +42,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
assets/scss/vendor/bootstrap/_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;
       }
     }

+ 2 - 2
assets/scss/vendor/bootstrap/_pagination.scss

@@ -23,7 +23,7 @@
   }
 
   &:focus {
-    z-index: 2;
+    z-index: 3;
     outline: $pagination-focus-outline;
     box-shadow: $pagination-focus-box-shadow;
   }
@@ -43,7 +43,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
assets/scss/vendor/bootstrap/_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
assets/scss/vendor/bootstrap/_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 {

+ 5 - 2
assets/scss/vendor/bootstrap/_progress.scss

@@ -20,6 +20,7 @@
   display: flex;
   flex-direction: column;
   justify-content: center;
+  overflow: hidden;
   color: $progress-bar-color;
   text-align: center;
   white-space: nowrap;
@@ -36,8 +37,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;
+      }
     }
   }
 }

+ 14 - 15
assets/scss/vendor/bootstrap/_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;
-  }
 }
 
 

+ 1 - 0
assets/scss/vendor/bootstrap/_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 {

+ 3 - 3
assets/scss/vendor/bootstrap/_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
assets/scss/vendor/bootstrap/_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;

+ 42 - 22
assets/scss/vendor/bootstrap/_variables.scss

@@ -101,6 +101,13 @@ $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"),
+) !default;
+
 
 // Options
 //
@@ -220,6 +227,7 @@ $container-max-widths: (
 
 $grid-columns:                12 !default;
 $grid-gutter-width:           30px !default;
+$grid-row-columns:            6 !default;
 
 
 // Components
@@ -366,7 +374,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 +419,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 +496,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 +526,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 +536,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 +556,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 +585,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 +661,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 +739,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 +768,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;
@@ -822,9 +833,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 +883,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 +942,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 +955,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 +977,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 +1053,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 +1089,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`)

+ 1 - 1
assets/scss/vendor/bootstrap/bootstrap-grid.scss

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

+ 1 - 1
assets/scss/vendor/bootstrap/bootstrap-reboot.scss

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

+ 1 - 1
assets/scss/vendor/bootstrap/bootstrap.scss

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

+ 3 - 2
assets/scss/vendor/bootstrap/mixins/_background-variant.scss

@@ -2,16 +2,17 @@
 
 // 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) {

+ 1 - 1
assets/scss/vendor/bootstrap/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%);
     }

+ 5 - 2
assets/scss/vendor/bootstrap/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,6 +17,9 @@
 
   &:focus,
   &.focus {
+    color: color-yiq($hover-background);
+    @include gradient-bg($hover-background);
+    border-color: $hover-border;
     // Avoid using mixin so we can pass custom focus shadow properly
     @if $enable-shadows {
       box-shadow: $btn-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;

+ 8 - 8
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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");
 }

+ 32 - 47
assets/scss/vendor/bootstrap/mixins/_forms.scss

@@ -10,7 +10,7 @@
 //
 // 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;
@@ -23,8 +23,23 @@
       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;

+ 8 - 3
assets/scss/vendor/bootstrap/mixins/_grid-framework.scss

@@ -33,10 +33,15 @@
         flex-grow: 1;
         max-width: 100%;
       }
+
+      @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 {

+ 18 - 0
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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
assets/scss/vendor/bootstrap/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);
 }

+ 1 - 1
assets/scss/vendor/bootstrap/utilities/_background.scss

@@ -1,7 +1,7 @@
 // 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 {

+ 2 - 2
assets/scss/vendor/bootstrap/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; }

+ 1 - 1
data/academic.toml

@@ -1,3 +1,3 @@
 # Academic
 
-version = "4.5.0"
+version = "4.8.0"

+ 21 - 7
data/assets.toml

@@ -12,13 +12,14 @@
   sri = "sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
   url = "https://cdnjs.cloudflare.com/ajax/libs/jquery/%s/jquery.min.js"
 [js.highlight]
-  version = "9.15.10"
-  sri = "sha256-1zu+3BnLYV9LdiY85uXMzii3bdrkelyp37e0ZyTAQh0="
+  version = "9.18.1"
+  sri = "sha256-eOgo0OtLL4cdq7RdwRUiGKLX9XsIJ7nGhWEKbohmVAQ="
   url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/%s/highlight.min.js"
 [js.mathJax]
   version = "3"
   sri = ""  # No SRI as dynamically generated.
   url = "https://cdn.jsdelivr.net/npm/mathjax@%s/es5/tex-chtml.js"
+  async = true
 [js.isotope]
   version = "3.0.6"
   sri = "sha256-CBrpuqrMhXwcLLUd5tvQ4euBHCdh7wGlDfNz8vbu/iI="
@@ -56,15 +57,24 @@
   sri = "sha256-pB/deHc9CGfFpJRjC43imB29Rse8tak+5eXqntO94ck="
   url = "https://cdnjs.cloudflare.com/ajax/libs/anchor-js/%s/anchor.min.js"
 [js.mermaid]
-  version = "8.3.1"
-  sri = "sha256-vOIuDSYDirTfyr+S2MjFnhOz6Rgiz4ODFAHATG0rFxw="
+  version = "8.4.8"
+  sri = "sha256-lyWCDMnMeZiXRi7Zl54sZGKYmgQs4izcT7+tKc+KUBk="
   url = "https://cdnjs.cloudflare.com/ajax/libs/mermaid/%s/mermaid.min.js"
+[js.lazysizes]
+  version = "5.1.2"
+  sri = "sha256-Md1qLToewPeKjfAHU1zyPwOutccPAm5tahnaw7Osw0A="
+  url = "https://cdnjs.cloudflare.com/ajax/libs/lazysizes/%s/lazysizes.min.js"
+  async = true
+[js.cookieconsent]
+  version = "3.1.1"
+  sri = "sha256-5VhCqFam2Cn+yjw61zbBNrbHVJ6SRydPeKopYlngbiQ="
+  url = "https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/%s/cookieconsent.min.js"
 
 # CSS
 
 [css.fontAwesome]
-  version = "5.11.2"
-  sri = "sha256-+N4/V/SbAFiW1MPBCXnfnP9QSN3+Keu+NlB+0ev/YKQ="
+  version = "5.12.0-1"
+  sri = "sha256-4w9DunooKSr3MFXHXWyFER38WmPdm361bQS/2KUWZbU="
   url = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/%s/css/all.min.css"
 [css.academicons]
   version = "1.8.6"
@@ -87,6 +97,10 @@
   sri = "sha256-uL8LUd3zkI/lXvc/Hv/oOu8ld6RJcOZiUY/8c+I+3/o="
   url = "https://cdnjs.cloudflare.com/ajax/libs/instantsearch.js/%s/instantsearch-theme-algolia.min.css"
 [css.highlight]
-  version = "9.15.10"
+  version = "9.18.1"
   sri = ""  # No SRI as highlight style is determined at run time.
   url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/%s/styles/%s.min.css"
+[css.cookieconsent]
+  version = "3.1.1"
+  sri = "sha256-zQ0LblD/Af8vOppw18+2anxsuaz3pWYyVWi+bTvTH8Q="
+  url = "https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/%s/cookieconsent.min.css"

+ 6 - 0
data/i18n/languages.yaml

@@ -1,22 +1,28 @@
 "ca": "Català"
+"cs": "Česky"
 "da": "Dansk"
 "de": "Deutsch"
 "el": "Ελληνικά"
 "en": "English"
 "es": "Español"
+"et": "Eesti"
 "eu": "Euskara"
 "fr": "Français"
 "hu": "Magyar"
 "id": "Bahasa Indonesia"
 "it": "Italiano"
 "ja": "日本語"
+"km": "ភាសាខ្មែរ"
 "ko": "한국어"
+"lv": "Latviešu"
 "nl": "Nederlands"
 "pl": "Polski"
 "pt": "Português"
 "ro": "Română"
 "ru": "Русский"
+"sv": "Svenska"
 "tr": "Türkçe"
+"uk": "Українська"
 "vi": "Tiếng Việt"
 "zh": "中文 (简体)"
 "zh-Hant": "中文 (繁體)"

+ 11 - 7
exampleSite/config/_default/config.toml

@@ -31,6 +31,7 @@ hasCJKLanguage = false  # Set `true` for Chinese/Japanese/Korean languages.
 defaultContentLanguageInSubdir = false
 removePathAccents = true  # Workaround for https://github.com/gohugoio/hugo/issues/5687
 
+summaryLength = 30  # Listing summary length in words. Also, see `abstract_length` in `params.toml`.
 paginate = 10  # Number of items per page in paginated lists.
 enableEmoji = true
 footnotereturnlinkcontents = "<sup>^</sup>"
@@ -47,13 +48,16 @@ ignoreFiles = ["\\.ipynb$", ".ipynb_checkpoints$", "\\.Rmd$", "\\.Rmarkdown$", "
   mediaType = "application/manifest+json"
   rel = "manifest"
 
-# Configure BlackFriday Markdown rendering.
-#   See: https://gohugo.io/getting-started/configuration/#configure-blackfriday
-[blackfriday]
-  hrefTargetBlank = true  # `true` opens external links in a new tab. See https://github.com/gohugoio/hugo/issues/2424
-	angledQuotes = false
-	latexDashes = true
-  extensions = ["backslashLineBreak"]
+[markup]
+  defaultMarkdownHandler = "goldmark"
+  [markup.goldmark]
+    [markup.goldmark.renderer]
+      unsafe = true  # Enable user to embed HTML snippets in Markdown content.
+  [markup.highlight]
+    codeFences = false  # Disable Hugo's code highlighter as it conflicts with Academic's highligher.
+  [markup.tableOfContents]
+    startLevel = 2
+    endLevel = 3
 
 [imaging]
   resampleFilter = "lanczos"

+ 31 - 13
exampleSite/config/_default/params.toml

@@ -46,10 +46,6 @@ org_name = ""
 # Description for social sharing and search engines. If undefined, superuser role is used in place.
 description = ""
 
-# Display a logo in navigation bar rather than title (optional).
-#   To enable, place an image in `static/img/` and reference its filename below. To disable, set the value to "".
-logo = ""
-
 ############################
 ## Site Features
 ############################
@@ -75,7 +71,7 @@ privacy_pack = false
 
 # Enable visitors to edit pages?
 #   `repo` defines the repository URL. `editable` defines which page types can be edited.
-edit_page = {repo_url = "https://github.com/gcushen/hugo-academic", repo_branch = "master", editable = {docs = true, page = false, post = false}}
+edit_page = {repo_url = "https://github.com/gcushen/hugo-academic", content_dir = "", repo_branch = "master", editable = {docs = true, page = false, post = false}}
 
 ############################
 ## Contact details
@@ -136,19 +132,15 @@ date_format = "Jan 2, 2006"
 #   Examples: "3:04 pm" or "15:04"
 time_format = "3:04 PM"
 
-# List delimiter (separates parts of an address)
-# Popular separators are ", " (comma), "<br>" (new line), " " (space)
-list_delimiter = ", "
+# Address format (choose from the [address_formats] list below or add you own to the list).
+address_format = "en-us"
 
 ############################
 ## Advanced
 ############################
 
-# Get user avatars from Gravatar.com? (true/false)
-gravatar = false
-
-# Align the main menu to the right of the page? (true/false)
-menu_align_right = false
+# Main menu alignment (l = left, c = center, r = right) and logo options.
+main_menu = {align = "l", show_logo = true}
 
 # Show estimated reading time for posts? (true/false)
 reading_time = true
@@ -163,10 +155,31 @@ sharing = true
 # Link authors to their profile page? (true/false)
 link_authors = true
 
+# Abstract length (characters) in the Compact and Portfolio Card list views. Also, see `summaryLength` in `config.toml`.
+abstract_length = 135
+
 # Load JS plugins
 #   E.g. To load `/assets/js/custom.js`, set `plugins_js = ["custom"]`.
 plugins_js  = []
 
+# Avatars.
+# An avatar is an image that appears next to a user's name.
+# An avatar can be uploaded as an image named `avatar` to each user's profile or fetched from Gravatar.com.
+[avatar]
+  # Get user avatars from Gravatar.com? (true/false)
+  gravatar = false
+
+  # Choose a shape for avatar images. Options: circle, square.
+  shape = "circle"
+
+# Available address formats.
+[address_formats]
+  en-us = {order = ['street', 'city', 'region', 'postcode'], delimiters = [', ', ', ', ' ', '']}
+  en-gb = {order = ['street', 'city', 'region', 'postcode'], delimiters = [', ', ', ', ', ', '']}
+  de = {order = ['street', 'postcode', 'city'], delimiters = ['<br>', ' ', '']}
+  fr-fr = {order = ['street', 'postcode', 'city'], delimiters = ['<br>', ' ', '']}
+  zh = {order = ['postcode', 'region', 'city', 'street'], delimiters = [' ', ' ', ' ', '']}
+
 # Configuration of publication pages.
 [publications]
   # Date format (refer to https://sourcethemes.com/academic/docs/customization/#date-format )
@@ -205,6 +218,11 @@ plugins_js  = []
     shortname = ""  # Paste the shortname from your Disqus dashboard.
     show_count = true  # Show comment count in page header? (true/false)
 
+  # Configuration of Commento.
+  [comments.commento]
+    # If self-hosting Commento, enter its URL here (e.g. "https://commento.?.com"), otherwise leave empty.
+    url = ""
+
 ############################
 ## Search
 ############################

+ 5 - 5
exampleSite/content/authors/admin/_index.md

@@ -38,7 +38,7 @@ education:
     year: 2008
 
 # Social/Academic Networking
-# For available icons, see: https://sourcethemes.com/academic/docs/widgets/#icons
+# For available icons, see: https://sourcethemes.com/academic/docs/page-builder/#icons
 #   For an email link, use "fas" icon pack, "envelope" icon, and a link in the
 #   form "mailto:your-email@example.com" or "#contact" for contact widget.
 social:
@@ -55,16 +55,16 @@ social:
   icon_pack: fab
   link: https://github.com/gcushen
 # Link to a PDF of your resume/CV from the About widget.
-# To enable, copy your resume/CV to `static/files/cv.pdf` and uncomment the lines below.  
+# To enable, copy your resume/CV to `static/files/cv.pdf` and uncomment the lines below.
 # - icon: cv
 #   icon_pack: ai
 #   link: files/cv.pdf
 
 # Enter email to display Gravatar (if Gravatar enabled in Config)
 email: ""
-  
+
 # Organizational groups that you belong to (for People widget)
-#   Set this to `[]` or comment out if you are not using People widget.  
+#   Set this to `[]` or comment out if you are not using People widget.
 user_groups:
 - Researchers
 - Visitors
@@ -72,4 +72,4 @@ user_groups:
 
 Nelson Bighetti is a professor of artificial intelligence at the Stanford AI Lab. His research interests include distributed robotics, mobile computing and programmable matter. He leads the Robotic Neurobiology group, which develops self-reconfiguring robots, systems of self-organizing robots, and mobile sensor networks.
 
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate. 
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.

+ 4 - 0
exampleSite/content/home/featured.md

@@ -21,11 +21,15 @@ subtitle = ""
   # Page order. Descending (desc) or ascending (asc) date.
   order = "desc"
 
+  # Show a "See all pages" link underneath the featured content?
+  link_to_archive = false
+
   # Filter posts by a taxonomy term.
   [content.filters]
     tag = ""
     category = ""
     publication_type = ""
+    author = ""
   
 [design]
   # Toggle between the various page layout types.

+ 4 - 1
exampleSite/content/home/hero.md

@@ -26,7 +26,10 @@ hero_media = "hero-academic.png"
   # Background image.
   # image = ""  # Name of image in `static/img/`.
   # image_darken = 0.6  # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
+  # image_size = "cover"  #  Options are `cover` (default), `contain`, or `actual` size.
+  # image_position = "center"  # Options include `left`, `center` (default), or `right`.
+  # image_parallax = true  # Use a fun parallax-like fixed background effect? true/false
+  
   # Text color (true=light or false=dark).
   text_color_light = true
 

+ 1 - 0
exampleSite/content/home/posts.md

@@ -28,6 +28,7 @@ subtitle = ""
     tag = ""
     category = ""
     publication_type = ""
+    author = ""
     exclude_featured = false
   
 [design]

+ 1 - 0
exampleSite/content/home/publications.md

@@ -28,6 +28,7 @@ subtitle = ""
     tag = ""
     category = ""
     publication_type = ""
+    author = ""
     exclude_featured = false
   
 [design]

+ 1 - 1
exampleSite/content/home/skills.md

@@ -12,7 +12,7 @@ subtitle = ""
 # 
 # Add/remove as many `[[feature]]` blocks below as you like.
 # 
-# For available icons, see: https://sourcethemes.com/academic/docs/widgets/#icons
+# For available icons, see: https://sourcethemes.com/academic/docs/page-builder/#icons
 
 [[feature]]
   icon = "r-project"

+ 1 - 0
exampleSite/content/home/talks.md

@@ -28,6 +28,7 @@ subtitle = ""
     tag = ""
     category = ""
     publication_type = ""
+    author = ""
     exclude_featured = false
     exclude_past = false
     exclude_future = false

+ 134 - 51
exampleSite/content/post/writing-technical-content/index.md

@@ -3,7 +3,6 @@ title: Writing technical content in Academic
 date: 2019-07-12
 math: true
 diagram: true
-markup: mmark
 image:
   placement: 3
   caption: 'Image credit: [**John Moeses Bauan**](https://unsplash.com/photos/OGZtQF8iC0g)'
@@ -37,9 +36,9 @@ data.head()
 
 ### Math
 
-Academic supports a Markdown extension for $\LaTeX$ math. You can enable this feature by toggling the `math` option in your `config/_default/params.toml` file and adding `markup: mmark` to your page front matter.
+Academic supports a Markdown extension for $\LaTeX$ math. You can enable this feature by toggling the `math` option in your `config/_default/params.toml` file.
 
-To render *inline* or *block* math, wrap your LaTeX math with `$$...$$`.
+To render *inline* or *block* math, wrap your LaTeX math with `$...$` or `$$...$$`, respectively.
 
 Example **math block**:
 
@@ -54,7 +53,7 @@ renders as
 
 $$\gamma_{n} = \frac{ \left | \left (\mathbf x_{n} - \mathbf x_{n-1} \right )^T \left [\nabla F (\mathbf x_{n}) - \nabla F (\mathbf x_{n-1}) \right ] \right |}{\left \|\nabla F(\mathbf{x}_{n}) - \nabla F(\mathbf{x}_{n-1}) \right \|^2}$$
 
-Example **inline math** `$$\left \|\nabla F(\mathbf{x}_{n}) - \nabla F(\mathbf{x}_{n-1}) \right \|^2$$` renders as $$\left \|\nabla F(\mathbf{x}_{n}) - \nabla F(\mathbf{x}_{n-1}) \right \|^2$$ .
+Example **inline math** `$\nabla F(\mathbf{x}_{n})$` renders as $\nabla F(\mathbf{x}_{n})$.
 
 Example **multi-line math** using the `\\` math linebreak:
 
@@ -75,79 +74,141 @@ Academic supports a Markdown extension for diagrams. You can enable this feature
 An example **flowchart**:
 
     ```mermaid
-    graph TD;
-      A-->B;
-      A-->C;
-      B-->D;
-      C-->D;
+    graph TD
+    A[Hard] -->|Text| B(Round)
+    B --> C{Decision}
+    C -->|One| D[Result 1]
+    C -->|Two| E[Result 2]
     ```
 
 renders as
 
 ```mermaid
-graph TD;
-  A-->B;
-  A-->C;
-  B-->D;
-  C-->D;
+graph TD
+A[Hard] -->|Text| B(Round)
+B --> C{Decision}
+C -->|One| D[Result 1]
+C -->|Two| E[Result 2]
 ```
 
 An example **sequence diagram**:
 
     ```mermaid
     sequenceDiagram
-      participant Alice
-      participant Bob
-      Alice->John: Hello John, how are you?
-      loop Healthcheck
-          John->John: Fight against hypochondria
-      end
-      Note right of John: Rational thoughts <br/>prevail...
-      John-->Alice: Great!
-      John->Bob: How about you?
-      Bob-->John: Jolly good!
+    Alice->>John: Hello John, how are you?
+    loop Healthcheck
+        John->>John: Fight against hypochondria
+    end
+    Note right of John: Rational thoughts!
+    John-->>Alice: Great!
+    John->>Bob: How about you?
+    Bob-->>John: Jolly good!
     ```
 
 renders as
 
 ```mermaid
 sequenceDiagram
-  participant Alice
-  participant Bob
-  Alice->John: Hello John, how are you?
-  loop Healthcheck
-      John->John: Fight against hypochondria
-  end
-  Note right of John: Rational thoughts <br/>prevail...
-  John-->Alice: Great!
-  John->Bob: How about you?
-  Bob-->John: Jolly good!
+Alice->>John: Hello John, how are you?
+loop Healthcheck
+    John->>John: Fight against hypochondria
+end
+Note right of John: Rational thoughts!
+John-->>Alice: Great!
+John->>Bob: How about you?
+Bob-->>John: Jolly good!
 ```
 
 An example **Gantt diagram**:
 
     ```mermaid
     gantt
-      dateFormat  YYYY-MM-DD
-      section Section
-      A task           :a1, 2014-01-01, 30d
-      Another task     :after a1  , 20d
-      section Another
-      Task in sec      :2014-01-12  , 12d
-      another task      : 24d
+    section Section
+    Completed :done,    des1, 2014-01-06,2014-01-08
+    Active        :active,  des2, 2014-01-07, 3d
+    Parallel 1   :         des3, after des1, 1d
+    Parallel 2   :         des4, after des1, 1d
+    Parallel 3   :         des5, after des3, 1d
+    Parallel 4   :         des6, after des4, 1d
     ```
 
 renders as
 
 ```mermaid
 gantt
-  dateFormat  YYYY-MM-DD
-  section Section
-  A task           :a1, 2014-01-01, 30d
-  Another task     :after a1  , 20d
-  section Another
-  Task in sec      :2014-01-12  , 12d
-  another task      : 24d
+section Section
+Completed :done,    des1, 2014-01-06,2014-01-08
+Active        :active,  des2, 2014-01-07, 3d
+Parallel 1   :         des3, after des1, 1d
+Parallel 2   :         des4, after des1, 1d
+Parallel 3   :         des5, after des3, 1d
+Parallel 4   :         des6, after des4, 1d
+```
+
+An example **class diagram**:
+
+    ```mermaid
+    classDiagram
+    Class01 <|-- AveryLongClass : Cool
+    <<interface>> Class01
+    Class09 --> C2 : Where am i?
+    Class09 --* C3
+    Class09 --|> Class07
+    Class07 : equals()
+    Class07 : Object[] elementData
+    Class01 : size()
+    Class01 : int chimp
+    Class01 : int gorilla
+    class Class10 {
+      <<service>>
+      int id
+      size()
+    }
+    ```
+
+renders as
+
+```mermaid
+classDiagram
+Class01 <|-- AveryLongClass : Cool
+<<interface>> Class01
+Class09 --> C2 : Where am i?
+Class09 --* C3
+Class09 --|> Class07
+Class07 : equals()
+Class07 : Object[] elementData
+Class01 : size()
+Class01 : int chimp
+Class01 : int gorilla
+class Class10 {
+  <<service>>
+  int id
+  size()
+}
+```
+
+An example **state diagram**:
+
+    ```mermaid
+    stateDiagram
+    [*] --> Still
+    Still --> [*]
+    Still --> Moving
+    Moving --> Still
+    Moving --> Crash
+    Crash --> [*]
+    ```
+
+renders as
+
+```mermaid
+stateDiagram
+[*] --> Still
+Still --> [*]
+Still --> Moving
+Moving --> Still
+Moving --> Crash
+Crash --> [*]
 ```
 
 ### Todo lists
@@ -186,14 +247,36 @@ renders as
 
 ### Asides
 
-Academic supports a Markdown extension for asides, also referred to as *notices* or *hints*. By prefixing a paragraph with `A>`, it will render as an aside. You can enable this feature by adding `markup: mmark` to your page front matter, or alternatively using the [*Alert* shortcode](https://sourcethemes.com/academic/docs/writing-markdown-latex/#alerts).
+Academic supports a [shortcode for asides](https://sourcethemes.com/academic/docs/writing-markdown-latex/#alerts), also referred to as *notices*, *hints*, or *alerts*. By wrapping a paragraph in `{{%/* alert note */%}} ... {{%/* /alert */%}}`, it will render as an aside.
+
+```markdown
+{{%/* alert note */%}}
+A Markdown aside is useful for displaying notices, hints, or definitions to your readers.
+{{%/* /alert */%}}
+```
+
+renders as
+
+{{% alert note %}}
+A Markdown aside is useful for displaying notices, hints, or definitions to your readers.
+{{% /alert %}}
+
+### Icons
+
+Academic enables you to use a wide range of [icons from _Font Awesome_ and _Academicons_](https://sourcethemes.com/academic/docs/page-builder/#icons) in addition to [emojis](https://sourcethemes.com/academic/docs/writing-markdown-latex/#emojis).
+
+Here are some examples using the `icon` shortcode to render icons:
 
 ```markdown
-A> A Markdown aside is useful for displaying notices, hints, or definitions to your readers.
+{{</* icon name="terminal" pack="fas" */>}} Terminal  
+{{</* icon name="python" pack="fab" */>}} Python  
+{{</* icon name="r-project" pack="fab" */>}} R
 ```
 
 renders as
 
-A> A Markdown aside is useful for displaying notices, hints, or definitions to your readers.
+{{< icon name="terminal" pack="fas" >}} Terminal  
+{{< icon name="python" pack="fab" >}} Python  
+{{< icon name="r-project" pack="fab" >}} R
 
 ### Did you find this page helpful? Consider sharing it 🙌

+ 4 - 4
exampleSite/content/slides/example/index.md

@@ -13,9 +13,9 @@ slides:
   highlight_style: dracula
 ---
 
-# Welcome to Slides
+# Create slides in Markdown with Academic
 
-[Academic](https://sourcethemes.com/academic/)
+[Academic](https://sourcethemes.com/academic/) | [Documentation](https://sourcethemes.com/academic/docs/managing-content/#create-slides)
 
 ---
 
@@ -161,6 +161,6 @@ Create `assets/css/reveal_custom.css` with:
 
 # Questions?
 
-[Ask](https://discourse.gohugo.io)
+[Ask](https://spectrum.chat/academic)
 
-[Documentation](https://sourcethemes.com/academic/docs/)
+[Documentation](https://sourcethemes.com/academic/docs/managing-content/#create-slides)

Datei-Diff unterdrückt, da er zu groß ist
+ 5 - 0
exampleSite/resources/_gen/assets/scss/scss/main.scss_6c95cc1249b26b124274204dbf970c34.content


+ 1 - 0
exampleSite/resources/_gen/assets/scss/scss/main.scss_6c95cc1249b26b124274204dbf970c34.json

@@ -0,0 +1 @@
+{"Target":"css/academic.css","MediaType":"text/css","Data":{}}

BIN
exampleSite/resources/_gen/images/authors/admin/avatar_hu52a603635ecebd45650b162dadabb4e5_12861_270x270_fill_q90_lanczos_center.jpg


BIN
exampleSite/resources/_gen/images/authors/admin2/avatar_hu52a603635ecebd45650b162dadabb4e5_12861_270x270_fill_q90_lanczos_center.jpg


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-1950s_huaf5482f8cea0c5a703a328640e3b7509_21614_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-apogee_hu4b45d99db97150df01464c393bfd17d4_24119_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-coffee-playfair_hu446a8f670cc5622adcc77b97ba95f6c5_22462_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-dark_hu1e8601ecc47f58eada7743fdcd709d3d_21456_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-default_huba6228b7bdf30e2f03f12ea91b2cba0d_21751_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-forest_hu4f093a1c683134431456584193ea41ee_21797_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-ocean_hu14831ccafc2219f30a7a096fa7617e01_21760_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/home/gallery/gallery/theme-strawberry_hu36b0b347fcca08bd39e2df22dcedbdfb_39532_0x190_resize_lanczos_2.png


BIN
exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_192x192_fill_lanczos_center_2.png


BIN
exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_32x32_fill_lanczos_center_2.png


BIN
exampleSite/resources/_gen/images/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_512x512_fill_lanczos_center_2.png


BIN
exampleSite/resources/_gen/images/post/getting-started/featured_hub9ee31969f44a6711206a2baf9f065b4_241861_1200x0_resize_q90_lanczos.jpg


BIN
exampleSite/resources/_gen/images/post/getting-started/featured_hub9ee31969f44a6711206a2baf9f065b4_241861_150x0_resize_q90_lanczos.jpg


BIN
exampleSite/resources/_gen/images/post/jupyter/featured_hub1daa031c2af6888ff37bd93eb033a1a_71549_150x0_resize_lanczos_2.png


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.