yury-typograph 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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