snippr 0.3.0 → 0.13.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.
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/README.md +143 -0
- data/Rakefile +5 -4
- data/lib/snippr.rb +14 -2
- data/lib/snippr/i18n.rb +9 -10
- data/lib/snippr/links.rb +59 -0
- data/lib/snippr/meta_data.rb +33 -0
- data/lib/snippr/normalizer.rb +18 -0
- data/lib/snippr/normalizer/camelizer.rb +18 -0
- data/lib/snippr/normalizer/de_rester.rb +25 -0
- data/lib/snippr/path.rb +27 -6
- data/lib/snippr/processor.rb +18 -0
- data/lib/snippr/processor/dynamics.rb +31 -0
- data/lib/snippr/processor/functions.rb +50 -0
- data/lib/snippr/processor/links.rb +20 -0
- data/lib/snippr/processor/wikilinks.rb +20 -0
- data/lib/snippr/snip.rb +57 -0
- data/lib/snippr/snippr.rb +41 -45
- data/lib/snippr/view_helper.rb +71 -0
- data/snippr.gemspec +30 -0
- data/spec/fixtures/a/path/aSnippet.snip +1 -0
- data/spec/fixtures/a/path/aSnippetWithParam.snip +1 -0
- data/spec/fixtures/controller/action/aSnippet.snip +1 -0
- data/spec/fixtures/empty.snip +3 -0
- data/spec/fixtures/i18n/list_de.snip +0 -0
- data/spec/fixtures/meta/broken.snip +5 -0
- data/spec/fixtures/meta/withContent.snip +5 -0
- data/spec/fixtures/meta/withContentNoNewline.snip +4 -0
- data/spec/fixtures/meta/withNoContent.snip +4 -0
- data/spec/fixtures/withUnderscore/andUnderscore/aSnippet.snip +1 -0
- data/spec/fixtures/withViewHelperMethod.snip +1 -0
- data/spec/snippr/i18n_spec.rb +30 -0
- data/spec/snippr/links_spec.rb +137 -0
- data/spec/snippr/normalizer/camelizer_spec.rb +13 -0
- data/spec/snippr/normalizer/de_rester_spec.rb +24 -0
- data/spec/snippr/normalizer_spec.rb +40 -0
- data/spec/snippr/path_spec.rb +87 -0
- data/spec/snippr/processor/dynamics_spec.rb +49 -0
- data/spec/snippr/processor/functions_spec.rb +72 -0
- data/spec/snippr/processor/links_spec.rb +12 -0
- data/spec/snippr/processor/wikilinks_spec.rb +12 -0
- data/spec/snippr/processor_spec.rb +35 -0
- data/spec/snippr/snip_spec.rb +179 -0
- data/spec/snippr/snippr_spec.rb +60 -55
- data/spec/snippr/view_helper_spec.rb +221 -0
- data/spec/spec_helper.rb +17 -3
- metadata +178 -87
- data/README.rdoc +0 -77
- data/lib/snippr/core_ext.rb +0 -12
- data/lib/snippr/helper.rb +0 -23
- data/lib/snippr/link.rb +0 -26
- data/spec/fixtures/tariff/einheit.snip +0 -1
- data/spec/fixtures/wiki.snip +0 -1
- data/spec/snippr/core_ext_spec.rb +0 -11
@@ -0,0 +1,18 @@
|
|
1
|
+
# = Snippr::Processor
|
2
|
+
#
|
3
|
+
# Provides methods to process snippr content.
|
4
|
+
module Snippr
|
5
|
+
module Processor
|
6
|
+
|
7
|
+
# Returns a (modifiable) list of processors that'll be used to process the content.
|
8
|
+
def self.processors
|
9
|
+
@processors ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Sends the given content and opts to all the configured processors and returns the result.
|
13
|
+
def self.process(content, opts)
|
14
|
+
@processors.inject(content) {|c, processor| processor.process c, opts}
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# = Snippr::Processor::Dynamics
|
2
|
+
#
|
3
|
+
# Replaces {placeholder} placeholders in the content with values taken from the given opts.
|
4
|
+
module Snippr
|
5
|
+
|
6
|
+
module Processor
|
7
|
+
|
8
|
+
class Dynamics
|
9
|
+
|
10
|
+
def process(content, opts = {})
|
11
|
+
opts.inject(content) do |c, pv|
|
12
|
+
placeholder, value = pv
|
13
|
+
c.gsub(/\{#{placeholder}(?:\.(.*?)\(["]?(.*?)["]?\))?\}/m) do |match|
|
14
|
+
if $1 && value.respond_to?($1)
|
15
|
+
method = $1
|
16
|
+
params = ($2 || "").gsub(/[\t\r\n]/,"").split("\",\"")
|
17
|
+
value.send(method, *params).to_s
|
18
|
+
elsif $1
|
19
|
+
match
|
20
|
+
else
|
21
|
+
value.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# = Snippr::Processor::Functions
|
2
|
+
#
|
3
|
+
# Processes several functions in {command:options} syntax.
|
4
|
+
module Snippr
|
5
|
+
|
6
|
+
module Processor
|
7
|
+
|
8
|
+
class Functions
|
9
|
+
|
10
|
+
def process(content, opts = {})
|
11
|
+
content.scan(/\{(.*?):(.*?)\}/) do |match|
|
12
|
+
command, func_options = match
|
13
|
+
options = opts.merge(hashify(func_options))
|
14
|
+
command = "cmd_#{command}"
|
15
|
+
content = send(command, content, options, func_options) if respond_to?(command, true)
|
16
|
+
end
|
17
|
+
content
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# expand another snip
|
23
|
+
# {snip:path/to/snippet}
|
24
|
+
def cmd_snip(unprocessed_content, opts, original_options)
|
25
|
+
path = opts[:default].split("/")
|
26
|
+
snip_content = Snippr::Snip.new(*path + [opts]).content
|
27
|
+
unprocessed_content.gsub("{snip:#{original_options}}", snip_content)
|
28
|
+
end
|
29
|
+
|
30
|
+
# home
|
31
|
+
# snip=home
|
32
|
+
# snip=home,var=1
|
33
|
+
def hashify(func_options="")
|
34
|
+
options = {}
|
35
|
+
func_options.split(",").each do |option|
|
36
|
+
opt_key, opt_value = option.split("=")
|
37
|
+
unless opt_value
|
38
|
+
opt_value = opt_key
|
39
|
+
opt_key = :default
|
40
|
+
end
|
41
|
+
options[opt_key.to_sym] = opt_value
|
42
|
+
end
|
43
|
+
options
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# = Snippr::Processor::Links
|
2
|
+
#
|
3
|
+
# Adjusts URLs in links.
|
4
|
+
module Snippr
|
5
|
+
|
6
|
+
module Processor
|
7
|
+
|
8
|
+
class Links
|
9
|
+
|
10
|
+
def process(content, opts = {})
|
11
|
+
content.gsub /<a [^>]+>[^<]*<\/a>/i do |match|
|
12
|
+
Snippr::Links.adjust_link match
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# = Snippr::Processor::Wikilinks
|
2
|
+
#
|
3
|
+
# Replaces links in [url|title] syntax with real links.
|
4
|
+
module Snippr
|
5
|
+
|
6
|
+
module Processor
|
7
|
+
|
8
|
+
class Wikilinks
|
9
|
+
|
10
|
+
def process(content, opts = {})
|
11
|
+
content.gsub /\[\[([^|]+)\|([^\]]+)\]\]/ do |match|
|
12
|
+
Snippr::Links.adjust_link "<a href=\"#{$1}\">#{$2}</a>"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/snippr/snip.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# # -*- encoding : utf-8 -*-
|
2
|
+
# = Snippr::Snip
|
3
|
+
#
|
4
|
+
# Represents a single snip and provides methods to read data.
|
5
|
+
module Snippr
|
6
|
+
class Snip
|
7
|
+
|
8
|
+
extend ActiveSupport::Memoizable
|
9
|
+
|
10
|
+
FILE_EXTENSION = 'snip'
|
11
|
+
|
12
|
+
def initialize(*names)
|
13
|
+
names = strip_empty_values(names)
|
14
|
+
@opts = names.last.kind_of?(Hash) ? names.pop : {}
|
15
|
+
@opts.symbolize_keys!
|
16
|
+
@name = "#{Path.normalize_name(*names)}#{ I18n.locale(@opts[:i18n]) }"
|
17
|
+
@path = Path.path_from_name @name, (@opts[:extension] || FILE_EXTENSION)
|
18
|
+
@unprocessed_content, @meta = MetaData.extract(names, raw_content)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :name, :path, :opts, :unprocessed_content, :meta
|
22
|
+
|
23
|
+
# Returns the processed and decorated content.
|
24
|
+
def content
|
25
|
+
if missing?
|
26
|
+
"<!-- missing snippr: #{name} -->"
|
27
|
+
else
|
28
|
+
content = Processor.process unprocessed_content, opts
|
29
|
+
"<!-- starting snippr: #{name} -->\n#{content}\n<!-- closing snippr: #{name} -->"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
memoize :content
|
33
|
+
alias :to_s :content
|
34
|
+
|
35
|
+
def raw_content
|
36
|
+
missing? ? '' : File.read(@path).strip
|
37
|
+
end
|
38
|
+
memoize :raw_content
|
39
|
+
|
40
|
+
# Returns whether the snip is missing or not.
|
41
|
+
def missing?
|
42
|
+
!File.exist? @path
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns whether the snip is empty or not.
|
46
|
+
def empty?
|
47
|
+
unprocessed_content.blank?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def strip_empty_values(names)
|
53
|
+
names - [nil, ""]
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/snippr/snippr.rb
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
require "snippr/path"
|
3
|
-
require "snippr/i18n"
|
4
|
-
require "snippr/link"
|
1
|
+
require "logger"
|
5
2
|
|
6
3
|
# = Snippr
|
7
4
|
# ==== File based content management
|
@@ -9,56 +6,55 @@ require "snippr/link"
|
|
9
6
|
# A snippr file is a piece of HTML or raw text to be included in a website. They are plain text
|
10
7
|
# files stored on the file system. Snippr files end with ".snip" and are read from the Snippr path.
|
11
8
|
module Snippr
|
12
|
-
extend
|
13
|
-
extend Snippr::I18n
|
14
|
-
extend Snippr::Link
|
9
|
+
extend self
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# The comments wrapping a snippr.
|
22
|
-
SnipprComments = "<!-- starting snippr: %s -->\n%s\n<!-- closing snippr: %s -->"
|
11
|
+
# Returns the path to the snippr files (from JVM properties if available).
|
12
|
+
def path
|
13
|
+
Path.path
|
14
|
+
end
|
23
15
|
|
24
|
-
|
25
|
-
|
16
|
+
# Sets the path to the snippr files.
|
17
|
+
def path=(path)
|
18
|
+
Path.path = path
|
19
|
+
end
|
26
20
|
|
21
|
+
# Returns whether to use I18n snippr files.
|
22
|
+
def i18n?
|
23
|
+
I18n.enabled?
|
24
|
+
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@name = name_from args
|
33
|
-
SnipprComments % [@name, content, @name]
|
34
|
-
end
|
26
|
+
# Sets whether to use I18n snippr files.
|
27
|
+
def i18n=(enabled)
|
28
|
+
I18n.enabled = enabled
|
29
|
+
end
|
35
30
|
|
36
|
-
|
31
|
+
# Returns the regular expressions used to determine which urls to exclude from adjustment.
|
32
|
+
def adjust_urls_except
|
33
|
+
Links.adjust_urls_except
|
34
|
+
end
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
# Sets the regular expressions used to determine which urls to exclude from adjustment.
|
37
|
+
def adjust_urls_except=(adjust_urls_except)
|
38
|
+
Links.adjust_urls_except = adjust_urls_except
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
def content
|
46
|
-
return MissingSnipprTag unless File.exist? file
|
47
|
-
|
48
|
-
content = File.read(file).strip
|
49
|
-
insert_dynamics content
|
50
|
-
linkify content
|
51
|
-
end
|
41
|
+
# Sets the logger to use.
|
42
|
+
attr_writer :logger
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
44
|
+
# Returns the logger. Uses the Rails logger when available or falls back to a custom logger.
|
45
|
+
def logger
|
46
|
+
@logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
47
|
+
end
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
49
|
+
# Expects the name of a snippr file. Also accepts a Hash of placeholders
|
50
|
+
# to be replaced with dynamic values.
|
51
|
+
def load(*args)
|
52
|
+
Snip.new(*args)
|
53
|
+
end
|
62
54
|
|
55
|
+
# Lists all snips inside a snippr directory specified by path parts.
|
56
|
+
def list(*args)
|
57
|
+
Path.list *args
|
63
58
|
end
|
59
|
+
|
64
60
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# = Snippr::ViewHelper
|
2
|
+
#
|
3
|
+
# This module is automatically included into +ActionView::Base+ when using the Snippr
|
4
|
+
# component with Rails. It provides a +snippr+ helper method for loading snippr files.
|
5
|
+
#
|
6
|
+
# %h1 Topup successful
|
7
|
+
# .topup.info
|
8
|
+
# = snippr :topup, :success
|
9
|
+
# %h1 Conditional output
|
10
|
+
# - snippr :topup, :conditional_snippr do |snip|
|
11
|
+
# #cond= snip
|
12
|
+
module Snippr
|
13
|
+
module ViewHelper
|
14
|
+
|
15
|
+
# Returns a snippr specified via +args+.
|
16
|
+
def snippr(*args)
|
17
|
+
snip = Snip.new *add_view_to_snippr_args(args)
|
18
|
+
content = snip.content.html_safe
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
if snip.missing? || snip.blank?
|
22
|
+
concat content
|
23
|
+
elsif content.strip.present?
|
24
|
+
yield content
|
25
|
+
end
|
26
|
+
0
|
27
|
+
else
|
28
|
+
extend_snip_content(content, snip)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def snippr_with_path(*args, &block)
|
33
|
+
path = if controller_name == "pages"
|
34
|
+
params[:id].split('/')
|
35
|
+
else
|
36
|
+
[controller_name, params[:action]]
|
37
|
+
end.compact.map { |e| e.to_s.camelize(:lower).to_sym }
|
38
|
+
snippr(*(path + args), &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def add_view_to_snippr_args(args)
|
44
|
+
variables = args.last.kind_of?(Hash) ? args.pop : {}
|
45
|
+
variables[:view] = self
|
46
|
+
args << variables
|
47
|
+
args
|
48
|
+
end
|
49
|
+
|
50
|
+
def extend_snip_content(content, snip)
|
51
|
+
content.class_eval %(
|
52
|
+
def missing?
|
53
|
+
#{snip.missing?}
|
54
|
+
end
|
55
|
+
def exists?
|
56
|
+
#{!snip.missing?}
|
57
|
+
end
|
58
|
+
def meta(key = nil)
|
59
|
+
meta = #{snip.meta.inspect}
|
60
|
+
key ? meta[key] : meta
|
61
|
+
end
|
62
|
+
)
|
63
|
+
content
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if defined? ActionView::Base
|
70
|
+
ActionView::Base.send :include, Snippr::ViewHelper
|
71
|
+
end
|
data/snippr.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = "snippr"
|
4
|
+
s.version = "0.13.1"
|
5
|
+
s.date = Time.now
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = ["Daniel Harrington", "Thomas Jachmann"]
|
8
|
+
s.email = ["me@rubiii.com", "self@thomasjachmann.com"]
|
9
|
+
s.homepage = "http://github.com/blaulabs/snippr"
|
10
|
+
s.summary = %q{File based content management}
|
11
|
+
s.description = %q{This gem provides ways to access file based cms resources from a rails app.}
|
12
|
+
|
13
|
+
s.rubyforge_project = "snippr"
|
14
|
+
|
15
|
+
s.add_runtime_dependency "i18n"
|
16
|
+
s.add_runtime_dependency "activesupport"
|
17
|
+
|
18
|
+
s.add_development_dependency "ci_reporter", "~> 1.6.5"
|
19
|
+
s.add_development_dependency "rspec", "~> 2.6.0"
|
20
|
+
s.add_development_dependency "mocha", "0.9.12"
|
21
|
+
s.add_development_dependency "rake", "~> 0.9.0"
|
22
|
+
# pin down ZenTest so that autotest works without upgrading rubygems
|
23
|
+
# see http://stackoverflow.com/questions/6802610/autotest-problem [mw, 2011-08-10]
|
24
|
+
s.add_development_dependency "ZenTest", "4.5.0"
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
a snippet
|
@@ -0,0 +1 @@
|
|
1
|
+
a snippet with param {param}
|
@@ -0,0 +1 @@
|
|
1
|
+
SNIPPET
|
File without changes
|