рдореИрдВрдиреЗ рдХреЗрд╡рд▓ рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреИрд╕реЗ рд▓рд┐рдЦрд╛





рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдореБрдЭреЗ рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рднрд╛рд╖рд╛ рдорд┐рд▓реА - рдХреНрд▓реЛрдЬрд░ред рдореБрдЭреЗ рддреБрд░рдВрдд рдЖрд▓рд╕реА рдФрд░ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕рдВрдЧреНрд░рд╣ рдкрд╕рдВрдж рдЖрдпрд╛, рдПрд╕рдЯреАрдПрдо, рдореИрдХреНрд░реЛрдЬрд╝, рд╕рднреА рдЕрд╡рд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдмреНрд░реИрдХреЗрдЯ рдФрд░ рдбреАрдПрд╕рдПрд▓ред

рдФрд░ рдореИрдВрдиреЗ рдХреЗрд╡рд▓ рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред



рдЖрд╡реЗрджрди



рдпрд╣ рдПрдХ рд╕рд░рд▓ рдЙрдкрд╢реАрд░реНрд╖рдХ рд╕рд╛рдзрдХ рдмрдирд╛рдиреЗ рдХрд╛ рдЗрд░рд╛рджрд╛ рдерд╛:



рдкрд╛рд░рд╕рд░реНрд╕



рд╣реИрд░рд╛рдиреА рдХреА рдмрд╛рдд рд╣реИ, рдкрд╛рд░реНрд╕рд░реНрд╕ рд▓рд┐рдЦрдирд╛ рдЖрд╕рд╛рди рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдерд╛ред рдкрд╣рд▓реЗ, рдРрд╕рд╛ рд▓рдЧрддрд╛ рдерд╛ рдХрд┐ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдмреНрд░реИрдХреЗрдЯ рдереЗ, рд▓реЗрдХрд┐рди рдореИрдХреНрд░реЛрдЬрд╝ ( -> , - >> , - <-> рдФрд░ - <> - рдЕрдЧрд▓реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рддрд░реНрдХ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкрд╛рд░рд┐рдд рдХрд░рдирд╛) рд╕реЗ рдмрд╣реБрдд рдорджрдж рдорд┐рд▓реАред



рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд╛рдпрдерди рдФрд░ рдХреНрд▓реЛрдЬрд░ рдореЗрдВ рдПрдХ рд╣реА рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдиреЛрдЯрд╛рдмреЛрди рдкрд╛рд░реНрд╕рд░ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛:

clojure рдЕрдЬрдЧрд░
(defn get-release-page-result "Get release page result" [page] (-<>> (get-release-page-url page) helpers/fetch (html/select <> [:ul.search-results :li :p :a]) (map (helpers/make-safe book-from-line nil)) (remove nil?) (map episodes-from-book) flatten))
      
      



 def get_release_page_result(page): """Get release page result""" url = get_release_page_url(page) content = requests.get(url).content soup = BeautifulSoup(content) for line in get_lines_from_soup(soup): book = get_book_from_line(line) if book: yield from get_episodes_from_book(book)
      
      



16 рдХреЛрд╖реНрдардХ 14 рдХреЛрд╖реНрдардХ
рдкрд░- рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд╛рд░реНрд╕рд░реНрд╕ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ HTML рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдирд▓рд╛рдЗрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдкрд░рд┐рдгрд╛рдо elasticsearch рдХреЛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред



рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб



рд╕рд░реНрд╡рд░


рд╕рд░реНрд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ http-kit рдХреЛ рдЪреБрдирд╛, рдореБрдЦреНрдпрддрдГ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдФрд░ рдЙрдиреНрд╣реЗрдВ рдпрд╣рд╛рдВ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдкрдбреЗрдЯ рдХреЗ рдмрд╛рдж рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдЙрдкрд╢реАрд░реНрд╖рдХ рдХреА рд╕рдВрдЦреНрдпрд╛ рднреЗрдЬрдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:

 (add-watch total-count :notifications #(doseq [con @subscribers] (send! con (prn-str {:total-count %4}))))
      
      





рдорд╛рд░реНрдЧ


рд░реВрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП - рдХрдВрдкреЛрдЬрд░ ред Django рдФрд░ рдЕрдиреНрдп рд▓реЛрдХрдкреНрд░рд┐рдп рд░реВрдкрд░реЗрдЦрд╛рдУрдВ рд╕реЗ рдХреЛрдИ рдорддрднреЗрдж рдирд╣реАрдВ рд╣реИрдВ:

 (defroutes main-routes (GET "/" [] (views/index-page)) (GET "/api/list-languages/" {params :params} (api/list-languages params)) (GET "/notifications/" [] push/notifications) (route/resources const/static-path))
      
      





рдПрдкреАрдЖрдИ


рдЪреВрдБрдХрд┐ рд╣рдо рд╣рд░ рдЬрдЧрд╣ рдХреНрд▓реЛрдЬрд╝рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдХреЛ рдореВрд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рдФрд░ json (рдЕрдЬрдЧрд░ рдореЗрдВ рдбреЗрд╕реНрдХрдЯреЙрдк рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП) рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореБрдЭреЗ рд╡рд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдирд╣реАрдВ рдорд┐рд▓реА рдЬреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╣реЛ рд╕рдХрддреА рд╣реИ (рдкрд╣рд▓реЗ рд╕реЗ рдорд┐рд▓реА рд╣реБрдИ) , рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдереЛрдбрд╝рд╛ рд╕рд╛ рд╕рд╛рдЗрдХрд┐рд▓ рдЪрд▓рд╛рдирд╛ рдкрдбрд╝рд╛ рдФрд░ рдЕрдкрдиреЗ рдЦреБрдж рдХреЗ рдорд┐рдиреА рдбреАрдПрд▓ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд░рдирд╛ рдкрдбрд╝рд╛:

 (defn- get-writer "Get writer from params" [params] (if (= (:format params) "json") json/write-str prn-str)) (defmacro defapi "Define api method" [name doc args & body] `(defn ~name ~args ((get-writer (first ~args)) ~@body)))
      
      





рдФрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ:

 (defapi list-languages "List all available languages" [params] (models/list-languages))
      
      





рд░рд╛рдп


Html рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ dsl - рд╣рд┐рдЪрдХреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЗрд╕рдХреЗ рд╕рд╛рде рдЯреЗрдореНрдкрд▓реЗрдЯ рдереЛрдбрд╝рд╛ "рдорд╛рд░реНрдЯрд┐рдпрди" рджрд┐рдЦрддрд╛ рд╣реИред

 (defn index-page [] (html5 [:head [:title "Subman - subtitle search service"] [:body [:h1 "Welcome to subman!"]]))
      
      





рд╢реИрд▓рд┐рдпреЛрдВ


рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЕрдкрдирд╛ рдбреАрдПрд╕рдПрд▓ - рдмрдЧреАрдЪрд╛ рднреА рд╣реИ ред рдЗрд╕рдХреЗ рд╕рд╛рде рдХреЛрдб рднреА рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИ:

 (defstyles main [:.search-input {:z-index 100 :background-color "#fff"}] [:.info-box {:text-align "center" :font-size (px 18)}] [:.search-result-holder {:padding-left 0 :padding-right 0}])
      
      





рдЧреНрд░рд╛рд╣рдХ рднрд╛рдЧ



рдореИрдВрдиреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рднрд╛рдЧ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреНрд▓реЛрдЬрд░ рдкрд░ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдХреНрд▓реЛрдЬрд░рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд░ рд▓рд┐рдЦрд╛ рдерд╛, рдЬреЛ рдЕрдВрддрддрдГ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ рдЕрднрд┐рдХрд░реНрдордХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ - рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдпрдХрд╛рд░реАред рдХреНрд▓реЛрдЬрд░ рдХреЗ рд▓рд┐рдП рдЬреЗрдПрд╕, рдЬреЛ рд╣рд░ рд╕реЗрдХрдВрдб (рдкрд░рдорд╛рдгреБрдУрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж) рдХреЗ рд▓рд┐рдП рд╡рд╕реНрддреБрдУрдВ рдХреА рдЬрд╛рдВрдЪ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдШрдЯрдХреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рд┐рдЪрдХреА рдЬреИрд╕реА рдбреАрдПрд╕рдПрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:

 (defn info-box "Show info box" [text] [:div.container.col-xs-12.info-box [:h2 text]])
      
      





рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ, рдЬрдм рддрдХ рдЖрдкрдХреЛ рд╕реАрдзреЗ рдЬреЗрдПрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЯрд╛рдЗрдк рдлрд╝реАрд▓реНрдб рдХреЛ рдЦреЛрдЬ рдлрд╝реАрд▓реНрдб рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдХреЛрдб:

 (defn init-autocomplete "Initiale autocomplete" [query langs sources] (let [input ($ "#search-input")] (.typeahead input (js-obj "highlight" true) (js-obj "source" (fn [query cb] (cb (apply array (take const/autocomplete-limit (map #(js-obj "value" %) (get-completion query @langs @sources)))))))) (.on input "typeahead:closed" (fn [] (reset! query (.val input))))))
      
      



) (defn init-autocomplete "Initiale autocomplete" [query langs sources] (let [input ($ "#search-input")] (.typeahead input (js-obj "highlight" true) (js-obj "source" (fn [query cb] (cb (apply array (take const/autocomplete-limit (map #(js-obj "value" %) (get-completion query @langs @sources)))))))) (.on input "typeahead:closed" (fn [] (reset! query (.val input))))))





UPD: рдереЛрдбрд╝рд╛ рд░рд┐рдлреИрдХреНрдЯрд┐рдВрдЧ рдХреЗ рдмрд╛рдж, рдХреЛрдб рдХрдо рдбрд░рд╛рд╡рдирд╛ рд╣реЛ рдЧрдпрд╛:

 (defn completion-source "Source for typeahead autocompletion" [langs sources query cb] (cb (->> (get-completion query @langs @sources) (map #(js-obj "value" %)) (take const/autocomplete-limit) (apply array)))) (defn init-autocomplete "Initiale autocomplete" [query langs sources] (let [input ($ "#search-input")] (.typeahead input #js {:highlight true} #js {:source (partial completion-source langs sources)}) (.on input "typeahead:closed" #(reset! query (.val input)))))
      
      





рдФрд░ "рд╕рдВрдХрд▓рд┐рдд" рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЖрдХрд╛рд░ рднреА рдЗрддрдирд╛ рдмрдбрд╝рд╛ рдирд╣реАрдВ рдерд╛ - рдХреЗрд╡рд▓ 290kbред



рдПрдХ рд╡рд┐рд╢рд╛рд▓ рдкреНрд▓рд╕ рдХреЗ рд░реВрдк рдореЗрдВ, рдХреНрд▓реЛрдЬрд░ рдХреЗ рд╕рд╛рде рдХреНрд▓реЛрдЬрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП - рдЖрдк рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдХреНрд▓рдЬреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред



рдирд┐рд╖реНрдХрд░реНрд╖



рдпрджреНрдпрдкрд┐ clojure рдЖрдкрдХреЛ html, css рдФрд░ javascript рдХреЗ рдЬреНрдЮрд╛рди рдФрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд┐рдирд╛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреА рдЙрддреНрдкрд╛рджрди рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рдХрд░рдиреЗ рдХреА рд╣рд┐рдореНрдордд рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ред



рдкрд░рд┐рдгрд╛рдо рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдбред

рдирддреАрдЬрд╛ рдЦреБрджред



All Articles