From a5e3052db66f392748c1978e1f7f52b3fe881d99 Mon Sep 17 00:00:00 2001 From: squidfunk Date: Sun, 12 Sep 2021 16:41:19 +0200 Subject: [PATCH] Set up blog and started article about new search --- .../blog/2021/search-better-faster-smaller.md | 235 ++++++++++++++++++ .../search-preview.png | Bin 0 -> 55976 bytes docs/blog/index.md | 15 ++ docs/reference/abbreviations.md | 4 +- docs/reference/code-blocks.md | 4 +- docs/reference/data-tables.md | 4 +- docs/reference/variables.md | 10 +- mkdocs.yml | 7 +- 8 files changed, 267 insertions(+), 12 deletions(-) create mode 100644 docs/blog/2021/search-better-faster-smaller.md create mode 100644 docs/blog/2021/search-better-faster-smaller/search-preview.png diff --git a/docs/blog/2021/search-better-faster-smaller.md b/docs/blog/2021/search-better-faster-smaller.md new file mode 100644 index 000000000..f0fdb8f4c --- /dev/null +++ b/docs/blog/2021/search-better-faster-smaller.md @@ -0,0 +1,235 @@ +--- +template: overrides/main.html +search: + boost: 0.5 +--- + +# Search: better, faster, smaller + +__This is the story of how we managed to completely rebuild client-side search, delivering a significantly better user experience, while making it faster and smaller at the same time.__ + + + + [1]: https://avatars.githubusercontent.com/u/932156 + +--- + +The [search][2] of Material for MkDocs is genuinely one of its best and most-loved assets: fast, [multi-lingual][3], [offline-capable][4] and most importantly: _all client-side_. It provides a solution to empower the users of your documentation to find what they're searching for instantly without the headache of managing additional servers. However, even though several iterations have been made, there's still some room for improvement, which is why we rebuilt the search plugin and integration from the ground up. This article shines some light on the internals of the new search, why it's much more powerful than the previous version and what's about to come. + +_The next section explains the architecture and issues of the current search implementation. If you immediately want to learn what's new, skip to the [next section][5]._ + + [2]: ../../setup/setting-up-site-search.md + [3]: ../../setup/setting-up-site-search.md#lang + [4]: ../../setup/setting-up-site-search.md#offline-search + [5]: #whats-new + +## Architecture + +Material for MkDocs uses [lunr][6] together with [lunr-languages][7] to implement its client-side search capabilities. When a documentation page is loaded and JavaScript is available, the search index as generated by the [built-in search plugin][8] during the build process is requested from the server: + +``` ts +const index$ = document.forms.namedItem("search") + ? __search?.index || requestJSON( + new URL("search/search_index.json", config.base) + ) + : NEVER +``` + + [6]: https://lunrjs.com + [7]: https://github.com/MihaiValentin/lunr-languages + [8]: ../../setup/setting-up-site-search.md#built-in-search + +### Search index + +The search index includes a stripped-down version of all pages. Let's take a look at an example, to understand precisely what the search index contains from the original Markdown file: + +??? example "Expand to see full example" + + === "`docs/page.md`" + + ```` markdown + # Example + + ## Text + + It's very easy to make some words **bold** and other words *italic* with + Markdown. You can even add [links](#), or even `code`: + + ``` + if (isAwesome) { + return true + } + ``` + + ## Lists + + Sometimes you want numbered lists: + + 1. One + 2. Two + 3. Three + + Sometimes you want bullet points: + + * Start a line with a star + * Profit! + ```` + + === "`search_index.json`" + + ``` json + { + "config": { + "indexing": "full", + "lang": [ + "en" + ], + "min_search_length": 3, + "prebuild_index": false, + "separator": "[\\s\\-]+" + }, + "docs": [ + { + "location": "page/", + "text": "Example Text It's very easy to make some words bold and other words italic with Markdown. You can even add links , or even code : if (isAwesome) { return true } Lists Sometimes you want numbered lists: One Two Three Sometimes you want bullet points: Start a line with a star Profit!", + "title": "Example" + }, + { + "location": "page/#example", + "text": "", + "title": "Example" + }, + { + "location": "page/#text", + "text": "It's very easy to make some words bold and other words italic with Markdown. You can even add links , or even code : if (isAwesome) { return true }", + "title": "Text" + }, + { + "location": "page/#lists", + "text": "Sometimes you want numbered lists: One Two Three Sometimes you want bullet points: Start a line with a star Profit!", + "title": "Lists" + } + ] + } + ``` + +If we inspect the search index, we immediately see several problems: + + 1. __All content is included twice__: the search index includes one entry with the entire contents of the page, and one entry for each section of the page, i.e. each block preceded by a headline or subheadline. This significantly increases the size of the search index. + + 2. __All structure is lost__: when the search index is built, all structural information like HTML tags and attributes are stripped from the content. While this approach works well for paragraphs and inline formatting, it might be problematic for lists and code blocks. An excerpt: + + ``` + [...] links , or even code : if (isAwesome) { ... } Lists Sometimes [...] + ``` + + - __Context__: for an untrained eye, the result can look like gibberish, as it's not immediately apparent what classifies as text and what as code. Furthermore, it's not clear that `Lists` is a headline as it's merged with the code block before and the paragraph after it. + + - __Punctuation__: inline elements like links, that are immediately followed by punctuation are separated by whitespace (see `,` and `:` in the excerpt). This is because all extracted text is joined with a whitespace character during the construction of the search index. + +It's not difficult to see that it can be quite challenging to implement a good search experience for theme authors, which is why Material for MkDocs (up to now) does some [monkey patching][9] to be able to render more meaningful search previews. + +### Search worker + +The actual search functionality is implemented as part of a web worker[^1], which creates and manages the [lunr][6] search index. When search is initialized, the following steps are taken: + + [^1]: Prior to [version 5.0][10], search was carried out in the main thread which locked up the browser, rendering it unusable. This problem was first reported in #904 and, after some back and forth, fixed and released in version 5.0. + +1. __Linking sections with pages__: The search index is parsed and each section is linked to its parent page. The parent page itself is _not indexed_, as it would lead to duplicate results, so only the sections remain. Linking is necessary, as search results need to be grouped by page. + +2. __Tokenization__: The `title` and `text` values of each section are split into tokens by using the [separator][11] as configured in `mkdocs.yml`. Tokenization itself is carried out by [lunr's default tokenizer][12], which doesn't allow for lookahead or separators spanning multiple characters. + + > Why is this important and a big deal? We will see later how much more we can achieve with a tokenizer that is capable of separating strings with lookahead. + +3. __Indexing__: As a final step, each section is indexed. When querying the index, if a search query includes one of the tokens as returned by step 2., the section is considered to be part of the search result and passed to the main thread. + +Now, that's basically how the search worker operates. Sure, there's a little more magic involved, e.g. search results are [post-processed][13] and [rescored][14] to account for some shortcomings of [lunr][6], but in general this is how search results get into and out of the index. + + [9]: https://github.com/squidfunk/mkdocs-material/blob/ec7ccd2b2d15dd033740f388912f7be7738feec2/src/assets/javascripts/integrations/search/document/index.ts#L68-L71 + [10]: https://squidfunk.github.io/mkdocs-material/upgrading/#upgrading-from-4x-to-5x + [11]: ../../setup/setting-up-site-search.md#separator + [12]: https://github.com/olivernn/lunr.js/blob/aa5a878f62a6bba1e8e5b95714899e17e8150b38/lunr.js#L413-L456 + [13]: https://github.com/squidfunk/mkdocs-material/blob/ec7ccd2b2d15dd033740f388912f7be7738feec2/src/assets/javascripts/integrations/search/_/index.ts#L249-L272 + [14]: https://github.com/squidfunk/mkdocs-material/blob/ec7ccd2b2d15dd033740f388912f7be7738feec2/src/assets/javascripts/integrations/search/_/index.ts#L274-L275 + +### Search previews + +Users should be able to quickly scan an evaluate the relevance of a search result in the given context, which is why a concise summary with highlighted occurrences of the words found is an essential part of a great search experience. + +This is where the current search preview generation falls short, as some of the search previews appear to not include any occurrence of any of the search terms. This was due to the fact that search previews were [truncated after 320 characters][15], as can be seen here: + +
+ +[![Search previews][16]][16] + +
+ +The first two results look like they're not relevant, as they don't seem to include the query string the user just searched for. Yet, they are. + +
+
+ +A better solution to this problem has been on the roadmap for a very, very long time, but in order to solve this once and for all, several factors need to be carefully considered: + +1. __Word boundaries__: some themes[^2] for static site generators generate search previews by expanding the text left and right next to an occurrence, stopping at a whitespace character when enough words have been consumed. A preview might look like this: + + ``` + ... channels, e.g. or which can be configured via mkdocs.yml. + ``` + + While this may work for languages that use whitespace as a separator between words, it breaks down for languages like Japanese or Chinese[^2], as they have non-whitespace word boundaries and use dedicated segmenters to split strings into tokens. + + [^2]: At the time of writing, [Just the Docs][17] and [Docusaurus][18] use this method for generating search previews. Note that the latter by default uses Algolia, which is a fully managed server-based solution. + + [^3]: In fact, China and Japan are both within the top 5 countries of origin of users of Material for MkDocs. + + [15]: https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/javascripts/templates/search/index.tsx#L90 + [16]: search-better-faster-smaller/search-preview.png + [17]: https://pmarsceill.github.io/just-the-docs/ + [18]: https://github.com/lelouch77/docusaurus-lunr-search + +2. __Context awareness__: Although whitespace doesn't work for all languages, one could argue that it could be a good-enough solution. Unfortunately, this is not necessarily true for code blocks, as the removal of whitespace might change meaning in some languages. + +3. __Structure__: Preserving structural information is not a must, but apparently beneficial to build more meaningful search previews which allow for a quick evaluation of relevance. If the user expects a match within a code block, it should be rendered as a code block. + +## What's new? + +After we built a solid understanding of the problem space and before we dive into the internals of the new search implementation to see which of the problems it already solves, a quick overview: + +- __Better__: support for [rich search results][19], preserving the structural information of code blocks, inline code and lists, so they are rendered as-is, as well as more [accurate highlighting][20] and improved stability of typeahead. Additionall, some small [interface improvements][21]. +- __Faster__: Up to 40% faster indexing and querying +- __Smaller__: Up to 50% savings in index size + + [19]: #rich-search-results + [20]: #accurate-highlighting + [21]: #interface-improvements + +### Rich search results + +- HTML awareness +- tokenization now +- faster indexing +- smaller index size +- faster search results + +## Highlighting + +x the problem with highlighting +x how highlighting was implemented +- how its implemented now +- division into blocks +- lookahead tokenization + +- add "jump to improvements" +- ux improvements + - scrolling more butotn + +## diff --git a/docs/blog/2021/search-better-faster-smaller/search-preview.png b/docs/blog/2021/search-better-faster-smaller/search-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca97e1cf3747bcd07a185f640789ff763566a1a GIT binary patch literal 55976 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%0DvXAgWBP)d_d>p%| zWoVk}74VDEJ$M>hVotdHvgXzEEoL3Qf}xjPvcLxUdi^Z3de3jgj*Ap|K)D>bphQU-UkCVHC2B`Thi4*DQ88Tse4DnQ5JqXTYfRR|*(C ziYsRF7=)TpMB-)hb*Df!$h z&ZQt0wWu%F;)p;7I^ijJ^FKjGWri#G3Ansr0Rw0J6C%uLVP!^dm3T07dFb*8U z!c)K>aUhSK&j;{8$&#D19mqhJCultotjZ{JDMwtaOu4N|@5h3e*8(V$*e$tim80Ic zEN{;3x<(d@I(|3B0fji#F5`vg8A?+x0_cI>lE|;Mx7fYR7k`5C!k|hV^HIGD0^Q_(LtYn$_D4J#T zMCEs_ctioR6l6r)o{Z*eJ}FSq>46O6@Jp?we0kyYdHK-WcUjdGoC$j6h(y35(YOmi zWDI|ws~QugIX-ys%D7TR6!hJ(*&=km$3FCi<3>=5ibZnT`Y9q4Cw&vWy6TT{Y6~h_ zr%tU`BMkeiVd3&zP)2^DoaKjdX9McDWiI7wWp2&Bqe`ATqsB(#`+O(U*59i~cIaH; z?!r^iO1u!qEzQefI^Y4}8BY6o_o~E>thiN|j+&G>#yc8dKb(zZFM5VDdoWZ{Fmg2a zL+g9~EC*-ZomBbNvdYyaC5G<_hz=Djy1c*?z7Olael1x#mP)5WxBV027lF~B1EZO?D8FBszh&T_vYKL`2)IK^~Ulj$!G zk8;~-P+%2Ks1w1>=m5 z#U#57x_;;|Tj>w5TpWETzFnzF9@*F3bm1BS*m`%iUg(mTl}VS15%^LRA3e05=NfSn z1rW-oD@3yh7qT>;w-)sxJaxs5caDA;3wVz6EgPJ1H{dV>2MF5mwp9;oL~8aZSN$b^ z#^|Q>oWPjk*|h)lOA>4fT^4vx-htivP~vZ(%Z5?u+x1fW1_)hvOBvrR%Lm+IUGWJ) zd1poGv@9}u$MY)-F`thf1a9}5EJ{nkqKHq&V9tV-V&S&i;N^!s;l5wAixqU<&WuXg zK!su6(tu*$lXymoq>rOYH|uD?&#B0$e?^PA!b%OY{&j4|8 z+?%xRrdUN$Q*)Z7m^|a9=wQ5=_L>$7 z|7Dw!(Xx?Ea+W*Oj1%5feh6VM!|toqm}|xW$L3Q1IK7THVoRQE=wn$KQEci|GQD|c z;7)%)mRFEU)tEI2#TcXOKOD$&Q>)|Ei1TX2sVD>@N*;vk0zhE^dr=a_JF};I_e%f2 z%;!RMj605SIfp!JKl27yuH*Eu?!*EIRROYywsG;=2f=AQ%fai0W1s&@iNq~&f0}aa z;x&m;G1{VE>R=|z4z6Z%9Q@4fK2~+zH?Tp>=nr`O>g=495y{(fE;yn!zXT`p*s!7X zVy=O?>xB%7SWWCYdf#`@)2Hs|Jt)=n`834 z<9>h>l2qPM4iJU+XPearo9-nsIZOGmE_)|TFSFp(9Xi5DiayC(j*tliN^o+41g=Ji zOq~4&k7Co)0OlvGv`%UA;cB*;c%|+N8c*%u?)ZGa{(sZ`1*eO_uTVSE#98>_FbiH= z`|||#k=qu}Ir=v@2Z_Dx*naAozg*~7)(X$)*B{AKp-eL1m;_(v)@jLqRJ_o)+bm-B z+Hdlv68>7L!wVsNjQe-R#Upk6OKqm#5XP7);5u#O;bQDfr3a;u5z?!msMyyvq^`xn zY4~D&%Ik2%6>SbZJuWX35_~H|=T8m?D59yUi0uW0z^1o>FYXTT_p7$>U?jQr47wGN z%nhy;sGG8B4S8RCY#yf{{U6FFm;}J#^P7KE;Pye-lt&_-x@E3i2oF4Hupn1s00zS$ zmkc+YW)RN`vDTia2h6yqz+=f$SjJ;Wq}JOasx7cvq&i{ZSEgdDGF4UUAUAiCQ>XB% z-^IbljXmMUW+Q`N(DpCQfsPweYet*8zwAG)qByE8)oEdVDI^%#`x?Y*=l@Yslx_iU zEkUmV+;c&KXuVzLDJV26{i}vjPB`x2bIno=M28i7?a}1NS23 zH=LxW+=(De4fQ)#MafE{_LQJQp$}~FFGU>-2RU$KC_f5c zJS%0lHlg*?F1+;C!8TRoQY&n147N=N*bS-p>K0*we$+;cZ+$ltpTbCiaT^GdBL* z1N)E4V6MmF3tcsrqSX$~CPHWHAnbZGbg-P6_Y$~JY)!p$# zy4s>KSF}LTVLU}1r2m9~^a}BOMn}CDlq@a|+Hku=zr{?s>fy4X-BNv}!QHltDj!46 ziX4&OM5{)&Q&Jt9N+x7EgMN^n2$W^dQ|;5Efj{g`kY?q=_{OEq;;rp0j!AGKCZf@b z>lEx3Kf9V~-#D}VE<3_$IYH-w$O4hGOkQT>5@g1>%(m`a-?RwY|Uf0w57|y{*3jW#(?8c}W>9N9eewSP#X=Kq_S#lzE zugkefbfH@*v;;@u=B&xbs&7iYst@te{lqMo+ldLW-75)>E@7;C=9H>?(EP?=Obx^X zOV^9O4F>+{*SE4V4xnm@bblTtLLQpaf)%xgyP&UB5`Xz@a3MnpSWFRvtYSh$5a$hA za;<{luP2JWobPVl*i_c!|G^4PD0!AOI`$SOE|KrP0Vj1TIMXl3;{A;zs(x9Fl{Zq) z%8qQ+8tW3fbfk4JNNH4IBt*Z6kjPUB0}!GIOHcz<|KA-Dn*Sd?`Tt{;L^X=<8$4)f z=g66c^Y5y!Q-5Q$w9An=<{G@GtZqZM*~JM}7Er2*Dqv<`|7bS74YD@7Tn1R+*cn6# zynYsVn0}s4NO;vK8h&wb3~+A;U7l(@a2%iXR5+F4?_!8Ig;?&^GM2rrv=qEQ@ICum z!K`?DCgk=a1px|R`2$z#GLqc0a2@Y|^J)-)iBPu5w_LPCzXINYZQz_fjj9&hWW6{AHMz*x^$LF}W01MpBt`TC8C@}2;KWAueC6z^eacF>BlRzwlQ zOZdzsVndS%xsPS@hEVuI{S@y#Q%x5`mKr1h+KvSVEz+epQE?HEHJSwY5F98IP{C zI$hZ5v``U{uyVvH1ccKulHy0Fr*J1gB58d+Zg^6JH!T$Z%-zDXssdh1hM^;5xyf24PQM`!g*YY6oB50P;z zW?-;b?DhvgN`cDZuGrRv>Ti<;n3_DFtRam2AUVNO@=ri|9iREPS(Mq{J=(WhDt78M zk77?lb*mvY&J8sOw>8a`Fq~6XL*l)G2X`-@kk|7eM~ut_5?@8?X@TzQMHX^kT?@U_ zC8gqYs<&LH*}GH?PCd(`JDeKL@+Ju~T`I%#+dojJu4Lzor!pEAG3~spn;L z)69-ky%90GPOB}yy{$P7rzB74su(O0G(&%FBJUD3#{xgpU7YSq-blE5xN#6RzMSn8 zi&Wv6OdhIx;ICIsbmjj=I^+G))|RZ>;i6PZDw>LnA!%T{6 z>g_kkq*JB%N`bHOs$ZKs~ zLruw*o2QW#!-FCVU85^OF%CSCAwk1ID9yNHc)J8($m^P5=T0k%4~d&yLk92oeI=1# za6-UfQy-Gs&pagT@2ctcad7<;IU0;x-lt2=4Or1+buZZNZfB5}ssYE;5OBON`?z4_ zyw`ttXQ%4*^aIZ99;^e=HC+q?2kAO}(3$Y(u?(V(K{O6Cm5<5Q#z1AAt2MC5O;+{Zj09t3pnUFy!7`wR%_OCYab(xC z@_B0(P}$sY>ACI#K^or`z8UO`rDz;;}ApXHO_57*&u{QI>nzjh0`ZON7*j>k2Lv!1rm0rMK8 zZuEt4I8qV7gCpPa-6x=^)vkdb)~l}9Qdxp|yNeP0MmDYFy}w~E@Hcy9U!d?sSX%U| zW>dfcJSg1!={m4i7Y{%mlVYHr9+?)j9uI;*4@Q@0QDG{-bXJXMw~fC08QhaH9ZjQN zmcKe8RF2|iYZ8*;-HhM-u#&|-XNu0DRO?UGx$Va?5rMNw`=mo3IQeUiFFd;ckY8Q? zz#Y+hAqvj)M}GZgJRXg3$?@)IiP=(@=TJ8{a9a4NYn~BvW-k^X@m?NP2Rm{0HwQ|%Pc!^`UnJv?l9K{g7V3{ocNO~389?vU>LA}s)Q%sS~vQ=APlB1wz~Q#xvI*nq<(FeE!|haC0J^3=R$=Ggjt%x{L9}w`%g2r2I7>{TWWoNL_Ni}hkfvX z6Y;{=2cT57LSi+ogng{i{14J*kjGpUXgKW)8G+(?KU|3qvXL+|M%o%-EeUNs4hI5# zS|e}f_J#RU*o>Jz;tw-92ys`BG|$T6Z~SsH`ic#C!U{`kcWKAVp{nuRLPs%HN7{PJ zs)1~D%_|h)^FFE>*#jvLF+{C zrR5nn)ED63ia(XAoiy^z;a3yiVE(@^Om#Z#GY&|?6Y7FxxE(gaGU z!HEeGgc1gCOqUNXxWkdtUmTO)&qO#K?1jubz$%SFj{2Y2M<=h=aPAq z)Xe&DFmQCm;Vc(J&9c&ZoYoVky=WiLfN8SJjyfZ2_~h7y2EJncJTJX$IH#em6sZ+y znRz}Eq8SupE?igN`8j)wc}jvDsNB?z957A8ZFP7dw0>iTUN+Og-K?HuQ`$*ZqG&eF zU7=oX@r{fvl`7J9^cs`tjlX?zpktOo#+26L1w&C{)Jjn576~@AFUE;QK_Ac0H=?ZB z<(h7`*)+6QGum~}`TUg-g`?8qun10$i~rpdeM8#!UI9h#MVgUfO$=bceS1(`iMq*xtjb9x>$SMf0Fe@*PpT-eN_({aebYSn-AAprYM&X5+^1Wls)vE9)) z^A%#tVmJG>Gvdf_wo3E%;K?a&!AIZIwr(RL)JddU z7L$#aV6GZ$l7Y06x9d*`s1PpaX*rJ0x3)GBlgS-SA@rb~pusUhaAPq94$&;7NP}A^ zsO>kkaYr+eH zhP?fJelL6OWjpyeoeAtId2@^yw4s5yCWp>JeAB4=+zR~s*z1vFQEAum%(@slCLs*Q z=Y(TUgU0SIH(lK2yYE~3NoY)ji-#^+3F71XSl@yJUi99GML_wpS>4P&R(mjjB0H zhsD)?S5;_}W6Kw1iGAsIe}3&9Lm7S!`iHEtOP^UE$Pdt8vxJInoSt}P;vU!D&voKA+SX|TdtZ2VkA zqOL|>nzr|d(r*&=?4=$}NU1&;Zid_;p-rRSQ3s8oCb5#kfmQa>X=&o`|I^xehqD2_ zdpv5jv}WzvTGVWfsI4|d%@`F$%~VxUL5)(>9yMx{5+z9OBKD>=Ld>cWMZ^kH73=!l z``o|pKll87{y69Jyx;en^E~JMzHjdkHswiS1qq2akpr=Y3v~ZWh=03Mg-#W_iWZYC zHu|JJw?br6*EdGR-J;_ZD&$5@@eZd5I8?28OQ^AKkL7Azr}X zZEJrBYjX=OY0)Vsn-iR?N3`9O-mJ(C8Dl|MK*EPV3WJ|%k=R)qKT4G5)WE$i{4MTR zJMSs7L|EQ)nnX)QHxjQLwSPkUlG-8@Uki(u4ZVW3-}}^7x)oeL!1N2Q_~JbKfpMu9 z)y=FzIdE_yU%h5us?P*pU-1w*@@ER)Vx>G5V;4+!*70I!gcXSbDmvmkQsTg zSA!F2W~#Z0n0D&6^d1O$Iadxma;xJ&bierrl_;IjD-=wQ@KvA>Z`!v=Mx?7D+U>R={rFvuqk|@6$ZUtLLc#iSZ zzWI#SU3m|)J^|Z!+YXZ|-y!qXF+GxQwiz#x|cV(i(xw+6OHfbqktR5y|(l!dDS zUrYq#kGSzOuwk8^QP#3um4o_tk1={E=_o5D&GKDbcESpJ^+FSjN}A zskwlEIBuk`Jt@CtNo{nh!|8DLu1eaRQCf zL{k}+p5n6H_?Th_j(tugy|ioh%5mT-#XR+XD%zF%#Z|$}7uY3jCOQ`Du50R=O37w# zpmEEHpmvSyPMV_O=%)#aF6lTvYrhXBmP@x@FI7>Pa?i5do#NjaGrE4Rhwt81!_`pje(C9U7DBUJ=Cg-ty&tUlFgftczlZZ zm|f7=jqp>ap;~6op%@s@r;Vtw`=}E=L&Ktzl6U71)W^W+dndITe?p7!P(z~;Tqay= zf+`>l&)TY^miIaD$x@7c;?qP=F^`!3Q9p-&T>wi&OiidH4 zwa>F?J3q{9T9&PfQ>9&>xTTucInQBE?`wFk+Gqmy^6Cbsj?nc1Pu~Dz0f(h=_z#lH zn5kvSO@8Ud$ju}7FHGNUb_Ap?q zkd;Ps12h)1DLmKJuKQu=Xmf5SkV9ikFCXQ6|H}{AM!SL^xbV;i-SA0pW{*kn` z%;g;sUf3fR0k;j~OPt|4RY&UjSCn938gZJRsKFciI;LtLa+ZVS!5Nd|k^O!!+NtWp z>wrJo7ZVEYv1F!yf4^^Wl@%Bo6?e{x*NFy|YQ*SmYuqNqp!r(aDg702U$Xy^?Q$qY zxQD@Z*=it1J>ODI4T?CzpE{xG$s0I$YhD9%m~m+XhGx+c`&*wW{2Ns$+80^dL8g~~ zt}zfQW;BIx)C$HFbF|V>9uE)kI#;&&+Y-a9$YHYZf*16hx6`n3o^*-21SOs;(GUPk zbCnhJanLqzc5W_8)7rpgqNsm|s-Z_Y(bCH+YT17!3SMFiApt-p6U za#GP2CH;CW_|pA{10;Ut0p{sZl{Jly0KmWPr9S9=I?rR_F_E`WFO~O2#d|R0Q|LAP z8s=f`(;@USHvsYFdybHUA$!H}k8alRA9l5^8Lf?tz5e}LEj-N$#%=}623qJDD= z`I2L^$*Tp)P`SA+Kc7&E-ZWB;wed9{WJp`l6q1@s00mHQ`xZ-17g2rb@#8Uz>mO{& zCNqtGt38qD19sYeGoeSQ`1QCm9PTUe%pL#uT0R}d#llfR;{c|z-MTxp#d-ei8tj)j z%fS4&zGrYAZC5NcbjzBn?}x5bA7ZsR!a^?RYdwuu_L0MV03-4}jB%<#y{Se$$86%f zIwL^g&?}DBB^gvorY~=CCPPG~=V`TYa%Qs@i37%#Lzo31) zpfh6bvBJ{UqHa!c!~V@S%ydFNITw=A98~y8WVRcC63-A^LP(k7yfC1c7vq zzSd@pTzE*bOtH`}s41tr+q*feH=CETOn0yz<)=~=YK%x(qItjWPeuPUAs4N>P6Ldf zW#(BZc!ZT;cm8zdrcHQ!s`%vGr$0(wY0vdmG@`=b-THJQEwD1^1yB}^Hd`4D8Mk(5 zF)w)B%Db9&>*H!(BgutaY+^7@tiUqfO$6NiOwu$a%6+l6y4gcgy}N`yq!j+*eXp=b zfLkGinN*kzP<8~D83=V)->c7_geh#;%*O6!sNSd4MOjtsJ&x24IZ@{Gkx642UPUus z?DUj&D0t&8(DXX%0;wycwC!1bMOja~AATFN`H32k_%Ns(jTD>Pt}fQ zBPF}ucHL-ndg{bWAu!iTVu-;014b`@US=4e<~mIor?^R5EEEH-mA&m z`f_GrKh*xtkn_(b-^3FFz<9X_qssO=5)`E<$=C_O^aE!a*x$LepnY8BeB9S{Rer z3i|QZuQr(hNR94vLt=~6pC7<#n-^FQ6z2)IBIVV)fKMXdjUyEuz<5y$T4&_+d-lwzqPbz zvnBOe0~dA~vgD(CGFwrF)F2a`zzKrz$#98@uRm~|6^U7{xv|gjmLT4o8 zdop(($u%85SNQqjX{*;#<|Y^r50Z0vs4|;jZB!L7w4gFzfo!W*bztAB^T@YDFnL3% z!PnL&N%gt$&yWzDZ%u^5k*lGDa6bK#8phjDvk&r9?KS8~sL$@4P^&7ZoNI5oR)Ji2 zv(i)wGqeVgL^gQ+=P$yTHbQsufqvrQ+7N?ZpLeq$jtC7=U?^mh6+cZN3w_9h74WcdWr_xq8LweF|t)IVH{a9HjWP!?Q zn};(WvdvuWoqh19NOMkxqa+iOY3cqW8^(-gOnQJUMdm)EG-Npz@>=Sc>0vV#r`OI?;m3Q-5yS4{WuoT+>!>j>2M>iT4rftu$v);#j^xkc|;w^AEyP8|W_{nV^UQTA~VK8a9$~&jImf4@IRdhdT@)N(;DspK#ZeIlawFh!smaNP6fJ8z_kH9beLSHQeeAZXRtn9Pa_Jx`;ol zUrhg;Dghho#SfS3O}~mQjG2Vm-;XQVY5b^^D>OLJ_pGi5F`5V>K6{ChR|6+I34{cH zEf`Mhh0G!D;q%QgFK?olz+^}{&wi)H+hPTowLEQC&Eg(-DM^sBsQ}g~G2cIa2F~=y z6ShjN4bKn$LN`oNoc$t*w=Q11I+8WNOgqqve`SJ0QQ+W{4b{5(1{BhhbK5mR5A}N| zD4SHhF1+jiWJi2f`NrF>f~F}o*#78Jal;HQIC3#gbMKn<*RAul{f*3@Lcq-Rf>Gs1 zStjdhAyt30V5IUKnh7stkO!nJeocA+_~){6!^9kph5v*|O(f5K%apdtq@^ ztBCJ~NVdXVA0*YSV7~#vk&H+T%sL|nqOUfV*J lu`y%We)s=6fWo8xNs0LdsikZ37yf6izP7Pe_2cIe{{`hwrcVF> literal 0 HcmV?d00001 diff --git a/docs/blog/index.md b/docs/blog/index.md index e69de29bb..6f0e8226f 100644 --- a/docs/blog/index.md +++ b/docs/blog/index.md @@ -0,0 +1,15 @@ +--- +template: overrides/main.html +--- + +# Blog + +

Search: better, faster, smaller

+ +__This is the story of how we managed to completely rebuild client-side search, delivering a significantly better user experience, while making it faster and smaller at the same time.__ + +The search of Material for MkDocs is genuinely one of its best and most-loved assets: fast, multi-lingual, offline-capable and most importantly: _all client-side_. It provides a solution to empower the users of your documentation to find what they're searching for instantly without the headache of managing additional servers. However, even though several iterations have been made, there's still some room for improvement, which is why we rebuilt the search plugin and integration from the ground up. This article shines some light on the internals of the new search, why it's much more powerful than the previous version and what's about to come. + +[Continue reading :octicons-arrow-right-24:][1]{ .md-button } + + [1]: 2021/search-better-faster-smaller.md diff --git a/docs/reference/abbreviations.md b/docs/reference/abbreviations.md index 2b3c99499..8220d90e5 100644 --- a/docs/reference/abbreviations.md +++ b/docs/reference/abbreviations.md @@ -76,7 +76,7 @@ and embed them into any other file. _Example_: -=== "docs/page.md" +=== "`docs/page.md`" ```` markdown The HTML specification is maintained by the W3C. @@ -84,7 +84,7 @@ _Example_: --8<-- "includes/abbreviations.md" ```` -=== "includes/abbreviations.md" +=== "`includes/abbreviations.md`" ```` markdown *[HTML]: Hyper Text Markup Language diff --git a/docs/reference/code-blocks.md b/docs/reference/code-blocks.md index ec4c06a25..0b5201cd7 100644 --- a/docs/reference/code-blocks.md +++ b/docs/reference/code-blocks.md @@ -53,7 +53,7 @@ configuring syntax highlighting of code blocks: respective stylesheet and JavaScript from a [CDN][9] serving Highlight.js in `mkdocs.yml`: - === "docs/javascripts/config.js" + === "`docs/javascripts/config.js`" ``` js document$.subscribe(() => { @@ -61,7 +61,7 @@ configuring syntax highlighting of code blocks: }) ``` - === "mkdocs.yml" + === "`mkdocs.yml`" ``` yaml extra_javascript: diff --git a/docs/reference/data-tables.md b/docs/reference/data-tables.md index 59f5aab6b..8ac18d5bf 100644 --- a/docs/reference/data-tables.md +++ b/docs/reference/data-tables.md @@ -120,7 +120,7 @@ If you want to make data tables sortable, you can add [tablesort][5], which is natively integrated with Material for MkDocs and will also work with [instant loading][6] via [additional JavaScript][2]: -=== "docs/javascripts/tables.js" +=== "`docs/javascripts/tables.js`" ``` js document$.subscribe(function() { @@ -131,7 +131,7 @@ loading][6] via [additional JavaScript][2]: }) ``` -=== "mkdocs.yml" +=== "`mkdocs.yml`" ``` yaml extra_javascript: diff --git a/docs/reference/variables.md b/docs/reference/variables.md index 5adea7738..3b8f07742 100644 --- a/docs/reference/variables.md +++ b/docs/reference/variables.md @@ -70,13 +70,13 @@ storage and management. _Example_: -=== "docs/page.md" +=== "`docs/page.md`" ```` markdown The unit price is {{ unit.price }} ```` -=== "mkdocs.yml" +=== "`mkdocs.yml`" ``` yaml extra: @@ -109,13 +109,13 @@ In your Markdown file, include snippets with Jinja's [`include`][4] function: _Example_: -=== "snippets/definitions.md" +=== "`snippets/definitions.md`" ``` markdown The unit price is {{ page.meta.unit.price }} ``` -=== "docs/page-1.md" +=== "`docs/page-1.md`" ``` markdown --- @@ -126,7 +126,7 @@ _Example_: {% include "definitions.md" %} ``` -=== "docs/page-2.md" +=== "`docs/page-2.md`" ``` markdown --- diff --git a/mkdocs.yml b/mkdocs.yml index 840905e81..424d712f4 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,7 +54,7 @@ theme: - content.tabs.link # - header.autohide # - navigation.expand - # - navigation.indexes + - navigation.indexes # - navigation.instant - navigation.sections - navigation.tabs @@ -211,6 +211,11 @@ nav: - MathJax: reference/mathjax.md - Meta tags: reference/meta-tags.md - Variables: reference/variables.md + - Blog: + - blog/index.md + - 2021: + - blog/2021/search-better-faster-smaller.md + - Insiders: - Sponsorship: insiders/index.md - Getting started: