Skip to content

Commit

Permalink
feat: Initial commit
Browse files Browse the repository at this point in the history
Code merged from Apress::Utils and Plugin base_class_extensions/string

Closes SG-3689
  • Loading branch information
sclinede committed Jul 16, 2015
1 parent 569f0d6 commit 29dd2f8
Show file tree
Hide file tree
Showing 15 changed files with 429 additions and 1 deletion.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--format documentation
--color
18 changes: 18 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
appraise 'rails3.1' do
gem 'activerecord', '~> 3.1.12'
gem 'actionpack', '~> 3.1.12'
gem 'activesupport', '~> 3.1.12'
end

appraise 'rails3.2' do
gem 'activerecord', '~> 3.2.0'
gem 'actionpack', '~> 3.2.0'
gem 'activesupport', '~> 3.2.0'
end

appraise 'rails4.0' do
gem 'activerecord', '~> 4.0.0'
gem 'actionpack', '~> 4.0.0'
gem 'activesupport', '~> 4.0.0'
end

4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in string_tools.gemspec
gemspec
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 Sergey D.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
RAILS_ENV = test
BUNDLE = RAILS_ENV=${RAILS_ENV} bundle
BUNDLE_OPTIONS = -j 2
RSPEC = rspec
APPRAISAL = appraisal

all: test

test: bundler/install appraisal/install
${BUNDLE} exec ${APPRAISAL} ${RSPEC} spec 2>&1

bundler/install:
if ! gem list bundler -i > /dev/null; then \
gem install bundler; \
fi
${BUNDLE} install ${BUNDLE_OPTIONS}

appraisal/install:
${BUNDLE} exec ${APPRAISAL} install
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
# string_tools
# StringTools

Here comes some string tools we often use in Abak-Press. We divided them in two groups. Some of them are class methods of StringTools class and others are extend base String class

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'string_tools'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install string_tools

## Usage

TODO: Write usage instructions here

## Development

After checking out the repo, run `bundle install` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

1. Fork it ( https://github.com/abak-press/string_tools/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require "bundler/gem_tasks"
7 changes: 7 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby

require 'bundler/setup'
require 'string_tools'

require "pry"
Pry.start
159 changes: 159 additions & 0 deletions lib/string_tools.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# coding: utf-8
require 'string_tools/version'
require 'ru_propisju'
require 'sanitize'
require 'active_support/core_ext/string'
require 'string_tools/core_ext/string'

module StringTools
module CharDet
# Возвращает true если строка содержит допустимую
# последовательность байтов для кодировки utf8 и false в обратном случае
# см. http://en.wikipedia.org/wiki/UTF-8
def valid_utf8? string
case string
when String then string.is_utf8?
else false
end
end

# shorthand
def detect_encoding(str)
str.detect_encoding
end

# привести строку к utf8
def to_utf8(str)
str.to_utf8
end

def to_cp1251(str)
str.to_cp1251
end

def cp1251_compatible_encodings
[
'windows-1253',
'windows-1254',
'windows-1255',
'windows-1256',
'windows-1258',
'EUC-TW',
'ISO-8859-8'
]
end
end
extend CharDet

module WordProcessing
def truncate_words(text, length = 75)
return if text.nil?

if text.mb_chars.size > length
new_length = text.mb_chars[0...length].rindex(/[^[:word:]]/)
text.mb_chars[0...new_length.to_i]
else
text
end
rescue
text[0...length]
end
end
extend WordProcessing

module ActionControllerExtension
def accepts_non_utf8_params(*args)
args.each do |arg|
next unless arg.is_a?(Symbol) || arg.is_a?(String)
arg = arg.to_sym

class_eval do
before_filter { |controller|
decode = lambda { |s|
if s.is_a?(Hash)
s.to_a.map { |k, v| [k, StringTools.to_utf8(v)]}.to_hash
elsif s.is_a?(Array)
s.map { |v| StringTools.to_utf8(v) }
else
StringTools.to_utf8(s)
end
}

controller.params[arg] = decode.call(controller.params[arg]) unless controller.params[arg].nil?
}
end
end
end

alias_method :accepts_non_utf8_param, :accepts_non_utf8_params
end

module Sanitizing
def sanitize(text, options = {})
sanitizer = options.delete(:sanitizer)
sanitizer = StringTools::Sanitizer::Base.new unless sanitizer.respond_to?(:sanitize)
sanitizer.sanitize(text, options)
end

# Public: вычищает ASCII Control Characters из строки
#
# string - String строка, из которой удаляем символы
#
# Returns String
def clear_control_characters(string)
string.tr("\u0000-\u001f", '')
end
end
extend Sanitizing

module Sanitizer
class Base

TAGS_WITH_ATTRIBUTES = {
'p' => %w(align style),
'div' => %w(align style),
'span' => %w(align style),
'td' => %w(align width valign colspan rowspan style),
'th' => %w(align width valign colspan rowspan style),
'a' => %w(href target name style),
'table' => %w(cellpadding cellspacing width border align style),
'img' => %w(src width height style)
}

TAGS_WITHOUT_ATTRIBUTES = %w(b strong i em sup sub ul ol li blockquote br tr u caption thead)

def sanitize(str, attr = {})
# для корректного обрезания utf строчек режем через mb_chars
# для защиты от перегрузки парсера пропускаем максимум 1 мегабайт текста
# длина русского символа в utf-8 - 2 байта, 1Мб/2б = 524288 = 2**19 символов
# длина по символам с перестраховкой, т.к. латинские символы(теги, например) занимают 1 байт
str = str.mb_chars.slice(0..(2**19)).to_s

attributes = TAGS_WITH_ATTRIBUTES

# Мерджим добавочные теги и атрибуты
attributes.merge!(attr)
elements = attributes.keys | TAGS_WITHOUT_ATTRIBUTES

Sanitize.fragment(str,
:attributes => attributes,
:elements => elements,
:css => {:properties => Sanitize::Config::RELAXED[:css][:properties]},
:remove_contents => %w(style javascript),
:allow_comments => false
)
end
end
end

module SumInWords
# Сумма в рублях прописью. Кол-во копеек выводится всегда. Первая буква заглавная
def rublej_propisju(amount)
kop = (amount.divmod(1)[1]*100).round
result = RuPropisju.rublej(amount.to_i).capitalize
result << " %.2d " % kop
result << RuPropisju.choose_plural(kop, 'копейка', 'копейки', 'копеек')
end
end
extend SumInWords
end
87 changes: 87 additions & 0 deletions lib/string_tools/core_ext/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require 'rchardet19'
require 'addressable/uri'
require 'active_support/core_ext/module'
require 'active_record'
require 'action_pack'

class String
%w[auto_link excerpt highlight sanitize simple_format word_wrap].each do |method|
eval <<-EVAL
def #{method}(*args)
ActionController::Base.helpers.#{method}(self, *args)
end
EVAL

end

# возвращает строку из которой удалены HTML-теги
# символы <>&" остаются без изменения
def strip_tags
ActionController::Base.helpers.strip_tags(self).to_str
end

# '11,3'.to_f
# => 11.3
def to_f_with_strip_comma
self.gsub(/,/,'.').to_f_without_strip_comma
end
alias_method_chain :to_f, :strip_comma

def to_b
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(self) || false
end

def to_script_safe_json
self.to_json.gsub('</script>', '</" + "script>" + "')
end

def naturalized
scan(/[^\d\.]+|[\d\.]+/).map{|f| f.match(/^\d+(\.\d+)?$/) ? f.to_f : f }
end


# Выполняет преобразование строки в punycode.
def to_punycode
Addressable::URI.parse(self).normalize.to_s
end


# shorthand
def detect_encoding
e = ::CharDet.detect(self)["encoding"]
e = 'windows-1251' if StringTools.cp1251_compatible_encodings.include?(e)
e
end

def to_utf8!
self.replace(self.to_utf8)
end

def to_utf8
# и так utf
return self if is_utf8?

enc = detect_encoding

# если utf или английские буквы, то тоже ок
return self if ['utf-8', 'ascii'].include?(enc)

# если неизвестная каша, то возвращаем пустую строку
return '' if enc.nil?

# иначе пытаемся перекодировать
encode 'utf-8', enc, :undef => :replace, :invalid => :replace
rescue
''
end

def to_cp1251
encode 'cp1251', :undef => :replace, :invalid => :replace
rescue
''
end

def to_cp1251!
self.replace(self.to_cp1251)
end
end
3 changes: 3 additions & 0 deletions lib/string_tools/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module StringTools
VERSION = "0.1.0"
end
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'string_tools'
Loading

0 comments on commit 29dd2f8

Please sign in to comment.