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
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# Snippr
|
2
|
+
## File based content management
|
3
|
+
|
4
|
+
A snippr file is a piece of HTML or raw text to be included in a website. They are plain text
|
5
|
+
files stored on the file system. Snippr files end with ".snip" and are read from the Snippr path.
|
6
|
+
|
7
|
+
## Snippr path
|
8
|
+
|
9
|
+
You need to specify the path to the directory where your Snippr files are stored:
|
10
|
+
|
11
|
+
Snippr.path = File.join File.dirname(__FILE__), "..", "snippr"
|
12
|
+
|
13
|
+
When running on JRuby, you can also set the path via JVM properties. The property you need to
|
14
|
+
specify is defined in Snippr::Path::JVMProperty. This allows system administrators to change the
|
15
|
+
path without having to touch your application.
|
16
|
+
|
17
|
+
## Loading a snippr
|
18
|
+
|
19
|
+
To load a snippr file, you can use the +load+ method, passing in the path to the snippr file as
|
20
|
+
a String (including path separators):
|
21
|
+
|
22
|
+
Snippr.load "tariff/einheit"
|
23
|
+
|
24
|
+
or by using multiple Strings or Symbols:
|
25
|
+
|
26
|
+
Snippr.load :tariff, :einheit
|
27
|
+
|
28
|
+
### Dynamic values
|
29
|
+
|
30
|
+
A snippr file may contain placeholders to be replaced with dynamic values. Placeholders are
|
31
|
+
wrapped in curly braces.
|
32
|
+
|
33
|
+
<p>You're topup of {topup_amount} at {date_today} was successful.</p>
|
34
|
+
|
35
|
+
To replace both {topup_amount} and {date_today} with a dynamic value, you just pass in a Hash of
|
36
|
+
placeholders and dynamic values when loading a snippr file.
|
37
|
+
|
38
|
+
Snippr.load :topup, :success, :topup_amount => number_to_currency(15), :date_today => Date.today
|
39
|
+
|
40
|
+
The result will obviously be something like:
|
41
|
+
|
42
|
+
<p>You're topup of 15,00 € at 2010-04-03 was successful.</p>
|
43
|
+
|
44
|
+
### calling methods on passed variables
|
45
|
+
|
46
|
+
You can call methods on passed parameters. Calling this:
|
47
|
+
|
48
|
+
class Klazz
|
49
|
+
def doit; "HELLO"; end
|
50
|
+
end
|
51
|
+
Snippr.load :snip :a_variable => Klass.new
|
52
|
+
|
53
|
+
on ...
|
54
|
+
|
55
|
+
<p>Snippr says: {a_variable.doit}</p>
|
56
|
+
|
57
|
+
will yield:
|
58
|
+
|
59
|
+
<p>Snippr says: HELLO</p>
|
60
|
+
|
61
|
+
You can even pass parameters to the call. Those *must* be enclosed in quotes ("):
|
62
|
+
|
63
|
+
class Klazz
|
64
|
+
def doitagain(p); "HELLO #{p}"; end
|
65
|
+
end
|
66
|
+
Snippr.load :snip :a_variable => Klass.new
|
67
|
+
|
68
|
+
on ...
|
69
|
+
|
70
|
+
<p>Snippr says: {a_variable.doitagain("SNIPPR")}</p>
|
71
|
+
|
72
|
+
will yield:
|
73
|
+
|
74
|
+
<p>Snippr says: HELLO SNIPPR</p>
|
75
|
+
|
76
|
+
### Meta Infos
|
77
|
+
|
78
|
+
A snippet can not only hold content but also meta infos for this snippet.
|
79
|
+
|
80
|
+
Inspired by [jekyll](http://jekyllrb.com) a snippet can host metdata that are accessable via the `.meta` method on a loaded snippet.
|
81
|
+
`.meta' will return an empty hash when no data was found.
|
82
|
+
|
83
|
+
Metadata must be placed at the top of the snippet and is delimited with three dashed.
|
84
|
+
The data itself is parsed as YAML:
|
85
|
+
|
86
|
+
---
|
87
|
+
a_yaml: hash
|
88
|
+
---
|
89
|
+
normal snippet content comes here until the end of the file
|
90
|
+
|
91
|
+
### Including snippr files inside other files
|
92
|
+
|
93
|
+
A snippr file can include another snippr file:
|
94
|
+
|
95
|
+
This snippr file includes another {snip:filepath/of/snip} file
|
96
|
+
|
97
|
+
This will cause `filepath/of/snip.snip` to be included in place.
|
98
|
+
|
99
|
+
Dynamic values of the parent snip will be accessable inside the included snip file.
|
100
|
+
|
101
|
+
You can pass additional dynamic values when using `{snip}`. These will override any parent parameter.
|
102
|
+
|
103
|
+
{snip:filepath/of/snip,dyn_key1=dyn_value,dyn_key2=dyn_value2}
|
104
|
+
|
105
|
+
Those will be available as {dyn_key1} and {dyn_key2} in filepath/of/snip.snip
|
106
|
+
|
107
|
+
## I18n
|
108
|
+
|
109
|
+
Snippr comes with support for I18n, but up until further notice, you have to manually enable this
|
110
|
+
behavior in your application.
|
111
|
+
|
112
|
+
Snippr.i18n = true
|
113
|
+
|
114
|
+
Afterwards Snippr uses the locale specified via I18n and automatically prepends the current locale
|
115
|
+
prefixed with a "_" to your snippr files.
|
116
|
+
|
117
|
+
I18n.locale = :de
|
118
|
+
Snippr.load :shop # tries to load "shop_de.snip" relative to your Snippr path
|
119
|
+
|
120
|
+
I18n.locale = :en
|
121
|
+
Snippr.load :shop # tries to load "shop_en.snip" relative to your Snippr path
|
122
|
+
|
123
|
+
## Wiki Syntax
|
124
|
+
|
125
|
+
Until now, only wiki links with text are supported by Snippr:
|
126
|
+
|
127
|
+
[[http://www.blaulabs.de|blaulabs]]
|
128
|
+
|
129
|
+
will be converted to:
|
130
|
+
|
131
|
+
<a href="http://www.blaulabs.de">blaulabs</a>
|
132
|
+
|
133
|
+
## Rails Helper
|
134
|
+
|
135
|
+
When using the Snippr module with Rails, it automatically adds the +Snippr::Helper+ module to
|
136
|
+
your views. You can then use the +snippr+ helper method to load snippr files.
|
137
|
+
|
138
|
+
%h1 Topup successful
|
139
|
+
.topup.info
|
140
|
+
= snippr :topup, :success
|
141
|
+
|
142
|
+
## Build Status
|
143
|
+

|
data/Rakefile
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
require "rubygems"
|
1
2
|
require "rake"
|
2
|
-
require "spec/rake/spectask"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'ci/reporter/rake/rspec'
|
6
|
+
RSpec::Core::RakeTask.new :spec
|
7
|
+
task :default => %w(ci:setup:rspec spec)
|
7
8
|
|
8
9
|
begin
|
9
10
|
require "hanna/rdoctask"
|
data/lib/snippr.rb
CHANGED
@@ -1,2 +1,14 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
Dir[File.expand_path '../snippr/*.rb', __FILE__].each {|f| require f}
|
4
|
+
Dir[File.expand_path '../snippr/normalizer/*.rb', __FILE__].each {|f| require f}
|
5
|
+
Dir[File.expand_path '../snippr/processor/*.rb', __FILE__].each {|f| require f}
|
6
|
+
|
7
|
+
Snippr::Normalizer.normalizers << Snippr::Normalizer::Camelizer.new
|
8
|
+
# don't use DeRester this for all apps, but configure it as needed
|
9
|
+
# Snippr::Normalizer.normalizers << Snippr::Normalizer::DeRester.new
|
10
|
+
|
11
|
+
Snippr::Processor.processors << Snippr::Processor::Functions.new
|
12
|
+
Snippr::Processor.processors << Snippr::Processor::Dynamics.new
|
13
|
+
Snippr::Processor.processors << Snippr::Processor::Links.new
|
14
|
+
Snippr::Processor.processors << Snippr::Processor::Wikilinks.new
|
data/lib/snippr/i18n.rb
CHANGED
@@ -2,25 +2,24 @@ require "i18n"
|
|
2
2
|
|
3
3
|
# = Snippr::I18n
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Provides support for I18n snippr files.
|
6
6
|
module Snippr
|
7
7
|
module I18n
|
8
8
|
|
9
|
-
#
|
10
|
-
def
|
11
|
-
|
9
|
+
# Returns whether to use I18n snippr files.
|
10
|
+
def self.enabled?
|
11
|
+
!!@@enabled
|
12
12
|
end
|
13
13
|
|
14
|
-
#
|
15
|
-
def
|
16
|
-
|
14
|
+
# Sets whether to use I18n snippr files.
|
15
|
+
def self.enabled=(enabled)
|
16
|
+
@@enabled = enabled
|
17
17
|
end
|
18
18
|
|
19
19
|
# Returns the current locale prefixed with a "_" from I18n if I18n is enabled.
|
20
20
|
# Otherwise defaults to an empty String.
|
21
|
-
def locale
|
22
|
-
|
23
|
-
["_", ::I18n.locale].join
|
21
|
+
def self.locale(enabled=nil)
|
22
|
+
(enabled.nil? ? enabled? : enabled) ? "_#{::I18n.locale}" : ''
|
24
23
|
end
|
25
24
|
|
26
25
|
end
|
data/lib/snippr/links.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# = Snippr::LinkHelper
|
2
|
+
#
|
3
|
+
# This module can be included to get functionality to adjust links.
|
4
|
+
module Snippr
|
5
|
+
module Links
|
6
|
+
|
7
|
+
HREF_REGEX = /(href *= *['"])([^'"]*)(['"])/i
|
8
|
+
|
9
|
+
# Returns the regular expressions used to determine which urls to exclude from adjustment.
|
10
|
+
def self.adjust_urls_except
|
11
|
+
@@adjust_urls_except ||= [/^#/, /^[a-z]+:/i]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sets the regular expressions used to determine which urls to exclude from adjustment.
|
15
|
+
def self.adjust_urls_except=(adjust_urls_except)
|
16
|
+
@@adjust_urls_except = adjust_urls_except
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adjusts a complete anchor tag, allowing the custom protocol popup: which will be converted to a javascript call to popup(this).
|
20
|
+
def self.adjust_link(link)
|
21
|
+
return link if link !~ HREF_REGEX
|
22
|
+
url = $2
|
23
|
+
if url =~ /popup:\/*(.*)$/i
|
24
|
+
url = adjust_url $1
|
25
|
+
onclick = "onclick=\"if (typeof popup == 'undefined') { return true; } else { popup(this); return false; }\""
|
26
|
+
# replace an existing onclick (if present)
|
27
|
+
link_with_onclick = link.gsub /onclick *= *['"][^'"]*['"]/i, onclick
|
28
|
+
# add a new onclick (when there was no existing onclick)
|
29
|
+
link_with_onclick = link.gsub /(^[^>]+)>/, "\\1 #{onclick}>" if link_with_onclick == link
|
30
|
+
link = link_with_onclick
|
31
|
+
else
|
32
|
+
url = adjust_url url
|
33
|
+
end
|
34
|
+
link.gsub HREF_REGEX, "\\1#{url}\\3"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Adjusts an url, prepending / and relative url root (context path) as needed.
|
38
|
+
def self.adjust_url(url)
|
39
|
+
adjust_urls_except.each do |regex|
|
40
|
+
return url if url =~ regex
|
41
|
+
end
|
42
|
+
root = relative_url_root
|
43
|
+
url.gsub(/^(#{root}|\/)?/, root)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the relative url root (context path) the application is deployed to.
|
47
|
+
def self.relative_url_root
|
48
|
+
if defined? ActionController::Base
|
49
|
+
root = ActionController::Base.config.relative_url_root || '/'
|
50
|
+
root = "/#{root}" unless root.start_with?('/')
|
51
|
+
root << '/' unless root.end_with?('/')
|
52
|
+
root
|
53
|
+
else
|
54
|
+
'/'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
# = Snippr::MetaData
|
5
|
+
#
|
6
|
+
# Handles Snippr's YAML Front Matter inspired by Jekyll.
|
7
|
+
# Useful for passing meta information about a Snip to the app.
|
8
|
+
module Snippr
|
9
|
+
|
10
|
+
class MetaData
|
11
|
+
|
12
|
+
def self.extract(name, content)
|
13
|
+
if content =~ /^(---\s*\n.*?\n?)^(---\s*$?)/m
|
14
|
+
content = Regexp.last_match.post_match.strip
|
15
|
+
meta = yaml_load(name, $1)
|
16
|
+
end
|
17
|
+
|
18
|
+
meta = meta ? meta : {}
|
19
|
+
[content, meta]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def self.yaml_load(name, yml)
|
25
|
+
YAML.load(yml)
|
26
|
+
rescue Exception => e
|
27
|
+
Snippr.logger.warn "Unable to extract meta data from Snip #{name.inspect}: #{e.message}"
|
28
|
+
{}
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# = Snippr::Normalizer
|
2
|
+
#
|
3
|
+
# Provides methods to normalize snippr path elements.
|
4
|
+
module Snippr
|
5
|
+
module Normalizer
|
6
|
+
|
7
|
+
# Returns a (modifiable) list of normalizers that'll be used to normalize a path element.
|
8
|
+
def self.normalizers
|
9
|
+
@normalizers ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Sends the given path element to all the configured normalizers and returns the result.
|
13
|
+
def self.normalize(path_element)
|
14
|
+
@normalizers.inject(path_element) {|e, normalizer| normalizer.normalize e}
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# = Snippr::Normalizer::Camelizer
|
2
|
+
#
|
3
|
+
# When given a symbol, normalizes it to a lower camelized string, otherwise just returns the given string.
|
4
|
+
module Snippr
|
5
|
+
|
6
|
+
module Normalizer
|
7
|
+
|
8
|
+
class Camelizer
|
9
|
+
|
10
|
+
def normalize(path_element)
|
11
|
+
path_element.kind_of?(Symbol) ? path_element.to_s.camelize(:lower) : path_element
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# = Snippr::Normalizer::DeRester
|
2
|
+
#
|
3
|
+
# "Redirects" REST path elements that are accessed via POST (create, update destroy) with
|
4
|
+
# their corresponding GET elements (new, edit, show) so that when eg create is rendered due
|
5
|
+
# to an error in the action, it just looks exactly like the new page it was issued from.
|
6
|
+
module Snippr
|
7
|
+
|
8
|
+
module Normalizer
|
9
|
+
|
10
|
+
class DeRester
|
11
|
+
|
12
|
+
def normalize(path_element)
|
13
|
+
case path_element.to_s
|
14
|
+
when "create" then "new"
|
15
|
+
when "update" then "edit"
|
16
|
+
when "destroy" then "show"
|
17
|
+
else path_element.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/snippr/path.rb
CHANGED
@@ -1,25 +1,46 @@
|
|
1
1
|
# = Snippr::Path
|
2
2
|
#
|
3
|
-
#
|
3
|
+
# Provides methods for dealing with the path to snippr files.
|
4
4
|
module Snippr
|
5
5
|
module Path
|
6
6
|
|
7
7
|
# The JVM property to set the path to the snippr files.
|
8
|
-
|
8
|
+
JVM_PROPERTY = 'cms.snippet.path'
|
9
9
|
|
10
10
|
# Returns the path to the snippr files (from JVM properties if available).
|
11
|
-
def path
|
12
|
-
|
11
|
+
def self.path
|
12
|
+
@@path ||= JavaLang::System.get_property(JVM_PROPERTY) rescue ""
|
13
13
|
end
|
14
14
|
|
15
15
|
# Sets the path to the snippr files.
|
16
|
-
def path=(path)
|
17
|
-
|
16
|
+
def self.path=(path)
|
17
|
+
@@path = path.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
# Builds a snippr name from an array of path parts.
|
21
|
+
def self.normalize_name(*names)
|
22
|
+
names.map do |name|
|
23
|
+
Normalizer.normalize(name)
|
24
|
+
end.join("/")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Builds a snippr path (inside the configured path) from a name and an optional extension.
|
28
|
+
def self.path_from_name(name, ext = nil)
|
29
|
+
File.join(path, (ext ? "#{name}.#{ext}" : name))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Lists all snips inside a snippr directory specified by path parts.
|
33
|
+
def self.list(*names)
|
34
|
+
dir = path_from_name normalize_name *names
|
35
|
+
Dir["#{dir}/*#{I18n.locale}.#{Snip::FILE_EXTENSION}"].map do |snip|
|
36
|
+
snip.gsub(/^.*\/([^\.]+)?\.#{Snip::FILE_EXTENSION}$/, '\1').gsub(/_.*$/, '').underscore
|
37
|
+
end.sort.map(&:to_sym)
|
18
38
|
end
|
19
39
|
|
20
40
|
private
|
21
41
|
|
22
42
|
if RUBY_PLATFORM =~ /java/
|
43
|
+
require 'java'
|
23
44
|
module JavaLang
|
24
45
|
include_package "java.lang"
|
25
46
|
end
|