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.
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