{"id":386507,"date":"2024-06-29T06:44:48","date_gmt":"2024-06-29T06:44:48","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=386507"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=386507","title":{"rendered":"<span>\u0425\u043e\u0447\u0443 \u043f\u043e\u0438\u0441\u043a \u043a\u0430\u043a \u0443 MDN<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/jc\/hw\/st\/jchwst6a3nwlxlscnmuw5tdhmry.png\" data-src=\"https:\/\/habrastorage.org\/webt\/jc\/hw\/st\/jchwst6a3nwlxlscnmuw5tdhmry.png\"\/>  <\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  <\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e (\u0433\u0434\u0435-\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u0430\u0432\u0433\u0443\u0441\u0442\u0430) \u0443 MDN \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 (\u043a\u0440\u0443\u0442\u043e\u0439, \u043f\u043e \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432) \u043f\u043e\u0438\u0441\u043a.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u0438\u0434\u0436\u0435\u0442\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/34\/j7\/tq\/34j7tqebk9v61hlfas_d-gzb8q8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/34\/j7\/tq\/34j7tqebk9v61hlfas_d-gzb8q8.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7y\/jo\/9s\/7yjo9s4mfq886c-mixhcxjxznxe.png\" data-src=\"https:\/\/habrastorage.org\/webt\/7y\/jo\/9s\/7yjo9s4mfq886c-mixhcxjxznxe.png\"\/>  <\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/github.com\/mdn\/yari\/blob\/main\/client\/src\/search.tsx\">\u0437\u0434\u0435\u0441\u044c<\/a>, \u0430 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435, \u043a\u0440\u043e\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/mdn\/yari\/tree\/main\/client\/src\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u043e \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a <code>https:\/\/developer.mozilla.org<\/code> \u043b\u043e\u043a\u0430\u043b\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>\/ru<\/code> \u0438 <code>\/search-index.json<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/od\/5q\/k9\/od5qk9sgcoxeqqjw2am_u6mbfny.png\" data-src=\"https:\/\/habrastorage.org\/webt\/od\/5q\/k9\/od5qk9sgcoxeqqjw2am_u6mbfny.png\"\/>  <\/p>\n<p>  \u041a\u043e\u0434 \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 <code>React<\/code> \u0438 <code>TypeScript<\/code>. \u0427\u0442\u043e \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442? \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0437\u0430 \u043c\u043d\u043e\u0439.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p><em>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435<\/em>: \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u0430 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>React<\/code>. \u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e <code>TypeScript<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u044f \u0432\u044b\u043d\u0435\u0441 \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/github.com\/harryheman\/Blog-Posts\/tree\/master\/mdn-search-clone\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043a\u043e\u0434\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043d\u0430\u0431\u0436\u0435\u043d\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c.<\/p>\n<p>  <\/p>\n<p>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/tp\/fa\/gw\/tpfagw-0c1byhodccxe2oslwurs.png\" data-src=\"https:\/\/habrastorage.org\/webt\/tp\/fa\/gw\/tpfagw-0c1byhodccxe2oslwurs.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/61796caf4615593b75e246c9\" data-style=\"\" id=\"61796caf4615593b75e246c9\" width=\"\"><\/div>\n<\/div>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/harryheman\/mdn-search-clone.git  cd mdn-search-clone  yarn  yarn start<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0431\u0449\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 MDN \u0442\u0430\u043a\u043e\u0432\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441\u0430\u0439\u0442\u0430, \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u043c\u0443 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 (\u0431\u043e\u043b\u0432\u0430\u043d\u043a\u0443). \u042d\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043b\u0438\u0448\u043d\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u043c<\/li>\n<li>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u043c, \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0438 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0431\u043e\u043b\u0432\u0430\u043d\u043a\u0443 \u043d\u0430 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0432\u0438\u0434\u0436\u0435\u0442<\/li>\n<li>\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044e \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u043d\u0430 \u0432\u0438\u0434\u0436\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0444\u043e\u043a\u0443\u0441\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u0438\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 <code>\/<\/code><\/li>\n<li>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0445\u0443\u043a\u0430 <code>useSWR<\/code> \u0438\u0437 <a href=\"https:\/\/swr.vercel.app\/\"><code>SWR<\/code><\/a> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043b\u043e\u043a\u0430\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 <code>URI<\/code> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>https:\/\/developer.mozilla.org\/ru<\/code>)<\/li>\n<li>\u0424\u0430\u0439\u043b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>search-index<\/code>, \u0438\u043c\u0435\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442 <code>JSON<\/code> \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441 \u0434\u0432\u0443\u043c\u044f \u043f\u043e\u043b\u044f\u043c\u0438 \u2014 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c \u0438 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>{ title: '\u0412\u0435\u0431-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432', url: '\/ru\/docs\/Web' }<\/code><\/li>\n<li>\u0421\u0430\u043c \u043f\u043e\u0438\u0441\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043b\u0430\u0432\u0438\u0448\u0438 <code>Enter<\/code> \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u0432\u0443\u0445 \u0432\u0438\u0434\u043e\u0432:<br \/> \n<ul>\n<li>\u043f\u043e\u0438\u0441\u043a \u043f\u043e <code>url<\/code> \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/fzf.netlify.app\/docs\/latest\"><code>Fzf<\/code><\/a> (\u044f \u043f\u0435\u0440\u0435\u0432\u0435\u043b &#171;fuzzy search&#187; \u043a\u0430\u043a &#171;\u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a&#187;, \u043d\u043e \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e). \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 <code>\/<\/code> \u0438 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432<\/li>\n<li>\u043f\u043e\u0438\u0441\u043a \u043f\u043e <code>title<\/code> \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/nextapps-de\/flexsearch\"><code>FlexSearch<\/code><\/a> (\u043f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u043e\u0438\u0441\u043a)<\/li>\n<\/ul>\n<\/li>\n<li>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043c\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0445\u0443\u043a\u0430 <code>useCombobox<\/code> \u0438\u0437 [<code>Downshift<\/code>] \u2014 \u044d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430<\/li>\n<li>\u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0438\u0441\u043a\u0430, \u043c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 (<code>prefetching<\/code>)<\/li>\n<li>\u041f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443 \u043f\u043e\u0438\u0441\u043a\u0430, \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>Downshift<\/code><\/li>\n<li>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c <code>Enter<\/code> \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e\u0438\u0441\u043a\u0430<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439, \u043c\u044b \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e\u0438\u0441\u043a\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u0442 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u0442\u044c\u0438, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043e\u0434\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u044e \u2014 <code>ru<\/code><\/li>\n<li>\u0412\u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 <code>MDN<\/code> \u0432 \u043d\u043e\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/li>\n<li>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u0435\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/li>\n<li>\u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0438\u043d\u043f\u0443\u0442\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e <code>Donwshift<\/code>, \u043f\u043e\u0434 \u0438\u043a\u043e\u043d\u043a\u043e\u0439 \u043b\u0443\u043f\u044b (\u0441\u0438\u043d\u0438\u0439 \u043a\u0440\u0435\u0441\u0442\u0438\u043a), \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435<\/li>\n<li>\u042f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b (\u043b\u0443\u043f\u0430) (\u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u044d\u0442\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442)<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 \u0441 \u0442\u0435\u043c, \u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 (\u0438 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430), \u043a\u0440\u043e\u043c\u0435 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f <code>prefething<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a.<\/p>\n<p>  <\/p>\n<p>\u0421 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0438\u044f, \u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u043e\u0449\u0443 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 const [shouldInitialize, setShouldInitialize] = useState(false) \/\/ \u041f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 const [searchIndex, setSearchIndex] = useState(null)  \/\/ \u0410\u0434\u0440\u0435\u0441 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 const url = `\/search-index.json`  const { error, data } = useSWR(  shouldInitialize ? url : null,  async (url) => {    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442    const response = await fetch(url)    if (!response.ok) {      \/\/ \u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435      \/\/ \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0430      throw new Error(await response.text())    }    \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 `JSON`    return await response.json()  },  \/\/ \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0443\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e - \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u0444\u043e\u043a\u0443\u0441\u0430  { revalidateOnFocus: false } )<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0430\u044f \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u0445\u0443\u043a\u0430 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0440\u0435\u0436\u0438\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u2014 <code>useSWR<\/code> \u0436\u0434\u0435\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043e\u043d \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e <code>shouldInitialize<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>true<\/code>. \u041a \u0441\u043b\u043e\u0432\u0443, \u0434\u043b\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 (revalidation) \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u0444\u043e\u043a\u0443\u0441\u0430 \u0438 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 <code>SWR<\/code> \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0445\u0443\u043a <a href=\"https:\/\/swr.vercel.app\/docs\/revalidation#disable-automatic-revalidations\"><code>useSWRImmutable<\/code><\/a> \u0438\u0437 <code>swr\/immutable<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u041c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u0438\u0434 \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0438\u0436\u0435 const flex = new FlexSearch.Index({ tokenize: 'forward' })  data.forEach(({ title }, i) => {  flex.add(i, title) })  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 `fzf` const fuzzy = new FuzzySearch(data)  setSearchIndex({ flex, fuzzy, items: data })<\/code><\/pre>\n<p>  <\/p>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0445\u0443\u043a\u0435 <code>useSearchIndex<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function useSearchIndex() {  \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430   return useMemo(    () => [      searchIndex,      error || null,      () => setShouldInitialize(true)    ],    [searchIndex, error, setShouldInitialize]  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0445\u0443\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430, \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>null<\/code>, \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u0438\u0434 \u043f\u043e\u0438\u0441\u043a\u0430.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u043e\u0439 \u043f\u043e\u0438\u0441\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c (\u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u0438\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439) \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function isFuzzySearchString(str: string) {  \/\/ \u0414\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 `true`,  \/\/ \u0435\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 `\/` \u0438 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432  return str.startsWith('\/') &amp;&amp; !\/\\s\/.test(str) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 <code>fzf<\/code> \u0438 <code>flexsearch<\/code> \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const data = [  {    title: '\u0412\u0435\u0431-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432',    url: '\/ru\/docs\/Web'  },  {    title: '\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects'  },  {    title: '\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u043e JavaScript',    url: '\/ru\/docs\/Web\/JavaScript\/Reference'  },  {    title: 'JavaScript',    url: '\/ru\/docs\/Web\/JavaScript'  },  {    title: 'Array',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array'  } ]<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e <code>url<\/code> \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442 <code>fzf<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState } from 'react' \/\/ yarn add fzf import { Fzf } from 'fzf'  const data = [  {    title: '\u0412\u0435\u0431-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432',    url: '\/ru\/docs\/Web'  },  {    title: '\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects'  },  {    title: '\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u043e JavaScript',    url: '\/ru\/docs\/Web\/JavaScript\/Reference'  },  {    title: 'JavaScript',    url: '\/ru\/docs\/Web\/JavaScript'  },  {    title: 'Array',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array'  } ]  \/\/ \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u043e \u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 const formattedData = data.map(({ title, url }) => ({  title,  url: url    .split('\/')    .slice(1)    .filter((i) => i !== 'docs')    .join(' \/ ') })) \/*   \u0411\u044b\u043b\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, `\/ru\/docs\/Web\/JavaScript`,   \u0441\u0442\u0430\u043b\u043e `ru \/ Web \/ JavaScript` *\/  \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 `fzf` \/\/ \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 const fzf = new Fzf(formattedData, {  \/\/ \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 (\u043b\u0443\u0447\u0448\u0438\u0445) \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432  limit: 3,  \/\/ \u041f\u043e\u043b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430  selector: (item) => item.url })<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <code>fzf<\/code> \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ `url` - \u044d\u0442\u043e \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \/\/ `positions` - \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 const HighlightChars = ({ url, positions }) => {  const chars = url.split('')   const nodes = chars.map((char, i) => {    if (positions.has(i)) {      return &lt;b key={i}>{char}&lt;\/b>    } else {      return char    }  })   return &lt;>{nodes}&lt;\/> }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">export const FzfSearch = () => {  \/\/ \u0421\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430  const [value, setValue] = useState('')  \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b  const [results, setResults] = useState([])   const search = (e) => {    e.preventDefault()    \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u0438\u0441\u043a    const results = fzf.find(value.trim())    \/\/ console.log(results)    \/*      [        {          item: {            title: '\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b',            url: 'ru \/ Web \/ JavaScript \/ Reference \/ Global_Objects'          },          positions: Set(4) { 14, 13, 12, 11 },          start: 11,          end: 15,          \/\/ \u0447\u0435\u043c \u0432\u044b\u0448\u0435 `score`, \u0442\u0435\u043c \u043b\u0443\u0447\u0448\u0435          score: 104        },        \/\/ ...      ]    *\/    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b    setResults(results)  }   return (    &lt;>      &lt;form onSubmit={search}>        &lt;input          type='text'          value={value}          onChange={(e) => setValue(e.target.value)}        \/>        &lt;button>Search&lt;\/button>      &lt;\/form>      &lt;ul>        {results.map((result, i) => (          &lt;li key={i}>            &lt;HighlightChars              url={result.item.url}              positions={result.positions}            \/>          &lt;\/li>        ))}      &lt;\/ul>    &lt;\/>  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u0438\u043d\u043f\u0443\u0442\u0435 <code>java<\/code> \u0438 \u043d\u0430\u0436\u0430\u0442\u044c <code>Enter<\/code>, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/74\/wm\/by\/74wmbygadpfphrlh33pmhexw_yi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/74\/wm\/by\/74wmbygadpfphrlh33pmhexw_yi.png\"\/>  <\/p>\n<p>  \u041f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>String.prototype.includes()<\/code>? \u0425\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044f \u043f\u043e\u043d\u0438\u043c\u0430\u044e, <code>fzf<\/code> \u0432\u044b\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 (\u0434\u043b\u0438\u043d\u043d\u044b\u0445) \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043e\u043d \u0443\u043c\u0435\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0438\u0441\u043a\u043e\u043c\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u0441\u0442\u0440\u043e\u043a\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 <code>aaYbbbbXccc<\/code> \u0438 \u043c\u044b \u0432\u0432\u0435\u043b\u0438 \u0432 \u0438\u043d\u043f\u0443\u0442\u0435 <code>yx<\/code>. \u0422\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 <code>fzf<\/code>, \u043d\u043e \u043d\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>includes()<\/code>, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u044b <code>y<\/code> \u0438 <code>x<\/code> \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u0448\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u0432 <code>search-index.json<\/code>, \u0442\u043e \u043f\u0440\u0438 \u0434\u043b\u0438\u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043c\u0435\u043d\u0435\u0435 4 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (&lt;= 3), \u043a\u0430\u043a \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0438\u0441\u043a\u0430, \u0432\u044b\u0431\u043e\u0440\u043a\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>includes()<\/code> \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0439, \u0447\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>fzf<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u043e\u0447\u0435\u043c\u0443 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f &#171;\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0430\u044f&#187; \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <code>fzf<\/code>. \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>fzf<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">fuzzy-search.ts<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import { Fzf, FzfResultItem } from 'fzf'  \/\/ \u0422\u0438\u043f \u0434\u043b\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 export interface Doc {  url: string  title: string }  \/\/ \u041a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 export class FuzzySearch {  \/\/ \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430  docs: Doc[]   constructor(docs: Doc[]) {    \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430    this.docs = docs  }   \/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430  \/\/ \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438:  \/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f  \/\/ \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 10 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u0441\u043c. \u043d\u0438\u0436\u0435)  search(needle: string, { limit = 10 }): FzfResultItem&lt;Doc>[] {    \/\/ Use `let` because we might come up with a new list (aka. shortlist)    \/\/ that makes the haystack search much simpler to send to `Fzf()`.     \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c `let`, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 (\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430)    \/\/ \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c \u0438\u0437 4 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432,    \/\/ \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d    let docs = this.docs    \/\/ The list of docs is possible over 10,000 entries (in 2021). If the    \/\/ search input is tiny, don't bother with the overhead of Fzf().    \/\/ Because we don't even need it when the test is so easy in that    \/\/ it just needs to contain a single character.     \/\/ \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0443\u0441\u0441\u043a\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u0438 \u043f\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u043d\u0430 24.10.2021 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 2910.    \/\/ \u0415\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c \u0438\u0437 4 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432    if (needle.length &lt;= 3) {      const needleLowerCase = needle.toLowerCase()      \/\/ The reason this works and makes sense is because the `this.docs` is      \/\/ already sorted by popularity.      \/\/ So if someone searches for something short like `x` we just take      \/\/ the top 'limit' docs that have an `x` in the `.url`. This is      \/\/ faster than going through every doc with Fzf.       \/\/ \u041f\u0440\u0438\u0447\u0438\u043d\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c,      \/\/ \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b `this.docs` \u0443\u0436\u0435 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438.      \/\/ \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0437 `x`,      \/\/ \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0435\u0440\u0435\u043c 10 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f `x`.      \/\/ \u042d\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e `Fzf`.      \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0434\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430      const shortlistDocs: Doc[] = []      \/\/ \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430      for (const doc of this.docs) {        \/\/ \u0415\u0441\u043b\u0438 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 (\u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430)        if (doc.url.toLowerCase().includes(needleLowerCase)) {          \/\/ \u041f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0432 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a          shortlistDocs.push(doc)          \/\/ \u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u043e\u0440 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043b\u0438\u043c\u0438\u0442\u0430          if (shortlistDocs.length === limit) {            break          }        }      }      \/\/ Suppose the needle was `yx` and the `limit` as 10, then if we only found      \/\/ 9 (which is less than 10) docs that match exactly this, then we might      \/\/ be missing out, so we can't use the shortlist.      \/\/ For example, there might be more docs like `aaYbbbbXccc` which      \/\/ will be found by Fzf() but wouldn't be find in our shortlist because      \/\/ the two characters aren't next to each other.       \/\/ \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `yx`, \u0430 `limit` - 10,      \/\/ \u0435\u0441\u043b\u0438 \u043c\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e 9 (\u0442.\u0435. \u043c\u0435\u043d\u0435\u0435 10) \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432,      \/\/ \u0442\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a.      \/\/ \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 `aaYbbbbXccc`.      \/\/ \u0422\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 `Fzf`, \u043d\u043e \u0435\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u043c \u0441\u043f\u0438\u0441\u043a\u0435,      \/\/ \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u044b `y` \u0438 `x` \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c.      \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0435\u0433\u043e      \/\/ \u0434\u043b\u0438\u043d\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u044f\u0435\u0442\u0441\u044f \u043b\u0438\u043c\u0438\u0442\u0443      if (shortlistDocs.length >= limit) {        docs = shortlistDocs      }    }     \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u043e\u0438\u0441\u043a\u0430    const haystack = new Fzf(docs, {      \/\/ \u041b\u0438\u043c\u0438\u0442      limit,      \/\/ \u041f\u043e\u043b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430      selector: (item: Doc) => item.url    })    \/\/ All longer strings, default to using the already initialized `Fzf()` instance.    \/\/ \u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u043e\u0438\u0441\u043a\u0430    return haystack.find(needle)  } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e. \u0421 <code>fzf<\/code> \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 (\u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0441 <code>\/<\/code> \u0438\u043b\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0431\u0435\u043b\u044b) \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u043f\u043e <code>title<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u043e\u0438\u0441\u043a.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState } from 'react' \/\/ yarn add flexsearch import { Index } from 'flexsearch'  const data = [  {    title: '\u0412\u0435\u0431-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432',    url: '\/ru\/docs\/Web'  },  {    title: '\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects'  },  {    title: '\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u043e JavaScript',    url: '\/ru\/docs\/Web\/JavaScript\/Reference'  },  {    title: 'JavaScript',    url: '\/ru\/docs\/Web\/JavaScript'  },  {    title: 'Array',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array'  } ]  const flex = new Index({ tokenize: 'forward' })  data.forEach(({ title }, i) => {  flex.add(i, title) })  \/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438\u0437 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0430 const HighlightMatch = ({ title, q }) => {  const words = q.trim().toLowerCase().split(\/[ ,]+\/)  const regexWords = words.map((s) => s.replace(\/[.*+?^${}()|[\\]\\\\]\/g, '\\\\$&amp;'))  const regex = `\\\\b(${regexWords.join('|')})`  const parts = title.split(new RegExp(regex, 'gi'))   return (    &lt;>      {parts.map((part, i) => {        const key = `${part}:${i}`        if (words.includes(part.toLowerCase())) {          return &lt;mark key={key}>{part}&lt;\/mark>        } else {          return &lt;span key={key}>{part}&lt;\/span>        }      })}    &lt;\/>  ) }  \/\/ \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u043e\u0438\u0441\u043a\u0430 export const FlexSearch = () => {  const [value, setValue] = useState('')  const [results, setResults] = useState([])   const search = (e) => {    e.preventDefault()    const indexes = flex.search(value, {      limit: 3    })    \/\/ console.log(indexes) \/\/ [3, 2]    const results = indexes.map((i) => data[i])    setResults(results)  }   return (    &lt;>      &lt;form onSubmit={search}>        &lt;input          type='text'          value={value}          onChange={(e) => setValue(e.target.value)}        \/>        &lt;button>Search&lt;\/button>      &lt;\/form>      &lt;ul>        {results.map((result, i) => (          &lt;li key={i}>            &lt;HighlightMatch title={result.title} q={value} \/>          &lt;\/li>        ))}      &lt;\/ul>    &lt;\/>  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <code>Index<\/code> \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0440\u0435\u0436\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u0438 <code>tokenize: 'forward'<\/code>. <code>forward<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e (\u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0443\u044e) \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u044e \u0432 \u043f\u0440\u044f\u043c\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438, \u0442.\u0435. \u0432\u043f\u0435\u0440\u0435\u0434. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/github.com\/nextapps-de\/flexsearch#tokenizer-prefix-search\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0432 \u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u043e\u0434 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 (\u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432).<\/p>\n<p>  <\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>flex.search()<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439. \u041c\u044b \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0438\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u0438\u043d\u043f\u0443\u0442\u0435 <code>java<\/code> \u0438 \u043d\u0430\u0436\u0430\u0442\u044c <code>Enter<\/code>, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/c1\/n8\/my\/c1n8myvr6h1r9rbln35t8jksoqu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/c1\/n8\/my\/c1n8myvr6h1r9rbln35t8jksoqu.png\"\/>  <\/p>\n<p>  \u041a \u0441\u043b\u043e\u0432\u0443, \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <code>flexsearch<\/code> \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0445\u0443\u043a <a href=\"https:\/\/github.com\/angeloashmore\/react-use-flexsearch\"><code>useFlexSearch<\/code><\/a>, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u043d\u0435 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u043d\u043e\u0432\u044b\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c <code>flexsearch<\/code>. \u0415\u0441\u043b\u0438 \u0435\u0433\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0447\u0435\u0441\u0430\u0442\u044c, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState, useMemo, useEffect } from 'react' import { Index } from 'flexsearch'  export const useFlexSearch = (query, providedIndex, store, searchOptions) => {  const [index, setIndex] = useState(null)   useEffect(() => {    if (!providedIndex &amp;&amp; !store)      console.warn(        'A FlexSearch index and store was not provided. Your search results will be empty.'      )    else if (!providedIndex)      console.warn(        'A FlexSearch index was not provided. Your search results will be empty.'      )    else if (!store)      console.warn(        'A FlexSearch store was not provided. Your search results will be empty.'      )  }, [providedIndex, store])   useEffect(() => {    if (!providedIndex) {      setIndex(null)      return    }     if (providedIndex instanceof Index) {      setIndex(providedIndex)      return    }     \/\/ \u0415\u0441\u043b\u0438 `providedIndex` - \u044d\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430,    if (typeof providedIndex === 'string') {      const importedIndex = new Index(searchOptions)      \/\/ \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430      importedIndex.import(providedIndex, localStorage.getItem(providedIndex))       setIndex(importedIndex)      return    }  }, [providedIndex, searchOptions])   return useMemo(() => {    if (!query || !index || !store) return []     const rawResults = index.search(query, searchOptions)     return rawResults.map((id) => store[id])  }, [query, index, store, searchOptions]) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0445\u0443\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState, useRef } from 'react' import { Index } from 'flexsearch' import { useFlexSearch } from 'hooks'  const data = [  {    title: '\u0412\u0435\u0431-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432',    url: '\/ru\/docs\/Web'  },  {    title: '\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects'  },  {    title: '\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u043e JavaScript',    url: '\/ru\/docs\/Web\/JavaScript\/Reference'  },  {    title: 'JavaScript',    url: '\/ru\/docs\/Web\/JavaScript'  },  {    title: 'Array',    url: '\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array'  } ]  const flex = new Index({ tokenize: 'forward' })  data.forEach(({ title }, i) => {  flex.add(i, title) })  const HighlightMatch = ({ title, q }) => {  const words = q.trim().toLowerCase().split(\/[ ,]+\/)  const regexWords = words.map((s) => s.replace(\/[.*+?^${}()|[\\]\\\\]\/g, '\\\\$&amp;'))  const regex = `\\\\b(${regexWords.join('|')})`  const parts = title.split(new RegExp(regex, 'gi'))   return (    &lt;>      {parts.map((part, i) => {        const key = `${part}:${i}`        if (words.includes(part.toLowerCase())) {          return &lt;mark key={key}>{part}&lt;\/mark>        } else {          return &lt;span key={key}>{part}&lt;\/span>        }      })}    &lt;\/>  ) }  export const FlexSearchHook = () => {  const [value, setValue] = useState('')  const inputRef = useRef()  const results = useFlexSearch(value, flex, data)  \/\/ console.log(results)   const search = (e) => {    e.preventDefault()    setValue(inputRef.current.value.trim())  }   return (    &lt;>      &lt;form onSubmit={search}>        &lt;input type='text' defaultValue='' ref={inputRef} \/>        &lt;button>Search&lt;\/button>      &lt;\/form>      &lt;ul>        {results.map((result, i) => (          &lt;li key={i}>            &lt;HighlightMatch title={result.title} q={value} \/>          &lt;\/li>        ))}      &lt;\/ul>    &lt;\/>  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u0421 <code>flexsearch<\/code> \u0442\u043e\u0436\u0435 \u0432\u0441\u0435 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432 \u0438 \u0445\u0443\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>basic-search-examples<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0441 \u043a\u043e\u0434\u043e\u043c \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0435\u0449\u0435 \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">search.tsx<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import React, { useEffect, useMemo, useRef, useState } from 'react' \/\/ \u0425\u0443\u043a\u0438 \u0434\u043b\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 - \/\/ \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \/\/ import { Link, useHistory } from 'react-router-dom'  \/\/ \u0425\u0443\u043a \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430, \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 import { useCombobox } from 'downshift' \/\/ \u041f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e `title` import FlexSearch from 'flexsearch' \/\/ \u0425\u0443\u043a \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 import useSWR from 'swr'  \/\/ \u0422\u0438\u043f \u0438 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \"\u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0433\u043e\" \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e `url` import { Doc, FuzzySearch } from '.\/fuzzy-search'  \/\/ \u0425\u0443\u043a \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u043a\u0430\u043b\u0438 - \/\/ \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \/\/ import { useLocale } from '.\/hooks'  \/\/ \u0423\u0442\u0438\u043b\u0438\u0442\u044b \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u0430 \u0438 \/\/ \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0444\u043e\u043a\u0443\u0441\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 `\/`, \/\/ \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0438\u043f \u0434\u043b\u044f \u043f\u0440\u043e\u043f\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 import { getPlaceholder, SearchProps, useFocusOnSlash } from '.\/search-utils'  const SHOW_INDEXING_AFTER_MS = 500  \/\/ \u0422\u0438\u043f\u044b \/\/ \u0414\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 type Item = {  url: string  title: string } \/\/ \u0414\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 type SearchIndex = {  flex: any  fuzzy: FuzzySearch  items: null | Item[] } \/\/ \u0414\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 type ResultItem = {  title: string  url: string  positions: Set&lt;number> }  \/\/ \u0425\u0443\u043a \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c function useSearchIndex(): readonly [  null | SearchIndex,  null | Error,  () => void ] {  \/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438  const [shouldInitialize, setShouldInitialize] = useState(false)  \/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430  const [searchIndex, setSearchIndex] = useState&lt;null | SearchIndex>(null)  \/\/ const locale = useLocale()   \/\/ Default to 'en-US' if you're on the home page without the locale prefix.  \/\/ \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043b\u043e\u043a\u0430\u043b\u044c \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 'en-US',  \/\/ \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0431\u0435\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043b\u043e\u043a\u0430\u043b\u0438   \/\/ const url = `${locale}\/search-index.json`  \/\/ \u041f\u043e\u0438\u0441\u043a \u0444\u0430\u0439\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 `public`  const url = `\/search-index.json`   \/\/ \u0415\u0441\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `true`,  \/\/ \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0445\u0443\u043a `useSWR`:  \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 - `url`, \u043e\u043d \u0436\u0435 \u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u043a\u0435\u0448\u0430,  \/\/ \u0432\u0442\u043e\u0440\u043e\u0439 - \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 `fetcher`, \u0444\u0443\u043d\u043a\u0446\u0438\u044f  \/\/ \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430-\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445,  \/\/ \u0442\u0440\u0435\u0442\u0438\u0439 - \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c  \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0444\u043e\u043a\u0443\u0441\u0430).  \/\/ \u0422\u0430\u043a\u0430\u044f \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0445\u0443\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438  \/\/ https:\/\/swr.vercel.app\/docs\/conditional-fetching  const { error, data } = useSWR&lt;null | Item[], Error | undefined>(    shouldInitialize ? url : null,    async (url: string) => {      \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442      const response = await fetch(url)      if (!response.ok) {        \/\/ \u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435        \/\/ \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0430        throw new Error(await response.text())      }      \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 `JSON`      return await response.json()    },    \/\/ \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0443\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e    { revalidateOnFocus: false }  )   \/\/ \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0443\u0441\u0441\u043a\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u0438  \/\/ console.log(data?.length) \/\/ 2910   \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442  useEffect(() => {    \/\/ \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445    \/\/ \u0438\u043b\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430    if (!data || searchIndex) {      return    }     \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441    \/\/ `tokenize` - \u044d\u0442\u043e \u0440\u0435\u0436\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u0438 (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435    \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u044f \u0432 \u043f\u0440\u044f\u043c\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438, \u0442.\u0435. \u0432\u043f\u0435\u0440\u0435\u0434)    \/\/ https:\/\/github.com\/nextapps-de\/flexsearch#tokenizer-prefix-search    const flex = new FlexSearch.Index({ tokenize: 'forward' })     \/\/ \u0414\u0430\u043d\u043d\u044b\u043c\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c\u0438 \u0438 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 -    \/\/ `{ title: '\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a', url: 'https:\/\/...' }`    \/\/ \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0438 \u0435\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441 (\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435) \u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441    data!.forEach(({ title }, i) => {      flex.add(i, title)    })     \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430    const fuzzy = new FuzzySearch(data as Doc[])     \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430    setSearchIndex({ flex, fuzzy, items: data! })  }, [searchIndex, shouldInitialize, data])   \/\/ \u0425\u0443\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0435\u043c\u043e\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 3 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:  \/\/ \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430, \u043e\u0448\u0438\u0431\u043a\u0438 (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `null`)  \/\/ \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438  return useMemo(    () => [searchIndex, error || null, () => setShouldInitialize(true)],    [searchIndex, error, setShouldInitialize]  ) }  \/\/ The fuzzy search is engaged if the search term starts with a '\/' \/\/ and does not have any spaces in it. \/\/ \u041d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \/\/ \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 `\/` \u0438 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432. \/\/ \u0414\u0430\u043d\u043d\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0434\u043e\u043b\u0436\u0435\u043d \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0438\u0441\u043a function isFuzzySearchString(str: string) {  return str.startsWith('\/') &amp;&amp; !\/\\s\/.test(str) }  \/\/ \u0423\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \/\/ \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \/\/ `title` - \u044d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 (\u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0439) \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \/\/ `q` - \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 function HighlightMatch({ title, q }: { title: string; q: string }) {  \/\/ FlexSearch doesn't support finding out which \"typo corrections\"  \/\/ were done unfortunately.  \/\/ See https:\/\/github.com\/nextapps-de\/flexsearch\/issues\/99  \/\/ `FlexSearch`, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0438   \/\/ Split on higlight term and include term into parts, ignore case.  \/\/ \u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430  const words = q.trim().toLowerCase().split(\/[ ,]+\/)   \/\/ $&amp; means the whole matched string  \/\/ `$&amp;` \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0446\u0435\u043b\u0438\u043a\u043e\u043c  const regexWords = words.map((s) => s.replace(\/[.*+?^${}()|[\\]\\\\]\/g, '\\\\$&amp;'))  const regex = `\\\\b(${regexWords.join('|')})`  \/\/ \u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044e  const parts = title.split(new RegExp(regex, 'gi'))   return (    &lt;b>      {\/* \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0447\u0430\u0441\u0442\u0438 *\/}      {parts.map((part, i) => {        const key = `${part}:${i}`        \/\/ \u0415\u0441\u043b\u0438 \u0447\u0430\u0441\u0442\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435\u043c        if (words.includes(part.toLowerCase())) {          \/\/ \u041f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0435\u0435          return &lt;mark key={key}>{part}&lt;\/mark>        } else {          return &lt;span key={key}>{part}&lt;\/span>        }      })}    &lt;\/b>  )  \/\/ \u0415\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u043f\u043e\u0438\u0441\u043a\u0435 `query`, \u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0432\u0435\u0440\u043d\u0435\u0442 \u0442\u0430\u043a\u0443\u044e \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443  \/*    &lt;b>      &lt;span>Document.&lt;\/span>      \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435      &lt;mark>query&lt;\/mark>      &lt;span>Selector()&lt;\/span>    &lt;\/b>  *\/ }  \/\/ \u0423\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \"\u0445\u043b\u0435\u0431\u043d\u044b\u0445 \u043a\u0440\u043e\u0448\u0435\u043a\" \u0434\u043b\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \/\/ \u0438 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f function BreadcrumbURI({  uri,  positions }: {  uri: string  positions?: Set&lt;number> }) {  \/\/ \u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435  \/\/ `positions` - \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432  if (positions &amp;&amp; positions.size) {    \/\/ \u0420\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432    const chars = uri.split('')     return (      &lt;small>        {chars.map((char, i) => {          \/\/ \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438          if (positions.has(i)) {            return &lt;mark key={i}>{char}&lt;\/mark>          } else {            return &lt;span key={i}>{char}&lt;\/span>          }        })}      &lt;\/small>    )  }   \/\/ \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 `url`  \/\/ \u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 `search-index.json`  \/\/ \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 `\/`, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f.  \/\/ \u0422\u0430\u043a\u0436\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f `docs`  const keep = uri    .split('\/')    \/\/ .slice(1)    .slice(3)    .filter((p) => p !== 'docs')  \/\/ \u041f\u0440\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f ' \/ '  return &lt;small className='search-item-uri'>{keep.join(' \/ ')}&lt;\/small>  \/\/ \u0411\u044b\u043b\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: `https:\/\/developer.mozilla.org\/ru\/docs\/Web`,  \/\/ \u0441\u0442\u0430\u043b\u043e: `ru \/ Web` }  \/\/ \u0422\u0438\u043f \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 type InnerSearchNavigateWidgetProps = SearchProps &amp; {  onResultPicked?: () => void  defaultSelection: [number, number] }  \/\/ \u0425\u0443\u043a \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u043f\u0443\u0442\u0430 function useHasNotChangedFor(value: string, ms: number) {  \/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439  const [hasNotChanged, setHasNotChanged] = useState(false)  \/\/ \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435  const previousValue = useRef(value)   \/\/ \u041f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439  useEffect(() => {    \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0432\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443,    \/\/ \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c    if (previousValue.current === value) {      return    }    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u043c    previousValue.current = value    setHasNotChanged(false)    \/\/ while timeouts are not accurate for counting time there error is only    \/\/ upwards, meaning they might trigger after more time than specified,    \/\/ which is fine in this case    \/\/ \u0417\u0434\u0435\u0441\u044c \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u044b \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f    \/\/ \u0445\u043e\u0440\u043e\u0448\u0438\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438,    \/\/ \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u043e\u0433\u0443\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438,    \/\/ \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e, \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u044b\u043c    const timeout = setTimeout(() => {      \/\/ \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u043f\u0443\u0442\u0430 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c,      \/\/ \u0437\u043d\u0430\u0447\u0438\u0442, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043d\u0435 \u0431\u044b\u043b\u043e :)      setHasNotChanged(true)    }, ms)    \/\/ \u041e\u0447\u0438\u0441\u0442\u043a\u0430 \u043f\u043e\u0431\u043e\u0447\u043d\u043e\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u0443\u0442\u0435\u0447\u0435\u043a \u043f\u0430\u043c\u044f\u0442\u0438    return () => {      clearTimeout(timeout)    }    \/\/ \u0425\u0443\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u043f\u0443\u0442\u0430 \u0438\u043b\u0438 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438  }, [value, ms])   \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435  return hasNotChanged }  \/\/ \u0412\u0438\u0434\u0436\u0435\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 function InnerSearchNavigateWidget(props: InnerSearchNavigateWidgetProps) {  \/\/ \u041f\u0440\u043e\u043f\u044b:  \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u043f\u0443\u0442\u0430  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f  \/\/ \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0442\u043e\u0433\u043e, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u0438\u043d\u043f\u0443\u0442 \u0432 \u0444\u043e\u043a\u0443\u0441\u0435  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0444\u043e\u043a\u0443\u0441\u0430  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430  \/\/ \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e  const {    inputValue,    onChangeInputValue,    isFocused,    onChangeIsFocused,    onResultPicked,    defaultSelection  } = props   \/\/ \u041e\u0431\u044a\u0435\u043a\u0442 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u043b\u043e\u043a\u0430\u043b\u044c -  \/\/ \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f  \/\/ const history = useHistory()  \/\/ const locale = useLocale()   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441, \u043e\u0448\u0438\u0431\u043a\u0443 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430  const [searchIndex, searchIndexError, initializeSearchIndex] =    useSearchIndex()   \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u043f\u043d\u0443\u0442  const inputRef = useRef&lt;null | HTMLInputElement>(null)  \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443  const formRef = useRef&lt;null | HTMLFormElement>(null)  \/\/ \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f  const isSelectionInitialized = useRef(false)   \/\/ \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439  const showIndexing = useHasNotChangedFor(inputValue, SHOW_INDEXING_AFTER_MS)   \/\/ \u041f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f  useEffect(() => {    \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043d\u043f\u0443\u0442 \u0438\u043b\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c    if (!inputRef.current || isSelectionInitialized.current) {      return    }     \/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u043f\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u043e\u043a\u0443\u0441\u0435    if (isFocused) {      \/\/ \u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `[0, 0]`      inputRef.current.selectionStart = defaultSelection[0]      inputRef.current.selectionEnd = defaultSelection[1]    }    \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435    isSelectionInitialized.current = true  }, [isFocused, defaultSelection])   \/\/ \u041c\u0435\u043c\u043e\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430  const resultItems: ResultItem[] = useMemo(() => {    \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u0438\u043b\u0438 \u0438\u043d\u043f\u0443\u0442, \u0438\u043b\u0438 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430,    \/\/ \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c    if (!searchIndex || !inputValue || searchIndexError) {      \/\/ This can happen if the initialized hasn't completed yet or      \/\/ completed un-successfully.      \/\/ \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438, \u0435\u0441\u043b\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0435\u0449\u0435 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c      \/\/ \u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e      return []    }     \/\/ The iPhone X series is 812px high.    \/\/ If the window isn't very high, show fewer matches so that the    \/\/ overlaying search results don't trigger a scroll.    \/\/ \u0414\u0430\u043d\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f    \/\/ \u043f\u043e\u043b\u043e\u0441\u044b \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0430\u0445 \u0441 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0432\u044b\u0441\u043e\u0442\u043e\u0439    const limit = window.innerHeight &lt; 850 ? 5 : 10     \/\/ \u0415\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 `\/` \u0438 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432,    \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a    if (isFuzzySearchString(inputValue)) {      \/\/ \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u043f\u0443\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f `\/`      if (inputValue === '\/') {        \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432        return []      } else {        \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u0438\u0441\u043a,        \/\/ \u0443\u0434\u0430\u043b\u044f\u044f \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 `\/`        const fuzzyResults = searchIndex.fuzzy.search(inputValue.slice(1), {          \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f 5 \u0438\u043b\u0438 10 \u043b\u0443\u0447\u0448\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432          limit        })        \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432        return fuzzyResults.map((fuzzyResult) => ({          \/\/ \u0410\u0434\u0440\u0435\u0441 \u0441\u0442\u0430\u0442\u044c\u0438          url: fuzzyResult.item.url,          \/\/ \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0442\u0430\u0442\u044c\u0438          title: fuzzyResult.item.title,          \/\/ \u041d\u0430\u0431\u043e\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432          positions: fuzzyResult.positions        }))      }    } else {      \/\/ Full-Text search      \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u043e\u0438\u0441\u043a      const indexResults: number[] = searchIndex.flex.search(inputValue, {        \/\/ \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435        limit,        \/\/ \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f        suggest: true \/\/ This can give terrible result suggestions        \/\/ \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u0443\u0436\u0430\u0441\u043d\u044b\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c :)      })      \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432      return indexResults.map(        (index: number) => (searchIndex.items || [])[index] as ResultItem      )    }    \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438    \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u043f\u0443\u0442\u0430, \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0438\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043a\u0438  }, [inputValue, searchIndex, searchIndexError])   \/\/ \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430  \/\/ const formAction = `\/${locale}\/search`  const formAction = `https:\/\/developer.mozilla.org\/ru-RU\/search`  \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430  const searchPath = useMemo(() => {    \/\/ \u041d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430    const sp = new URLSearchParams()    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f `?q=inputValue`    sp.set('q', inputValue.trim())    \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c    \/\/ \u0415\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u0438\u043d\u043f\u0443\u0442\u0435 `qwerty`,    \/\/ \u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f `https:\/\/developer.mozilla.org\/ru\/search?q=qwerty`    return `${formAction}?${sp.toString()}`  }, [formAction, inputValue])   \/\/ \u041f\u0443\u0441\u0442\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 - \u043a\u043e\u0433\u0434\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e  const nothingFoundItem = useMemo(    () => ({ url: searchPath, title: '', positions: new Set() }),    [searchPath]  )   \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0432\u0441\u0435\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438  const {    getInputProps,    getItemProps,    getMenuProps,    getComboboxProps,     \/\/ \u0418\u043d\u0434\u0435\u043a\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430\u0432\u0435\u0434\u0435\u043d \u043a\u0443\u0440\u0441\u043e\u0440 \u0438\u043b\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u043e\u043a\u0443\u0441\u0435    highlightedIndex,    \/\/ \u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0442\u043e\u0433\u043e, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u043c\u0435\u043d\u044e \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438    isOpen,     reset,    toggleMenu  } = useCombobox({    \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u043f\u0443\u0441\u0442\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430    items: resultItems.length === 0 ? [nothingFoundItem] : resultItems,    \/\/ \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u043f\u0443\u0442\u0430    inputValue,    \/\/ \u0421\u043f\u0438\u0441\u043e\u043a \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438    \/\/ \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u043a\u0435 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442\u0435    defaultIsOpen: isFocused,    \/\/ \u041f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043f\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 (highlightedIndex) \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443    onSelectedItemChange: ({ selectedItem }) => {      if (selectedItem) {        \/\/ history.push(selectedItem.url)        \/\/ \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u043d\u0430 MDN        window.open(selectedItem.url, '_blank')        \/\/ \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u043f\u0443\u0442\u0430 \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u0442\u0441\u044f        onChangeInputValue('')        \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0431\u0440\u043e\u0441 \u043c\u0435\u043d\u044e        reset()        \/\/ \u041c\u0435\u043d\u044e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f        toggleMenu()        \/\/ \u0420\u0430\u0441\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u043a\u0430        inputRef.current?.blur()        \/\/ \u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432,        \/\/ \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u0435        if (onResultPicked) {          onResultPicked()        }        \/\/ \u041f\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430 \u0432 \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0447\u0430\u0441\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430        window.scroll({          top: 0,          left: 0,          behavior: 'smooth'        })      }    }  })   \/\/ \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 `\/` \u043d\u0430 \u0438\u043d\u043f\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u043e\u043a\u0443\u0441  useFocusOnSlash(inputRef)   \/\/ \u041f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430  useEffect(() => {    \/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u043f\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u043e\u043a\u0443\u0441\u0435    if (isFocused) {      \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e      initializeSearchIndex()    }  }, [initializeSearchIndex, isFocused])   \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430 - \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433  \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f `IIFE` - \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435  const searchResults = (() => {    \/\/ \u0415\u0441\u043b\u0438 \u043c\u0435\u043d\u044e \u0437\u0430\u043a\u0440\u044b\u0442\u043e, \u0442.\u0435. \u0438\u043d\u043f\u0443\u0442 \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u043e\u043a\u0443\u0441\u0435,    \/\/ \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u043f\u0443\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 (\u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432),    \/\/ \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c    if (!isOpen || !inputValue.trim()) {      return null    }     \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430    if (searchIndexError) {      return (        \/\/ &lt;div className='searchindex-error'>Error initializing search index&lt;\/div>        &lt;div className='searchindex-error'>          \u041f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430        &lt;\/div>      )    }     \/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0435\u0449\u0435 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c    if (!searchIndex) {      \/\/ \u0438 \u043d\u0435 \u0431\u044b\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u043f\u0443\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 500 \u043c\u0441      return showIndexing ? (        &lt;div className='indexing-warning'>          {\/* &lt;em>Initializing index&lt;\/em> *\/}          &lt;em>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430&lt;\/em>        &lt;\/div>      ) : null    }     return (      &lt;>        {\/* \u0415\u0441\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u043f\u0443\u0442\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f `\/` *\/}        {resultItems.length === 0 &amp;&amp; inputValue !== '\/' ? (          &lt;div            {...getItemProps({              className:                'nothing-found result-item ' +                (highlightedIndex === 0 ? 'highlight' : ''),              \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442              item: nothingFoundItem,              index: 0            })}          >            {\/* No document titles found. *\/}            \u041f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e.            &lt;br \/>            {\/* &lt;Link to={searchPath}>              Site search for `{inputValue}`            &lt;\/Link> *\/}            {\/* \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0441\u0442\u0430\u0442\u044c\u0438, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 *\/}            &lt;a href={searchPath} target='_blank' rel='noopener noreferrer'>              \u0418\u0441\u043a\u0430\u0442\u044c \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 MDN `{inputValue}`            &lt;\/a>          &lt;\/div>        ) : (          \/\/ \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0438\u0441\u043a\u0430          resultItems.map((item, i) => (            &lt;div              {...getItemProps({                key: item.url,                className:                  'result-item ' + (i === highlightedIndex ? 'highlight' : ''),                item,                index: i              })}            >              {\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f *\/}              &lt;HighlightMatch title={item.title} q={inputValue} \/>              &lt;br \/>              {\/* \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0445\u043b\u0435\u0431\u043d\u044b\u0435 \u043a\u0440\u043e\u0448\u043a\u0438 \u0434\u043b\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 *\/}              &lt;BreadcrumbURI uri={item.url} positions={item.positions} \/>            &lt;\/div>          ))        )}        {\/* \u0415\u0441\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a *\/}        {isFuzzySearchString(inputValue) &amp;&amp; (          \/\/ &lt;div className='fuzzy-engaged'>Fuzzy searching by URI&lt;\/div>          &lt;div className='fuzzy-engaged'>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u043f\u043e URI&lt;\/div>        )}      &lt;\/>    )  })()   \/\/ \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433  return (    &lt;form      action={formAction}      {...getComboboxProps({        \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443        ref: formRef as any, \/\/ downshift's types hardcode it as a div        \/\/ \u0434\u043b\u044f `downshift` \u0432\u0441\u0435 \u0435\u0441\u0442\u044c `div` \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 :)        className: 'search-form',        id: 'nav-main-search',        role: 'search',        \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b        onSubmit: (e) => {          \/\/ This comes into effect if the input is completely empty and the          \/\/ user hits Enter, which triggers the native form submission.          \/\/ When something *is* entered, the onKeyDown event is triggered          \/\/ on the &lt;input> and within that handler you can          \/\/ access `event.key === 'Enter'` as a signal to submit the form.           \/\/ \u0417\u0434\u0435\u0441\u044c \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0438\u043d\u043f\u0443\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c \u0438          \/\/ \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 `Enter`, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u043e\u0440\u043c\u044b.          \/\/ \u0415\u0441\u043b\u0438 \u0436\u0435 \u0438\u043d\u043f\u0443\u0442 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0444\u043e\u0440\u043c\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c          \/\/ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e`event.key === 'Enter'` \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435          \/\/ \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448\u0438 `onKeyDown`.          \/\/ \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b          e.preventDefault()          \/\/ \u042d\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u043b\u043e \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b \u0432 \u0432\u0438\u0434\u0435 \u043b\u0443\u043f\u044b (\u0441\u043c. \u043d\u0438\u0436\u0435)        }      })}    >      &lt;div className='search-field'>        &lt;label htmlFor='main-q' className='visually-hidden'>          {\/* Search MDN *\/}          \u041f\u043e\u0438\u0441\u043a MDN        &lt;\/label>         &lt;input          {...getInputProps({            type: 'search',            className: isOpen              ? 'has-search-results search-input-field'              : 'search-input-field',            id: 'main-q',            name: 'q',            \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b            placeholder: getPlaceholder(isFocused),            \/\/ \u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442            \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430            onMouseOver: initializeSearchIndex,            \/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0444\u043e\u043a\u0443\u0441\u0430            onFocus: () => {              onChangeIsFocused(true)            },            \/\/ \u0438 \u0437\u0434\u0435\u0441\u044c            onBlur: () => onChangeIsFocused(false),            \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448            onKeyDown(event) {              \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0436\u0430\u0442\u0430 \u043a\u043b\u0430\u0432\u0438\u0448\u0430 `Escape` \u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0438\u043d\u043f\u0443\u0442              if (event.key === 'Escape' &amp;&amp; inputRef.current) {                \/\/ \u041c\u0435\u043d\u044e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0438\u043d\u043f\u0443\u0442 \u043e\u0447\u0438\u0449\u0430\u0435\u0442\u0441\u044f                toggleMenu()              } else if (                \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0436\u0430\u0442\u0430 \u043a\u043b\u0430\u0432\u0438\u0448\u0430 `Enter`, \u0438\u043d\u043f\u0443\u0442 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0438\u0441\u043a\u0430                event.key === 'Enter' &amp;&amp;                inputValue.trim() &amp;&amp;                highlightedIndex === -1              ) {                \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0444\u043e\u043a\u0443\u0441 \u0441 \u0438\u043d\u043f\u0443\u0442\u0430                inputRef.current!.blur()                \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043e\u0440\u043c\u0443                \/\/ formRef.current!.submit()                \/\/ \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 MDN                window.open(searchPath, '_blank')              }            },            \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u043f\u0443\u0442\u0430            onChange(event) {              if (event.target instanceof HTMLInputElement) {                onChangeInputValue(event.target.value)              }            },            \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442            ref: (input) => {              inputRef.current = input            }          })}        \/>         {\/* \u041a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 *\/}        {\/* \u0441\u043e\u0437\u0434\u0430\u043b \u043f\u0443\u043b\u0440\u0435\u043a\u0432\u0435\u0441\u0442 :) *\/}        &lt;input          type='submit'          className='search-button'          value=''          aria-label='\u041f\u043e\u0438\u0441\u043a'          onClick={() => {            if (inputValue.trim() &amp;&amp; inputValue !== '\/') {              \/\/ history.push(searchPath)              window.open(searchPath, '_blank')            }          }}        \/>      &lt;\/div>       {\/* \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 *\/}      &lt;div {...getMenuProps()}>        {searchResults &amp;&amp; &lt;div className='search-results'>{searchResults}&lt;\/div>}      &lt;\/div>    &lt;\/form>  ) }  \/\/ \u041f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u044c - \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0448\u0438\u0431\u043e\u043a class SearchErrorBoundary extends React.Component {  \/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438  state = { hasError: false }   \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438  static getDerivedStateFromError(error: Error) {    \/\/ console.error('There was an error while trying to render search', error)    console.error('\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430', error)    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438    return { hasError: true }  }  render() {    return this.state.hasError ? (      \/\/ &lt;div>Error while rendering search. Check console for details.&lt;\/div>      &lt;div>        \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u0417\u0430\u0433\u043b\u044f\u043d\u0438\u0442\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438.      &lt;\/div>    ) : (      this.props.children    )  } }  \/\/ \u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u043e\u0433\u043e \u0432 \u043f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u044c export default function SearchNavigateWidget(  props: InnerSearchNavigateWidgetProps ) {  return (    &lt;SearchErrorBoundary>      &lt;InnerSearchNavigateWidget {...props} \/>    &lt;\/SearchErrorBoundary>  ) }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0421 \u0442\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0445\u0443\u043a <code>useCombobox<\/code>, \u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0432\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e (<a href=\"https:\/\/github.com\/downshift-js\/downshift\/tree\/master\/src\/hooks\/useCombobox\">\u0432\u043e\u0442<\/a> \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f).<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u044d\u0442\u043e \u0432\u0441\u0435, \u0447\u0435\u043c \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u0432\u0430\u0448\u0435\u043c \u0440\u0430\u0441\u043f\u043e\u0440\u044f\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0438\u0441\u043f\u043e\u0441\u043e\u0431\u0438\u0442\u044c \u0434\u043b\u044f \u043d\u0443\u0436\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u0435\u0433\u043e \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043c\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 &#171;\u043a\u0440\u0443\u0442\u043e\u0441\u0442\u0438&#187; \u043f\u043e\u0438\u0441\u043a\u0430, \u0431\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448. \u042f \u0431\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b \u043a\u043e\u0434, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0445\u043e\u0436\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0449\u0435\u0439 \u043b\u0438\u0448\u043d\u0438\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u044f \u0443\u0431\u0440\u0430\u043b \u0431\u044b \u043f\u0430\u0440\u043e\u0447\u043a\u0443 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d\u0438 \u0441\u0442\u043e\u044f\u0442 \u0434\u043e\u0440\u043e\u0436\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0437-\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u0422\u0430\u043a\u0436\u0435 \u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435, \u0441\u0443\u0434\u044f \u043f\u043e \u0432\u0441\u0435\u043c\u0443, \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0435\u044f\u0432\u043d\u044b\u0439 \u0442\u0438\u043f <code>any<\/code> (<code>\"noImplicitAny\": false<\/code>), \u0447\u0442\u043e, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u0430\u043c \u0431\u044b\u043b\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u0438 \u043c\u043d\u0435.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442\u0441\u044f \u043b\u044e\u0431\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438.<\/p>\n<p>  <\/p>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0434\u043d\u044f!<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<blockquote><p><a href=\"https:\/\/t.me\/timewebru\"><b>\u041d\u043e\u0432\u043e\u0441\u0442\u0438, \u043e\u0431\u0437\u043e\u0440\u044b \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432 \u0438 \u043a\u043e\u043d\u043a\u0443\u0440\u0441\u044b \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Timeweb.Cloud \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c Telegram-\u043a\u0430\u043d\u0430\u043b\u0435<\/b><\/a> \u21a9<\/p><\/blockquote>\n<p><a href=\"https:\/\/timeweb.cloud\/?i=106909\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/b5\/pj\/of\/b5pjofdoxth14ro-rjsrn7sbmiy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/b5\/pj\/of\/b5pjofdoxth14ro-rjsrn7sbmiy.png\"\/><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/585910\/\"> https:\/\/habr.com\/ru\/articles\/585910\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/jc\/hw\/st\/jchwst6a3nwlxlscnmuw5tdhmry.png\" data-src=\"https:\/\/habrastorage.org\/webt\/jc\/hw\/st\/jchwst6a3nwlxlscnmuw5tdhmry.png\"\/>  <\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  <\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e (\u0433\u0434\u0435-\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u0430\u0432\u0433\u0443\u0441\u0442\u0430) \u0443 MDN \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 (\u043a\u0440\u0443\u0442\u043e\u0439, \u043f\u043e \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432) \u043f\u043e\u0438\u0441\u043a.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u0438\u0434\u0436\u0435\u0442\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/34\/j7\/tq\/34j7tqebk9v61hlfas_d-gzb8q8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/34\/j7\/tq\/34j7tqebk9v61hlfas_d-gzb8q8.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7y\/jo\/9s\/7yjo9s4mfq886c-mixhcxjxznxe.png\" data-src=\"https:\/\/habrastorage.org\/webt\/7y\/jo\/9s\/7yjo9s4mfq886c-mixhcxjxznxe.png\"\/>  <\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/github.com\/mdn\/yari\/blob\/main\/client\/src\/search.tsx\">\u0437\u0434\u0435\u0441\u044c<\/a>, \u0430 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435, \u043a\u0440\u043e\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/mdn\/yari\/tree\/main\/client\/src\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u043e \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a <code>https:\/\/developer.mozilla.org<\/code> \u043b\u043e\u043a\u0430\u043b\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>\/ru<\/code> \u0438 <code>\/search-index.json<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/od\/5q\/k9\/od5qk9sgcoxeqqjw2am_u6mbfny.png\" data-src=\"https:\/\/habrastorage.org\/webt\/od\/5q\/k9\/od5qk9sgcoxeqqjw2am_u6mbfny.png\"\/>  <\/p>\n<p>  \u041a\u043e\u0434 \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 <code>React<\/code> \u0438 <code>TypeScript<\/code>. \u0427\u0442\u043e \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442? \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0437\u0430 \u043c\u043d\u043e\u0439.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-386507","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=386507"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386507\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=386507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=386507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=386507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}