liquid_markdown 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45f8086f20ee4250420ca3654c2d33fa6def1938
4
+ data.tar.gz: 4b5765a5d6bbe9925b559321459acbab7dfc6663
5
+ SHA512:
6
+ metadata.gz: 1f0162db51321fafb8cada8d21a32695f3dd9cd9db3dc33288f03e19ddf4a1b91b3e461ca533747c509ccd1a05ad13a95bac77e39fa4f26620c929c59484f1a6
7
+ data.tar.gz: d2faee0bb5c59f6ed2d0ddc6334840300d8b0519554a682c9480eb674cb0fe737bdeb183b2b60a276b2d910d54a143d83ac7d421f7eef548e1b7684a6ae0a786
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /todo.txt
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.2
5
+ before_install: gem install bundler -v 1.12.4
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at gary@buzzware.com.au. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in liquid_markdown.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Gary McGhee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # LiquidMarkdown
2
+
3
+ Combines [Liquid](https://github.com/Shopify/liquid) and [Markdown](https://daringfireball.net/projects/markdown/) templating
4
+ for generic templating and Rails Mailers.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'liquid_markdown'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install liquid_markdown
21
+
22
+ ## Usage
23
+
24
+ You can use `liquid_markdown` in your mailer with `.liqmd` file extension
25
+
26
+ ```ruby
27
+ # app/mailers/user_mailer.rb
28
+ class UserMailer < ApplicationMailer
29
+ def welcome(user)
30
+ @user = user
31
+ @lmVariables = @user.values
32
+
33
+ mail(to: @user.email, subject: 'liquid markdown layout') do |format|
34
+ format.html
35
+ format.text
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+ # app/views/user_mailer/welcome.liqmd
42
+
43
+ # Hello Admin
44
+
45
+ Below are the list of products that you purchased
46
+
47
+ <ul id="products">
48
+ <li>
49
+ <h2>{{ product.name }}</h2>
50
+ Only {{ product.price | price }}
51
+ </li>
52
+ </ul>
53
+
54
+ Thanks
55
+ ------
56
+ ABC XYZ
57
+ ```
58
+
59
+ We can compile Liquid templates manually using `html` to convert into html format and `text` to convert into plain text.
60
+
61
+ ```ruby
62
+ lm = LiquidMarkdown::Render.new("Hello {{user.profile.name}}!", {user: {profile: {name: 'Bob'}}})
63
+ lm.html # => "<p>Hello Bob!</p>"
64
+ lm.text # => "Hello Bob!"
65
+ ```
66
+
67
+ ```ruby
68
+ lm = LiquidMarkdown::Render.new("# my first heading")
69
+ lm.html # => "<h1>my first heading</h1>"
70
+ lm.text # => "my first heading"
71
+ ```
72
+
73
+ We can combine both Liquid and Markdown together, Liquid will get compiled first and then Markdown will get compiled
74
+
75
+ ```ruby
76
+ lm = LiquidMarkdown::Render.new("# Hello {{username | upcase}}", {username: 'Admin'})
77
+ lm.html # => "<h1>Hello ADMIN</h1>"
78
+ lm.text # => "Hello ADMIN"
79
+ ```
80
+
81
+ ## Depricated (need to remove this)
82
+ We can also setup layout options to wrap result within that layout. use `{{yield}}` block in your template where we can render output.
83
+
84
+ ```ruby
85
+ lm = LiquidMarkdown::Render.new("# Hello {{username | upcase}}", {username: 'Admin'})
86
+ lm.layout = "<html><head></head><body>{{yield}}</body></html>"
87
+ lm.html # => "<html><head></head><body><h1>Hello ADMIN</h1></body></html>"
88
+ ```
89
+
90
+ ## Development
91
+
92
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
93
+
94
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
95
+
96
+ ## Contributing
97
+
98
+ Bug reports and pull requests are welcome on GitHub at https://github.com/buzzware/liquid_markdown. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
99
+
100
+
101
+ ## License
102
+
103
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
104
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # https://github.com/gettalong/kramdown/pull/219/commits/8dbaf6e2987b283cf82594bae4e95c7ebd5d422d
4
+ #--
5
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
6
+ #
7
+ #
8
+ # This file is part of kramdown which is licensed under the MIT.
9
+ #++
10
+ #
11
+
12
+ require 'kramdown'
13
+ require 'kramdown/converter'
14
+
15
+ module Kramdown
16
+ module Converter
17
+
18
+ # Converts tree to plain text. Removes all formatting and attributes.
19
+ # This converter can be used to generate clean text for use in meta tags,
20
+ # plain text emails, etc.
21
+ class PlainText < Base
22
+
23
+ TEXT_TYPES ||= [
24
+ :smart_quote,
25
+ :typographic_sym,
26
+ :entity,
27
+ :text
28
+ ].freeze
29
+
30
+ def initialize(root, options)
31
+ super
32
+ @plain_text = '' # bin for plain text
33
+ end
34
+
35
+ def convert(el)
36
+ type = el.type
37
+ category = ::Kramdown::Element.category(el)
38
+
39
+ @plain_text << convert_type(type, el) if TEXT_TYPES.include?(type)
40
+ @plain_text << "\n" if category == :block
41
+
42
+ el.children.each { |e| convert(e) }
43
+
44
+ @plain_text.strip if type == :root
45
+ end
46
+
47
+ def convert_type(type, el)
48
+ send("convert_#{type}", el)
49
+ end
50
+
51
+ def convert_text(el)
52
+ el.value
53
+ end
54
+
55
+ def convert_entity(el)
56
+ el.value.char
57
+ end
58
+
59
+ def convert_smart_quote(el)
60
+ smart_quote_entity(el).char
61
+ end
62
+
63
+ def convert_typographic_sym(el)
64
+ ::Kramdown::Converter::Html::TYPOGRAPHIC_SYMS[el.value]
65
+ .map(&:char)
66
+ .join('')
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,173 @@
1
+ # Extracted from rails
2
+ # https://raw.githubusercontent.com/rails/rails/master/activesupport/lib/active_support/core_ext/hash/keys.rb
3
+
4
+ class Hash
5
+ # Returns a new hash with all keys converted using the +block+ operation.
6
+ #
7
+ # hash = { name: 'Rob', age: '28' }
8
+ #
9
+ # hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
10
+ #
11
+ # If you do not provide a +block+, it will return an Enumerator
12
+ # for chaining with other methods:
13
+ #
14
+ # hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
15
+ def transform_keys
16
+ return enum_for(:transform_keys) { size } unless block_given?
17
+ result = {}
18
+ each_key do |key|
19
+ result[yield(key)] = self[key]
20
+ end
21
+ result
22
+ end
23
+
24
+ # Destructively converts all keys using the +block+ operations.
25
+ # Same as +transform_keys+ but modifies +self+.
26
+ def transform_keys!
27
+ return enum_for(:transform_keys!) { size } unless block_given?
28
+ keys.each do |key|
29
+ self[yield(key)] = delete(key)
30
+ end
31
+ self
32
+ end
33
+
34
+ # Returns a new hash with all keys converted to strings.
35
+ #
36
+ # hash = { name: 'Rob', age: '28' }
37
+ #
38
+ # hash.stringify_keys
39
+ # # => {"name"=>"Rob", "age"=>"28"}
40
+ def stringify_keys
41
+ transform_keys(&:to_s)
42
+ end
43
+
44
+ # Destructively converts all keys to strings. Same as
45
+ # +stringify_keys+, but modifies +self+.
46
+ def stringify_keys!
47
+ transform_keys!(&:to_s)
48
+ end
49
+
50
+ # Returns a new hash with all keys converted to symbols, as long as
51
+ # they respond to +to_sym+.
52
+ #
53
+ # hash = { 'name' => 'Rob', 'age' => '28' }
54
+ #
55
+ # hash.symbolize_keys
56
+ # # => {:name=>"Rob", :age=>"28"}
57
+ def symbolize_keys
58
+ transform_keys { |key| key.to_sym rescue key }
59
+ end
60
+ alias_method :to_options, :symbolize_keys
61
+
62
+ # Destructively converts all keys to symbols, as long as they respond
63
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
64
+ def symbolize_keys!
65
+ transform_keys! { |key| key.to_sym rescue key }
66
+ end
67
+ alias_method :to_options!, :symbolize_keys!
68
+
69
+ # Validates all keys in a hash match <tt>*valid_keys</tt>, raising
70
+ # +ArgumentError+ on a mismatch.
71
+ #
72
+ # Note that keys are treated differently than HashWithIndifferentAccess,
73
+ # meaning that string and symbol keys will not match.
74
+ #
75
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
76
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
77
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
78
+ def assert_valid_keys(*valid_keys)
79
+ valid_keys.flatten!
80
+ each_key do |k|
81
+ unless valid_keys.include?(k)
82
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
83
+ end
84
+ end
85
+ end
86
+
87
+ # Returns a new hash with all keys converted by the block operation.
88
+ # This includes the keys from the root hash and from all
89
+ # nested hashes and arrays.
90
+ #
91
+ # hash = { person: { name: 'Rob', age: '28' } }
92
+ #
93
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
94
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
95
+ def deep_transform_keys(&block)
96
+ _deep_transform_keys_in_object(self, &block)
97
+ end
98
+
99
+ # Destructively converts all keys by using the block operation.
100
+ # This includes the keys from the root hash and from all
101
+ # nested hashes and arrays.
102
+ def deep_transform_keys!(&block)
103
+ _deep_transform_keys_in_object!(self, &block)
104
+ end
105
+
106
+ # Returns a new hash with all keys converted to strings.
107
+ # This includes the keys from the root hash and from all
108
+ # nested hashes and arrays.
109
+ #
110
+ # hash = { person: { name: 'Rob', age: '28' } }
111
+ #
112
+ # hash.deep_stringify_keys
113
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
114
+ def deep_stringify_keys
115
+ deep_transform_keys(&:to_s)
116
+ end
117
+
118
+ # Destructively converts all keys to strings.
119
+ # This includes the keys from the root hash and from all
120
+ # nested hashes and arrays.
121
+ def deep_stringify_keys!
122
+ deep_transform_keys!(&:to_s)
123
+ end
124
+
125
+ # Returns a new hash with all keys converted to symbols, as long as
126
+ # they respond to +to_sym+. This includes the keys from the root hash
127
+ # and from all nested hashes and arrays.
128
+ #
129
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
130
+ #
131
+ # hash.deep_symbolize_keys
132
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
133
+ def deep_symbolize_keys
134
+ deep_transform_keys { |key| key.to_sym rescue key }
135
+ end
136
+
137
+ # Destructively converts all keys to symbols, as long as they respond
138
+ # to +to_sym+. This includes the keys from the root hash and from all
139
+ # nested hashes and arrays.
140
+ def deep_symbolize_keys!
141
+ deep_transform_keys! { |key| key.to_sym rescue key }
142
+ end
143
+
144
+ private
145
+ # support methods for deep transforming nested hashes and arrays
146
+ def _deep_transform_keys_in_object(object, &block)
147
+ case object
148
+ when Hash
149
+ object.each_with_object({}) do |(key, value), result|
150
+ result[yield(key)] = _deep_transform_keys_in_object(value, &block)
151
+ end
152
+ when Array
153
+ object.map { |e| _deep_transform_keys_in_object(e, &block) }
154
+ else
155
+ object
156
+ end
157
+ end
158
+
159
+ def _deep_transform_keys_in_object!(object, &block)
160
+ case object
161
+ when Hash
162
+ object.keys.each do |key|
163
+ value = object.delete(key)
164
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
165
+ end
166
+ object
167
+ when Array
168
+ object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
169
+ else
170
+ object
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,15 @@
1
+ class String
2
+ # Returns a new string after stripping all html tags
3
+ #
4
+ # string = "<hello>threre</hello>"
5
+ #
6
+ # string.strip_html_tags => "there"
7
+ def strip_html_tags
8
+ empty = ''.freeze
9
+ self.to_s
10
+ .gsub(/<script.*?<\/script>/m, empty)
11
+ .gsub(/<!--.*?-->/m, empty)
12
+ .gsub(/<style.*?<\/style>/m, empty)
13
+ .gsub(/<.*?>/m, empty)
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module TextFilter
2
+ def strip_html(input)
3
+ input.strip_html_tags
4
+ end
5
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright 2007 by Domizio Demichelis
2
+ # This library is free software. It may be used, redistributed and/or modified
3
+ # under the same terms as Ruby itself
4
+ #
5
+ # This extension is usesd in order to expose the object of the implementing class
6
+ # to liquid as it were a Drop. It also limits the liquid-callable methods of the instance
7
+ # to the allowed method passed with the liquid_methods call
8
+ # Example:
9
+ #
10
+ # class SomeClass
11
+ # liquid_methods :an_allowed_method
12
+ #
13
+ # def an_allowed_method
14
+ # 'this comes from an allowed method'
15
+ # end
16
+ # def unallowed_method
17
+ # 'this will never be an output'
18
+ # end
19
+ # end
20
+ #
21
+ # if you want to extend the drop to other methods you can defines more methods
22
+ # in the class <YourClass>::LiquidDropClass
23
+ #
24
+ # class SomeClass::LiquidDropClass
25
+ # def another_allowed_method
26
+ # 'and this from another allowed method'
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # usage:
32
+ # @something = SomeClass.new
33
+ #
34
+ # template:
35
+ # {{something.an_allowed_method}}{{something.unallowed_method}} {{something.another_allowed_method}}
36
+ #
37
+ # output:
38
+ # 'this comes from an allowed method and this from another allowed method'
39
+ #
40
+ # You can also chain associations, by adding the liquid_method call in the
41
+ # association models.
42
+ #
43
+ class Module
44
+
45
+ def liquid_methods(*allowed_methods)
46
+ drop_class = eval "class #{self.to_s}::LiquidDropClass < Liquid::Drop; self; end"
47
+ define_method :to_liquid do
48
+ drop_class.new(self)
49
+ end
50
+ drop_class.class_eval do
51
+ def initialize(object)
52
+ @object = object
53
+ end
54
+ allowed_methods.each do |sym|
55
+ define_method sym do
56
+ @object.send sym
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,45 @@
1
+ module LiquidMarkdown
2
+ class Render
3
+ # setup your html layout layout to wrap around your LiquidMarkdown output
4
+ # layout = "<html><head></head><body>{{yield}}</body></html>"
5
+ attr_reader :template, :liquid_hash, :global_filter_proc
6
+ attr_writer :layout
7
+ attr_accessor :markdown_settings, :liquid_settings
8
+
9
+ def initialize(template, liquid_hash={})
10
+ @template = template
11
+ @liquid_hash = liquid_hash
12
+ @markdown_settings = {auto_ids: false, parse_block_html: true}
13
+ @liquid_settings = {strict_filters: true, strict_variables: true}
14
+ @global_filter_proc = ->(output) { output.is_a?(String) ? output.strip_html_tags : output }
15
+ end
16
+
17
+ def html
18
+ rendered_content = markdown(liquidize)
19
+ insert_into_template(rendered_content.to_html)
20
+ end
21
+
22
+ def text
23
+ rendered_content = markdown(liquidize)
24
+ rendered_content.to_plain_text
25
+ end
26
+
27
+ def markdown(template_value)
28
+ Kramdown::Document.new(template_value, @markdown_settings)
29
+ end
30
+
31
+ def liquidize
32
+ Liquid::Template.parse(@template)
33
+ .render(@liquid_hash, @liquid_settings, global_filter: @global_filter_proc)
34
+ end
35
+
36
+ def insert_into_template(rendered_content)
37
+ return rendered_content if layout == ''
38
+ layout.sub('{{yield}}', rendered_content)
39
+ end
40
+
41
+ def layout
42
+ @layout ||= ''
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,83 @@
1
+ require 'panoramic/orm/active_record'
2
+
3
+ module LiquidMarkdown
4
+ class Resolver < ActionView::Resolver
5
+ require 'singleton'
6
+ include Singleton
7
+
8
+ # this method is mandatory to implement a Resolver
9
+ def find_templates(name, prefix, partial, details, key=nil, locals=[])
10
+ return [] if @@resolver_options[:only] && !@@resolver_options[:only].include?(prefix)
11
+
12
+ conditions = {
13
+ :path => build_path(name, prefix),
14
+ :locale => [normalize_array(details[:locale]).first, nil],
15
+ :format => normalize_array(details[:formats]),
16
+ :handler => normalize_array(details[:handlers]),
17
+ :partial => partial || false
18
+ }
19
+
20
+ @records = []
21
+ @@model.find_model_templates(conditions).map do |record|
22
+ @records << record
23
+ if record.format == 'html'
24
+ rec = OpenStruct.new(record.attributes)
25
+ rec.format = 'text'
26
+ @records << rec
27
+ else
28
+ rec = OpenStruct.new(record.attributes)
29
+ rec.format = 'html'
30
+ @records << rec
31
+ end
32
+ end
33
+
34
+ @records.map do |record|
35
+ initialize_template(record, record.format)
36
+ end
37
+ end
38
+
39
+ # Instantiate Resolver by passing a model (decoupled from ORMs)
40
+ def self.using(model, options={})
41
+ @@model = model
42
+ @@resolver_options = options
43
+ self.instance
44
+ end
45
+
46
+ private
47
+
48
+ # Initialize an ActionView::Template object based on the record found.
49
+ def initialize_template(record, format)
50
+ source = record.body
51
+ identifier = "#{record.class} - #{record.id} - #{record.path.inspect} (#{format})"
52
+ handler = ActionView::Template.registered_template_handler(record.handler)
53
+
54
+ details = {
55
+ :format => Mime[format],
56
+ :updated_at => record.updated_at,
57
+ :virtual_path => virtual_path(record.path, record.partial)
58
+ }
59
+
60
+ ActionView::Template.new(source, identifier, handler, details)
61
+ end
62
+
63
+ # Build path with eventual prefix
64
+ def build_path(name, prefix)
65
+ prefix.present? ? "#{prefix}/#{name}" : name
66
+ end
67
+
68
+ # Normalize array by converting all symbols to strings.
69
+ def normalize_array(array)
70
+ array.map(&:to_s)
71
+ end
72
+
73
+ # returns a path depending if its a partial or template
74
+ def virtual_path(path, partial)
75
+ return path unless partial
76
+ if index = path.rindex("/")
77
+ path.insert(index + 1, "_")
78
+ else
79
+ "_#{path}"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,41 @@
1
+ module LiquidMarkdown
2
+ module TemplateHandler
3
+ UNDERSCORE = '_'.freeze
4
+ OBJECT_ATTRIBUTE_MATCHER = /%\{([a-z0-9_]+\.[a-z0-9_]+)\}/i
5
+
6
+ def self.render(template, context, format)
7
+ variables = expand_variables(template, extract_variables(context))
8
+ liquid_variables = variables.deep_stringify_keys
9
+ lm = LiquidMarkdown::Render.new(template, liquid_variables)
10
+ lm.send(format)
11
+ end
12
+
13
+ def self.expand_variables(template, variables)
14
+ template.scan(OBJECT_ATTRIBUTE_MATCHER)
15
+ .map(&:first)
16
+ .each_with_object(variables) do |match, buffer|
17
+ target, attribute = match.split('.')
18
+ buffer[match.to_sym] = variables[target.to_sym].public_send(attribute)
19
+ end
20
+ end
21
+
22
+ def self.extract_variables(context)
23
+ context
24
+ .instance_variable_get(:@_assigns)
25
+ .each_with_object({}) do |(name, value), buffer|
26
+ next if name.start_with?(UNDERSCORE)
27
+ buffer[name.to_sym] = value
28
+ end
29
+ end
30
+
31
+ class LIQMD
32
+ def self.call(template)
33
+ if template.formats.include?(:html)
34
+ "LiquidMarkdown::TemplateHandler.render(#{template.source.inspect}, self, :html)"
35
+ else
36
+ "LiquidMarkdown::TemplateHandler.render(#{template.source.inspect}, self, :text)"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module LiquidMarkdown
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,21 @@
1
+ module LiquidMarkdown
2
+ require 'kramdown'
3
+ require 'liquid'
4
+ require 'action_view'
5
+ require 'action_mailer'
6
+
7
+ require 'liquid_markdown/core_ext/hash/keys'
8
+ require 'liquid_markdown/core_ext/string/strip'
9
+ require 'liquid_markdown/liquid/liquid_methods'
10
+
11
+ require 'liquid_markdown/filters/text_filter'
12
+ require 'liquid_markdown/converter/plain_text'
13
+
14
+ require 'liquid_markdown/version'
15
+ require 'liquid_markdown/template_handler'
16
+ require 'liquid_markdown/render'
17
+ # require 'liquid_markdown/resolver' # don't automatically require this, as it requires panoramic - leave that for users to require themselves
18
+ end
19
+
20
+ ActionView::Template.register_template_handler :liqmd, LiquidMarkdown::TemplateHandler::LIQMD
21
+ Liquid::Template.register_filter(TextFilter)
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'liquid_markdown/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'liquid_markdown'
8
+ spec.version = LiquidMarkdown::VERSION
9
+ spec.authors = ['Gary McGhee']
10
+ spec.email = ['gary@buzzware.com.au']
11
+
12
+ spec.summary = %q{Combines Liquid and Markdown templating for generic templating and Rails Mailers}
13
+ spec.description = spec.summary
14
+ spec.homepage = 'https://github.com/buzzware/liquid_markdown'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_runtime_dependency 'kramdown', '~> 1.12', '>= 1.12.0'
23
+ spec.add_dependency 'liquid', '~> 4.0', '>= 4.0.0'
24
+ spec.add_dependency 'actionmailer', '>= 4.0'
25
+ spec.add_dependency 'actionview', '>= 4.0'
26
+ spec.add_dependency 'panoramic', '~> 0.0.6'
27
+
28
+ spec.add_development_dependency 'bundler', '~> 1.12'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec', '~> 3.0'
31
+ spec.add_development_dependency 'pry-meta', '~> 0.0.10'
32
+ end
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="FacetManager">
4
+ <facet type="gem" name="Ruby Gem">
5
+ <configuration>
6
+ <option name="GEM_APP_ROOT_PATH" value="$MODULE_DIR$" />
7
+ <option name="GEM_APP_TEST_PATH" value="$MODULE_DIR$/test" />
8
+ <option name="GEM_APP_LIB_PATH" value="$MODULE_DIR$/lib" />
9
+ </configuration>
10
+ </facet>
11
+ </component>
12
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
13
+ <exclude-output />
14
+ <content url="file://$MODULE_DIR$">
15
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
16
+ <excludeFolder url="file://$MODULE_DIR$/.bundle" />
17
+ <excludeFolder url="file://$MODULE_DIR$/vendor/bundle" />
18
+ </content>
19
+ <orderEntry type="jdk" jdkName="RVM: ruby-2.2.5" jdkType="RUBY_SDK" />
20
+ <orderEntry type="sourceFolder" forTests="false" />
21
+ <orderEntry type="library" scope="PROVIDED" name="actionmailer (v5.0.0.1, RVM: ruby-2.2.5) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="actionview (v5.0.0.1, RVM: ruby-2.2.5) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v1.14.6, RVM: ruby-2.2.5) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="byebug (v9.0.6, RVM: ruby-2.2.5) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="coderay (v1.1.1, RVM: ruby-2.2.5) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.2.5) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="kramdown (v1.12.0, RVM: ruby-2.2.5) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="loofah (v2.0.3, RVM: ruby-2.2.5) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="method_source (v0.8.2, RVM: ruby-2.2.5) [gem]" level="application" />
30
+ <orderEntry type="library" scope="PROVIDED" name="mime-types (v3.1, RVM: ruby-2.2.5) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="mime-types-data (v3.2016.0521, RVM: ruby-2.2.5) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.1.0, RVM: ruby-2.2.5) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="panoramic (v0.0.6, RVM: ruby-2.2.5) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="pry (v0.10.4, RVM: ruby-2.2.5) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="rack-test (v0.6.3, RVM: ruby-2.2.5) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.0.3, RVM: ruby-2.2.5) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.4.2, RVM: ruby-2.2.5) [gem]" level="application" />
38
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v3.5.0, RVM: ruby-2.2.5) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.5.2, RVM: ruby-2.2.5) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.5.0, RVM: ruby-2.2.5) [gem]" level="application" />
41
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.5.0, RVM: ruby-2.2.5) [gem]" level="application" />
42
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.5.0, RVM: ruby-2.2.5) [gem]" level="application" />
43
+ <orderEntry type="library" scope="PROVIDED" name="slop (v3.6.0, RVM: ruby-2.2.5) [gem]" level="application" />
44
+ <orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.0, RVM: ruby-2.2.5) [gem]" level="application" />
45
+ <orderEntry type="library" scope="PROVIDED" name="thor (v0.19.4, RVM: ruby-2.2.5) [gem]" level="application" />
46
+ <orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.2, RVM: ruby-2.2.5) [gem]" level="application" />
47
+ </component>
48
+ </module>
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liquid_markdown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Gary McGhee
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kramdown
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.12.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.12'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.12.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: liquid
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 4.0.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '4.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 4.0.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: actionmailer
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '4.0'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '4.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: actionview
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '4.0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '4.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: panoramic
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: 0.0.6
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: 0.0.6
95
+ - !ruby/object:Gem::Dependency
96
+ name: bundler
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '1.12'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.12'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rake
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '10.0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '10.0'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rspec
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '3.0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '3.0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: pry-meta
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: 0.0.10
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: 0.0.10
151
+ description: Combines Liquid and Markdown templating for generic templating and Rails
152
+ Mailers
153
+ email:
154
+ - gary@buzzware.com.au
155
+ executables: []
156
+ extensions: []
157
+ extra_rdoc_files: []
158
+ files:
159
+ - ".gitignore"
160
+ - ".rspec"
161
+ - ".travis.yml"
162
+ - CODE_OF_CONDUCT.md
163
+ - Gemfile
164
+ - LICENSE.txt
165
+ - README.md
166
+ - Rakefile
167
+ - lib/liquid_markdown.rb
168
+ - lib/liquid_markdown/converter/plain_text.rb
169
+ - lib/liquid_markdown/core_ext/hash/keys.rb
170
+ - lib/liquid_markdown/core_ext/string/strip.rb
171
+ - lib/liquid_markdown/filters/text_filter.rb
172
+ - lib/liquid_markdown/liquid/liquid_methods.rb
173
+ - lib/liquid_markdown/render.rb
174
+ - lib/liquid_markdown/resolver.rb
175
+ - lib/liquid_markdown/template_handler.rb
176
+ - lib/liquid_markdown/version.rb
177
+ - liquid_markdown.gemspec
178
+ - liquid_markdown.iml
179
+ homepage: https://github.com/buzzware/liquid_markdown
180
+ licenses:
181
+ - MIT
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.4.8
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Combines Liquid and Markdown templating for generic templating and Rails
203
+ Mailers
204
+ test_files: []