yury-typograph 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ .idea
2
+ pkg
data/README ADDED
@@ -0,0 +1 @@
1
+ Ruby port of http://emuravjev.ru/works/tg php typograph
@@ -0,0 +1,13 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "typograph"
5
+ gemspec.summary = "ruby html typograph"
6
+ gemspec.description = "apply some basic typography rules to text"
7
+ gemspec.email = "yury.korolev@gmail.com"
8
+ gemspec.homepage = "http://github.com/yury/typograph"
9
+ gemspec.authors = ["Yury Korolev"]
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
13
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,23 @@
1
+ module Typograph
2
+ autoload :Rules, 'typograph/rules'
3
+
4
+ @@rules = [Rules::QuoteRules.new,
5
+ Rules::DashRules.new,
6
+ Rules::PunchmarkRules.new,
7
+ Rules::MathRules.new,
8
+ Rules::EtcRules.new]
9
+
10
+ def self.run! text
11
+ for rule in @@rules
12
+ next if rule.disabled
13
+ text = rule.parse text
14
+ end
15
+ text
16
+ end
17
+
18
+ def self.run text
19
+ self.run! text.dup
20
+ end
21
+ end
22
+
23
+ require 'typograph/string_sub_each'
@@ -0,0 +1,64 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ autoload :DashRules, 'typograph/rules/dash_rules'
5
+ autoload :EtcRules, 'typograph/rules/etc_rules'
6
+ autoload :MathRules, 'typograph/rules/math_rules'
7
+ autoload :PunchmarkRules, 'typograph/rules/punchmark_rules'
8
+ autoload :QuoteRules, 'typograph/rules/quote_rules'
9
+
10
+ # base class for all rules in typograph
11
+ class Rule
12
+
13
+ NBSP = " "
14
+ QUOTE_FIRS_OPEN = '«';
15
+ QUOTE_FIRS_CLOSE = '»';
16
+ QUOTE_CRAWSE_OPEN = '„';
17
+ QUOTE_CRAWSE_CLOSE = '“';
18
+
19
+ attr_accessor :disabled
20
+
21
+ def initialize
22
+ @disabled = false
23
+ @rules = []
24
+ end
25
+
26
+ def add name, opts = {}
27
+ @rules << {:name => name, :opts => opts}
28
+ end
29
+
30
+ def pre_parse text
31
+ text
32
+ end
33
+
34
+ def post_parse text
35
+ text
36
+ end
37
+
38
+ def parse text
39
+ return text if self.disabled
40
+
41
+ text = self.pre_parse text
42
+
43
+ @rules.each do |rule|
44
+ opts = rule[:opts]
45
+ next if opts[:disabled]
46
+ replacement = opts[:replacement]
47
+ if replacement.class == Proc
48
+ text.sub_each! opts[:pattern], &replacement
49
+ else
50
+ text.gsub! opts[:pattern], opts[:replacement]
51
+ end
52
+ end
53
+
54
+ self.post_parse text
55
+ end
56
+
57
+ def self.run text
58
+ t = self.new
59
+ t.parse text
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,41 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ class DashRules < Rule
5
+
6
+ def initialize
7
+ super
8
+
9
+ add :m_dash,
10
+ :pattern => /([a-zа-я0-9]+|,|:|\)|&raquo;|\|")(\040|\t)(\-|&mdash;)(\s|$|<)/u,
11
+ :replacement => '\1&nbsp;&mdash;\4'
12
+
13
+ add :m_dash_2,
14
+ :pattern => /(\n|\r|^|>)(\-|&mdash;)(\t|\040)/,
15
+ :replacement => '\1&mdash;&nbsp;'
16
+
17
+ add :m_dash_3,
18
+ :pattern => /(\.|!|\?|&hellip;)(\040|\t|&nbsp;)(\-|&mdash;)(\040|\t|&nbsp;)/,
19
+ :replacement => '\1 &mdash;&nbsp;'
20
+
21
+ add :years,
22
+ :pattern => /(с|по|период|середины|начала|начало|конца|конец|половины|в|между)(\s+|&nbsp;)([\d]{4})(-)([\d]{4})(г|гг)?/eui,
23
+ :replacement => lambda {|m| "#{m[1]}#{m[2]}#{build_years(m[3],m[5],m[4])}#{m[6]}" }
24
+
25
+ add :iz_za_pod,
26
+ :pattern => /(\s|&nbsp;|>)(из)(\040|\t|&nbsp;)\-?(за|под)([\.,!\?:;]|\040|&nbsp;)/uie,
27
+ :replacement => lambda {|m| "#{m[1] == NBSP ? " " : m[1]}#{m[2]}-#{m[4]}#{m[5] == NBSP ? " " : m[5]}" }
28
+
29
+ add :to_libo_nibud,
30
+ :pattern => /(\s|^|&nbsp;|>)(кто|кем|когда|зачем|почему|как|что|чем|где|чего|кого)\-?(\040|\t|&nbsp;)\-?(то|либо|нибудь)([\.,!?;]|\040|&nbsp;|$)/ui,
31
+ :replacement => lambda {|m| "#{m[1] == NBSP ? " " : m[1]}#{m[2]}-#{m[4]}#{m[5] == NBSP ? " " : m[5]}" }
32
+ end
33
+
34
+ def build_years start_date, end_date, sep
35
+ start_date = start_date.to_i
36
+ end_date = end_date.to_i
37
+ start_date >= end_date ? "#{start_date}#{sep}#{end_date}" : "#{start_date}&ndash;#{end_date}"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ class EtcRules < Rule
5
+
6
+ def initialize
7
+ super
8
+ add :tm_replace,
9
+ :pattern => /([\040\t])?\(tm\)/i,
10
+ :replacement => '&trade;'
11
+
12
+ # TODO: encrypted tags
13
+ #add :r_sign_replace,
14
+ # :pattern => /\(r\)/ei
15
+
16
+
17
+ add :copy_replace,
18
+ :pattern => /\((c|с)\)\s+/iu,
19
+ :replacement => '&copy;&nbsp;'
20
+
21
+ add :acute_accent,
22
+ :pattern => /(у|е|ы|а|о|э|я|и|ю|ё)`(\w)/iu,
23
+ :replacement => '\1&#769;\2'
24
+
25
+ #add :auto_links
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ class MathRules < Rule
5
+
6
+ def initialize
7
+ super
8
+
9
+ add :auto_times_x,
10
+ :pattern => /(\d+)(\040*)(x|х)(\040*)(\d+)/u,
11
+ :replacement => '\1&times;\5'
12
+
13
+ add :frac_1, # replaces 1/2 and 1/4
14
+ :pattern => /(\D)1\/(2|4)(\D)/,
15
+ :replacement => '\1&frac1\2;\3'
16
+
17
+ add :frac_3, # replaces 3/4
18
+ :pattern => /(\D)3\/4(\D)/,
19
+ :replacement => '\1&frac34;\2'
20
+
21
+ add :not_equal,
22
+ :pattern => /!=/,
23
+ :replacement => '&#8800;'
24
+
25
+ add :plus_minus,
26
+ :pattern => /\+-/,
27
+ :replacement => '&plusmn;'
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ class PunchmarkRules < Rule
5
+
6
+ def initialize
7
+ super
8
+
9
+ add :auto_comma,
10
+ :pattern => /([a-zа-я])(\s|&nbsp;)(но|а)(\s|&nbsp;)/iu,
11
+ :replacement => '\1,\2\3\4'
12
+
13
+ add :punctuation_marks_limit,
14
+ :pattern => /([!.?]){4,}/,
15
+ :replacement => '\1\1\1'
16
+
17
+ add :punctuation_marks_base_limit,
18
+ :pattern => /([,:;]){2,}/,
19
+ :replacement => '\1'
20
+
21
+ add :hellip,
22
+ :pattern => /\.\.+/,
23
+ :replacement => '&hellip;'
24
+
25
+ add :eng_apostrophe,
26
+ :pattern => /(\s|^|>)([a-z]{2,})'([a-z]+)/i,
27
+ :replacement => '\1\2&rsquo;\3'
28
+
29
+ add :fix_pmarks,
30
+ :pattern => /([a-zа-я0-9])(!|\.|\?){2}(\s|$|<)/iu,
31
+ :replacement => '\1\2\3'
32
+
33
+ add :fix_l_bracket,
34
+ :pattern => /(\()(\040|\t)+/,
35
+ :replacement => '\1'
36
+
37
+ add :fix_r_bracket,
38
+ :pattern => /(\040|\t)+(\))/,
39
+ :replacement => '\2'
40
+
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ module Typograph
2
+ module Rules
3
+
4
+ class QuoteRules < Rule
5
+
6
+ def initialize
7
+ super
8
+
9
+ add :quotes_outside_a,
10
+ :pattern => /(<%%__.+?>)"(.+?)"(<\/%%__.+?>)/s,
11
+ :replacement => '"\1\2\3"'
12
+
13
+ add :open_quote,
14
+ :pattern => /(^|\(|\s)("|\\")(\S+)/iue,
15
+ :replacement => "\\1#{QUOTE_FIRS_OPEN}\\3"
16
+
17
+ add :close_quote,
18
+ :pattern => /([a-zа-я0-9]|\.|&hellip;|!|\?)("|\\")+(\.|&hellip;|;|:|\?|!|,|\s|\)|<\/|$)/uie,
19
+ :replacement => "\\1#{QUOTE_FIRS_CLOSE}\\3"
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ require "strscan"
2
+
3
+ class String
4
+ def sub_each regexp, &block
5
+ return unless block_given?
6
+ scanner = StringScanner.new self
7
+ while scanner.scan(regexp)
8
+ pre_match = scanner.pre_match
9
+ replacement = block[scanner]
10
+ new_pos = pre_match.length + replacement.length
11
+ scanner.string = pre_match << replacement << scanner.post_match
12
+ scanner.pos = new_pos
13
+ end
14
+ scanner.string
15
+ end
16
+
17
+ def sub_each! regexp, &block
18
+ self.replace(self.sub_each(regexp, &block))
19
+ end
20
+ end
@@ -0,0 +1,90 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require "test/unit"
4
+ require "typograph"
5
+
6
+ class TypographTest < Test::Unit::TestCase
7
+
8
+ include Typograph
9
+ include Typograph::Rules
10
+
11
+ def test_dash_rules
12
+ assert_equal "как-то", DashRules.run("как-то")
13
+ assert_equal "привет&nbsp;&mdash; привет", DashRules.run("привет - привет")
14
+ assert_equal "с 2000&ndash;3000", DashRules.run("с 2000-3000")
15
+ assert_equal "изза", DashRules.run("изза")
16
+ assert_equal " из-за ", DashRules.run(" из -за ")
17
+ assert_equal " как-то ", DashRules.run(" как- то ")
18
+ end
19
+
20
+ def test_etc_rules
21
+ assert_equal "anjlab&trade;", EtcRules.run("anjlab(tm)")
22
+ assert_equal "anjlab&copy;&nbsp;", EtcRules.run("anjlab(c) ")
23
+ assert_equal "приве&#769;т", EtcRules.run("приве`т")
24
+ end
25
+
26
+ def test_math_rules
27
+ assert_equal "2&times;5", MathRules.run("2x5")
28
+ assert_equal " &frac12; ", MathRules.run(" 1/2 ")
29
+ assert_equal " &frac14; ", MathRules.run(" 1/4 ")
30
+ assert_equal " &frac34; ", MathRules.run(" 3/4 ")
31
+ assert_equal " &frac34;&#8800;&frac12; ", MathRules.run(" 3/4!=1/2 ")
32
+ assert_equal " &frac34; + &frac14; + &frac12; ", MathRules.run(" 3/4 + 1/4 + 1/2 ")
33
+ assert_equal "&plusmn;", MathRules.run("+-")
34
+ assert_equal "&plusmn;5", MathRules.run("+-5")
35
+ end
36
+
37
+ # punchamark rules tests
38
+ def test_auto_comma
39
+ assert_equal "вы будете, а я нет", PunchmarkRules.run("вы будете а я нет")
40
+ assert_equal "вы будете, а я нет", PunchmarkRules.run("вы будете, а я нет")
41
+ end
42
+
43
+ def test_punctuation_marks_limit
44
+ assert_equal "hello!!!", PunchmarkRules.run("hello!!!!!!!!!!!!!!!!!!")
45
+ assert_equal "WTF???", PunchmarkRules.run("WTF???????")
46
+ end
47
+
48
+ def test_punctuation_marks_base_limit
49
+ assert_equal ":", PunchmarkRules.run(":::")
50
+ assert_equal ",", PunchmarkRules.run(",,")
51
+ end
52
+
53
+ def test_hellip
54
+ assert_equal "&hellip;", PunchmarkRules.run("..")
55
+ assert_equal "&hellip;", PunchmarkRules.run("...")
56
+ assert_equal "&hellip;", PunchmarkRules.run("....")
57
+ end
58
+
59
+ def test_eng_apostrophe
60
+ assert_equal "she&rsquo;s", PunchmarkRules.run("she's")
61
+ end
62
+
63
+ def test_fix_brackets
64
+ assert_equal "(круто)", PunchmarkRules.run("( круто )")
65
+ end
66
+
67
+ def test_quote_rules
68
+ assert_equal "&laquo;как-то&raquo;", QuoteRules.run('"как-то"')
69
+ assert_equal "&laquo;как-то&raquo; &laquo;как-то&raquo;", QuoteRules.run('"как-то" "как-то"')
70
+ assert_equal "привет всем &laquo;крутым&raquo; штукам", QuoteRules.run('привет всем "крутым" штукам')
71
+ assert_equal "&laquo;как-то &laquo;как-то&raquo;", QuoteRules.run('"как-то "как-то""')
72
+ end
73
+
74
+ def test_complex_processing
75
+ src = '"Кока-Кола" впервые появилась в СССР в 1979 году в
76
+ ходе подготовки Олимпийских игр в Москве. Её автор -
77
+ фармацевт Джон Стит Пембертон, бывший офицер американской
78
+ Армии конфедерации!!!! ( сам напиток был придуман в 1886 году
79
+ в штате Джорджия ) и дальше какая-то байда....'
80
+
81
+ dest = '&laquo;Кока-Кола&raquo; впервые появилась в СССР в 1979 году в
82
+ ходе подготовки Олимпийских игр в Москве. Её автор&nbsp;&mdash;
83
+ фармацевт Джон Стит Пембертон, бывший офицер американской
84
+ Армии конфедерации!!! (сам напиток был придуман в 1886 году
85
+ в штате Джорджия) и дальше какая-то байда&hellip;'
86
+
87
+ assert_equal dest, Typograph.run(src)
88
+ end
89
+
90
+ end
@@ -0,0 +1,52 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{typograph}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Yury Korolev"]
12
+ s.date = %q{2009-08-25}
13
+ s.description = %q{apply some basic typography rules to text}
14
+ s.email = %q{yury.korolev@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "lib/typograph.rb",
24
+ "lib/typograph/rules.rb",
25
+ "lib/typograph/rules/dash_rules.rb",
26
+ "lib/typograph/rules/etc_rules.rb",
27
+ "lib/typograph/rules/math_rules.rb",
28
+ "lib/typograph/rules/punchmark_rules.rb",
29
+ "lib/typograph/rules/quote_rules.rb",
30
+ "lib/typograph/string_sub_each.rb",
31
+ "test/typograph_test.rb",
32
+ "typograph.gemspec"
33
+ ]
34
+ s.homepage = %q{http://github.com/yury/typograph}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{ruby html typograph}
39
+ s.test_files = [
40
+ "test/typograph_test.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
+ else
49
+ end
50
+ else
51
+ end
52
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yury-typograph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Yury Korolev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: apply some basic typography rules to text
17
+ email: yury.korolev@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - .gitignore
26
+ - README
27
+ - Rakefile
28
+ - VERSION
29
+ - lib/typograph.rb
30
+ - lib/typograph/rules.rb
31
+ - lib/typograph/rules/dash_rules.rb
32
+ - lib/typograph/rules/etc_rules.rb
33
+ - lib/typograph/rules/math_rules.rb
34
+ - lib/typograph/rules/punchmark_rules.rb
35
+ - lib/typograph/rules/quote_rules.rb
36
+ - lib/typograph/string_sub_each.rb
37
+ - test/typograph_test.rb
38
+ - typograph.gemspec
39
+ has_rdoc: false
40
+ homepage: http://github.com/yury/typograph
41
+ licenses:
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: ruby html typograph
66
+ test_files:
67
+ - test/typograph_test.rb