guileless 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTk5NzVjNzdhY2JhMGVlNGQzYjY3OWQyYjdiY2VjNTJhM2Y5YTI0NQ==
5
+ data.tar.gz: !binary |-
6
+ YTcxMzkzNGIwODYxZTkzZWRiMDdkY2Q4ZTY3NWMwYTZiMjY5MjFjOQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MTY5N2UwYzg3YTQ0Yzk4OGJlMDQwZWQ1ZGM3NGY4YjE1MjBjNTRhZDBiODM3
10
+ YmIwMWI1MzY4ZGRkMDE5ZDE4ZTQwNDgwYWFlZDFiMTVlZThiZTk1ODhjOTUw
11
+ NTdkZmJlMjY4MTJhMDE5NjdkYTM0MzExZTVhMGEzZWMyNTQzNDQ=
12
+ data.tar.gz: !binary |-
13
+ YzgwYWY1ZWY2M2U2OTBmYTkyNTI5NTUwMzk0MDAwMTNmM2Q2ZDViOThjNDlj
14
+ YTU3YjNiYWJiODAxNjk5ZjBhZDVhZjg1NjgxMDhjZjAxYmQ5MDZkZjVlN2Q4
15
+ NDIxYmRmMTY3MjIyZjVmZWIxN2RiMGQwYmRmZDQwMDg5ODA3Nzk=
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ script:
6
+ - bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ GEM
2
+ specs:
3
+ diff-lcs (1.2.4)
4
+ rspec (2.14.1)
5
+ rspec-core (~> 2.14.0)
6
+ rspec-expectations (~> 2.14.0)
7
+ rspec-mocks (~> 2.14.0)
8
+ rspec-core (2.14.5)
9
+ rspec-expectations (2.14.3)
10
+ diff-lcs (>= 1.1.3, < 2.0)
11
+ rspec-mocks (2.14.3)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Inge Jørgensen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Guileless [![Build Status](https://travis-ci.org/elektronaut/guileless.png)](https://travis-ci.org/elektronaut/guileless) [![Code Climate](https://codeclimate.com/github/elektronaut/guileless.png)](https://codeclimate.com/github/elektronaut/guileless)
2
+
3
+ Guileless is a naive HTML preprocessor. It does three things:
4
+
5
+ 1. Single line breaks are converted to `<br>`
6
+ 2. Several consecutive line breaks are treated as paragraphs and wrapped in `<p>`
7
+ 3. Converts stray `<`, `>`, and `&`s to HTML entities.
8
+
9
+ Why is this more useful than, say, Rails' built in `simple_format`?
10
+
11
+ Well, it's actually a real (if simplistic) HTML parser. It understands nested
12
+ tags, and will happily format text nodes inside `div`s and `blockquote`s.
13
+
14
+ However, it does **NOT** do any sanitation on the input.
15
+
16
+ ## Usage
17
+
18
+ ```ruby
19
+ Guileless.format("<div>foo</div>") # => "<div><p>foo</p></div>"
20
+ ```
21
+
22
+ ## License
23
+
24
+ Copyright (c) 2013 Inge Jørgensen
25
+
26
+ Permission is hereby granted, free of charge, to any person obtaining a copy
27
+ of this software and associated documentation files (the "Software"), to deal
28
+ in the Software without restriction, including without limitation the rights
29
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30
+ copies of the Software, and to permit persons to whom the Software is
31
+ furnished to do so, subject to the following conditions:
32
+
33
+ The above copyright notice and this permission notice shall be included in
34
+ all copies or substantial portions of the Software.
35
+
36
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42
+ THE SOFTWARE.
data/guileless.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "guileless/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'guileless'
8
+ s.version = Guileless::VERSION
9
+ s.date = '2013-10-20'
10
+ s.summary = "Naive HTML preprocessor"
11
+ s.description = "Naive HTML preprocessor"
12
+ s.authors = ["Inge Jørgensen"]
13
+ s.email = 'inge@elektronaut.no'
14
+ s.files = ["lib/hola.rb"]
15
+ s.homepage = 'http://github.com/elektronaut/guileless'
16
+ s.license = 'MIT'
17
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.2")
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ end
data/lib/guileless.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "guileless/input_stream"
2
+ require "guileless/output_buffer"
3
+ require "guileless/parse_methods"
4
+ require "guileless/state_machine"
5
+ require "guileless/tag_library"
6
+ require "guileless/parser"
7
+ require "guileless/version"
8
+
9
+ module Guileless
10
+ class << self
11
+ def format(str)
12
+ Parser.new(str).to_html
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ module Guileless
2
+ class InputStream
3
+ def initialize(input)
4
+ @buffer = input.chars.to_a
5
+ end
6
+
7
+ def reinject(char)
8
+ @buffer.unshift(char)
9
+ end
10
+
11
+ def empty?
12
+ @buffer.length == 0
13
+ end
14
+
15
+ def fetch
16
+ @buffer.shift
17
+ end
18
+
19
+ def discard(count=1)
20
+ count.times { @buffer.shift }
21
+ end
22
+
23
+ def strip_whitespace
24
+ @buffer.shift while @buffer.first == "\n"
25
+ end
26
+
27
+ def peek?(patterns)
28
+ match = false
29
+ Array(patterns).each do |pattern|
30
+ if pattern.kind_of?(Regexp)
31
+ match = true if self.to_s =~ pattern
32
+ elsif pattern.kind_of?(String)
33
+ match = true if self.to_s[0...(pattern.length)] == pattern
34
+ end
35
+ end
36
+ match
37
+ end
38
+
39
+ def to_s
40
+ @buffer.join
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ module Guileless
2
+ class OutputBuffer
3
+ def initialize
4
+ @output_buffer = []
5
+ @output = []
6
+ end
7
+
8
+ def add(str)
9
+ str = str.chars.to_a if str.kind_of?(String)
10
+ @output_buffer += Array(str)
11
+ str
12
+ end
13
+
14
+ def buffered?
15
+ @output_buffer.length > 0
16
+ end
17
+
18
+ def flush
19
+ @output += @output_buffer
20
+ @output_buffer = []
21
+ end
22
+
23
+ def wrap(prefix, postfix)
24
+ prefix = prefix.chars.to_a if prefix.kind_of?(String)
25
+ postfix = postfix.chars.to_a if postfix.kind_of?(String)
26
+ @output_buffer = Array(prefix) + @output_buffer + Array(postfix)
27
+ end
28
+
29
+ def to_s
30
+ @output.join
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,158 @@
1
+ module Guileless
2
+ module ParseMethods
3
+
4
+ def parse_attribute_name(char)
5
+ case
6
+ when char !=~ /[\w\-]/
7
+ stream.reinject char
8
+ [false, :tag]
9
+ when char == "=" && stream.peek?("'")
10
+ stream.discard
11
+ ["='", :attribute_value_single_quote]
12
+ when char == "=" && stream.peek?("\"")
13
+ stream.discard
14
+ ["=\"", :attribute_value_double_quote]
15
+ when char == "="
16
+ [char, :attribute_value]
17
+ end
18
+ end
19
+
20
+ def parse_attribute_value(char)
21
+ case
22
+ when char !=~ /[\w\d]/
23
+ stream.reinject char
24
+ [false, :tag]
25
+ end
26
+ end
27
+
28
+ def parse_attribute_value_single_quote(char)
29
+ case
30
+ when char == "'"
31
+ [char, :tag]
32
+ end
33
+ end
34
+
35
+ def parse_attribute_value_double_quote(char)
36
+ case
37
+ when char == "\""
38
+ [char, :tag]
39
+ end
40
+ end
41
+
42
+ def parse_comment(char)
43
+ case
44
+ when char == "-" && stream.peek?("->")
45
+ stream.discard(2)
46
+ ["-->", :text]
47
+ end
48
+ end
49
+
50
+ def parse_tag(char)
51
+ case
52
+ when char =~ /\w/
53
+ [char, :attribute_name]
54
+ when char == ">"
55
+ [char, :text]
56
+ end
57
+ end
58
+
59
+ def parse_closing_tag(char)
60
+ case
61
+ when char == ">"
62
+ [char, :text]
63
+ end
64
+ end
65
+
66
+ def parse_tag_name(char)
67
+ case
68
+ when char =~ /\w/
69
+ @tag_name += char
70
+ char
71
+ else
72
+ stream.reinject char
73
+ [false, :tag]
74
+ end
75
+ end
76
+
77
+ def parse_closing_tag_name(char)
78
+ case
79
+ when char =~ /\w/
80
+ @tag_name += char
81
+ char
82
+ else
83
+ stream.reinject char
84
+ [false, :closing_tag]
85
+ end
86
+ end
87
+
88
+ def parse_left_angled_quote(char)
89
+ case
90
+
91
+ # Comment
92
+ when stream.peek?("!--")
93
+ stream.discard(3)
94
+ ["<!--", :comment]
95
+
96
+ # Opening block tag
97
+ when stream.peek?(block_level_tags)
98
+ flush_buffer
99
+ [char, :tag_name]
100
+
101
+ # Opening tag
102
+ when stream.peek?(html_tags)
103
+ [char, :tag_name]
104
+
105
+ # Closing block level tag
106
+ when stream.peek?(closing(block_level_tags))
107
+ flush_buffer
108
+ stream.discard
109
+ ["</", :closing_tag_name]
110
+
111
+ # Closing tag
112
+ when stream.peek?(closing(html_tags))
113
+ stream.discard
114
+ ["</", :closing_tag_name]
115
+
116
+ # Escape left angled bracket
117
+ else
118
+ @char_count += 4
119
+ "&lt;"
120
+ end
121
+ end
122
+
123
+ def parse_text(char)
124
+ case
125
+
126
+ # Comment
127
+ when char == "<"
128
+ parse_left_angled_quote(char)
129
+
130
+ # Escape right angled bracket
131
+ when char == ">"
132
+ @char_count += 4
133
+ "&gt;"
134
+
135
+ # Escape ampersands
136
+ when char == "&" && !stream.peek?("amp;")
137
+ @char_count += 5
138
+ "&amp;"
139
+
140
+ # Paragraph break
141
+ when char == "\n" && stream.peek?("\n")
142
+ flush_buffer
143
+ stream.strip_whitespace
144
+ false
145
+
146
+ # Line break
147
+ when char == "\n"
148
+ "<br>"
149
+
150
+ when char !=~ /\s/
151
+ @char_count += 1
152
+ char
153
+
154
+ end
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,96 @@
1
+ module Guileless
2
+ class Parser < Guileless::StateMachine
3
+ include Guileless::TagLibrary
4
+ include Guileless::ParseMethods
5
+
6
+ attr_reader :input, :stream, :tag_stack, :buffer, :tag_name, :char_count
7
+
8
+ before_transition :reset_tag_name, [:tag_name, :closing_tag_name]
9
+ before_transition :add_tag_to_stack, :text, from: [:tag]
10
+ before_transition :close_tag, :text, from: [:closing_tag]
11
+ before_transition :finish_tag, :text, from: [:tag, :closing_tag]
12
+ before_transition :flush_buffer, :end
13
+
14
+ def initialize(input)
15
+ @input = input
16
+ end
17
+
18
+ def to_html
19
+ parse!
20
+ buffer.to_s
21
+ end
22
+
23
+ def parse!
24
+ reset!
25
+ read while !stream.empty?
26
+ transition(:end)
27
+ end
28
+
29
+ def read
30
+ char = stream.fetch
31
+ value, next_state = Array(self.send("parse_#{state}".to_sym, char))
32
+
33
+ if value === nil
34
+ buffer.add char
35
+ elsif value
36
+ buffer.add value
37
+ end
38
+
39
+ transition(next_state) if next_state
40
+ end
41
+
42
+ def wrap_in_paragraph?
43
+ state == :text &&
44
+ char_count > 0 &&
45
+ buffer.buffered? &&
46
+ (!last_block_level_tag || paragraph_container_tags.include?(last_block_level_tag))
47
+ end
48
+
49
+ def flush_buffer
50
+ if wrap_in_paragraph?
51
+ if buffer.buffered? && char_count > 0
52
+ buffer.wrap("<p>", "</p>")
53
+ end
54
+ end
55
+ @char_count = 0
56
+ buffer.flush
57
+ end
58
+
59
+ def finish_tag
60
+ if block_level_tags.include?(tag_name)
61
+ flush_buffer
62
+ end
63
+ end
64
+
65
+ def add_tag_to_stack
66
+ @tag_stack << tag_name
67
+ end
68
+
69
+ def close_tag
70
+ unwind_tag_stack(tag_name)
71
+ end
72
+
73
+ def unwind_tag_stack(tag)
74
+ if tag_stack.include?(tag)
75
+ last_tag = tag_stack.pop while last_tag != tag
76
+ end
77
+ end
78
+
79
+ def last_block_level_tag
80
+ tag_stack.reverse.select{|t| block_level_tags.include?(t) }.first
81
+ end
82
+
83
+ def reset_tag_name
84
+ @tag_name = ""
85
+ end
86
+
87
+ def reset!
88
+ @char_count = 0
89
+ @buffer = Guileless::OutputBuffer.new
90
+ @stream = Guileless::InputStream.new(input)
91
+ @tag_stack = []
92
+ reset_tag_name
93
+ @state = :text
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,33 @@
1
+ module Guileless
2
+ class StateMachine
3
+ class NoStateError < StandardError; end
4
+
5
+ class << self
6
+ def transitions
7
+ @transitions ||= []
8
+ end
9
+
10
+ def before_transition(name, states, options={})
11
+ transitions << [name, Array(states), options]
12
+ end
13
+ end
14
+
15
+ def state
16
+ raise NoStateError unless @state
17
+ @state
18
+ end
19
+
20
+ def transition(new_state)
21
+ self.class.transitions.each do |callback, callback_states, options|
22
+ if callback_states.include?(new_state)
23
+ if !options[:from] || options[:from].include?(state)
24
+ self.send("#{callback}".to_sym)
25
+ end
26
+ end
27
+ end
28
+
29
+ @state = new_state
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Guileless
2
+ module TagLibrary
3
+ def closing(tags)
4
+ tags.map{|t| "/#{t}" }
5
+ end
6
+
7
+ def html_tags
8
+ %w{
9
+ a abbr address area article aside audio b base bdi bdo blockquote
10
+ body br button canvas caption cite code col colgroup data datalist
11
+ dd del details dfn div dl dt em embed fieldset figcaption figure
12
+ footer form h1 h2 h3 h4 h5 h6 head header hr html i iframe img
13
+ input ins kbd keygen label legend li link main map mark math menu
14
+ menuitem meta meter nav noscript object ol optgroup option output
15
+ p param pre progress q rp rt ruby s samp section select small source
16
+ span strong style sub summary svg table tbody td textarea tfoot th
17
+ thead time title tr track u ul var video wbr
18
+ }
19
+ end
20
+
21
+ def block_level_tags
22
+ %w{
23
+ address article aside audio blockquote canvas dd div dl fieldset
24
+ figcaption figure footer form h1 h2 h3 h4 h5 h6 header hgroup hr
25
+ noscript ol output p pre section table tfoot ul video
26
+ }
27
+ end
28
+
29
+ def paragraph_container_tags
30
+ %w{article aside blockquote div footer header}
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ module Guileless
2
+ unless Guileless.const_defined?('VERSION')
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guileless do
4
+ describe ".format" do
5
+ it "allows comments" do
6
+ Guileless.format("foo <!-- <b>comment</b> --> bar").should == "<p>foo <!-- <b>comment</b> --> bar</p>"
7
+ end
8
+
9
+ it "doesn't wrap comments" do
10
+ Guileless.format("<!-- <b>comment</b> -->").should == "<!-- <b>comment</b> -->"
11
+ end
12
+
13
+ it "doesn't wrap empty block tags" do
14
+ Guileless.format("<div></div>").should == "<div></div>"
15
+ end
16
+
17
+ it "ignores empty tags" do
18
+ Guileless.format("<b></b>").should == "<b></b>"
19
+ end
20
+
21
+ it "converts single breaks to <br>" do
22
+ Guileless.format("foo\nbar").should == "<p>foo<br>bar</p>"
23
+ end
24
+
25
+ it "converts double breaks to <br>" do
26
+ Guileless.format("foo\n\nbar").should == "<p>foo</p><p>bar</p>"
27
+ end
28
+
29
+ it "escapes left angled brackets" do
30
+ Guileless.format("<").should == "<p>&lt;</p>"
31
+ end
32
+
33
+ it "escapes right angled brackets" do
34
+ Guileless.format(">").should == "<p>&gt;</p>"
35
+ end
36
+
37
+ it "escapes ampersands" do
38
+ Guileless.format("&").should == "<p>&amp;</p>"
39
+ end
40
+
41
+ it "doesn't escape already escaped ampersands" do
42
+ Guileless.format("&amp;").should == "<p>&amp;</p>"
43
+ end
44
+
45
+ it "understands empty attributes" do
46
+ Guileless.format("<blockquote data-foo>stuff</blockquote>").should == "<blockquote data-foo><p>stuff</p></blockquote>"
47
+ end
48
+
49
+ it "understands single quoted attributes" do
50
+ Guileless.format("<blockquote data-foo='bar'>stuff</blockquote>").should == "<blockquote data-foo='bar'><p>stuff</p></blockquote>"
51
+ end
52
+
53
+ it "understands double quoted attributes" do
54
+ Guileless.format("<blockquote data-foo=\"bar\">stuff</blockquote>").should == "<blockquote data-foo=\"bar\"><p>stuff</p></blockquote>"
55
+ end
56
+
57
+ it "ignores non-closed tags" do
58
+ Guileless.format("<blockquote><b>stuff</blockquote>").should == "<blockquote><p><b>stuff</p></blockquote>"
59
+ end
60
+
61
+ it "nests tags properly" do
62
+ Guileless.format("foo<blockquote>bar</blockquote>baz").should == "<p>foo</p><blockquote><p>bar</p></blockquote><p>baz</p>"
63
+ end
64
+
65
+ it "doesn't wrap existing paragraphs" do
66
+ Guileless.format("<p>foo</p>").should == "<p>foo</p>"
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,20 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require_relative '../lib/guileless'
9
+
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = 'random'
20
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guileless
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Inge Jørgensen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Naive HTML preprocessor
14
+ email: inge@elektronaut.no
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - .gitignore
20
+ - .rspec
21
+ - .travis.yml
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE
25
+ - README.md
26
+ - guileless.gemspec
27
+ - lib/guileless.rb
28
+ - lib/guileless/input_stream.rb
29
+ - lib/guileless/output_buffer.rb
30
+ - lib/guileless/parse_methods.rb
31
+ - lib/guileless/parser.rb
32
+ - lib/guileless/state_machine.rb
33
+ - lib/guileless/tag_library.rb
34
+ - lib/guileless/version.rb
35
+ - spec/guileless_spec.rb
36
+ - spec/spec_helper.rb
37
+ homepage: http://github.com/elektronaut/guileless
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: 1.9.2
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.1.4
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Naive HTML preprocessor
61
+ test_files:
62
+ - spec/guileless_spec.rb
63
+ - spec/spec_helper.rb
64
+ has_rdoc: