texter 0.3.0 → 1.0.0
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.
- data/app/assets/javascripts/texter/texts.js +26 -26
- data/app/controllers/texter/texts_controller.rb +2 -5
- data/app/helpers/texter/texts_helper.rb +8 -35
- data/app/lib/texter/art_typograph_preprocessor.rb +13 -0
- data/app/lib/texter/build_text.rb +38 -0
- data/app/lib/texter/callable_class.rb +11 -0
- data/app/lib/texter/clean_preprocessor.rb +7 -0
- data/app/lib/texter/formatter.rb +26 -0
- data/app/lib/texter/markdown_formatter.rb +41 -0
- data/app/lib/texter/preprocessor.rb +17 -0
- data/app/lib/texter/run_preprocessors_on_text.rb +29 -0
- data/app/lib/texter/simple_formatter.rb +11 -0
- data/app/lib/texter/textile_formatter.rb +42 -0
- data/app/models/texter/text.rb +6 -6
- data/app/presenters/texter/text_presenter.rb +60 -0
- data/app/views/texter/texts/_edit.html.erb +1 -1
- data/app/views/texter/texts/update.js.erb +3 -2
- data/config/locales/texter.ru.yml +10 -0
- data/db/migrate/20121231021051_create_texter_texts.rb +1 -2
- data/lib/texter.rb +27 -5
- data/lib/texter/engine.rb +0 -8
- data/lib/texter/version.rb +1 -1
- metadata +61 -51
- data/app/decorators/texter/text_decorator.rb +0 -42
- data/lib/texter/clean_body.rb +0 -11
- data/lib/texter/text_factory.rb +0 -23
- data/lib/texter/typograph.rb +0 -21
@@ -1,33 +1,33 @@
|
|
1
1
|
$(function(){
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
$('body').on('click', '.js-edit', function(){
|
3
|
+
EditText($(this));
|
4
|
+
});
|
5
5
|
|
6
|
-
|
6
|
+
function EditText(elem){
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
function removePopup(){
|
9
|
+
popup.fadeOut('fast', function(){
|
10
|
+
popup.remove();
|
11
|
+
});
|
12
|
+
$(window).off('keyup');
|
13
|
+
}
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
$('body').append('<div id="popup"><span class="close"></span><div id="form"></div></div>');
|
16
|
+
var popup = $('#popup');
|
17
|
+
$(window).on('keyup', function(e){
|
18
|
+
if(e.keyCode == 27){
|
19
|
+
removePopup();
|
20
|
+
}
|
21
|
+
});
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
popup.on('click', '.close', function(){
|
24
|
+
removePopup();
|
25
|
+
});
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
$.get(elem.data('url'), function(){
|
28
|
+
popup.fadeIn('fast', function(){
|
29
|
+
popup.find('textarea:first').focus();
|
30
|
+
});
|
31
|
+
});
|
32
|
+
}
|
33
33
|
});
|
@@ -2,8 +2,6 @@ require_dependency "texter/application_controller"
|
|
2
2
|
|
3
3
|
module Texter
|
4
4
|
class TextsController < ApplicationController
|
5
|
-
Texter.controller_setup.call(self)
|
6
|
-
|
7
5
|
respond_to :js
|
8
6
|
before_filter :load_text
|
9
7
|
|
@@ -11,10 +9,9 @@ module Texter
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def update
|
14
|
-
|
12
|
+
RunPreprocessorsOnText.call(@text)
|
15
13
|
|
16
|
-
if @text.
|
17
|
-
@text = TextDecorator.new(@text)
|
14
|
+
if @text.save
|
18
15
|
render :update
|
19
16
|
else
|
20
17
|
render :edit
|
@@ -1,44 +1,17 @@
|
|
1
1
|
module Texter
|
2
2
|
module TextsHelper
|
3
|
-
def inline(path)
|
4
|
-
display_text(path, :inline)
|
3
|
+
def inline(path, options = {})
|
4
|
+
display_text(path, :inline, options)
|
5
5
|
end
|
6
6
|
|
7
|
-
def block(path)
|
8
|
-
display_text(path, :block)
|
7
|
+
def block(path, options = {})
|
8
|
+
display_text(path, :block, options)
|
9
9
|
end
|
10
10
|
|
11
|
-
def display_text(path, tag_type)
|
12
|
-
text = Texter::
|
13
|
-
text
|
14
|
-
|
15
|
-
|
16
|
-
def text_can_be_edited?(text)
|
17
|
-
moderator_signed_in?
|
18
|
-
end
|
19
|
-
|
20
|
-
def textile(string, *rules)
|
21
|
-
return nil if string.blank?
|
22
|
-
|
23
|
-
textilize = ::RedCloth.new(string, rules)
|
24
|
-
textilize.to_html(:block_textile_prefix, :block_textile_lists, :inline_textile_link).html_safe
|
25
|
-
|
26
|
-
# refs_textile:: Textile references (i.e. [hobix]http://hobix.com/)
|
27
|
-
# block_textile_table:: Textile table block structures
|
28
|
-
# block_textile_lists:: Textile list structures
|
29
|
-
# block_textile_prefix:: Textile blocks with prefixes (i.e. bq., h2., etc.)
|
30
|
-
# inline_textile_image:: Textile inline images
|
31
|
-
# inline_textile_link:: Textile inline links
|
32
|
-
# inline_textile_span:: Textile inline spans
|
33
|
-
# inline_textile_glyphs:: Textile entities (such as em-dashes and smart quotes)
|
34
|
-
end
|
35
|
-
|
36
|
-
def textile_block(string)
|
37
|
-
textile(string)
|
38
|
-
end
|
39
|
-
|
40
|
-
def textile_inline(string)
|
41
|
-
textile(string, :lite_mode)
|
11
|
+
def display_text(path, tag_type, options = {})
|
12
|
+
text = Texter::BuildText.call(path, tag_type, @virtual_path)
|
13
|
+
presenter = Texter::TextPresenter.new(text, self, options)
|
14
|
+
presenter.body
|
42
15
|
end
|
43
16
|
end
|
44
17
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'art_typograph'
|
2
|
+
|
3
|
+
module Texter
|
4
|
+
class ArtTypographPreprocessor < Preprocessor
|
5
|
+
def call
|
6
|
+
processed = ArtTypograph.process(body)
|
7
|
+
processed.gsub! %r{</p>}m, "\n"
|
8
|
+
processed.gsub! %r{<p.*?>}, ''
|
9
|
+
processed.gsub! %r{</?(nobr|span).*?>}, ''
|
10
|
+
processed.strip
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Texter
|
2
|
+
class BuildText
|
3
|
+
include CallableClass
|
4
|
+
|
5
|
+
attr_reader :path, :tag_type, :virtual_path
|
6
|
+
|
7
|
+
# @param [String] path
|
8
|
+
# @param [Symbol] tag_type (:block, :inline)
|
9
|
+
# @param [String, NilClass] virtual_path
|
10
|
+
def initialize(path, tag_type, virtual_path)
|
11
|
+
@path = path
|
12
|
+
@tag_type = tag_type
|
13
|
+
@virtual_path = virtual_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
text = Texter::Text.find_or_initialize_by_path(full_path)
|
18
|
+
text.tag_type = tag_type
|
19
|
+
text
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def full_path
|
25
|
+
return path unless relative_path?
|
26
|
+
|
27
|
+
if virtual_path
|
28
|
+
virtual_path.gsub(%r{/_?}, ".") + path.to_s
|
29
|
+
else
|
30
|
+
raise "Cannot use #{path.inspect} shortcut because path is not available"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def relative_path?
|
35
|
+
path.starts_with?(".")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Texter
|
2
|
+
class Formatter
|
3
|
+
attr_reader :body, :options
|
4
|
+
|
5
|
+
def initialize(body, options = {})
|
6
|
+
@body = body
|
7
|
+
@options = options.dup
|
8
|
+
reverse_merge_defaults
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [String, NilClass]
|
12
|
+
def inline
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String, NilClass]
|
17
|
+
def block
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def reverse_merge_defaults
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rdiscount'
|
2
|
+
|
3
|
+
module Texter
|
4
|
+
class MarkdownFormatter < Formatter
|
5
|
+
# :smart - Enable SmartyPants processing.
|
6
|
+
# :filter_styles - Do not output <style> tags.
|
7
|
+
# :filter_html - Do not output any raw HTML tags included in the source text.
|
8
|
+
# :fold_lines - RedCloth compatible line folding (not used).
|
9
|
+
# :footnotes - PHP markdown extra-style footnotes.
|
10
|
+
# :generate_toc - Enable Table Of Contents generation
|
11
|
+
# :no_image - Do not output any <img> tags.
|
12
|
+
# :no_links - Do not output any <a> tags.
|
13
|
+
# :no_tables - Do not output any tables.
|
14
|
+
# :strict - Disable superscript and relaxed emphasis processing.
|
15
|
+
# :autolink - Greedily urlify links.
|
16
|
+
# :safelink - Do not make links for unknown URL types.
|
17
|
+
# :no_pseudo_protocols - Do not process pseudo-protocols.
|
18
|
+
cattr_accessor :extensions
|
19
|
+
self.extensions = []
|
20
|
+
|
21
|
+
# extracts html from the first paragraph or header
|
22
|
+
def inline
|
23
|
+
block.match(%r{<[hp]\d?>(.*?)</[hp]\d?>}).try(:[], 1)
|
24
|
+
end
|
25
|
+
|
26
|
+
def block
|
27
|
+
return nil if body.blank?
|
28
|
+
|
29
|
+
markdown = ::RDiscount.new(body, *options[:extensions])
|
30
|
+
markdown.to_html
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def reverse_merge_defaults
|
36
|
+
options.assert_valid_keys(:extensions)
|
37
|
+
options.reverse_merge!(:extensions => extensions)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Texter
|
2
|
+
class Preprocessor
|
3
|
+
include CallableClass
|
4
|
+
|
5
|
+
attr_reader :body
|
6
|
+
|
7
|
+
# @param [String] body
|
8
|
+
def initialize(body)
|
9
|
+
@body = body
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String, NilClass]
|
13
|
+
def call
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Texter
|
2
|
+
class RunPreprocessorsOnText
|
3
|
+
include CallableClass
|
4
|
+
|
5
|
+
attr_reader :text, :options
|
6
|
+
|
7
|
+
# @param [Texter::Text] text
|
8
|
+
# @param [Hash] options (:force => true to force processing)
|
9
|
+
def initialize(text, options = {})
|
10
|
+
@text = text
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
attributes.each do |attr|
|
16
|
+
body = text.send(attr)
|
17
|
+
processed = Texter.preprocessors.inject(body) { |memo, preprocessor| Texter.find_preprocessor(preprocessor).call(memo) }
|
18
|
+
text.send "#{attr}=", processed
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def attributes
|
25
|
+
return Texter.bodies if options[:force]
|
26
|
+
Texter.bodies & text.changed
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'RedCloth'
|
2
|
+
|
3
|
+
module Texter
|
4
|
+
class TextileFormatter < Formatter
|
5
|
+
cattr_accessor :rules, :restrictions
|
6
|
+
|
7
|
+
self.rules = []
|
8
|
+
|
9
|
+
# :filter_html
|
10
|
+
# :sanitize_html
|
11
|
+
# :filter_styles
|
12
|
+
# :filter_classes
|
13
|
+
# :filter_ids
|
14
|
+
# :lite_mode
|
15
|
+
# :no_span_caps
|
16
|
+
self.restrictions = [:no_span_caps]
|
17
|
+
|
18
|
+
def inline
|
19
|
+
restrictions_with_lite_mode = (options[:restrictions] + [:lite_mode]).uniq
|
20
|
+
textile :restrictions => restrictions_with_lite_mode
|
21
|
+
end
|
22
|
+
|
23
|
+
def block
|
24
|
+
textile
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def textile(redefine_options = {})
|
30
|
+
return nil if body.blank?
|
31
|
+
|
32
|
+
redefined_options = options.merge(redefine_options)
|
33
|
+
textile = ::RedCloth.new(body, redefined_options[:restrictions])
|
34
|
+
textile.to_html(*redefined_options[:rules]).html_safe
|
35
|
+
end
|
36
|
+
|
37
|
+
def reverse_merge_defaults
|
38
|
+
options.assert_valid_keys(:rules, :restrictions)
|
39
|
+
options.reverse_merge!(:rules => rules, :restrictions => restrictions)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/app/models/texter/text.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Texter
|
2
2
|
class Text < ActiveRecord::Base
|
3
|
-
|
3
|
+
BLOCK = 'block'
|
4
|
+
TAG_TYPES = [BLOCK, 'inline']
|
5
|
+
|
4
6
|
attr_writer :tag_type
|
5
7
|
|
6
8
|
attr_accessible *Texter.bodies, :tag_type
|
7
|
-
|
8
9
|
validates_uniqueness_of :path, :allow_blank => false
|
9
|
-
validates_presence_of *Texter.bodies
|
10
10
|
|
11
11
|
def self.find_or_create_from_translations_by_path(path)
|
12
12
|
text = find_or_initialize_by_path(path)
|
@@ -19,15 +19,15 @@ module Texter
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def get_body(options = {})
|
22
|
-
persisted? ? body :
|
22
|
+
persisted? ? body : Texter.translate(path, options)
|
23
23
|
end
|
24
24
|
|
25
25
|
def tag_type
|
26
|
-
TAG_TYPES.include?(@tag_type.to_s) ? @tag_type :
|
26
|
+
TAG_TYPES.include?(@tag_type.to_s) ? @tag_type : BLOCK
|
27
27
|
end
|
28
28
|
|
29
29
|
def default_attributes
|
30
|
-
{:body => get_body}
|
30
|
+
{ :body => get_body }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Texter
|
3
|
+
class TextPresenter
|
4
|
+
attr_reader :text, :h, :options
|
5
|
+
|
6
|
+
delegate :tag_type, :get_body, :path, :to => :text
|
7
|
+
|
8
|
+
def initialize(text, h, options = {})
|
9
|
+
@text = text
|
10
|
+
@h = h
|
11
|
+
@options = options
|
12
|
+
|
13
|
+
options.assert_valid_keys(:locale, :formatter, :formatter_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def body
|
17
|
+
return formatted unless can_be_edited?
|
18
|
+
|
19
|
+
h.content_tag(content_tag_name, formatted, {
|
20
|
+
:data => {
|
21
|
+
:url => h.texter.edit_text_path(path, :js, :text => {
|
22
|
+
:tag_type => tag_type
|
23
|
+
})
|
24
|
+
},
|
25
|
+
:class => "js-edit #{path_for_class}"
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
def path_for_class
|
30
|
+
path.gsub(/\./, '-')
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def formatter
|
36
|
+
Texter.find_formatter(options[:formatter] || Texter.formatter)
|
37
|
+
end
|
38
|
+
|
39
|
+
def content_tag_name
|
40
|
+
{
|
41
|
+
:block => :div,
|
42
|
+
:inline => :span
|
43
|
+
}.fetch(tag_type.to_sym)
|
44
|
+
end
|
45
|
+
|
46
|
+
def formatted
|
47
|
+
body = get_body(locale_options)
|
48
|
+
body = Texter.translate("edit", locale_options.merge(:default => 'Редактировать')) if can_be_edited? && body.blank?
|
49
|
+
formatter.new(body, options[:formatter_options] || {}).send(tag_type)
|
50
|
+
end
|
51
|
+
|
52
|
+
def can_be_edited?
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
def locale_options
|
57
|
+
options.slice(:locale)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -3,5 +3,5 @@
|
|
3
3
|
<% Texter.bodies.each do |body| %>
|
4
4
|
<%= f.input body %>
|
5
5
|
<% end %>
|
6
|
-
<%= f.submit
|
6
|
+
<%= f.submit Texter.translate('submit', :default => 'Сохранить'), :disable_with => Texter.translate('disable_with', :default => '✔ Сохраняется...') %>
|
7
7
|
<% end %>
|
@@ -1,4 +1,5 @@
|
|
1
|
+
<% presenter = Texter::TextPresenter.new(@text, self) %>
|
1
2
|
$("#popup").remove();
|
2
|
-
$(".<%=
|
3
|
-
$(this).replaceWith($("<%= j(
|
3
|
+
$(".<%= presenter.path_for_class %>").each(function(){
|
4
|
+
$(this).replaceWith($("<%= j(presenter.body) %>"));
|
4
5
|
});
|
@@ -1,9 +1,8 @@
|
|
1
1
|
class CreateTexterTexts < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :texter_texts do |t|
|
4
|
-
t.string :path, :null => false
|
4
|
+
t.string :path, :null => false
|
5
5
|
t.text :body
|
6
|
-
t.timestamps
|
7
6
|
end
|
8
7
|
add_index :texter_texts, :path, :unique => true
|
9
8
|
end
|
data/lib/texter.rb
CHANGED
@@ -1,11 +1,33 @@
|
|
1
|
-
require
|
1
|
+
require 'texter/engine'
|
2
|
+
require 'simple_form'
|
2
3
|
|
3
4
|
module Texter
|
4
|
-
# body attributes for text
|
5
|
-
# it can be %w{body_ru body_en} for instance
|
5
|
+
# [Array<String>] body attributes for text
|
6
|
+
# it can be %w{body_ru body_en} for instance if you use multiple languages
|
6
7
|
mattr_accessor :bodies
|
7
8
|
self.bodies = %w{body}
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
# [Array<Symbol>]
|
11
|
+
mattr_accessor :preprocessors
|
12
|
+
self.preprocessors = [:clean]
|
13
|
+
|
14
|
+
# [Symbol]
|
15
|
+
mattr_accessor :formatter
|
16
|
+
self.formatter = :simple
|
17
|
+
|
18
|
+
class <<self
|
19
|
+
# @param [Symbol, String] name
|
20
|
+
def find_formatter(name)
|
21
|
+
"Texter::#{name.to_s.classify}Formatter".constantize
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [Symbol, String] name
|
25
|
+
def find_preprocessor(name)
|
26
|
+
"Texter::#{name.to_s.classify}Preprocessor".constantize
|
27
|
+
end
|
28
|
+
|
29
|
+
def translate(path, options = {})
|
30
|
+
I18n.t(path, { :scope => 'texter' }.merge(options))
|
31
|
+
end
|
32
|
+
end
|
11
33
|
end
|
data/lib/texter/engine.rb
CHANGED
data/lib/texter/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: texter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 3.2.9
|
22
22
|
type: :runtime
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 3.2.9
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: 3.2.3
|
38
38
|
type: :runtime
|
@@ -40,66 +40,66 @@ dependencies:
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 3.2.3
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: simple_form
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: '0'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: rspec-rails
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
type: :
|
69
|
+
version: '2.12'
|
70
|
+
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: '2.12'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
79
|
+
name: capybara
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
82
|
requirements:
|
83
|
-
- -
|
83
|
+
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
86
|
-
type: :
|
85
|
+
version: 2.0.1
|
86
|
+
type: :development
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
|
-
- -
|
91
|
+
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: 2.0.1
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
95
|
+
name: sqlite3
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
99
|
- - ! '>='
|
100
100
|
- !ruby/object:Gem::Version
|
101
101
|
version: '0'
|
102
|
-
type: :
|
102
|
+
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
@@ -108,76 +108,77 @@ dependencies:
|
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
111
|
+
name: database_cleaner
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
113
113
|
none: false
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ! '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
none: false
|
122
122
|
requirements:
|
123
|
-
- -
|
123
|
+
- - ! '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '
|
125
|
+
version: '0'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
127
|
+
name: rdiscount
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
129
129
|
none: false
|
130
130
|
requirements:
|
131
|
-
- -
|
131
|
+
- - ! '>='
|
132
132
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
133
|
+
version: '0'
|
134
134
|
type: :development
|
135
135
|
prerelease: false
|
136
136
|
version_requirements: !ruby/object:Gem::Requirement
|
137
137
|
none: false
|
138
138
|
requirements:
|
139
|
-
- -
|
139
|
+
- - ! '>='
|
140
140
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
141
|
+
version: '0'
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
143
|
+
name: RedCloth
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
145
145
|
none: false
|
146
146
|
requirements:
|
147
|
-
- -
|
147
|
+
- - ~>
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version:
|
149
|
+
version: 4.2.9
|
150
150
|
type: :development
|
151
151
|
prerelease: false
|
152
152
|
version_requirements: !ruby/object:Gem::Requirement
|
153
153
|
none: false
|
154
154
|
requirements:
|
155
|
-
- -
|
155
|
+
- - ~>
|
156
156
|
- !ruby/object:Gem::Version
|
157
|
-
version:
|
157
|
+
version: 4.2.9
|
158
158
|
- !ruby/object:Gem::Dependency
|
159
|
-
name:
|
159
|
+
name: art_typograph
|
160
160
|
requirement: !ruby/object:Gem::Requirement
|
161
161
|
none: false
|
162
162
|
requirements:
|
163
|
-
- -
|
163
|
+
- - ~>
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version:
|
165
|
+
version: 0.1.1
|
166
166
|
type: :development
|
167
167
|
prerelease: false
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
169
169
|
none: false
|
170
170
|
requirements:
|
171
|
-
- -
|
171
|
+
- - ~>
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
173
|
+
version: 0.1.1
|
174
174
|
description: ! '* Лёгкий вывод блочных и инлайновых текстов, отформатированных с помощью
|
175
|
-
Textile
|
175
|
+
Textile, Markdown или simple_format
|
176
176
|
|
177
177
|
* Дефолтные тексты в I18n
|
178
178
|
|
179
|
-
*
|
180
|
-
|
179
|
+
* При редактировании тексты сохраняются в базе
|
180
|
+
|
181
|
+
* Подключаемые обработчики (препроцессоры) — можно легко подключить «Типограф Лебедева»
|
181
182
|
|
182
183
|
* Удобный, встроенный в сайт интерфейс редактирования'
|
183
184
|
email:
|
@@ -193,26 +194,35 @@ files:
|
|
193
194
|
- app/assets/stylesheets/texter/application.css
|
194
195
|
- app/controllers/texter/application_controller.rb
|
195
196
|
- app/controllers/texter/texts_controller.rb
|
196
|
-
- app/decorators/texter/text_decorator.rb
|
197
197
|
- app/helpers/texter/application_helper.rb
|
198
198
|
- app/helpers/texter/texts_helper.rb
|
199
|
+
- app/lib/texter/art_typograph_preprocessor.rb
|
200
|
+
- app/lib/texter/build_text.rb
|
201
|
+
- app/lib/texter/callable_class.rb
|
202
|
+
- app/lib/texter/clean_preprocessor.rb
|
203
|
+
- app/lib/texter/formatter.rb
|
204
|
+
- app/lib/texter/markdown_formatter.rb
|
205
|
+
- app/lib/texter/preprocessor.rb
|
206
|
+
- app/lib/texter/run_preprocessors_on_text.rb
|
207
|
+
- app/lib/texter/simple_formatter.rb
|
208
|
+
- app/lib/texter/textile_formatter.rb
|
199
209
|
- app/models/texter/text.rb
|
210
|
+
- app/presenters/texter/text_presenter.rb
|
200
211
|
- app/views/texter/texts/_edit.html.erb
|
201
212
|
- app/views/texter/texts/edit.js.erb
|
202
213
|
- app/views/texter/texts/update.js.erb
|
214
|
+
- config/locales/texter.ru.yml
|
203
215
|
- config/routes.rb
|
204
216
|
- db/migrate/20121231021051_create_texter_texts.rb
|
205
217
|
- lib/tasks/texter_tasks.rake
|
206
|
-
- lib/texter/clean_body.rb
|
207
218
|
- lib/texter/engine.rb
|
208
|
-
- lib/texter/text_factory.rb
|
209
|
-
- lib/texter/typograph.rb
|
210
219
|
- lib/texter/version.rb
|
211
220
|
- lib/texter.rb
|
212
221
|
- Rakefile
|
213
222
|
homepage: http://github.com/macovsky/texter
|
214
223
|
licenses: []
|
215
|
-
post_install_message:
|
224
|
+
post_install_message: Texter 1.0.0 is backwards incompatible, please take a look at
|
225
|
+
the changelog.
|
216
226
|
rdoc_options: []
|
217
227
|
require_paths:
|
218
228
|
- lib
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'draper'
|
3
|
-
|
4
|
-
module Texter
|
5
|
-
class TextDecorator < Draper::Decorator
|
6
|
-
decorates 'Texter::Text'
|
7
|
-
delegate_all
|
8
|
-
|
9
|
-
def body
|
10
|
-
return textile unless can_edit?
|
11
|
-
|
12
|
-
h.content_tag(content_tag, textile, {
|
13
|
-
:data => {
|
14
|
-
:url => h.texter.edit_text_path(path, :js, :text => {
|
15
|
-
:tag_type => tag_type
|
16
|
-
})
|
17
|
-
},
|
18
|
-
:class => "js-edit #{path_for_class}"
|
19
|
-
})
|
20
|
-
end
|
21
|
-
|
22
|
-
def path_for_class
|
23
|
-
path.gsub(/\./, '-')
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def content_tag
|
29
|
-
{:block => :div, :inline => :span}[tag_type.to_sym]
|
30
|
-
end
|
31
|
-
|
32
|
-
def textile
|
33
|
-
body = get_body
|
34
|
-
body = "Редактировать" if can_edit? && body.blank?
|
35
|
-
h.send("textile_#{tag_type}", body)
|
36
|
-
end
|
37
|
-
|
38
|
-
def can_edit?
|
39
|
-
h.text_can_be_edited?(model)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/lib/texter/clean_body.rb
DELETED
data/lib/texter/text_factory.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Texter
|
2
|
-
class TextFactory < Struct.new(:path, :tag_type, :virtual_path)
|
3
|
-
def build
|
4
|
-
text = Texter::Text.find_or_initialize_by_path(full_path)
|
5
|
-
text.tag_type = tag_type
|
6
|
-
Texter::TextDecorator.new(text)
|
7
|
-
end
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
def full_path
|
12
|
-
if path.to_s.first == "."
|
13
|
-
if virtual_path
|
14
|
-
virtual_path.gsub(%r{/_?}, ".") + path.to_s
|
15
|
-
else
|
16
|
-
raise "Cannot use #{path.inspect} shortcut because path is not available"
|
17
|
-
end
|
18
|
-
else
|
19
|
-
path
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/texter/typograph.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Texter
|
2
|
-
class Typograph < Struct.new(:text)
|
3
|
-
def process(*attrs)
|
4
|
-
return true if attrs.blank?
|
5
|
-
|
6
|
-
options = attrs.flatten.inject({}){|memo, attr|
|
7
|
-
memo.merge! attr => self.class.process(text.send(attr))
|
8
|
-
}
|
9
|
-
|
10
|
-
text.update_attributes options
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.process(text)
|
14
|
-
s = ArtTypograph.process(text)
|
15
|
-
s.gsub! %r{</p>}m, "\n"
|
16
|
-
s.gsub! %r{<p.*?>}, ''
|
17
|
-
s.gsub! %r{</?(nobr|span).*?>}, ''
|
18
|
-
s.strip
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|