snippr 0.3.0 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/README.md +143 -0
  6. data/Rakefile +5 -4
  7. data/lib/snippr.rb +14 -2
  8. data/lib/snippr/i18n.rb +9 -10
  9. data/lib/snippr/links.rb +59 -0
  10. data/lib/snippr/meta_data.rb +33 -0
  11. data/lib/snippr/normalizer.rb +18 -0
  12. data/lib/snippr/normalizer/camelizer.rb +18 -0
  13. data/lib/snippr/normalizer/de_rester.rb +25 -0
  14. data/lib/snippr/path.rb +27 -6
  15. data/lib/snippr/processor.rb +18 -0
  16. data/lib/snippr/processor/dynamics.rb +31 -0
  17. data/lib/snippr/processor/functions.rb +50 -0
  18. data/lib/snippr/processor/links.rb +20 -0
  19. data/lib/snippr/processor/wikilinks.rb +20 -0
  20. data/lib/snippr/snip.rb +57 -0
  21. data/lib/snippr/snippr.rb +41 -45
  22. data/lib/snippr/view_helper.rb +71 -0
  23. data/snippr.gemspec +30 -0
  24. data/spec/fixtures/a/path/aSnippet.snip +1 -0
  25. data/spec/fixtures/a/path/aSnippetWithParam.snip +1 -0
  26. data/spec/fixtures/controller/action/aSnippet.snip +1 -0
  27. data/spec/fixtures/empty.snip +3 -0
  28. data/spec/fixtures/i18n/list_de.snip +0 -0
  29. data/spec/fixtures/meta/broken.snip +5 -0
  30. data/spec/fixtures/meta/withContent.snip +5 -0
  31. data/spec/fixtures/meta/withContentNoNewline.snip +4 -0
  32. data/spec/fixtures/meta/withNoContent.snip +4 -0
  33. data/spec/fixtures/withUnderscore/andUnderscore/aSnippet.snip +1 -0
  34. data/spec/fixtures/withViewHelperMethod.snip +1 -0
  35. data/spec/snippr/i18n_spec.rb +30 -0
  36. data/spec/snippr/links_spec.rb +137 -0
  37. data/spec/snippr/normalizer/camelizer_spec.rb +13 -0
  38. data/spec/snippr/normalizer/de_rester_spec.rb +24 -0
  39. data/spec/snippr/normalizer_spec.rb +40 -0
  40. data/spec/snippr/path_spec.rb +87 -0
  41. data/spec/snippr/processor/dynamics_spec.rb +49 -0
  42. data/spec/snippr/processor/functions_spec.rb +72 -0
  43. data/spec/snippr/processor/links_spec.rb +12 -0
  44. data/spec/snippr/processor/wikilinks_spec.rb +12 -0
  45. data/spec/snippr/processor_spec.rb +35 -0
  46. data/spec/snippr/snip_spec.rb +179 -0
  47. data/spec/snippr/snippr_spec.rb +60 -55
  48. data/spec/snippr/view_helper_spec.rb +221 -0
  49. data/spec/spec_helper.rb +17 -3
  50. metadata +178 -87
  51. data/README.rdoc +0 -77
  52. data/lib/snippr/core_ext.rb +0 -12
  53. data/lib/snippr/helper.rb +0 -23
  54. data/lib/snippr/link.rb +0 -26
  55. data/spec/fixtures/tariff/einheit.snip +0 -1
  56. data/spec/fixtures/wiki.snip +0 -1
  57. data/spec/snippr/core_ext_spec.rb +0 -11
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ .bundle
2
+ .DS_Store
3
+ nbproject
4
+ pkg
5
+ doc
6
+ coverage
7
+ .loadpath
8
+ .project
9
+ *~
10
+ *.gem
11
+ spec/reports
12
+ Gemfile.lock
13
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - jruby-18mode # JRuby in 1.8 mode
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ notifications:
8
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in snippr.gemspec
4
+ gemspec
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 &euro; 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
+ ![Travis-CI](https://secure.travis-ci.org/blaulabs/snippr.png)
data/Rakefile CHANGED
@@ -1,9 +1,10 @@
1
+ require "rubygems"
1
2
  require "rake"
2
- require "spec/rake/spectask"
3
3
 
4
- task :default => :spec
5
-
6
- Spec::Rake::SpecTask.new
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 "snippr/snippr"
2
- require "snippr/helper"
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
- # Extends the Snippr module adding support for I18n snippr files.
5
+ # Provides support for I18n snippr files.
6
6
  module Snippr
7
7
  module I18n
8
8
 
9
- # Sets whether to use I18n snippr files.
10
- def i18n=(enabled)
11
- @enabled = enabled
9
+ # Returns whether to use I18n snippr files.
10
+ def self.enabled?
11
+ !!@@enabled
12
12
  end
13
13
 
14
- # Returns whether to use I18n snippr files.
15
- def i18n?
16
- !!@enabled
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
- return "" unless i18n?
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
@@ -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
- # Extends the Snippr module with methods dealing the path to the snippr files.
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
- JVMProperty = "cms.snippet.path"
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
- @path ||= JavaLang::System.get_property(JVMProperty) rescue ""
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
- @path = path.to_s
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