multi_typograf 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ report/report.html
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - jruby-18mode
4
+ - jruby-19mode
5
+ - 1.9.2
6
+ - 1.9.3
7
+ - ruby-head
8
+ # - rbx-18mode
9
+ # - rbx-19mode
10
+ # - 1.8.7
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'art_typograf', :require => nil
4
+ gem 'typographer', :require => nil
5
+ gem 'typographica', :require => nil
6
+ gem 'typograf', ">= 0.0.3", :require => nil
7
+
8
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 sterebooster
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ # MultiTypograf [![Build Status](https://secure.travis-ci.org/stereobooster/multi_typograf.png?branch=master)](https://secure.travis-ci.org/#!/stereobooster/multi_typograf) [![Dependency Status](https://gemnasium.com/stereobooster/multi_typograf.png?travis)](https://gemnasium.com/stereobooster/multi_typograf) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/stereobooster/multi_typograf)
2
+
3
+ There are lot of Ruby libraries for typographing text.
4
+ Instead of choosing a single implementation and forcing users of your library to be
5
+ stuck with it, you can use MultiTypograf instead, which will simply choose the
6
+ best available tipographer. Here's how to use it:
7
+
8
+ ```ruby
9
+ require 'multi_typograf'
10
+
11
+ MultiTypograf.process('тест') #=> 'тест'
12
+ ```
13
+
14
+ The `use` method, which sets the MultiTypograf adapter, takes either a symbol or a
15
+ class (to allow for custom CSS minifier) that responds to `.process` at the class level.
16
+
17
+ MultiTypograf tries to have intelligent defaulting. That is, if you have any of the
18
+ supported engines already loaded, it will utilize them before attempting to
19
+ load any.
20
+ It will load libraries in following order:
21
+
22
+ - [art_typograf](https://github.com/stereobooster/art_typograf) wrapper for http://www.artlebedev.ru/tools/typograf/
23
+ - TODO [typographer](https://github.com/brain-geek/typographer)
24
+ - TODO [typographica](https://github.com/akolosov/typographica)
25
+
26
+ If no other library is available, MultiTypograf falls back to [typograf](https://github.com/stereobooster/typograf) wrapper for http://www.typograf.ru/.
27
+
28
+ ## HTML::Pipeline
29
+
30
+ ```ruby
31
+ pipeline = HTML::Pipeline.new [
32
+ MultiTypograf::Filter
33
+ ]
34
+ pipeline.call('тест') #=> 'тест'
35
+ ```
36
+
37
+ ## TODO
38
+
39
+ - map options
40
+ - [HtmlPipeline](https://github.com/jch/html-pipeline) filter
41
+ - [Rails plugin](http://guides.rubyonrails.org/plugins.html)
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
@@ -0,0 +1,53 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ desc "Run all examples"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+
10
+ desc "generate report"
11
+ RSpec::Core::RakeTask.new(:report) do |task|
12
+ task.pattern = 'report/*_spec.rb'
13
+ task.fail_on_error = false
14
+ task.rspec_opts = "--format ReportFormatter --require #{File.expand_path('../report/report_formatter', __FILE__)} --out report/report.html"
15
+ end
16
+
17
+ desc "publish report"
18
+ task "report:publish" do # => :report do
19
+ # TODO fail if something not commited
20
+ # sh 'git status'
21
+ # fail ""
22
+
23
+ log = `git log -1`
24
+ options = {}
25
+ options[:sha] = /commit ([0-9a-f]{40})/.match(log)[1]
26
+ options[:message] = log.split("\n")[4].gsub(/^\s+|\s+$/, '')
27
+ options[:date] = Time.now.strftime("%d.%m.%Y")
28
+ options[:table] = File.open("report/report.html", "rb").read
29
+ o = {}
30
+ options.each { |key, val| o["{% #{key} %}"] = val }
31
+ template = File.open('report/template/index.html', 'rb').read
32
+ template.gsub!(/\{% ([\w\d]+) %\}/, o)
33
+ pwd = Dir.pwd
34
+ files = Dir.glob("#{pwd}/report/template/*") - ["#{pwd}/report/template/index.html"]
35
+
36
+ dir = "#{pwd}/tmp"
37
+ FileUtils.rm_rf "#{dir}"
38
+ Dir.mkdir(dir) unless File.exists? dir
39
+
40
+ Dir.chdir(dir)
41
+ sh "git clone #{pwd}"
42
+ Dir.chdir("#{dir}/multi_typograf")
43
+ sh 'git checkout --orphan gh-pages'
44
+ sh 'git rm -rf .'
45
+
46
+ FileUtils.cp files, "#{dir}/multi_typograf"
47
+ File.open('index.html', 'w+') { |f| f.write(template) }
48
+ sh "git add ."
49
+ sh "git commit -m\"report: #{options[:message]} #{options[:sha]}\""
50
+ sh 'git push -u origin gh-pages -f'
51
+
52
+ # FileUtils.rm_rf "#{dir}"
53
+ end
@@ -0,0 +1,112 @@
1
+ require "multi_typograf/version"
2
+ require "multi_typograf/filter"
3
+
4
+ module MultiTypograf
5
+ class Error < StandardError
6
+ def initialize(message="", backtrace=nil)
7
+ super(message)
8
+ self.set_backtrace(backtrace) if backtrace
9
+ end
10
+ end
11
+
12
+ @adapter = nil
13
+
14
+ REQUIREMENT_MAP = [
15
+ ["art_typograf", :art_typograf],
16
+ ["typographer/parsers/basic", :typographer],
17
+ ["typographica", :typographica],
18
+ ["typograf", :typograf]
19
+ ]
20
+
21
+ class << self
22
+
23
+ # The default adapter based on what you currently
24
+ # have loaded and installed. First checks to see
25
+ # if any adapters are already loaded, then checks
26
+ # to see which are installed if none are loaded.
27
+ def default_adapter
28
+ return :art_typograf if defined?(::ArtTypograf)
29
+ return :typographer if defined?(::TypographerHelper::Parsers::Basic)
30
+ return :typographica if defined?(::Typographica)
31
+ return :typograf if defined?(::Typograf)
32
+
33
+ REQUIREMENT_MAP.each do |(library, adapter)|
34
+ begin
35
+ require library
36
+ return adapter
37
+ rescue LoadError
38
+ next
39
+ end
40
+ end
41
+
42
+ :typograf
43
+ end
44
+ # :nodoc:
45
+ alias :default_engine :default_adapter
46
+
47
+ # Get the current adapter class.
48
+ def adapter
49
+ return @adapter if @adapter
50
+ self.use self.default_adapter
51
+ @adapter
52
+ end
53
+ # :nodoc:
54
+ alias :engine :adapter
55
+
56
+ # Set the adapter utilizing a symbol, string, or class.
57
+ # Supported by default are:
58
+ #
59
+ # * <tt>:typograf</tt>
60
+ # * <tt>:art_typograf</tt>
61
+ # * <tt>:typographer</tt>
62
+ # * <tt>:typography</tt>
63
+ # * <tt>:typographica</tt>
64
+ def use(new_adapter)
65
+ @adapter = load_adapter(new_adapter)
66
+ end
67
+ alias :adapter= :use
68
+ # :nodoc:
69
+ alias :engine= :use
70
+
71
+ def load_adapter(new_adapter)
72
+ case new_adapter
73
+ when String, Symbol
74
+ require "multi_typograf/adapters/#{new_adapter}"
75
+ self::Adapters.const_get(:"#{new_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}")
76
+ when NilClass, FalseClass
77
+ default_adapter = self.default_adapter
78
+ require "multi_typograf/adapters/#{default_adapter}"
79
+ self::Adapters.const_get(:"#{default_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}")
80
+ when Class
81
+ new_adapter
82
+ else
83
+ raise "Did not recognize your adapter specification. Please specify either a symbol or a class."
84
+ end
85
+ end
86
+
87
+ def current_adapter(options)
88
+ if new_adapter = (options || {}).delete(:adapter)
89
+ load_adapter(new_adapter)
90
+ else
91
+ adapter
92
+ end
93
+ end
94
+
95
+ # Minify CSS
96
+ def process(string, options={})
97
+ string = string.read if string.respond_to?(:read)
98
+
99
+ adapter = current_adapter(options)
100
+ if defined?(adapter::ParseError)
101
+ begin
102
+ adapter.process(string, options)
103
+ rescue adapter::ParseError => exception
104
+ raise ::MultiTypograf::Error.new(exception.message, exception.backtrace)
105
+ end
106
+ else
107
+ adapter.process(string, options)
108
+ end
109
+ end
110
+
111
+ end
112
+ end
@@ -0,0 +1,13 @@
1
+ require "art_typograf" unless defined?(::ArtTypograf)
2
+
3
+ module MultiTypograf
4
+ module Adapters
5
+ class ArtTypograf
6
+ Error = ::ArtTypograf::NetworkError
7
+
8
+ def self.process(text, options={}) #:nodoc:
9
+ ::ArtTypograf.process(text, options)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "typograf" unless defined?(::Typograf)
2
+
3
+ module MultiTypograf
4
+ module Adapters
5
+ class Typograf
6
+ Error = ::Typograf::NetworkError
7
+
8
+ def self.process(text, options={}) #:nodoc:
9
+ ::Typograf.process(text, options)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require "typographer/parsers/basic" unless defined?(::TypographerHelper)
2
+
3
+ module MultiTypograf
4
+ module Adapters
5
+ class Typographer
6
+ def self.process(text, options={}) #:nodoc:
7
+ ::TypographerHelper::Parsers::Basic.new(options).parse(text)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require "typographica" unless defined?(::Typographica)
2
+
3
+ module MultiTypograf
4
+ module Adapters
5
+ class Typographica
6
+ def self.process(text, options={}) #:nodoc:
7
+ ::Typographica.typography(text, options.delete(:shy))
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require "typography/core" unless defined?(::TypographyHelper)
2
+
3
+ module MultiTypograf
4
+ module Adapters
5
+ class Typography
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::TypographyHelper::Core.new(text, options).typography
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ begin
2
+ require 'html/pipeline'
3
+
4
+ module MultiTypograf
5
+ class Filter < ::HTML::Pipeline::TextFilter
6
+ def call
7
+ MultiTypograf.process(@text, context[:typograf])
8
+ end
9
+ end
10
+ end
11
+ rescue LoadError
12
+ end
@@ -0,0 +1,3 @@
1
+ module MultiTypograf
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multi_typograf/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "multi_typograf"
8
+ gem.version = MultiTypograf::VERSION
9
+ gem.authors = ["sterebooster"]
10
+ gem.email = ["stereobooster@gmail.com"]
11
+ gem.description = %q{A generic swappable back-end for typographing text.}
12
+ gem.summary = %q{A generic swappable back-end for typographing text.}
13
+ gem.homepage = "https://github.com/stereobooster/multi_typograf"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency 'typograf'
22
+
23
+ gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'simplecov'
26
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ class HtmlPrinter
6
+ include ERB::Util # for the #h method
7
+ def initialize(output)
8
+ @output = output
9
+ end
10
+
11
+ def print_summary( was_dry_run, duration, example_count, failure_count, pending_count )
12
+ # TODO - kill dry_run?
13
+ # if was_dry_run
14
+ # totals = "This was a dry-run"
15
+ # else
16
+ # totals = "#{example_count} example#{'s' unless example_count == 1}, "
17
+ # totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
18
+ # totals << ", #{pending_count} pending" if pending_count > 0
19
+ # end
20
+ # formatted_duration = sprintf("%.5f", duration)
21
+ # @output.puts "<script>document.getElementById('duration').innerHTML = \"Finished in <strong>#{formatted_duration} seconds</strong>\";</script>"
22
+ # @output.puts "<script>document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
23
+ end
24
+
25
+ def print_table(table, table_header)
26
+ @output.puts '<thead><tr><th>&nbsp;</th>'
27
+ totals = {}
28
+ table_header.keys.each do |name|
29
+ @output.puts "<th>#{h(name)}</th>"
30
+ totals[name] = 0
31
+ end
32
+ @output.puts "</tr></thead><tbody>"
33
+ table.each do |name, examples|
34
+ @output.puts "<tr><td>#{h(name)}</td>"
35
+ examples.each do |name, value|
36
+ value = if value == true
37
+ totals[name] += 1
38
+ "<td>+</td>"
39
+ else
40
+ value = value.gsub(/^[\r\n\s]+|[\r\n\s]+$/m, '')
41
+ .gsub('expected: ', 'expected:')
42
+ .gsub(/^\s+got: /, 'got:')
43
+ .gsub('&nbsp;', '&amp;nbsp;')
44
+ .gsub("\"(compared using ==)", "\"\n(compared using ==)")
45
+ "<td title='#{value}'>-</td>"
46
+ end
47
+ @output.puts value
48
+ end
49
+ @output.puts "</tr>"
50
+ end
51
+ @output.puts "<tr><td>Итого (всего: #{table.keys.length}):</td>"
52
+ totals.each do |name, total|
53
+ @output.puts "<td>#{total}</td>"
54
+ end
55
+ @output.puts "</tr></tbody>"
56
+ end
57
+
58
+ def flush
59
+ @output.flush
60
+ end
61
+ end