guileless 0.1.0

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,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: