Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃帀 Material 5 Beta 3 #1483

Closed
squidfunk opened this issue Mar 5, 2020 · 60 comments
Closed

馃帀 Material 5 Beta 3 #1483

squidfunk opened this issue Mar 5, 2020 · 60 comments
Labels

Comments

@squidfunk
Copy link
Owner

@squidfunk squidfunk commented Mar 5, 2020

Material 5 Beta 3 is here! See deploy preview.

This will be the last beta before the first RC. The API can be considered stable, so from this beta on no big changes should be expected to the HTML or CSS.

Please post any problems you encounter during migration in this issue.

Installation

pip install "mkdocs-material>=5.0.0b3"

Features

  • Reactive architecture 鈥 try __material.dialog$.next("Hi!") in the console!
  • Instant loading 鈥 make Material behave like a Single Page Application!
  • Improved CSS customization with CSS variables 鈥 define your CI colors!
  • Improved CSS resilience, e.g. proper sidebar locking for customized headers
  • Improved icon integration and configuration 鈥 now including over 5k icons!
  • Added possibility to use any icon for logo, repository and social links
  • Search UI does not freeze anymore (moved to web worker)
  • Search index built only once when using instant loading
  • Improved extensible keyboard handling
  • Support for prebuilt search indexes
  • Support for displaying stars and forks for GitLab repositories
  • Support for scroll snapping of sidebars and search results
  • Reduced HTML and CSS footprint due to deprecation of Internet Explorer support
  • Slight facelifting of some UI elements (Admonitions, tables, ...)

Migration

Material 5 includes some long awaited but breaking changes. The migration guide will help you switch to the latest version.

Changes to mkdocs.yml

Following is a list of changes that need to be made to your mkdocs.yml. Note that you only need to adjust the values if you defined them. Click on the options to see examples.

theme.featuretheme.features

Material 4.x

theme:
  feature:
    tabs: true

Material 5.x

theme:
  features:
    - tabs
    - instant
theme.logo.icontheme.icon.logo

Material 4.x

theme:
  logo:
    icon: cloud

Material 5.x

theme:
  icon:
    logo: material/cloud
extra.repo_icontheme.icon.repo

Material 4.x

extra:
  repo_icon: gitlab

Material 5.x

theme:
  icon:
    repo: fontawesome/brands/gitlab
extra.searchplugins.search

Material 4.x

extra:
  search:
    language: en, de, ru
    tokenizer: [\s\-\.]+

Material 5.x

plugins:
  - search:
      separator: '[\s\-\.]+'
      lang:
        - en
        - de
        - ru
extra.social.*.typeextra.social.*.icon

Material 4.x

extra:
  social:
    - type: github
      link: https://github.com/squidfunk
    - type: twitter
      link: https://twitter.com/squidfunk
    - type: linkedin
      link: https://www.linkedin.com/in/squidfunk

Material 5.x

extra:
  social:
    - icon: fontawesome/brands/github-alt
      link: https://github.com/squidfunk
    - icon: fontawesome/brands/twitter
      link: https://twitter.com/squidfunk
    - icon: fontawesome/brands/linkedin
      link: https://www.linkedin.com/in/squidfunk/

Changes to *.html files

The templates have undergone a set of necessary changes to make them future-proof. If you've used theme extension to override a template block or HTML file, make sure that the structure of the HTML matches the new structure.

  1. If you've overridden a block, check base.html for potential changes
  2. If you've overridden a template, check the respective *.html file for potential changes
base.html
diff --git a/material/base.html b/material/base.html
index f26b7283..34340f8c 100644
--- a/material/base.html
+++ b/material/base.html
@@ -2,7 +2,6 @@
   This file was automatically generated - do not edit
 -#}
 {% import "partials/language.html" as lang with context %}
-{% set feature = config.theme.feature %}
 {% set palette = config.theme.palette %}
 {% set font = config.theme.font %}
 <!doctype html>
@@ -30,21 +29,8 @@
       {% elif config.site_author %}
         <meta name="author" content="{{ config.site_author }}">
       {% endif %}
-      {% for key in [
-        "clipboard.copy",
-        "clipboard.copied",
-        "search.language",
-        "search.pipeline.stopwords",
-        "search.pipeline.trimmer",
-        "search.result.none",
-        "search.result.one",
-        "search.result.other",
-        "search.tokenizer"
-      ] %}
-        <meta name="lang:{{ key }}" content="{{ lang.t(key) }}">
-      {% endfor %}
       <link rel="shortcut icon" href="{{ config.theme.favicon | url }}">
       <meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-5.0.0b2-1">
     {% endblock %}
     {% block htmltitle %}
       {% if page and page.meta and page.meta.title %}
@@ -56,9 +42,9 @@
       {% endif %}
     {% endblock %}
     {% block styles %}
-      <link rel="stylesheet" href="{{ 'assets/stylesheets/application.adb8469c.css' | url }}">
+      <link rel="stylesheet" href="{{ 'assets/stylesheets/main.14bb5ffa.min.css' | url }}">
       {% if palette.primary or palette.accent %}
-        <link rel="stylesheet" href="{{ 'assets/stylesheets/application-palette.a8b3c06d.css' | url }}">
+        <link rel="stylesheet" href="{{ 'assets/stylesheets/palette.f5f04e6f.min.css' | url }}">
       {% endif %}
       {% if palette.primary %}
         {% import "partials/palette.html" as map %}
@@ -68,25 +54,22 @@
         <meta name="theme-color" content="{{ primary }}">
       {% endif %}
     {% endblock %}
     {% block libs %}
-      <script src="{{ 'assets/javascripts/modernizr.86422ebf.js' | url }}"></script>
     {% endblock %}
     {% block fonts %}
       {% if font != false %}
         <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
         <link rel="stylesheet" href="https://fonts.googleapis.com/css?family={{
             font.text | replace(' ', '+') + ':300,400,400i,700%7C' +
             font.code | replace(' ', '+')
           }}&display=fallback">
         <style>body,input{font-family:"{{ font.text }}","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"{{ font.code }}","Courier New",Courier,monospace}</style>
       {% endif %}
     {% endblock %}
-    <link rel="stylesheet" href="{{ 'assets/fonts/material-icons.css' | url }}">
     {% if config.extra.manifest %}
       <link rel="manifest" href="{{ config.extra.manifest | url }}" crossorigin="use-credentials">
     {% endif %}
     {% for path in config["extra_css"] %}
       <link rel="stylesheet" href="{{ path | url }}">
     {% endfor %}
     {% block analytics %}
       {% if config.google_analytics %}
@@ -95,47 +78,46 @@
     {% endblock %}
     {% block extrahead %}{% endblock %}
   </head>
+  {% set direction = config.theme.direction | default(lang.t('direction')) %}
   {% if palette.primary or palette.accent %}
     {% set primary = palette.primary | replace(" ", "-") | lower %}
     {% set accent  = palette.accent  | replace(" ", "-") | lower %}
-    <body dir="{{ lang.t('direction') }}" data-md-color-primary="{{ primary }}" data-md-color-accent="{{ accent }}">
+    <body dir="{{ direction }}" data-md-color-primary="{{ primary }}" data-md-color-accent="{{ accent }}">
   {% else %}
-    <body dir="{{ lang.t('direction') }}">
+    <body dir="{{ direction }}">
   {% endif %}
-    <svg class="md-svg">
-      <defs>
-        {% set platform = config.extra.repo_icon or config.repo_url %}
-        {% if "github" in platform %}
-          {% include "assets/images/icons/github.f0b8504a.svg" %}
-        {% elif "gitlab" in platform %}
-          {% include "assets/images/icons/gitlab.6dd19c00.svg" %}
-        {% elif "bitbucket" in platform %}
-          {% include "assets/images/icons/bitbucket.1b09e088.svg" %}
-        {% endif %}
-      </defs>
-    </svg>
     <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
     <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
+    <label class="md-overlay" for="__drawer"></label>
     {% if page.toc | first is defined %}
-      <a href="{{ (page.toc | first).url }}" tabindex="0" class="md-skip">
+      {% set skip = page.toc | first %}
+      <a href="{{ skip.url | url }}" class="md-skip" data-md-component="skip">
         {{ lang.t('skip.link.title') }}
       </a>
     {% endif %}
+    {% if self.announce() %}
+      <aside class="md-announce" data-md-component="announce">
+        <div class="md-announce__inner md-grid md-typeset">
+          {% block announce %}{% endblock %}
+        </div>
+      </aside>
+    {% endif %}
     {% block header %}
       {% include "partials/header.html" %}
     {% endblock %}
-    <div class="md-container">
+    <div class="md-container" data-md-component="container">
       {% block hero %}
         {% if page and page.meta and page.meta.hero %}
           {% include "partials/hero.html" with context %}
         {% endif %}
       {% endblock %}
-      {% if feature.tabs %}
-        {% include "partials/tabs.html" %}
-      {% endif %}
+      {% block tabs %}
+        {% if "tabs" in config.theme.features %}
+          {% include "partials/tabs.html" %}
+        {% endif %}
+      {% endblock %}
-      <main class="md-main" role="main">
-        <div class="md-main__inner md-grid" data-md-component="container">
+      <main class="md-main" data-md-component="main">
+        <div class="md-main__inner md-grid">
           {% block site_nav %}
             {% if nav %}
               <div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
@@ -160,41 +142,25 @@
             <article class="md-content__inner md-typeset">
               {% block content %}
                 {% if page.edit_url %}
-                  <a href="{{ page.edit_url }}" title="{{ lang.t('edit.link.title') }}" class="md-icon md-content__icon">&#xE3C9;</a>
+                  <a href="{{ page.edit_url }}" title="{{ lang.t('edit.link.title') }}" class="md-content__button md-icon">
+                    {% include ".icons/material/pencil.svg" %}
+                  </a>
                 {% endif %}
+                {% block source %}
+                  {% if page and page.meta and page.meta.source %}
+                    {% include "partials/source-link.html" %}
+                  {% endif %}
+                {% endblock %}
                 {% if not "\x3ch1" in page.content %}
                   <h1>{{ page.title | default(config.site_name, true)}}</h1>
                 {% endif %}
                 {{ page.content }}
-                {% block source %}
-                  {% if page and page.meta and page.meta.source %}
-                    <h2 id="__source">{{ lang.t("meta.source") }}</h2>
-                    {% set repo = config.repo_url %}
-                    {% if repo | last == "/" %}
-                      {% set repo = repo[:-1] %}
-                    {% endif %}
-                    {% set path = page.meta.path | default([""]) %}
-                    {% set file = page.meta.source %}
-                    <a href="{{ [repo, path, file] | join('/') }}" title="{{ file }}" class="md-source-file">
-                      {{ file }}
-                    </a>
-                  {% endif %}
-                {% endblock %}
+                {% if page and page.meta %}
+                  {% if page.meta.git_revision_date_localized or
+                        page.meta.revision_date
+                  %}
+                    {% include "partials/source-date.html" %}
+                  {% endif %}
+                {% endblock %}
-                {% if page and page.meta and (
-                      page.meta.git_revision_date_localized or
-                      page.meta.revision_date
-                ) %}
-                  {% set label = lang.t("source.revision.date") %}
-                  <hr>
-                  <div class="md-source-date">
-                    <small>
-                      {% if page.meta.git_revision_date_localized %}
-                        {{ label }}: {{ page.meta.git_revision_date_localized }}
-                      {% elif page.meta.revision_date %}
-                        {{ label }}: {{ page.meta.revision_date }}
-                      {% endif %}
-                    </small>
-                  </div>
-                {% endif %}
-              {% endblock %}
               {% block disqus %}
@@ -208,29 +174,40 @@
         {% include "partials/footer.html" %}
       {% endblock %}
     </div>
+    {% block config %}
+      <script>var __config={}</script>
+    {% endblock %}
     {% block scripts %}
-      <script src="{{ 'assets/javascripts/application.df00da5d.js' | url }}"></script>
-      {% if lang.t("search.language") != "en" %}
-        {% set languages = lang.t("search.language").split(",") %}
-        {% if languages | length and languages[0] != "" %}
-          {% set path = "assets/javascripts/lunr/" %}
-          <script src="{{ (path ~ 'lunr.stemmer.support.js') | url }}"></script>
-          {% for language in languages | map("trim") %}
-            {% if language != "en" %}
-              {% if language == "ja" %}
-                <script src="{{ (path ~ 'tinyseg.js') | url }}"></script>
-              {% endif %}
-              {% if language in ("ar", "da", "de", "es", "fi", "fr", "hu", "it", "ja", "nl", "no", "pt", "ro", "ru", "sv", "th", "tr", "vi") %}
-                <script src="{{ (path ~ 'lunr.' ~ language ~ '.js') | url }}"></script>
-              {% endif %}
-            {% endif %}
-          {% endfor %}
-          {% if languages | length > 1 %}
-            <script src="{{ (path ~ 'lunr.multi.js') | url }}"></script>
-          {% endif %}
-        {% endif %}
-      {% endif %}
-      <script>app.initialize({version:"{{ mkdocs_version }}",url:{base:"{{ base_url }}"}})</script>
+      <script src="{{ 'assets/javascripts/vendor.31a2e7b9.min.js' | url }}"></script>
+      <script src="{{ 'assets/javascripts/bundle.5b33ad8d.min.js' | url }}"></script>
+      {%- set translations = {} -%}
+      {%- for key in [
+        "clipboard.copy",
+        "clipboard.copied",
+        "search.config.lang",
+        "search.config.pipeline",
+        "search.config.separator",
+        "search.result.placeholder",
+        "search.result.none",
+        "search.result.one",
+        "search.result.other"
+      ] -%}
+        {%- set _ = translations.update({ key: lang.t(key) }) -%}
+      {%- endfor -%}
+      <script id="__lang" type="application/json">
+        {{ translations | tojson }}
+      </script>
+      <script>
+        __material = initialize(Object.assign({
+          url: {
+            base: "{{ base_url }}",
+            worker: {
+              search: "{{ 'assets/javascripts/worker/search.edc88caf.min.js' | url }}"
+            }
+          },
+          features: {{ config.theme.features | tojson }}
+        }, __config))
+      </script>
       {% for path in config["extra_javascript"] %}
         <script src="{{ path | url }}"></script>
       {% endfor %}
partials/footer.html
diff --git a/material/partials/footer.html b/material/partials/footer.html
index c2f5a1c0..ca248f62 100644
--- a/material/partials/footer.html
+++ b/material/partials/footer.html
@@ -7,32 +7,32 @@
     <div class="md-footer-nav">
       <nav class="md-footer-nav__inner md-grid">
         {% if page.previous_page %}
-          <a href="{{ page.previous_page.url | url }}" title="{{ page.previous_page.title | striptags }}" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
-            <div class="md-flex__cell md-flex__cell--shrink">
-              <i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
+          <a href="{{ page.previous_page.url | url }}" title="{{ page.previous_page.title | striptags }}" class="md-footer-nav__link md-footer-nav__link--prev" rel="prev">
+            <div class="md-footer-nav__button md-icon">
+              {% include ".icons/material/arrow-left.svg" %}
             </div>
-            <div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
-              <span class="md-flex__ellipsis">
+            <div class="md-footer-nav__title">
+              <div class="md-ellipsis">
                 <span class="md-footer-nav__direction">
                   {{ lang.t("footer.previous") }}
                 </span>
                 {{ page.previous_page.title }}
-              </span>
+              </div>
             </div>
           </a>
         {% endif %}
         {% if page.next_page %}
-          <a href="{{ page.next_page.url | url }}" title="{{ page.next_page.title | striptags }}" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
-            <div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
-              <span class="md-flex__ellipsis">
+          <a href="{{ page.next_page.url | url }}" title="{{ page.next_page.title | striptags }}" class="md-footer-nav__link md-footer-nav__link--next" rel="next">
+            <div class="md-footer-nav__title">
+              <div class="md-ellipsis">
                 <span class="md-footer-nav__direction">
                   {{ lang.t("footer.next") }}
                 </span>
                 {{ page.next_page.title }}
-              </span>
+              </div>
             </div>
-            <div class="md-flex__cell md-flex__cell--shrink">
-              <i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
+            <div class="md-footer-nav__button md-icon">
+              {% include ".icons/material/arrow-right.svg" %}
             </div>
           </a>
         {% endif %}
partials/header.html
diff --git a/material/partials/header.html b/material/partials/header.html
index cfaf1a3b..90438e8c 100644
--- a/material/partials/header.html
+++ b/material/partials/header.html
@@ -3,50 +3,44 @@
 -#}
 <header class="md-header" data-md-component="header">
   <nav class="md-header-nav md-grid">
-    <div class="md-flex">
-      <div class="md-flex__cell md-flex__cell--shrink">
-        <a href="{{ config.site_url | default(nav.homepage.url, true) | url }}" title="{{ config.site_name }}" aria-label="{{ config.site_name }}" class="md-header-nav__button md-logo">
-          {% if config.theme.logo.icon %}
-            <i class="md-icon">{{ config.theme.logo.icon }}</i>
-          {% else %}
-            <img alt="logo" src="{{ config.theme.logo | url }}" width="24" height="24">
-          {% endif %}
-        </a>
-      </div>
-      <div class="md-flex__cell md-flex__cell--shrink">
-        <label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
-      </div>
-      <div class="md-flex__cell md-flex__cell--stretch">
-        <div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
-          {% if config.site_name == page.title %}
+    <a href="{{ config.site_url | default(nav.homepage.url, true) | url }}" title="{{ config.site_name }}" aria-label="{{ config.site_name }}" class="md-header-nav__button md-logo">
+      {% if config.theme.logo %}
+        <img src="{{ config.theme.logo | url }}" alt="logo">
+      {% else %}
+        {% include ".icons/" ~ config.theme.icon.logo ~ ".svg" %}
+      {% endif %}
+    </a>
+    <label class="md-header-nav__button md-icon" for="__drawer">
+      {% include ".icons/material/menu" ~ ".svg" %}
+    </label>
+    <div class="md-header-nav__title" data-md-component="header-title">
+      <div class="md-header-nav__ellipsis md-ellipsis">
+        {% if config.site_name == page.title %}
+          {{ config.site_name }}
+        {% else %}
+          <span class="md-header-nav__topic">
             {{ config.site_name }}
-          {% else %}
-            <span class="md-header-nav__topic">
-              {{ config.site_name }}
-            </span>
-            <span class="md-header-nav__topic">
-              {% if page and page.meta and page.meta.title %}
-                {{ page.meta.title }}
-              {% else %}
-                {{ page.title }}
-              {% endif %}
-            </span>
-          {% endif %}
-        </div>
-      </div>
-      <div class="md-flex__cell md-flex__cell--shrink">
-        {% if "search" in config["plugins"] %}
-          <label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
-          {% include "partials/search.html" %}
+          </span>
+          <span class="md-header-nav__topic">
+            {% if page and page.meta and page.meta.title %}
+              {{ page.meta.title }}
+            {% else %}
+              {{ page.title }}
+            {% endif %}
+          </span>
         {% endif %}
       </div>
-      {% if config.repo_url %}
-        <div class="md-flex__cell md-flex__cell--shrink">
-          <div class="md-header-nav__source">
-            {% include "partials/source.html" %}
-          </div>
-        </div>
-      {% endif %}
     </div>
+    {% if "search" in config["plugins"] %}
+      <label class="md-header-nav__button md-icon" for="__search">
+        {% include ".icons/material/magnify.svg" %}
+      </label>
+      {% include "partials/search.html" %}
+    {% endif %}
+    {% if config.repo_url %}
+      <div class="md-header-nav__source">
+        {% include "partials/source.html" %}
+      </div>
+    {% endif %}
   </nav>
 </header>
partials/hero.html
diff --git a/material/partials/hero.html b/material/partials/hero.html
index 3d6a2cc8..2c244e18 100644
--- a/material/partials/hero.html
+++ b/material/partials/hero.html
@@ -1,9 +1,8 @@
 {#-
   This file was automatically generated - do not edit
 -#}
-{% set feature = config.theme.feature %}
 {% set class = "md-hero" %}
-{% if not feature.tabs %}
+{% if "tabs" not in config.theme.features %}
   {% set class = "md-hero md-hero--expand" %}
 {% endif %}
 <div class="{{ class }}" data-md-component="hero">
partials/language.html
diff --git a/material/partials/language.html b/material/partials/language.html
index d0314ffc..46188a6b 100644
--- a/material/partials/language.html
+++ b/material/partials/language.html
@@ -3,12 +3,4 @@
 -#}
 {% import "partials/language/" + config.theme.language + ".html" as lang %}
 {% import "partials/language/en.html" as fallback %}
-{% macro t(key) %}{{ {
-  "direction": config.theme.direction,
-  "search.language": (
-    config.extra.search | default({})
-  ).language,
-  "search.tokenizer": (
-    config.extra.search | default({})
-  ).tokenizer | default("", true),
-}[key] or lang.t(key) or fallback.t(key) }}{% endmacro %}
+{% macro t(key) %}{{ lang.t(key) | default(fallback.t(key)) }}{% endmacro %}
partials/nav-item.html
diff --git a/material/partials/nav-item.html b/material/partials/nav-item.html
index 54c06034..15e626ab 100644
--- a/material/partials/nav-item.html
+++ b/material/partials/nav-item.html
@@ -8,15 +8,21 @@
 {% if nav_item.children %}
   <li class="{{ class }} md-nav__item--nested">
     {% if nav_item.active %}
       <input class="md-nav__toggle md-toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}" checked>
     {% else %}
       <input class="md-nav__toggle md-toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}">
     {% endif %}
     <label class="md-nav__link" for="{{ path }}">
       {{ nav_item.title }}
+      <span class="md-nav__icon md-icon">
+        {% include ".icons/material/chevron-right.svg" %}
+      </span>
     </label>
-    <nav class="md-nav" data-md-component="collapsible" data-md-level="{{ level }}">
+    <nav class="md-nav" data-md-level="{{ level }}">
       <label class="md-nav__title" for="{{ path }}">
+        <span class="md-nav__icon md-icon">
+          {% include ".icons/material/arrow-left.svg" %}
+        </span>
         {{ nav_item.title }}
       </label>
       <ul class="md-nav__list" data-md-scrollfix>
@@ -32,13 +38,16 @@
 {% elif nav_item == page %}
   <li class="{{ class }}">
     {% set toc_ = page.toc %}
     <input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
     {% if toc_ | first is defined and "\x3ch1 id=" in page.content %}
       {% set toc_ = (toc_ | first).children %}
     {% endif %}
     {% if toc_ | first is defined %}
       <label class="md-nav__link md-nav__link--active" for="__toc">
         {{ nav_item.title }}
+        <span class="md-nav__icon md-icon">
+          {% include ".icons/material/table-of-contents.svg" %}
+        </span>
       </label>
     {% endif %}
     <a href="{{ nav_item.url | url }}" title="{{ nav_item.title | striptags }}" class="md-nav__link md-nav__link--active">
partials/nav.html
diff --git a/material/partials/nav.html b/material/partials/nav.html
index b72383d4..0735f58e 100644
--- a/material/partials/nav.html
+++ b/material/partials/nav.html
@@ -2,12 +2,12 @@
   This file was automatically generated - do not edit
 -#}
 <nav class="md-nav md-nav--primary" data-md-level="0">
-  <label class="md-nav__title md-nav__title--site" for="__drawer">
-    <a href="{{ config.site_url | default(nav.homepage.url, true) | url }}" title="{{ config.site_name }}" class="md-nav__button md-logo">
-      {% if config.theme.logo.icon %}
-        <i class="md-icon">{{ config.theme.logo.icon }}</i>
+  <label class="md-nav__title" for="__drawer">
+    <a href="{{ config.site_url | default(nav.homepage.url, true) | url }}" title="{{ config.site_name }}" aria-label="{{ config.site_name }}" class="md-nav__button md-logo">
+      {% if config.theme.logo %}
+        <img src="{{ config.theme.logo | url }}" alt="logo">
       {% else %}
-        <img alt="logo" src="{{ config.theme.logo | url }}" width="48" height="48">
+        {% include ".icons/" ~ config.theme.icon.logo ~ ".svg" %}
       {% endif %}
     </a>
     {{ config.site_name }}
partials/search.html
diff --git a/material/partials/search.html b/material/partials/search.html
index 4863b708..4510355b 100644
--- a/material/partials/search.html
+++ b/material/partials/search.html
@@ -6,15 +6,18 @@
   <label class="md-search__overlay" for="__search"></label>
   <div class="md-search__inner" role="search">
     <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" aria-label="search" name="query" placeholder="{{ lang.t('search.placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
+      <input type="text" class="md-search__input" name="query" aria-label="search" placeholder="{{ lang.t('search.placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active" required>
       <label class="md-search__icon md-icon" for="__search">
+        {% include ".icons/material/magnify.svg" %}
+        {% include ".icons/material/arrow-left.svg" %}
       </label>
-      <button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
-        &#xE5CD;
+      <button type="reset" class="md-search__icon md-icon" data-md-component="search-reset" tabindex="-1">
+        {% include ".icons/material/close.svg" %}
       </button>
     </form>
     <div class="md-search__output">
       <div class="md-search__scrollwrap" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="result">
+        <div class="md-search-result" data-md-component="search-result">
           <div class="md-search-result__meta">
             {{ lang.t("search.result.placeholder") }}
           </div>
partials/social.html
diff --git a/material/partials/social.html b/material/partials/social.html
index 391385e5..8b4ebdfe 100644
--- a/material/partials/social.html
+++ b/material/partials/social.html
@@ -3,9 +3,10 @@
 -#}
 {% if config.extra.social %}
   <div class="md-footer-social">
-    <link rel="stylesheet" href="{{ 'assets/fonts/font-awesome.css' | url }}">
     {% for social in config.extra.social %}
-      <a href="{{ social.link }}" target="_blank" rel="noopener" title="{{ social.type }}" class="md-footer-social__link fa fa-{{ social.type }}"></a>
+      <a href="{{ social.link }}" target="_blank" rel="noopener" class="md-footer-social__link">
+        {% include ".icons/" ~ social.icon ~ ".svg" %}
+      </a>
     {% endfor %}
   </div>
 {% endif %}
partials/source-date.html
diff --git a/material/partials/source-date.html b/material/partials/source-date.html
new file mode 100644
index 00000000..9c72b8bc
--- /dev/null
+++ b/material/partials/source-date.html
@@ -0,0 +1,15 @@
+{#-
+  This file was automatically generated - do not edit
+-#}
+{% import "partials/language.html" as lang with context %}
+{% set label = lang.t("source.revision.date") %}
+<hr>
+<div class="md-source-date">
+  <small>
+    {% if page.meta.git_revision_date_localized %}
+      {{ label }}: {{ page.meta.git_revision_date_localized }}
+    {% elif page.meta.revision_date %}
+      {{ label }}: {{ page.meta.revision_date }}
+    {% endif %}
+  </small>
+</div>
partials/source-link.html
diff --git a/material/partials/source-link.html b/material/partials/source-link.html
new file mode 100644
index 00000000..86418fa1
--- /dev/null
+++ b/material/partials/source-link.html
@@ -0,0 +1,17 @@
+{#-
+  This file was automatically generated - do not edit
+-#}
+{% import "partials/language.html" as lang with context %}
+{% set repo = config.repo_url %}
+{% if repo | last == "/" %}
+  {% set repo = repo[:-1] %}
+{% endif %}
+{% set path = page.meta.path | default([""]) %}
+{% set file = page.meta.source %}
+{% set repo_icon = config.extra.repo_icon | default(
+  "fontawesome/brands/git-alt"
+) %}
+<a href="{{ [repo, path, page.meta.source] | join('/') }}" title="{{ file }}" class="md-content__button md-icon">
+  {{ lang.t("meta.source") }}
+  {% include ".icons/" ~ repo_icon ~ ".svg" %}
+</a>
partials/source.html
diff --git a/material/partials/source.html b/material/partials/source.html
index 742d42de..a65295a4 100644
--- a/material/partials/source.html
+++ b/material/partials/source.html
@@ -2,24 +2,10 @@
   This file was automatically generated - do not edit
 -#}
 {% import "partials/language.html" as lang with context %}
-{% set platform = config.extra.repo_icon or config.repo_url %}
-{% if "github" in platform %}
-  {% set repo_type = "github" %}
-{% elif "gitlab" in platform %}
-  {% set repo_type = "gitlab" %}
-{% elif "bitbucket" in platform %}
-  {% set repo_type = "bitbucket" %}
-{% else %}
-  {% set repo_type = "" %}
-{% endif %}
-<a href="{{ config.repo_url }}" title="{{ lang.t('source.link.title') }}" class="md-source" data-md-source="{{ repo_type }}">
-  {% if repo_type %}
-    <div class="md-source__icon">
-      <svg viewBox="0 0 24 24" width="24" height="24">
-        <use xlink:href="#__{{ repo_type }}" width="24" height="24"></use>
-      </svg>
-    </div>
-  {% endif %}
+<a href="{{ config.repo_url }}" title="{{ lang.t('source.link.title') }}" class="md-source">
+  <div class="md-source__icon md-icon">
+    {% include ".icons/" ~ config.theme.icon.repo ~ ".svg" %}
+  </div>
   <div class="md-source__repository">
     {{ config.repo_name }}
   </div>
partials/tabs-item.html
diff --git a/material/partials/tabs-item.html b/material/partials/tabs-item.html
index 1f3179d3..64ced43b 100644
--- a/material/partials/tabs-item.html
+++ b/material/partials/tabs-item.html
@@ -1,7 +1,7 @@
 {#-
   This file was automatically generated - do not edit
 -#}
-{% if nav_item.is_homepage %}
+{% if nav_item.is_homepage or nav_item.url == "index.html" %}
   <li class="md-tabs__item">
     {% if not page.ancestors | length and nav | selectattr("url", page.url) %}
       <a href="{{ nav_item.url | url }}" class="md-tabs__link md-tabs__link--active">
partials/toc.html
diff --git a/material/partials/toc.html b/material/partials/toc.html
index 14a5e070..db4cfbea 100644
--- a/material/partials/toc.html
+++ b/material/partials/toc.html
@@ -3,34 +3,21 @@
 -#}
 {% import "partials/language.html" as lang with context %}
 <nav class="md-nav md-nav--secondary">
   {% set toc = page.toc %}
   {% if toc | first is defined and "\x3ch1 id=" in page.content %}
     {% set toc = (toc | first).children %}
   {% endif %}
   {% if toc | first is defined %}
     <label class="md-nav__title" for="__toc">
+      <span class="md-nav__icon md-icon">
+        {% include ".icons/material/arrow-left.svg" %}
+      </span>
       {{ lang.t("toc.title") }}
     </label>
     <ul class="md-nav__list" data-md-scrollfix>
       {% for toc_item in toc %}
         {% include "partials/toc-item.html" %}
       {% endfor %}
-      {% if page.meta.source and page.meta.source | length > 0 %}
-        <li class="md-nav__item">
-          <a href="#__source" class="md-nav__link md-nav__link--active">
-            {{ lang.t("meta.source") }}
-          </a>
-        </li>
-      {% endif %}
-      {% set disqus = config.extra.disqus %}
-      {% if page and page.meta and page.meta.disqus is string %}
-        {% set disqus = page.meta.disqus %}
-      {% endif %}
-      {% if not page.is_homepage and disqus %}
-        <li class="md-nav__item">
-          <a href="#__comments" class="md-nav__link md-nav__link--active">
-            {{ lang.t("meta.comments") }}
-          </a>
-        </li>
-      {% endif %}
     </ul>
   {% endif %}
 </nav>

Notes

Instant loading

The basic idea is: why should we reconstruct the whole page again and again when only the content and navigation changes? When instant loading is enabled, all internal links are intercepted and dispatched via XHR. The resulting document is parsed, injected and all event handlers are automatically rebound. The search index will remain intact in-between loads.

With instant loading enabled, Material effectively behaves like a Single Page Application.

This feature shows the true beauty of the new architecture - everything is observable and automatically updates when new values become available. The following gifs were recorded on Fast 3G to show the speed advantage of instant loading:

Without instant loading

No Instant Loading

With instant loading

Instant Loading

Social links

FontAwesome was updated to the latest version and is now provided via inline SVGs which reduces the overall footprint. To reference an icon, reference its path from the top-level .icons directory which is distributed with the theme without the .svg at the end. Besides FontAwesome, the Material icons and GitHub's octicons are also bundled with the theme.

Note that mkdocs build will now terminate with an error if an invalid icon is referenced.

Known bugs

  • Instant loading sometimes doubles the URL (race condition) 80f1d3e
  • direction="None" when no direction is set 584eac8

Feedback is appreciated!

@squidfunk squidfunk pinned this issue Mar 5, 2020
This was referenced Mar 5, 2020
@XhmikosR

This comment has been minimized.

Copy link
Contributor

@XhmikosR XhmikosR commented Mar 5, 2020

@squidfunk just started testing this and looks good so far!

A few thoughts:

  1. there's an HTML validation error Bad value None for attribute dir on element body.
  2. not sure if it's intentional but the repo icon is now the git icon

Everything else seems to work fine from my testing so far 馃

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 5, 2020

@XhmikosR thanks for reporting!

  1. Seems to be related to an invalid default value of config.theme.direction. Should have no impact on usage, but should be easy to fix

  2. Yep, the default icon now is just the git icon. To change it see the original post - it can now be changed to any icon!

@XhmikosR

This comment has been minimized.

Copy link
Contributor

@XhmikosR XhmikosR commented Mar 5, 2020

Yep, the default icon now is just the git icon. To change it see the original post - it can now be changed to any icon!

All good, I changed it already, I was wondering if the change was intentional :)

Another thing I noticed is that there are some new Lighthouse issues (ignore the page is blocked and canonical errors): https://lighthouse-dot-webdotdevsite.appspot.com//lh/html?url=https://deploy-preview-275--pihole-docs.netlify.com/

Also, I was wondering, have you thought about loading the search index file when the search form is focused or something like that, instead of page load?

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 5, 2020

There's a lot of noise in the Lighthouse report. Could you isolate what you mean specifically? The link titles? We should definitely fix them.

Regarding the search index 鈥 we could load it on focus, but then we'll have a delay and I don't want to do that at least until we have a loading indicator. I would try to leave it as is for the initial release and if it leads to problems or people complain we can delay it (or even introduce an option whether to load on page load or on interaction).

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

@facelessuser reported a problem on Gitter (which currently gives me 504) where sometimes, when instant loading is enabled, the URL would double, so a link click on ./installation/ would resolve to ./installation/installation. This is caused by the first request being served with a 304 which the theme currently doesn't recognize as a successful XHR (due to no response body) and will fallback to regular loading which then doubles the entry because in MkDocs, all internal links are relative. I added it to the list of known bugs in the OP and will provide a fix in a post release.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 6, 2020

  1. As discussed, IE deprecation is a big thing for us, but I fully understand and support that decision. I think I will just go for it, release a version without IE support, and see how strong the backlash from our customers is. If it is too strong, I'll follow up on what you described here.
    Are you planning to display some kind of browser info message for IE users? If not, I will add that to our docs project myself. IE check:
return (navigator.userAgent.indexOf("MSIE ") > -1 || navigator.userAgent.indexOf("Trident/") > -1);
  1. Can you easily disable instant loading on runtime? If yes, a check that disables instant loading on local access (file:// protocol) would be nice. If not, never mind.
@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

@wilhelmer regarding 1., I would like to leave it up to the user. Maybe we'll integrate something into the theme later, but I don't want to force a specific way onto users. Also, some people may decide they want to support IE. Regarding 2., that's actually a good idea. We could detect the file:// protocol and omit the repository info loading and instant loading altogether.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

The race condition which @facelessuser reported and direction=None were fixed and released as part of 5.0.0b3-2. Upgrade with:

pip install --upgrade --force-reinstall "mkdocs-material>=5.0.0b3"
@XhmikosR

This comment has been minimized.

Copy link
Contributor

@XhmikosR XhmikosR commented Mar 6, 2020

There's a lot of noise in the Lighthouse report. Could you isolate what you mean specifically? The link titles? We should definitely fix them.

I meant these:

  1. Buttons do not have an accessible name
  2. Links do not have a discernible name (for the footer icons using aria-hidden with an aria-label might be enough)
  3. Tap targets are not sized appropriately (AFAICT this is because you set a width and height for the a elements without margin between them, so the links are very close to one another)
@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

Could you craft a PR so we can discuss some potential fixes? Unfortunately I have too much stuff on my plate to finally get v5 out of the door.

@XhmikosR

This comment has been minimized.

Copy link
Contributor

@XhmikosR XhmikosR commented Mar 6, 2020

I'll see what I can do because I'm not familiar with your development process (but shouldn't be too hard judging from a quick look). I can make a separate issue if you want to track the Lighthouse issues in the meantime, although these are issues specific to v5.0.0.

@XhmikosR

This comment has been minimized.

Copy link
Contributor

@XhmikosR XhmikosR commented Mar 6, 2020

BTW if v5 doesn't support IE, you can probably remove <meta http-equiv="x-ua-compatible" content="ie=edge">

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

The templates in question are located in the src folder (not material), so just included your changes there. You may also remove the IE-compat header 馃槉

@FISHMANPET

This comment has been minimized.

Copy link
Contributor

@FISHMANPET FISHMANPET commented Mar 6, 2020

Is there an example of using the custom CSS stuff to change colors? It looks like I have to build a CSS file with color definitions in it and somehow tell mkdocs to use that CSS? Looks like there's nothing in the docs about it yet either. If I had an example I could probably reverse engineer and maybe even add some stuff to the docs about it.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

@FISHMANPET I linked the definitions in the original post; here it is again:

:root {
// Default color shades
--md-default-fg-color: hsla(0, 0%, 0%, 0.87);
--md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);
--md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.26);
--md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);
--md-default-bg-color: hsla(0, 0%, 100%, 1);
--md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);
--md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);
--md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);
// Primary color shades
--md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);
--md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-300)}, 1);
--md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1);
--md-primary-bg-color: var(--md-default-bg-color);
--md-primary-bg-color--light: var(--md-default-bg-color--light);
// Accent color shades
--md-accent-fg-color: hsla(#{hex2hsl($clr-indigo-a200)}, 1);
--md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-indigo-a200)}, 0.1);
--md-accent-bg-color: var(--md-default-bg-color);
--md-accent-bg-color--light: var(--md-default-bg-color--light);
// Code block color shades
--md-code-bg-color: hsla(0, 0%, 92.5%, 0.5);
--md-code-fg-color: hsla(200, 18%, 26%, 1);
}

You can just copy those definitions in an extra CSS file and override only those which you need.

I鈥檒l provide an example in the new documentation when I find some time.

@FISHMANPET

This comment has been minimized.

Copy link
Contributor

@FISHMANPET FISHMANPET commented Mar 6, 2020

I'll play around with it a bit, and this may be my complete inexeperience with CSS or HTML showing, but it doesn't seem to be behaving the way I would expect. I copied that block, and got it loaded using extra_css. When I open developer view I can see Chrome has loaded my css file. But even if I leave them as default, the ones I'm interested in aren't valid, and show like this in the style viewer:
image
Mousing over the yellow triangle it says Unknown Property Name.

@FISHMANPET

This comment has been minimized.

Copy link
Contributor

@FISHMANPET FISHMANPET commented Mar 6, 2020

OK there's... some kind of issue, possibly with character encoding, in what I've copied. This didn't work:

    // Primary color shades
    --md-primary-fg-color:               hsla(348, 100%, 24%, 1);
    --md-primary-fg-color--light:        hsla(#{hex2hsl($clr-indigo-300)}, 1);

This does:

    // Primary color shades
    --md-primary-fg-color--light:        hsla(#{hex2hsl($clr-indigo-300)}, 1);
    --md-primary-fg-color:               hsla(348, 100%, 24%, 1);

The "unknown property" is always the element after the comments, If I move the element I care about (in this case md-primary-fg-color) to not be the first element after the comment, it's accepted. So odds are good this is my fault somehow, an issue of how I copy pasted or character encoding or something like that.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 6, 2020

The original source is compiled with SCSS, a preprocessor, and references non-CSS functions. As values you should just use normal CSS colors, e.g. #FF0000

@FISHMANPET

This comment has been minimized.

Copy link
Contributor

@FISHMANPET FISHMANPET commented Mar 6, 2020

OK, it was an issue with my lack of knowledge around CSS. I wasn't having a problem with the color definitions, CSS will accept hsla(348, 100%, 24%, 1);. The problem is that SCSS comments are different from CSS comments, so just copy and pasting what you'd defined didn't work, I either have to remove all the comments, or replace // comment with /* comment */.

And hex2hsl function doesn't work, so any of those that are used have to be taken out. I think I understand this enough, I might try and document it myself.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Small issue: If tabs is set to false, .md-header has a shadow, but that shadow is added after FMP, through data-md-state="shadow". That causes some jitter, or at least looks a little jittery.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Could you provide a screen recording showing the issue? It should be pretty much the same as with the current version.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Note the header shadow when I keep pressing F5:

header-jitter

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

That's the same for Material 4, isn't it?

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

It should be - the CSS seems identical. But somehow, it doesn't flicker when using v4. 馃

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

I get the exact same "flickering" on v4. The header shadow is actually applied after it's loaded because the header might be above the tabs. Since the tabs come after the header there's no way of telling from CSS alone if we need to show the shadow or not, so it must be determined based on scroll offset.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

This is the result of pressing reload for v4 on latest Chrome, macOS:

Ohne Titel

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

This one is probably hard to debug, but there are strange things going on with the prebuilt index.
When I set prebuild_index to true or python, I often get weird or missing search results.

For example, look at this search for "hardware". Up to "hardwar", there are some search results, but the top results are already missing (there should be pages like "Hardware Installation" on top of the list). Then, when I type "hardware", I suddenly get no results at all:

search-strange

This does not happen with the MkDocs default theme, and also not with prebuild_index set to false.

Unfortunately, I can't provide you with my sources. Maybe you can fire up the King James bible project to reproduce that?

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Probably related to differences in the pipeline used to produce the index (Python) and load the index (JavaScript). Material alters the pipeline, so it might be related to that. What happens if you set this line:

"search.config.pipeline": "trimmer, stopWordFilter",

to stemmer, trimmer, stopWordFilter?

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

No difference.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Have you rebuilt the theme so the changes propagated to the material folder?

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

I added the file (en.html) to my custom_dir. Also changed a language string for visual check, and the language string changed.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Okay. Could you try to isolate the problem? Support for prebuilt indexes is actually quite new so I expect that there're some problems yet to be discovered with this being the first one.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Another thing that comes to my mind that could be related - Material automatically adds trailing wildcards and does some post-processing on the search query before submitting it to the index. This is not done in the MkDocs documentation. To see what Material does to the query before submitting it, type this into your console:

__material.search$.subscribe(({ query }) => console.log(query))

... and then take the exact same query and enter it in the original MkDocs theme. This will give you:

Bildschirmfoto 2020-03-09 um 15 08 14

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Interesting. If I enter "hardware*" in the original MkDocs theme, I get 0 results. So that probably causes the error.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

That was my point. The search UX in the original theme is very suboptimal as the search results "dance" a lot when entering a search term. This is why Material uses wildcards. However, it may be interesting to know why this is happening but this seems to be something related to Lunr.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Apparently, a search for "hardware*" excludes results with "hardware". It expects at least 1 char matching the wildcard.

Maybe always use searchterm* searchterm?

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

When I search for color or metadata on the Material docs, it includes those specific results, even though there is no further character.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Did you search with prebuild_index set to true?`

Side note: Maybe fuzzy match is an alternative? A search for hardware~1 in the original theme yields the correct results, and it also works as kind of a wildcard when using hardw~1

https://lunrjs.com/guides/searching.html

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

Hmm, metadata works when setting it to prebuild_index: true, but some other terms yield worse results. We can improve on this topic after version 5 is out. Prebuilt indexes were not supported before so support should be considered experimental anyways.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Okay, the entire lunr syntax doesn't work for me when using prebuild_index. Neither +foo nor -bar nor foo*. And because Material uses the wildcard internally, the search results get screwed up.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

There will be a possibility to completely disable the search query preprocessing but for most of the cases it yields the best results.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

@wilhelmer could you open an issue once v5 is out on this topic which provides a minimal, reproducible test case, ideally with a mint MkDocs repository that shows the issue? v5 is already packed with so much stuff so we definitely have to postpone that post-release.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Aye 馃憤

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

BTW, as the search worker implementation is configurable, there's the option to replace search with a completely custom implementation, if you're not happy with search. Just provide an alternative worker script to the template and adhere to the message structure. This also opens the possibility to use an entirely different backend like ElasticSearch or some SaaS service.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Modified the theme to replace all * in search queries with ~1. Runs fine now 馃榿

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

The problem with fuzzy search is that it is much more computationally intensive than wildcard search and yields worse results on average.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 9, 2020

Might be related to stemming, see here: olivernn/lunr.js#256

(No need to reply, just saving this for later.)

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 9, 2020

... ah, and there the reason why we removed the stemmer from the pipeline in the first place comes back to my mind. Regarding stemming we must distinguish two cases:

  1. With stemming enabled you cannot use wildcards which will make the search "jumpy" or return no results at all except for completely entered search terms. Try to search for search on the official MkDocs page. IMHO this is rather bad search UX, as a good typeahead is expected for every search interface we encounter, because, well, Google. The counter argument is that you can always add a wildcard to your search, but from a practical perspective this would mean that you enter a wildcard, then press ArrowLeft and then enter your search term. Material does this automatically for a reason.

  2. With stemming disabled you can use wildcards, but then the prebuilt search index must also be built with stemming disabled, or hardware will stem to hardwar and the search for hardware will return no results. The information is essentially lost during the building stage.

From the top of my head I can think of no other way than patching the generation of the search index to not use the stemmer. Unfortunately, the pipeline seems not to be configurable for when the index is prebuilt.

However, the transformation function should be overridable via configuration when the final version of v5 is released, so you can always disable the wildcard search by overriding the following function:

function defaultTransform(value: string): string {
return value
.replace(/(?:^|\s+)[*+-:^~]+(?=\s+|$)/g, "")
.trim()
.replace(/\s+|\b$/g, "* ")

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 10, 2020

Okay. So that function is not overridable right now, but will be until the final version of v5?

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 10, 2020

Yes, or probably with 5.1. However, if you fork the theme you can change it to your liking as of now.

@wilhelmer

This comment has been minimized.

Copy link
Contributor

@wilhelmer wilhelmer commented Mar 10, 2020

And the alternative is adding an option to the official search plugin to make the lunr pipeline configurable, especially for prebuilt indexes, e.g.:

- search:
    prebuild_index: python
    pipeline:
        - stemmer: false
        - trimmer: true
        - stopWordFilter: true

@waylan Is that possible / on the roadmap / worth opening an issue for?

@waylan

This comment has been minimized.

Copy link
Contributor

@waylan waylan commented Mar 10, 2020

@waylan Is that possible / on the roadmap / worth opening an issue for?

Please feel free to open an issue. At a minimum that gives us a place to track this and document any decisions we make. There is a lot of good stuff in this discussion, but it also contains a lot of noise (all the non-search stuff). So a summary would be helpful in a MkDocs issue along with a link to this issue.

@squidfunk

This comment has been minimized.

Copy link
Owner Author

@squidfunk squidfunk commented Mar 10, 2020

Superseded by #1498 鈥 thanks to all testers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can鈥檛 perform that action at this time.