mdspell 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 557ab534f964bbd18e0453ddcbe9561698441d5b
4
+ data.tar.gz: bb03a5b7f5a40b1e1fe689d383abd1a35a4ccaa8
5
+ SHA512:
6
+ metadata.gz: 21066ee2957e17175a5c353dacd2d9aea1a0a7067ef83813fad211c4548705027867509cfed1a4195893840013e2e92986b9ab8a34ffe6f22c66c81bc3562299
7
+ data.tar.gz: c96d072fc81fb88d458807e34953dcae4c01f96d3ec997f8269e527025ee5f1b6b4f4216ce1a9ffc50875b25efdf26b97478e5510833b888cde9ddf0777ecb1f
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Marek Tuchowski
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.
@@ -0,0 +1,44 @@
1
+ # MdSpell
2
+
3
+ [![Build Status](https://travis-ci.org/mtuchowski/mdspell.svg)](
4
+ https://travis-ci.org/mtuchowski/mdspell)
5
+ [![Code Climate](https://codeclimate.com/github/mtuchowski/mdspell/badges/gpa.svg)](
6
+ https://codeclimate.com/github/mtuchowski/mdspell)
7
+ [![Test Coverage](https://codeclimate.com/github/mtuchowski/mdspell/badges/coverage.svg)](
8
+ https://codeclimate.com/github/mtuchowski/mdspell/coverage)
9
+
10
+ A Ruby markdown spell checking tool.
11
+
12
+ ## Installation
13
+
14
+ To install from [rubygems.org](http://rubygems.org/), run:
15
+
16
+ ```console
17
+ gem install mdspell
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ To spell-check markdown files, simply run `mdspell` with the filenames as a parameter:
23
+
24
+ ```console
25
+ mdspell README.md
26
+ ```
27
+
28
+ To check all markdown files within the directory:
29
+
30
+ ```console
31
+ mdspell docs/
32
+ ```
33
+
34
+ For each spelling error found, MdSpell will display the misspelled word, filename and line number:
35
+
36
+ ```console
37
+ Spell-checking ./README.md...
38
+ ./README.md:10: actualy
39
+ ```
40
+
41
+ ## MIT Licensed
42
+
43
+ See [LICENSE](https://github.com/mtuchowski/mdspell/blob/master/LICENSE) file for full license
44
+ text.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require 'mdspell'
4
+ rescue LoadError
5
+ # For running in development without bundler
6
+ $LOAD_PATH << File.expand_path('../lib', File.dirname(__FILE__))
7
+ require 'mdspell'
8
+ end
9
+
10
+ MdSpell.run
@@ -0,0 +1,37 @@
1
+ require_relative 'mdspell/cli'
2
+ require_relative 'mdspell/configuration'
3
+ require_relative 'mdspell/spell_checker'
4
+ require_relative 'mdspell/text_line'
5
+ require_relative 'mdspell/typo'
6
+ require_relative 'mdspell/version'
7
+
8
+ require 'rainbow'
9
+
10
+ # This module holds all the MdSpell code (except mdspell shell command).
11
+ module MdSpell
12
+ def self.run
13
+ cli = MdSpell::CLI.new
14
+ cli.run
15
+
16
+ # Spell-check each file.
17
+ cli.files.each do |filename|
18
+ verbose "Spell-checking #{filename}..."
19
+
20
+ SpellChecker.new(filename).typos.each do |typo|
21
+ error "#{filename}:#{typo.line.location}: #{typo.word}"
22
+ end
23
+ end
24
+ end
25
+
26
+ # Private class methods
27
+
28
+ def self.verbose(str)
29
+ puts str if Configuration[:verbose]
30
+ end
31
+ private_class_method :verbose
32
+
33
+ def self.error(str)
34
+ puts Rainbow(str).red
35
+ end
36
+ private_class_method :error
37
+ end
@@ -0,0 +1,58 @@
1
+ require 'mixlib/cli'
2
+
3
+ module MdSpell
4
+ # Class responsible for parsing all of command line arguments.
5
+ class CLI
6
+ include Mixlib::CLI
7
+
8
+ banner "Usage: #{File.basename($PROGRAM_NAME)} [options] [FILE.md|DIR ...]"
9
+
10
+ option :config_file,
11
+ short: '-c',
12
+ long: '--config FILE',
13
+ description: 'The configuration file to use',
14
+ default: '~/.mdspell'
15
+
16
+ option :language,
17
+ short: '-l',
18
+ long: '--language LANG',
19
+ description: 'Set documents language',
20
+ default: 'en_US'
21
+
22
+ option :verbose,
23
+ short: '-v',
24
+ long: '--[no-]verbose',
25
+ description: 'Be more/less verbose',
26
+ boolean: true
27
+
28
+ option :version,
29
+ on: :tail,
30
+ short: '-V',
31
+ long: '--version',
32
+ description: 'Show version',
33
+ boolean: true,
34
+ proc: proc { puts MdSpell::VERSION },
35
+ exit: 0
36
+
37
+ def run(argv = ARGV)
38
+ parse_options(argv)
39
+
40
+ # Load optional config file if it's present.
41
+ config_filename = File.expand_path(config[:config_file])
42
+ MdSpell::Configuration.from_file(config_filename) if File.exist?(config_filename)
43
+
44
+ # Store command line configuration options.
45
+ MdSpell::Configuration.merge!(config)
46
+ end
47
+
48
+ # List of markdown files from argument list.
49
+ def files
50
+ cli_arguments.each_with_index do |filename, index|
51
+ if Dir.exist?(filename)
52
+ cli_arguments[index] = Dir["#{filename}/**/*.md"]
53
+ end
54
+ end
55
+ cli_arguments.flatten!
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,8 @@
1
+ require 'mixlib/config'
2
+
3
+ module MdSpell
4
+ # Stores configuration from both command line and config file.
5
+ class Configuration
6
+ extend Mixlib::Config
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'configuration'
2
+
3
+ require 'kramdown'
4
+ require 'ffi/aspell'
5
+
6
+ module MdSpell
7
+ # A class for finding spelling errors in document.
8
+ class SpellChecker
9
+ # Name of the file this object was created from.
10
+ attr_reader :filename
11
+
12
+ # A Kramdown::Document object containing the parsed markdown document.
13
+ attr_reader :document
14
+
15
+ # Create a new instance from specified file.
16
+ # @param filename [String] a name of file to load.
17
+ def initialize(filename)
18
+ @filename = filename
19
+ @document = Kramdown::Document.new(File.read(filename), input: 'GFM')
20
+ end
21
+
22
+ # Returns found spelling errors.
23
+ def typos
24
+ results = []
25
+
26
+ FFI::Aspell::Speller.open(Configuration[:language]) do |speller|
27
+ TextLine.scan(document).each do |line|
28
+ line.words.each do |word|
29
+ unless speller.correct? word
30
+ results << Typo.new(line, word, speller.suggestions(word))
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ results
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,113 @@
1
+ require 'kramdown'
2
+
3
+ module MdSpell
4
+ # Containing concatenated text from single document line.
5
+ class TextLine
6
+ # Accepted types of elements.
7
+ ELEMENT_TYPES = [:text, :smart_quote]
8
+
9
+ # Line number of the element in document.
10
+ attr_reader :location
11
+
12
+ # Textual content of the element.
13
+ attr_reader :content
14
+
15
+ # Create a new TextLine from Kramdown::Element object.
16
+ # @param element [Kramdown::Element]
17
+ def initialize(element)
18
+ TextLine.assert_element_type element
19
+
20
+ @content = ''
21
+ @location = element.options[:location]
22
+ self << element
23
+ end
24
+
25
+ # Return all words in this element.
26
+ def words
27
+ @content.scan(/[\w\']+/)
28
+ end
29
+
30
+ # Append Kramdown::Element's content to this element.
31
+ # @param element [Kramdown::Element]
32
+ # @raise ArgumentError if element is in different location.
33
+ def <<(element)
34
+ TextLine.assert_element_type element
35
+
36
+ return self unless ELEMENT_TYPES.include? element.type
37
+ return self unless element.options[:location] == @location
38
+
39
+ value = element.value
40
+
41
+ if element.type == :smart_quote
42
+ appent_quote(value)
43
+ else
44
+ append_text(value)
45
+ end
46
+
47
+ self
48
+ end
49
+
50
+ # Scan Kramdown::Document for TextLines.
51
+ # @param document [Kramdown::Document]
52
+ def self.scan(document)
53
+ results = []
54
+
55
+ get_all_textual_elements(document.root.children).each do |element|
56
+ matching_element_found = results.any? do |text_element|
57
+ if text_element.location == element.options[:location]
58
+ text_element << element
59
+ true
60
+ else
61
+ false
62
+ end
63
+ end
64
+
65
+ results << TextLine.new(element) unless matching_element_found
66
+ end
67
+
68
+ results
69
+ end
70
+
71
+ private
72
+
73
+ def append_text(value)
74
+ return if value.nil? || value.empty?
75
+
76
+ value = value.strip
77
+ if @content.empty? || @content[-1] == "'"
78
+ @content += value
79
+ else
80
+ @content += ' ' + value
81
+ end
82
+ end
83
+
84
+ def appent_quote(type)
85
+ case type
86
+ when :lsquo, :rsquo
87
+ @content += "'"
88
+ when :ldquo, :rdquo
89
+ @content += '"'
90
+ end
91
+ end
92
+
93
+ # Private class methods
94
+
95
+ def self.assert_element_type(elem)
96
+ fail ArgumentError, 'expected Kramdown::Element' unless elem.instance_of? Kramdown::Element
97
+ end
98
+
99
+ def self.get_all_textual_elements(elements)
100
+ result = []
101
+
102
+ elements.each do |element|
103
+ if ELEMENT_TYPES.include? element.type
104
+ result << element
105
+ else
106
+ result |= get_all_textual_elements(element.children)
107
+ end
108
+ end
109
+
110
+ result
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,44 @@
1
+ module MdSpell
2
+ # A wrapper class for single, misspelled word.
3
+ class Typo
4
+ # A TextLine that contains this error.
5
+ attr_reader :line
6
+
7
+ # A misspelled word.
8
+ attr_reader :word
9
+
10
+ # A list of suggestions for this error.
11
+ attr_reader :suggestions
12
+
13
+ # Create a new SpellingError.
14
+ # @param line [TextLine] the TextLine that contains the error.
15
+ # @param word [String] the misspelled word.
16
+ # @param suggestions [Array] an array of suggestions for the word.
17
+ def initialize(line, word, suggestions)
18
+ assert_proper_line_type(line)
19
+ assert_proper_word_type(word)
20
+ assert_proper_suggestions_type(suggestions)
21
+
22
+ @line = line
23
+ @word = word
24
+ @suggestions = suggestions
25
+ end
26
+
27
+ private
28
+
29
+ def assert_proper_line_type(line)
30
+ fail ArgumentError, "expected TextLine, got #{line.class.inspect}" unless
31
+ line.class == TextLine
32
+ end
33
+
34
+ def assert_proper_word_type(word)
35
+ fail ArgumentError, "expected String, got #{word.class.inspect}" unless
36
+ word.class == String
37
+ end
38
+
39
+ def assert_proper_suggestions_type(suggestions)
40
+ fail ArgumentError, "expected Array, got #{suggestions.class.inspect}" unless
41
+ suggestions.class == Array
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module MdSpell
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,39 @@
1
+ example_id | status | run_time |
2
+ --------------------------------------------- | ------- | --------------- |
3
+ ./spec/mdspell/spell_checker_spec.rb[1:1:1] | passed | 0.00141 seconds |
4
+ ./spec/mdspell/spell_checker_spec.rb[1:1:2] | passed | 0.00088 seconds |
5
+ ./spec/mdspell/spell_checker_spec.rb[1:1:3] | passed | 0.00055 seconds |
6
+ ./spec/mdspell/spell_checker_spec.rb[1:2:1] | passed | 0.00014 seconds |
7
+ ./spec/mdspell/spell_checker_spec.rb[1:2:2] | passed | 0.00048 seconds |
8
+ ./spec/mdspell/spell_checker_spec.rb[1:2:3] | failed | 0.01636 seconds |
9
+ ./spec/mdspell/spell_checker_spec.rb[1:3:1] | passed | 0.03322 seconds |
10
+ ./spec/mdspell/spell_checker_spec.rb[1:3:2:1] | failed | 0.00015 seconds |
11
+ ./spec/mdspell/spell_checker_spec.rb[1:4:1] | passed | 0.00181 seconds |
12
+ ./spec/mdspell/spell_checker_spec.rb[1:5:1] | failed | 0.00789 seconds |
13
+ ./spec/mdspell/spell_checker_spec.rb[1:5:2] | passed | 0.00703 seconds |
14
+ ./spec/mdspell/spell_checker_spec.rb[1:5:3] | pending | 0.00001 seconds |
15
+ ./spec/mdspell/text_line_spec.rb[1:1:1] | passed | 0.00007 seconds |
16
+ ./spec/mdspell/text_line_spec.rb[1:1:2] | passed | 0.00008 seconds |
17
+ ./spec/mdspell/text_line_spec.rb[1:1:3] | passed | 0.00008 seconds |
18
+ ./spec/mdspell/text_line_spec.rb[1:1:4] | passed | 0.00009 seconds |
19
+ ./spec/mdspell/text_line_spec.rb[1:2:1] | passed | 0.0004 seconds |
20
+ ./spec/mdspell/text_line_spec.rb[1:3:1] | passed | 0.00008 seconds |
21
+ ./spec/mdspell/text_line_spec.rb[1:4:1] | passed | 0.00009 seconds |
22
+ ./spec/mdspell/text_line_spec.rb[1:5:1] | passed | 0.0001 seconds |
23
+ ./spec/mdspell/text_line_spec.rb[1:6:1] | passed | 0.00014 seconds |
24
+ ./spec/mdspell/text_line_spec.rb[1:6:2:1] | passed | 0.00008 seconds |
25
+ ./spec/mdspell/text_line_spec.rb[1:6:3:1] | passed | 0.00011 seconds |
26
+ ./spec/mdspell/text_line_spec.rb[1:6:3:2] | passed | 0.0001 seconds |
27
+ ./spec/mdspell/text_line_spec.rb[1:6:4:1] | passed | 0.00009 seconds |
28
+ ./spec/mdspell/text_line_spec.rb[1:7:1] | passed | 0.00012 seconds |
29
+ ./spec/mdspell/text_line_spec.rb[1:7:2] | passed | 0.00086 seconds |
30
+ ./spec/mdspell/typo_spec.rb[1:1:1] | passed | 0.00011 seconds |
31
+ ./spec/mdspell/typo_spec.rb[1:1:2] | passed | 0.0001 seconds |
32
+ ./spec/mdspell/typo_spec.rb[1:1:3] | passed | 0.00008 seconds |
33
+ ./spec/mdspell/typo_spec.rb[1:2:1] | passed | 0.00012 seconds |
34
+ ./spec/mdspell/typo_spec.rb[1:2:2] | passed | 0.00016 seconds |
35
+ ./spec/mdspell/typo_spec.rb[1:2:3] | passed | 0.00014 seconds |
36
+ ./spec/mdspell/typo_spec.rb[1:3:1] | passed | 0.00044 seconds |
37
+ ./spec/mdspell/typo_spec.rb[1:4:1] | passed | 0.00007 seconds |
38
+ ./spec/mdspell/typo_spec.rb[1:5:1] | passed | 0.00008 seconds |
39
+ ./spec/mdspell/typo_spec.rb[1:5:2] | passed | 0.0001 seconds |
@@ -0,0 +1,5 @@
1
+ # Simple
2
+
3
+ markdown
4
+
5
+ *file*
@@ -0,0 +1,5 @@
1
+ # This file has mispelled words
2
+
3
+ And qiute few of them actualy.
4
+
5
+ Four tobe precise.
@@ -0,0 +1,70 @@
1
+ describe MdSpell::SpellChecker do
2
+ let(:simple) { MdSpell::SpellChecker.new('spec/examples/simple.md') }
3
+ let(:with_errors) { MdSpell::SpellChecker.new('spec/examples/with_errors.md') }
4
+ let(:from_stdin) do
5
+ allow(STDIN).to receive(:read) { '# Header' }
6
+ MdSpell::SpellChecker.new('-')
7
+ end
8
+
9
+ context 'attributes' do
10
+ subject { simple }
11
+
12
+ it { is_expected.to respond_to :filename }
13
+ it { is_expected.to respond_to :document }
14
+ it { is_expected.to respond_to :typos }
15
+ end
16
+
17
+ context '#initialize' do
18
+ it 'should expect filename' do
19
+ expect { MdSpell::SpellChecker.new }.to raise_error ArgumentError
20
+ end
21
+
22
+ it 'should fail if given wrong filename' do
23
+ expect { MdSpell::SpellChecker.new('not_existing.md') }.to raise_error Errno::ENOENT
24
+ end
25
+
26
+ it "should read from stdin if given '-' as filename" do
27
+ allow(STDIN).to receive(:read) { '# Header' }
28
+ expect { MdSpell::SpellChecker.new('-') }.not_to raise_error
29
+ end
30
+ end
31
+
32
+ context '#filename' do
33
+ it 'should return proper path' do
34
+ expect(simple.filename).to eq 'spec/examples/simple.md'
35
+ expect(with_errors.filename).to eq 'spec/examples/with_errors.md'
36
+ end
37
+
38
+ context 'if initialized from stdin' do
39
+ it "should return 'stdin'" do
40
+ expect(stdin_md.filename).to eq 'stdin'
41
+ end
42
+ end
43
+ end
44
+
45
+ context '#document' do
46
+ it 'should be of proper type' do
47
+ expect(simple.document).to be_instance_of Kramdown::Document
48
+ expect(with_errors.document).to be_instance_of Kramdown::Document
49
+ end
50
+ end
51
+
52
+ context '#typos' do
53
+ it 'should return empty array if there are no errors' do
54
+ expect(simple.typos).to have(0).items
55
+ expect(from_stdin.typos).to have(0).items
56
+ end
57
+
58
+ it 'should return proper results' do
59
+ typos = with_errors.typos
60
+
61
+ expect(typos).to have(4).items
62
+ expect(typos[0].word).to eq 'mispelled'
63
+ expect(typos[1].word).to eq 'qiute'
64
+ expect(typos[2].word).to eq 'actualy'
65
+ expect(typos[3].word).to eq 'tobe'
66
+ end
67
+
68
+ it 'should use configured language'
69
+ end
70
+ end
@@ -0,0 +1,111 @@
1
+ describe MdSpell::TextLine do
2
+ let(:md_p_element) { Kramdown::Element.new(:p) }
3
+ let(:md_header_element) { Kramdown::Element.new(:header) }
4
+ let(:md_text_element) { Kramdown::Element.new(:text, "Joe's shop", nil, location: 42) }
5
+ let(:md_other_text_element) { Kramdown::Element.new(:text, 'text', nil, location: 42) }
6
+ let(:md_quote_element) { Kramdown::Element.new(:smart_quote, :lsquo, nil, location: 42) }
7
+ let(:md_empty_text_element) { Kramdown::Element.new(:text, nil, nil, location: 42) }
8
+ let(:md_empty_quote_element) { Kramdown::Element.new(:smart_quote, nil, nil, location: 42) }
9
+ let(:md_text_element_diff_location) { Kramdown::Element.new(:text, 'test', nil, location: 41) }
10
+
11
+ subject { MdSpell::TextLine.new(md_text_element) }
12
+
13
+ context 'attributes' do
14
+ it { is_expected.to respond_to :location }
15
+ it { is_expected.to respond_to :content }
16
+ it { is_expected.to respond_to :words }
17
+ it { is_expected.to respond_to :<< }
18
+ end
19
+
20
+ context '#initialize' do
21
+ it 'should expect Kramdown::Element as argument' do
22
+ expect { MdSpell::TextLine.new }.to raise_error ArgumentError
23
+ expect { MdSpell::TextLine.new('test') }.to raise_error ArgumentError
24
+ end
25
+ end
26
+
27
+ context '#location' do
28
+ it 'should return proper value' do
29
+ expect(subject.location).to eq 42
30
+ end
31
+ end
32
+
33
+ context '#content' do
34
+ it 'should contain proper text' do
35
+ expect(subject.content).to eq "Joe's shop"
36
+ end
37
+ end
38
+
39
+ context '#words' do
40
+ it 'should return proper content' do
41
+ expect(subject.words).to eq ["Joe's", 'shop']
42
+ end
43
+ end
44
+
45
+ context '#<<' do
46
+ it 'should accept only Kramdown::Element' do
47
+ expect { subject << 'p_element' }.to raise_error ArgumentError
48
+ expect { subject << nil }.to raise_error ArgumentError
49
+ expect { subject << md_empty_text_element }.not_to raise_error
50
+ expect { subject << md_empty_quote_element }.not_to raise_error
51
+ end
52
+
53
+ context 'when given text element' do
54
+ it 'should update content' do
55
+ subject << md_other_text_element
56
+ expect(subject.content).to eq "Joe's shop text"
57
+ end
58
+ end
59
+
60
+ context 'when given smart quote element' do
61
+ let(:lsquo_element) { Kramdown::Element.new(:smart_quote, :lsquo, nil, location: 42) }
62
+ let(:rsquo_element) { Kramdown::Element.new(:smart_quote, :rsquo, nil, location: 42) }
63
+ let(:ldquo_element) { Kramdown::Element.new(:smart_quote, :ldquo, nil, location: 42) }
64
+ let(:rdquo_element) { Kramdown::Element.new(:smart_quote, :rdquo, nil, location: 42) }
65
+
66
+ it 'should translate to content properly' do
67
+ subject << lsquo_element
68
+ expect(subject.content).to eq "Joe's shop'"
69
+ subject << ldquo_element
70
+ expect(subject.content).to eq "Joe's shop'\""
71
+ subject << rsquo_element
72
+ expect(subject.content).to eq "Joe's shop'\"'"
73
+ subject << rdquo_element
74
+ expect(subject.content).to eq "Joe's shop'\"'\""
75
+ end
76
+
77
+ it 'should properly concatenate words' do
78
+ subject << md_quote_element
79
+ subject << md_other_text_element
80
+ expect(subject.content).to eq "Joe's shop'text"
81
+ subject << md_other_text_element
82
+ expect(subject.content).to eq "Joe's shop'text text"
83
+ end
84
+ end
85
+
86
+ context 'when given element from different location' do
87
+ it 'should not update content' do
88
+ subject << md_text_element_diff_location
89
+ expect(subject.content).to eq "Joe's shop"
90
+ end
91
+ end
92
+ end
93
+
94
+ context '::scan' do
95
+ let(:simple_md) { Kramdown::Document.new(File.read('spec/examples/simple.md'), input: 'GFM') }
96
+
97
+ it 'should expect Kramdown::Document as argument' do
98
+ expect { MdSpell::TextLine.scan }. to raise_error ArgumentError
99
+ end
100
+
101
+ it 'should find proper lines' do
102
+ lines = MdSpell::TextLine.scan(simple_md)
103
+
104
+ expect(lines).to have(3).items
105
+
106
+ expect(lines[0].content).to eq 'Simple'
107
+ expect(lines[1].content).to eq 'markdown'
108
+ expect(lines[2].content).to eq 'file'
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,83 @@
1
+ describe MdSpell::Typo do
2
+ let(:text_line) do
3
+ MdSpell::TextLine.new(Kramdown::Element.new(:text, 'black rabit', nil, location: 42))
4
+ end
5
+ let(:misspelled_word) { 'rabit' }
6
+ let(:suggested_word) { 'rabbit' }
7
+
8
+ subject { MdSpell::Typo.new(text_line, misspelled_word, [suggested_word]) }
9
+
10
+ context 'attributes' do
11
+ it { is_expected.to respond_to :line }
12
+ it { is_expected.to respond_to :word }
13
+ it { is_expected.to respond_to :suggestions }
14
+ end
15
+
16
+ context '#initialize' do
17
+ it 'should expect TextLine as first argument' do
18
+ expect do
19
+ MdSpell::Typo.new(nil, misspelled_word, [suggested_word])
20
+ end.to raise_error ArgumentError, 'expected TextLine, got NilClass'
21
+
22
+ expect do
23
+ MdSpell::Typo.new('black rabit', misspelled_word, [suggested_word])
24
+ end.to raise_error ArgumentError, 'expected TextLine, got String'
25
+
26
+ expect do
27
+ MdSpell::Typo.new(text_line, misspelled_word, [suggested_word])
28
+ end.not_to raise_error
29
+ end
30
+
31
+ it 'should expect word as second argument' do
32
+ expect do
33
+ MdSpell::Typo.new(text_line, nil, [suggested_word])
34
+ end.to raise_error ArgumentError, 'expected String, got NilClass'
35
+
36
+ expect do
37
+ MdSpell::Typo.new(text_line, :c, [suggested_word])
38
+ end.to raise_error ArgumentError, 'expected String, got Symbol'
39
+
40
+ expect do
41
+ MdSpell::Typo.new(text_line, misspelled_word, [suggested_word])
42
+ end.not_to raise_error
43
+ end
44
+
45
+ it 'should expect array as third argument' do
46
+ expect do
47
+ MdSpell::Typo.new(text_line, misspelled_word, nil)
48
+ end.to raise_error ArgumentError, 'expected Array, got NilClass'
49
+
50
+ expect do
51
+ MdSpell::Typo.new(text_line, misspelled_word, 'a')
52
+ end.to raise_error ArgumentError, 'expected Array, got String'
53
+
54
+ expect { MdSpell::Typo.new(text_line, misspelled_word, []) }.not_to raise_error
55
+ expect do
56
+ MdSpell::Typo.new(text_line, misspelled_word, [suggested_word])
57
+ end.not_to raise_error
58
+ end
59
+ end
60
+
61
+ context '#line' do
62
+ it 'should return proper object' do
63
+ expect(subject.line).to be text_line
64
+ end
65
+ end
66
+
67
+ context '#word' do
68
+ it 'should return proper word' do
69
+ expect(subject.word).to eq misspelled_word
70
+ end
71
+ end
72
+
73
+ context '#suggestions' do
74
+ it 'should be an array' do
75
+ expect(subject.suggestions).to be_instance_of Array
76
+ end
77
+
78
+ it 'should return proper items' do
79
+ expect(subject.suggestions).to have(1).item
80
+ expect(subject.suggestions).to eq [suggested_word]
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,68 @@
1
+ # Conventionally, all specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
2
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this file to always
3
+ # be loaded, without a need to explicitly require it in any files.
4
+ #
5
+ # Given that it is always loaded, keep this file as light-weight as possible. Requiring heavyweight
6
+ # dependencies from this file will add to the boot time of test suite on EVERY test run, even for
7
+ # an individual file that may not need all of that loaded. Instead, consider making a separate
8
+ # helper file that requires the additional dependencies and performs the additional setup,
9
+ # and require it from the spec files that actually need it.
10
+ #
11
+ # The `.rspec` file also contains a few flags that are not defaults but that are commonly wanted.
12
+ #
13
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
14
+
15
+ # Setup Code Climate test reporter.
16
+ require 'codeclimate-test-reporter'
17
+
18
+ CodeClimate::TestReporter.start
19
+
20
+ # For checking arrays.
21
+ require 'rspec/collection_matchers'
22
+
23
+ # The whole lib is not that big, requiring it here cleans up the specs a little bit.
24
+ require 'mdspell'
25
+
26
+ RSpec.configure do |config|
27
+ # rspec-expectations config goes here.
28
+ config.expect_with :rspec do |expectations|
29
+ # This option will default to `true` in RSpec 4. It makes the `description` and
30
+ # `failure_message` of custom matchers include text for helper methods defined using
31
+ # `chain`, e.g.:
32
+ # be_bigger_than(2).and_smaller_than(4).description
33
+ # # => "be bigger than 2 and smaller than 4"
34
+ # ...rather than:
35
+ # # => "be bigger than 2"
36
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
37
+
38
+ # Only allow expect syntax.
39
+ expectations.syntax = :expect
40
+ end
41
+
42
+ # rspec-mocks config goes here.
43
+ config.mock_with :rspec do |mocks|
44
+ # Prevents from mocking or stubbing a method that does not exist on a real object.
45
+ # This is generally recommended, and will default to `true` in RSpec 4.
46
+ mocks.verify_partial_doubles = true
47
+ end
48
+
49
+ # Allows RSpec to persist some state between runs in order to support the `--only-failures` and
50
+ # `--next-failure` CLI options. Source control system should be configured to ignore this file.
51
+ config.example_status_persistence_file_path = 'spec/examples.cache'
52
+
53
+ # Run specs in random order to surface order dependencies. To debug an order dependency after
54
+ # finding one, fix the order by providing the seed, which is printed after each run.
55
+ # --seed 1234
56
+ config.order = :random
57
+
58
+ # Seed global randomization in this process using the `--seed` CLI option. Setting this allows
59
+ # to use `--seed` to deterministically reproduce test failures related to randomization
60
+ # by passing the same `--seed` value as the one that triggered the failure.
61
+ Kernel.srand config.seed
62
+
63
+ # Allow filtering specs with `focus: true`.
64
+ config.filter_run focus: true
65
+
66
+ # Run all specs if none are filtered.
67
+ config.run_all_when_everything_filtered = true
68
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mdspell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marek Tuchowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-30 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.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ffi-aspell
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ description: Check markdown files for spelling errors.
42
+ email: marek@tuchowski.com.pl
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files:
46
+ - README.md
47
+ - LICENSE
48
+ files:
49
+ - LICENSE
50
+ - README.md
51
+ - bin/mdspell
52
+ - lib/mdspell.rb
53
+ - lib/mdspell/cli.rb
54
+ - lib/mdspell/configuration.rb
55
+ - lib/mdspell/spell_checker.rb
56
+ - lib/mdspell/text_line.rb
57
+ - lib/mdspell/typo.rb
58
+ - lib/mdspell/version.rb
59
+ - spec/examples.cache
60
+ - spec/examples/simple.md
61
+ - spec/examples/with_errors.md
62
+ - spec/mdspell/spell_checker_spec.rb
63
+ - spec/mdspell/text_line_spec.rb
64
+ - spec/mdspell/typo_spec.rb
65
+ - spec/spec_helper.rb
66
+ homepage: https://github.com/mtuchowski/mdspell
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options:
72
+ - "--charset"
73
+ - UTF-8
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.0.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.4.8
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: A Ruby markdown spell checking tool.
92
+ test_files:
93
+ - spec/spec_helper.rb
94
+ - spec/examples/with_errors.md
95
+ - spec/examples/simple.md
96
+ - spec/mdspell/text_line_spec.rb
97
+ - spec/mdspell/typo_spec.rb
98
+ - spec/mdspell/spell_checker_spec.rb
99
+ - spec/examples.cache
100
+ has_rdoc: