From fd9a559475ac6bff7c82594dc313d762ab807592 Mon Sep 17 00:00:00 2001 From: unwox Date: Wed, 16 Oct 2024 22:40:09 +0600 Subject: improve site structure for seo --- bin/serve.fnl | 134 +++++++++++++++++++++++++++++++++++++---------------- lib/string.fnl | 19 ++++++-- spellfix.fnl | 2 +- static/favicon.png | Bin 0 -> 3720 bytes static/style.css | 17 ++++++- texts.fnl | 101 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 225 insertions(+), 48 deletions(-) create mode 100644 static/favicon.png diff --git a/bin/serve.fnl b/bin/serve.fnl index 4cbb905..62e3962 100644 --- a/bin/serve.fnl +++ b/bin/serve.fnl @@ -11,7 +11,7 @@ (local str (require :lib.string)) (local texts (require :texts)) (local spellfix (require :spellfix)) -(local {: must} (require :lib.utils)) +(local {: must : measure} (require :lib.utils)) (local ozchai (require :parser.ozchai)) (local ipuer (require :parser.ipuer)) @@ -39,6 +39,16 @@ (string.gsub """ "\"") (string.gsub "&" "&")))) +(fn category-menu-path [category] + (. {"Красный чай" "red-tea" + "Шен пуэр" "sheng-puer" + "Шу пуэр" "shou-puer" + "Улун" "oolong" + "Зеленый чай" "green-tea" + "Белый чай" "white-tea" + "Желтый чай" "yellow-tea" + "Посуда" "teaware"} category)) + (fn get-query-string [query key] (if (and query (. query key) @@ -55,9 +65,9 @@ (tonumber (. query key 1)) nil)) -(fn collect-form [params] +(fn collect-form [params category] {:query (str.trim (or (get-query-string params "query") "")) - :tags (filter #(~= "" $2) (or params.tags [])) + :tags (filter #(~= "" $2) (or params.tags [category])) :min-price (get-query-number params "min-price") :max-price (get-query-number params "max-price") :price-per (= "on" (get-query-string params "price-per"))}) @@ -140,7 +150,7 @@ (if (. query-synonyms q) (.. "(" q "* OR " (. query-synonyms q) "*)") (.. q "*"))) - (str.split query)) + (str.split query " ")) " AND "))) (when (and min-price (< 0 min-price)) (if price-per @@ -202,29 +212,24 @@ (fn site-name-template [name] (if (= name "ipuer") - [:a {:class "site-icon" :href "https://ipuer.ru" - :alt "Логотип Институт чай пуэр"} - [:img {:src "/static/ipuer.jpg"}] + [:a {:class "site-icon" :href "https://ipuer.ru"} + [:img {:src "/static/ipuer.jpg" :alt "Логотип Институт чай пуэр"}] "Институт чая пуэр"] (= name "artoftea") - [:a {:class "site-icon" :href "https://artoftea.ru" - :alt "Логотип Art of tea"} - [:img {:src "/static/artoftea.png"}] + [:a {:class "site-icon" :href "https://artoftea.ru"} + [:img {:src "/static/artoftea.png" :alt "Логотип Art of tea"}] "Art of tea"] (= name "ozchai") - [:a {:class "site-icon" :href "https://ozchai.ru" - :alt "Логотип #OZCHAI"} - [:img {:src "/static/ozchai.ico"}] + [:a {:class "site-icon" :href "https://ozchai.ru"} + [:img {:src "/static/ozchai.ico" :alt "Логотип #OZCHAI"}] "Чайная #OZCHAI"] (= name "clubcha") - [:a {:class "site-icon" :href "https://clubcha.ru" - :alt "Логотип Железный Феникс"} - [:img {:src "/static/clubcha.png"}] + [:a {:class "site-icon" :href "https://clubcha.ru"} + [:img {:src "/static/clubcha.png" :alt "Логотип Железный Феникс"}] "Железный Феникс"] (= name "chaekshop") - [:a {:class "site-icon" :href "https://chaekshop.ru" - :alt "Логотип Интернет-магазин фермерского китайского чая «Чаёк»"} - [:img {:src "/static/chaekshop.svg"}] + [:a {:class "site-icon" :href "https://chaekshop.ru"} + [:img {:src "/static/chaekshop.svg" :alt "Логотип Интернет-магазин «Чаёк»"}] "Интернет-магазин «Чаёк»"] "")) @@ -267,7 +272,7 @@ (if (< page last-page) [:a {:href (form->path (+ page 1) form)} "→"] "")] - [:div {} "Всего результатов: " [:strong {} (string.format "%d" total)]]] + [:div {} "Всего: " [:strong {} (string.format "%d" total)]]] "")) (fn aside-template [form paginator] @@ -275,9 +280,9 @@ [:div {:class "aside-content"} (if (not (form-empty? form)) [:a {:href "/" :style "display: block;"} - [:img {:class "logo" :src "static/logo.svg" + [:img {:class "logo" :src "/static/logo.svg" :alt "Логотип meicha.ru" :title "Логотип meicha.ru"}]] - [:img {:class "logo" :src "static/logo.svg" + [:img {:class "logo" :src "/static/logo.svg" :alt "Логотип meicha.ru" :title "Логотип meicha.ru"}]) [:form {:class "form"} [:input {:type :search :name "query" :value form.query @@ -305,22 +310,49 @@ [:button {:type :submit} "Искать"]] paginator]]) +(fn menu-template [] + [:nav {:class "menu"} + [:a {:href "/red-tea"} "Красный чай"] + [:a {:href "/sheng-puer"} "Шен пуэр"] + [:a {:href "/shou-puer"} "Шу пуэр"] + [:a {:href "/oolong"} "Улун"] + [:a {:href "/green-tea"} "Зеленый чай"] + [:a {:href "/white-tea"} "Белый чай"] + [:a {:href "/yellow-tea"} "Желтый чай"] + [:a {:href "/teaware"} "Посуда"]]) + (fn base-template [form page total items] (local paginator (paginator-template form page 48 total)) + (local menu-path + (if (and form.tags (< 0 (# form.tags))) + (category-menu-path (. form.tags 1)) + nil)) (local spellfix-suggestion (if (and (not (str.empty? form.query)) items (< 0 (# items))) nil (spellfix.guess form.query))) - [:html {:lang "en"} + [:html {:lang "ru-RU"} [:head {} - [:meta {:charset "UTF-8"}] - [:link {:rel :stylesheet :href "static/style.css"}] - [:title {} "A new cool web server for lua"]] + [:meta {:charset "utf-8"}] + [:meta {:name "viewport" :content "width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=5.0"}] + [:link {:rel "stylesheet" :href "/static/style.css"}] + [:link {:rel "icon" :href "/static/favicon.png"}] + [:title {} (if (str.empty? form.query) + texts.meta-title + (.. form.query " | " texts.meta-title))] + [:meta {:name "description" :content texts.meta-description}]] [:body {} [:div {:class "container"} [:div {:class "content"} (aside-template form paginator) [:section {} + (menu-template) + (if (. form.tags 1) + [:h1 {} (. form.tags 1)] + "") + (if (and menu-path (. texts (.. menu-path "-description"))) + [:NO-ESCAPE (. texts (.. menu-path "-description"))] + "") (if (< 0 (# items)) [:div {:class "list"} (table.unpack (map #(item-template $2) items))] @@ -333,20 +365,40 @@ [:footer {} paginator]]]]]]) (fn root-handler [{: path : query}] - (if (= path "/") - (let [headers {:content-type "text/html"} - page (or (get-query-number query "page") 1) - form (collect-form query) - {: results : total} - (if (not (form-empty? form)) - (query-products form page) - {:total 48 :results (random-products 48)})] - (values - 200 headers - (html.render - (base-template form page total results) - true))) - (values 404 {} "not found"))) + (fn respond [query category] + (let [headers {:content-type "text/html"} + page (or (get-query-number query "page") 1) + form (collect-form query category) + {: results : total} + (if (not (form-empty? form)) + (measure "query products" #(query-products form page)) + {:total 48 :results (measure "random products" #(random-products 48))})] + (values + 200 headers + (.. "\n" + (measure "render" + #(html.render + (base-template form page total results) + true)))))) + + (match (str.split path "/") + ["red-tea"] (respond query "Красный чай") + ["sheng-puer"] (respond query "Шен пуэр") + ["shou-puer"] (respond query "Шу пуэр") + ["oolong"] (respond query "Улун") + ["green-tea"] (respond query "Зеленый чай") + ["white-tea"] (respond query "Белый чай") + ["yellow-tea"] (respond query "Желтый чай") + ["teaware"] (respond query "Посуда") + [] (respond query) + _ (values 404 {} "not found"))) + +(fn robots-handler [] + (values 200 {:content-type "text/plain"} "User-agent: *\nAllow: /")) -(must (luna.router.route "GET /" root-handler)) +(must (luna.router.route + "GET /" + (fn [req] + (measure "root handler" #(root-handler req))))) +(must (luna.router.route "GET /robots.txt" robots-handler)) (must (luna.router.static "GET /static/" "static/")) diff --git a/lib/string.fnl b/lib/string.fnl index 1696a64..6538827 100644 --- a/lib/string.fnl +++ b/lib/string.fnl @@ -12,11 +12,22 @@ (table.insert result (must (luna.utf8.sub str i 1)))) result) -(fn split [str] - (accumulate [res [] v _ (str:gmatch "%S+")] +(fn split [str delimiter] + (if (empty? str) + [] (do - (table.insert res v) - res))) + (local result {}) + (local len (# str)) + (var cursor 1) + (var (start end) (str:find delimiter)) + (while start + (when (< cursor start) + (table.insert result (str:sub cursor (- start 1)))) + (set cursor (+ end 1)) + (set (start end) (str:find delimiter cursor))) + (when (<= cursor len) + (table.insert result (str:sub cursor len))) + result))) (fn ends-with [str end] (= (string.sub str (- (# end))) end)) diff --git a/spellfix.fnl b/spellfix.fnl index 00642ac..5ecb870 100644 --- a/spellfix.fnl +++ b/spellfix.fnl @@ -301,7 +301,7 @@ (array.sort index #(< $1.distance $2.distance))) (local most-similar (. sorted-index 1)) most-similar.word) - (str.split string)) + (str.split string " ")) " ")) (if (~= result string) result diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..644e91f Binary files /dev/null and b/static/favicon.png differ diff --git a/static/style.css b/static/style.css index 39f3685..1dc0bc2 100644 --- a/static/style.css +++ b/static/style.css @@ -24,6 +24,17 @@ body { top: 3rem; } +.menu { + display: flex; + gap: 0.75rem 1.5rem; + flex-wrap: wrap; + margin-bottom: 2rem; +} + +.menu a { + color: blue; +} + .list { display: flex; flex-wrap: wrap; @@ -83,6 +94,10 @@ body { width: 10rem; } +.form { + margin-bottom: 1rem; +} + .form input[type="search"], .form select, .form-price, @@ -103,7 +118,7 @@ body { .form-price input { flex: 1; - max-width: calc(50% - 0.5rem); + max-width: calc(50% - 1rem); } .form-price-per input { diff --git a/texts.fnl b/texts.fnl index f30c037..4d769eb 100644 --- a/texts.fnl +++ b/texts.fnl @@ -1,2 +1,101 @@ {:no-results "По вашему запросу нет результатов. Попробуйте изменить параметры поиска." - :no-results-with-suggestion "По вашему запросу нет результатов. Возможно, вы имели в виду %s?"} + :no-results-with-suggestion "По вашему запросу нет результатов. Возможно, вы имели в виду %s?" + :meta-title "meicha.ru — каталог китайского чая" + :meta-description "Каталог китайского чая и связанных товаров, автоматически собирающий данные с сайтов чайных." + :red-tea-description " +

Красный китайский чай, известный за пределами Китая как черный чай, имеет несколько характерных особенностей:

+
    +
  1. Процесс ферментации: Листья проходят полную ферментацию, что придаёт чаю насыщенный вкус и тёмный цвет.
  2. +
  3. Вкус: Красный чай обычно обладает крепким, богатым вкусом с нотами карамели, шоколада или фруктов.
  4. +
  5. Аромат: У него яркий и глубокий аромат, который может варьироваться от сладковатого до древесного.
  6. +
  7. Цвет настоя: Напиток имеет тёмно-красный или бурый цвет.
  8. +
  9. Польза для здоровья: Содержит антиоксиданты, которые могут поддерживать здоровье сердца и способствовать пищеварению.
  10. +
  11. Популярные сорта: Среди известных сортов — Цзюньшань Хун Ча, Дянь Хун и Лапсанг Сушонг.
  12. +
+

Этот чай часто используется как в чистом виде, так и в сочетании с молоком или специями.

" + :white-tea-description " +

Белый чай, один из самых деликатных видов чая, имеет свои особенности:

+
    +
  1. Минимальная обработка: Листья собираются и сушатся на солнце, что сохраняет их натуральный вкус и аромат.
  2. +
  3. Вкус: Обладает легким, нежным вкусом с цветочными и травяными нотами, иногда с лёгкой сладостью.
  4. +
  5. Цвет настоя: Напиток имеет светло-желтый или бледно-зеленый цвет.
  6. +
  7. Антиоксиданты: Содержит высокое количество антиоксидантов, полезных для здоровья.
  8. +
  9. Популярные сорта: К известным сортам относятся Бянь Хао (Silver Needle) и Шуан Гу (White Peony).
  10. +
  11. Чувствительность к завариванию: Требует более низкой температуры воды и короткого времени настаивания, чтобы избежать горечи.
  12. +
+

Этот чай часто ценится за свою утонченность и лёгкость, идеально подходит для медитативного наслаждения.

" + :green-tea-description " +

Зеленый чай имеет ряд отличительных особенностей:

+
    +
  1. Минимальная ферментация: Листья подвергаются легкой обработке (парообработке или обжарке), что сохраняет их свежесть и зеленый цвет.
  2. +
  3. Вкус: Обладает свежим, травянистым вкусом, который может варьироваться от сладковатого до слегка горьковатого, в зависимости от сорта.
  4. +
  5. Цвет настоя: Напиток обычно светло-зеленый или желтый.
  6. +
  7. Польза для здоровья: Содержит много антиоксидантов и может поддерживать метаболизм, а также улучшать общее состояние здоровья.
  8. +
  9. Популярные сорта: Известные сорта включают Сенча, Матча, Лунцзин (Драконий колодец) и Гунпай.
  10. +
  11. Чувствительность к завариванию: Требует более низкой температуры воды и короткого времени настаивания, чтобы избежать горечи и сохранить аромат.
  12. +
+

Зеленый чай часто ценится за свою лёгкость и разнообразие вкусовых профилей, что делает его популярным выбором во многих культурах.

" + :sheng-puer-description " +

Шен пуэр — это сырой (неферментированный) чай из провинции Юннань, который обладает уникальными характеристиками. Вот несколько его особенностей:

+
    +
  1. Производственный процесс: Шен пуэр производится из свежих листьев чайного дерева, которые подвергаются процессу сушки и скручивания. В отличие от шен пуэра, шуй пуэр проходит процесс ферментации.
  2. +
  3. Вкус и аромат: У шен пуэра ярко выраженный свежий, травяной вкус с легкой сладостью и иногда фруктовыми нотами. С возрастом чай становится более мягким и глубоким, развивая сложные ароматы.
  4. +
  5. Возраст и созревание: Шен пуэр может долго храниться, и со временем его вкус и аромат становятся более насыщенными и гармоничными. Старые сорта ценятся высоко.
  6. +
  7. Цвет настоя: Настой шен пуэра обычно светлый, золотисто-желтый, особенно в молодом виде. С возрастом цвет может становиться более насыщенным.
  8. +
  9. Польза для здоровья: Шен пуэр считается полезным для пищеварения и может помогать в контроле веса. Содержит антиоксиданты и другие полезные соединения.
  10. +
  11. Культуры и традиции: Потребление шен пуэра связано с определёнными культурными традициями, включая специальные ритуалы заваривания чая.
  12. +
+

Эти характеристики делают шен пуэр уникальным и желанным для многих любителей чая.

" + :shou-puer-description " +

Шу пуэр — это ферментированный чай, также из провинции Юннань, который отличается от шен пуэра рядом особенностей:

+
    +
  1. Производственный процесс: Шу пуэр проходит процесс искусственной ферментации, который называется \"вотя\" (или \"шу пуэр\"). Это позволяет ускорить процесс созревания и придаёт чаю характерный вкус.
  2. +
  3. Вкус и аромат: Шу пуэр обычно имеет более насыщенный, земляной и глубокий вкус с нотами древесины, шоколада и иногда даже кофе. Он более мягкий и менее терпкий, чем шен пуэр.
  4. +
  5. Цвет настоя: Настой шу пуэра тёмный, насыщенно коричневый или чёрный, что отражает его степень ферментации.
  6. +
  7. Созревание: Шу пуэр можно пить сразу после производства, хотя и он может улучшаться с возрастом, становясь более мягким и глубоким.
  8. +
  9. Польза для здоровья: Шу пуэр также обладает полезными свойствами, включая поддержку пищеварения, улучшение обмена веществ и антиоксидантные свойства.
  10. +
  11. Культуры и традиции: Шу пуэр также окружён культурными традициями, с акцентом на методы заваривания и сервировки, которые могут варьироваться в зависимости от региона и предпочтений.
  12. +
+

Шу пуэр привлекает тех, кто предпочитает более тёмные и насыщенные чаи, и его ценят за богатство вкуса и аромата.

+" + :oolong-description " +

Улуны — это полуферментированные чаи, которые занимают промежуточное положение между зелеными и черными чаями. Вот основные особенности улунов:

+
    +
  1. Производственный процесс: Улуны проходят частичную ферментацию, что придаёт им уникальные характеристики. Процесс включает в себя сушки, скручивание и иногда обжаривание.
  2. +
  3. Вкус и аромат: Улуны могут иметь широкий спектр вкусов — от цветочных и фруктовых до ореховых и карамельных. В зависимости от степени ферментации вкус может быть как мягким и сладким, так и более насыщенным и сложным.
  4. +
  5. Цвет настоя: Настой улунов обычно золотистого или медного цвета, в зависимости от типа и степени ферментации.
  6. +
  7. Разнообразие: Существует множество сортов улунов, таких как Тайваньский оолонг, Да Хун Пао, Тегуаньинь и другие. Каждый сорт обладает своими уникальными особенностями и вкусами.
  8. +
  9. Польза для здоровья: Улуны содержат антиоксиданты и могут способствовать улучшению обмена веществ, поддержанию здоровья кожи и снижению уровня стресса.
  10. +
  11. Методы заваривания: Улуны часто заваривают в гайвани или чайниках с использованием высоких температур воды, что позволяет раскрыть их аромат и вкус. Многие любители чая практикуют многократное заваривание одних и тех же листьев.
  12. +
+

Улуны привлекают многих любителей чая своей сложностью и разнообразием, а также богатым ароматом и вкусом, который раскрывается в процессе заваривания.

" + :yellow-tea-description " +

Желтый чай — это один из самых редких и деликатных видов чая, который ценится за свой особый процесс обработки и уникальный вкус. Вот его основные особенности:

+
    +
  1. Производственный процесс: Желтый чай проходит легкую ферментацию, схожую с процессом производства зеленого чая, но включает дополнительный этап \"прокаливания\" или \"завяливания\". Это помогает смягчить вкус и добавить сладость.
  2. +
  3. Вкус и аромат: У желтого чая мягкий, сладковатый вкус с легкими цветочными и фруктовыми нотами. Он часто менее терпкий, чем зеленый чай, и обладает более насыщенным послевкусием.
  4. +
  5. Цвет настоя: Настой желтого чая имеет светло-желтый или золотистый оттенок, который становится более насыщенным с возрастом.
  6. +
  7. Редкость и ценность: Желтый чай редко производится и чаще всего встречается в Китае, что делает его довольно дорогим и желанным среди ценителей.
  8. +
  9. Польза для здоровья: Как и другие виды чая, желтый чай богат антиоксидантами и может способствовать улучшению обмена веществ и поддержанию здоровья сердца.
  10. +
  11. Методы заваривания: Для заваривания желтого чая рекомендуется использовать воду температурой около 80-85°C и настаивать 2-3 минуты, чтобы избежать горечи и раскрыть его тонкие ароматы.
  12. +
+

Желтый чай привлекает тех, кто ищет что-то особенное и уникальное в мире чая, благодаря своей утонченности и редкости.

" + :teaware-description " +

Чайная посуда играет важную роль в культуре чаепития и может значительно влиять на вкус и аромат чая. Вот основные особенности различных видов чайной посуды:

+ +

Чайники

+Материал: Чайники могут быть керамическими, фарфоровыми, стеклянными, металлическими или глиняными (например, из юннаньской глины). Каждый материал по-своему влияет на теплообмен и вкус. +Форма: Форма чайника может варьироваться, что также влияет на процесс заваривания. Например, чайники с широким дном позволяют лучше раскрывать ароматы. + +

Гайвани

+ +Это традиционный китайский чайник для заваривания улунов и других сортов. Он обычно имеет широкое горлышко и позволяет наблюдать за цветом настоя. + +

Чашки

+Материалы: Чашки могут быть из фарфора, стекла, глины или металла. Фарфоровые чашки сохраняют тепло и подчеркивают аромат, а глиняные — могут добавлять свои нотки во вкус. +Размер и форма: Меньшие чашки предпочтительнее для крепких чаёв, таких как пуэр, в то время как большие могут использоваться для легких, цветочных сортов. +Сито и фильтры: +Используются для отделения чайных листьев от настоя. Это может быть встроенное сито в чайнике или отдельные фильтры. + +

Выбор чайной посуды может зависеть от типа чая, способа заваривания и культурных традиций. Правильная посуда не только помогает раскрыть вкус и аромат чая, но и создает атмосферу чаепития.

" +} -- cgit v1.2.3