Created
February 11, 2009 10:34
-
-
Save Inviz/61952 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Extracts first sentence or a first phrase from given string and adds a link there | |
#to be used with RSS headings | |
class String | |
EXTRACT_SENTENCES = /\s*(?: - |- | -|[.,!?:]|&[a-z]*;)\s*/u.freeze | |
def associate_with_link(url, max = 30, title = nil) | |
return %{<a href="#{url}">#{self}</a>} if chars.size < max | |
sentenses = chars.split(EXTRACT_SENTENCES).delete_if {|i| i.empty?} | |
if sentenses.size == 1 || sentenses.last.chars.size > max | |
sentenses = chars[-max, size].split(" ", 2) | |
end | |
regex = %r{(\s+)((?:(?:[^ ]+-)|(?:[MCVIX]*|без|с|не|как|по|где|когда|почему|над|от|в|к|от|под|о|об|и|да|зачем|чему|так[аои][еяйм])\s+)*)#{sentenses.last.escape_regexp}([!?.])?}i | |
gsub(regex, %{\\1<a href="#{url}" title="#{title || self}">\\2#{sentenses.last}\\3</a>}) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Templating | |
class Buffer | |
attr_accessor :buffer | |
def initialize(controller, language = :html) | |
@controller = controller | |
@hooks = {} | |
@counter = 0 | |
self.extend language == "wml" ? WML : HTML | |
self.extend Abstract | |
self.buffer = [] | |
end | |
def counter | |
@counter += 1 | |
@counter - 1 | |
end | |
def before(&block) | |
@hooks[:before] = block | |
end | |
def after(&block) | |
@hooks[:after] = block | |
end | |
def output(&block) #good thing, but unused | |
if block | |
instance_eval &block | |
else | |
to_s | |
end | |
end | |
def to_s | |
page_open + call_hook(:before) + (buffer * " ") + call_hook(:after) + page_close | |
end | |
def each | |
#this is a hack. Merb calls `each` on the object, if action returns it. | |
#I tie render here, so i dont need to specify it in each action of controller | |
yield(to_s) | |
end | |
private | |
def call_hook(which = :before) | |
return '' unless @hooks[which] | |
buff = @buffer | |
@buffer = [] | |
@hooks[which].call(self) | |
ret = @buffer * " " | |
@buffer = buff | |
ret | |
end | |
end | |
module Abstract #are the tags to be used | |
def link_to(text, url, key = false) | |
puts link(text, url, key) | |
end | |
def heading(text, url = nil) | |
puts header(url ? link(text, url) : text) | |
end | |
def message(text = "") | |
puts paragraph(text) | |
end | |
def separator | |
puts hr | |
end | |
def paginator(items) | |
formatted_paginator items | |
end | |
def list(items, empty_message = "Список пуст") | |
sub = [] | |
unless items.empty? | |
sub << list_open | |
items.each do |i| | |
sub << list_item_open | |
sub << (i.respond_to?(:to_item) ? link(*i.to_item) : i.to_s) | |
sub << list_item_close | |
end | |
sub << list_close | |
else | |
sub << empty_message | |
end | |
puts sub | |
paginator(items) if (!items.empty? && items.respond_to?(:next_page)) | |
self | |
end | |
def quickform(*args) | |
puts form(*args) | |
end | |
def puts(*args) | |
buffer << (args * " ") | |
self | |
end | |
end | |
module WML | |
def page_open | |
['<?xml version="1.0" encoding="UTF-8"?>', | |
'<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">', | |
'<wml>', | |
'<meta http-equiv="Cache-Control" content="no-cache" forua="true"/>', | |
'<card id="index" title="', | |
@controller.page_title, | |
'">', back].join | |
end | |
def page_close | |
'</card>' + 'back' + '</wml>' | |
end | |
def paragraph(text) | |
"#{text}<br /><br />" | |
end | |
def header(text, big = false) | |
"<big>#{text}</big><br />" | |
end | |
def list_open | |
"" | |
end | |
def list_close | |
"<br />" | |
end | |
def list_item_open | |
"- " | |
end | |
def list_item_close | |
"<br />" | |
end | |
def link(text, url = "#", key = false) | |
"<a href='#{@controller.sessioned(url)}' accesskey='#{key || counter}'>#{text}</a>" | |
end | |
def hr | |
"<br /><br />" | |
end | |
def accept(label = "Ещё", url = false) # phone buttons remapper | |
"<do type='accept' name='a' label='#{label}'><go href='#{url}'/></do>" | |
end | |
def back(label = "Назад") | |
"<do type='back' label='#{label}'><prev /></do>" | |
end | |
def formatted_paginator(items) | |
#nator = Paginator.new(items, self, :outer_window => -1, :inner_window => -1, :prev_label => "Назад", :next_label => "Ещё") | |
#nator.to_s | |
if items.next_page && (items.next_page <= items.total_pages) | |
puts accept("Ещё", @controller.sessioned("?page=#{items.next_page}")) | |
end | |
end | |
def form(label = "Найти", label2 = "Искать", url = "/", param = "id") | |
"#{label}<br /><input name='ss'/><anchor><go href='#{@controller.sessioned(url + '$ss', 'q')}'/>#{label2}</anchor>" | |
end | |
end | |
module HTML | |
def page_open | |
['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', | |
'<html>', | |
'<head>', | |
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8">', | |
'<title>', | |
@controller.page_title, | |
'</title>', | |
'</head>'].join | |
end | |
def page_close | |
'</html></body>' | |
end | |
def link(text, url = "#", key = false) | |
"<a href='#{@controller.sessioned(url)}' accesskey='#{key || counter}'>#{text}</a>" | |
end | |
def header(text, big = false) | |
tag = big ? "h2" : "h1" | |
"<#{tag}>#{text}</#{tag}>" | |
end | |
def list_open | |
"<ul>" | |
end | |
def list_close | |
"</ul>" | |
end | |
def list_item_open | |
"<li>" | |
end | |
def list_item_close | |
"</li>" | |
end | |
def paragraph(text) | |
"<p>#{text}</p>" | |
end | |
def hr | |
"<hr />" | |
end | |
def formatted_paginator(items) | |
Paginator.new(items, self).to_s | |
end | |
def form(label = "Найти", label2 = "Искать", url = "/", param = "id") | |
"#{label}:<br /><form action='#{@controller.sessioned(url, 'q')}'><input name='#{param}' /> <input type='submit' value='#{label2}' /></form>" | |
end | |
end | |
# This is extracted from another app | |
# Atleast it's 267 times cleaner than WP | |
class Paginator | |
attr_accessor :r | |
def initialize(collection, r, opts = {}) | |
@options = { | |
:prev_label => opts.delete(:prev_label) || "<", | |
:next_label => opts.delete(:next_label) || ">", | |
:inner_window => opts.delete(:inner_window) || 3, | |
:outer_window => opts.delete(:outer_window) || 2 | |
} | |
@collection = collection | |
@r = r | |
@url = "?#{opts.delete(:param_name) || 'page'}=%s" | |
end | |
def visible_pages | |
outer = @options[:outer_window] | |
inner = @options[:inner_window] | |
current = @collection.current_page | |
count = @collection.total_pages | |
#following is ruby cuteness | |
((1..(inner + 1)).entries | #left | |
((current - inner)..(current + inner)).entries | #middle | |
((count - outer)..count).entries) & #right | |
(1..count).entries #now intersect | |
end | |
def url_for_page(page = nil) | |
@url % page if page | |
end | |
def item(text, page) | |
if !page || page.zero? || (page == @collection.current_page) | |
r.puts text | |
else | |
r.link_to text, url_for_page(page) | |
end | |
end | |
def show? | |
@collection.total_pages > 1 | |
end | |
def to_s | |
return "" unless show? | |
item @options[:prev_label], @collection.previous_page | |
visible_pages.each do |page| | |
item page, page | |
end | |
item @options[:next_label], @collection.next_page | |
end | |
end | |
end | |
#used like that: | |
module Search | |
def random(model) | |
r.heading "Случайные результаты:" | |
r.list model.find(:all, :limit => 3, :order => "random()") | |
end | |
def filter(q, model, label = "Искать") | |
r.quickform label, "Найти", "?q=" | |
r.separator | |
if q.blank? | |
random(model) | |
else | |
contents = model.paginate(:page => current_page, :conditions => ["lower(name) like ?", "%#{q.downcase}%"]) | |
if contents.blank? | |
r.message "Ничего не найдено." | |
random(model) | |
else | |
r.list contents | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def fetch_news | |
Yandex::News::List.new("Ulan-Ude").each do |item| | |
New.create_from_item(item) | |
end | |
end | |
$kcode = 'u' | |
require 'rss/1.0' | |
require 'rss/2.0' | |
require 'open-uri' | |
require 'iconv' | |
module Yandex | |
module News | |
class List | |
attr_reader :url, :items | |
include Enumerable | |
def initialize(category = nil) | |
@rss = ["http://news.yandex.ru", category, "index.rss"].compact * "/" | |
end | |
def each(&block) | |
fetch.each(&block) | |
end | |
private | |
def fetch | |
items.map { |item| Item.new(item) } | |
end | |
def items | |
content = "" | |
open(@rss) { |s| content = s.read } | |
@items = ::RSS::Parser.parse(content, false).items or raise "Unable to parse #{@rss}" | |
end | |
end | |
class Item | |
attr_reader :date, :link | |
def initialize(item) | |
@date = item.pubDate | |
@link = item.link | |
end | |
def title | |
data[:title] | |
end | |
def summaries | |
data[:summaries] | |
end | |
def category | |
data[:category] | |
end | |
def quote | |
data[:quote] | |
end | |
private | |
def data | |
@data ||= Item.parse_url(@link) | |
end | |
class << self | |
TITLE_RE = /<H2>([^<]*)/m.freeze | |
SUMMARIES_RE = /<dl class="lefts">(.*)<\/dl>/m.freeze | |
SUMMARY_RE = /<dd>(.*?)\s*<span class=source> <!--→ --><a href="(.*?)"[^>]*>(.*?)</m.freeze | |
CATEGORY_RE = /<p class="toplinks">[^>]*>(.*?)</m.freeze | |
def parse_url(url) | |
content = "" | |
open(url) { |s| content = s.read } | |
content = converter.iconv content | |
data = {} | |
begin | |
data[:title] = content.match(TITLE_RE)[1] | |
data[:category] = content.match(CATEGORY_RE)[1] | |
data[:category] = nil if data[:category].blank? | |
data[:summaries] = content.match(SUMMARIES_RE)[1].scan(SUMMARY_RE).map do |summary| | |
{:body => summary[0], :link => summary[1], :source => summary[2]} | |
end | |
rescue | |
raise "Unable to parse #{url}. Has layout changed there?" | |
end | |
data | |
end | |
def converter | |
@converter ||= Iconv.new('UTF-8','WINDOWS-1251') | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment