middleman-spellcheck 0.9.0 → 0.9.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fea98d00ab58220965c1e2b8118063d0fbf50b13
4
- data.tar.gz: e35c46312d5c3a4afafea88635142e982d920368
3
+ metadata.gz: d50552923d8b8b4e3f9f0bcdc9a6f17f5229ecf9
4
+ data.tar.gz: fdd05ae0af2f6c4bcd0ca9674c28e226456c510c
5
5
  SHA512:
6
- metadata.gz: ae6225286fc01dbcfd6abe17f91b3b3b99f0250a1ed3ea2bbc8d2eb9b499af404826262b57e14146931318904b21dc65b51a3836cad6c7f3405b12e68c1cbfe6
7
- data.tar.gz: 694260deefae946b9b7c8d76aeb3eb17ae7ffd4edbda7fb81c361113daac96dcacd32ac66917dd291b41cd30b4e461a19d682351f143bf60b49bad4d790a3c55
6
+ metadata.gz: 14cb5229c5da423142e23b3efe3cd0d5d7f3e2e5b0c099211e20ad3e677a3031d778cb8cf3e83a0c225c32722ec6b2f3d758c6c9911e5c70fe7b9d4480f065d1
7
+ data.tar.gz: e04e1cf5302675eaac3d9d06161fb0b0a2307ff24a3c10d93a8e7b95f655a954f01f021e1009220e4fdd9e7a9f7dc81748a89ecf8b9fdc2e59f2378cc5d9ab1e
data/README.md CHANGED
@@ -25,31 +25,50 @@ middleman spellcheck source/blog/
25
25
 
26
26
  ## Usage
27
27
 
28
- You can spellcheck only some resources using a regex with the URL:
28
+ There are several ways to select what content will be checked.
29
29
 
30
- ```ruby
31
- activate :spellcheck, page: "documentation/*" # you can use regexes, too, e.g. /post_[1-9]/
32
- ```
30
+ 1. To spellcheck only some resources using a regex with the URL:
33
31
 
34
- You can limit which tags the spell checker will only run through:
32
+ ```ruby
33
+ activate :spellcheck, page: "documentation/*" # you can use regexes, too, e.g. /post_[1-9]/
34
+ ```
35
35
 
36
- ```ruby
37
- activate :spellcheck, tags: :p # pass an array of tags if you have more!
38
- ```
36
+ 2. To limit which tags the spell checker will only run through:
39
37
 
40
- If there are some words that you would like to be allowed
38
+ ```ruby
39
+ activate :spellcheck, tags: :p # pass an array of tags if you have more!
40
+ ```
41
41
 
42
- ```ruby
43
- activate :spellcheck, allow: ["Gooby", "pls"]
44
- ```
42
+ 3. To ignore sections by using css selectors
43
+ For example, to ignore all sections with a class of `CodeRay`:
44
+
45
+ ```ruby
46
+ activate :spellcheck, ignore_selector: '.CodeRay'
47
+ ```
48
+
49
+ Or to ignore all tables in a document:
50
+
51
+ ```ruby
52
+ activate :spellcheck, ignore_selector: 'table'
53
+ ```
45
54
 
46
- Middleman-spellcheck automatically ignores `.css`, `.js`, & `.coffee` file
55
+ Or to ignore all `<p class="technical-jargon">`:
56
+ ```ruby
57
+ activate :spellcheck, ignore_selector: 'p.technical-jargon'
58
+ ```
59
+
60
+ To ignore multiple selectors, seperate them with a comma
61
+ ```ruby
62
+ activate :spellcheck, ignore_selector: 'p.technical-jargon, .CodeRay'
63
+ ```
64
+
65
+ 4. Middleman-spellcheck automatically ignores `.css`, `.js`, & `.coffee` file
47
66
  extensions. If there are some additional file type extensions that you would
48
67
  like to skip:
49
68
 
50
- ```ruby
51
- activate :spellcheck, ignored_exts: [".xml", ".png"]
52
- ```
69
+ ```ruby
70
+ activate :spellcheck, ignored_exts: [".xml", ".png"]
71
+ ```
53
72
 
54
73
  To select a dictionary used by a spellchecker, use lang: option. For
55
74
  example, to use Polish dictionary, use:
@@ -60,12 +79,15 @@ activate :spellcheck, lang: "pl"
60
79
 
61
80
  If you define the ``lang`` metadata in your pages / articles, then spellcheck will use those language.
62
81
 
63
- Middleman-spellcheck can issue many warnings if you run it over a new
64
- content. If you want to give yourself a chance to fix mistakes gradually and
65
- not fail each time you build, use :dontfail flag:
82
+ ## Options
83
+
84
+
85
+ For warnings only (allow build to pass), use `dontfail` option.
86
+ This is helpful when you want to give yourself a chance to fix mistakes or false hits gradually and
87
+ not fail each time you build.
66
88
 
67
89
  ```ruby
68
- activate :spellcheck, lang: "en", dontfail: 1
90
+ activate :spellcheck, dontfail: 1
69
91
  ```
70
92
 
71
93
  You can also disable the automatic spellcheck after build (and only run manual checks from the command line):
@@ -89,9 +111,84 @@ who encountered issues, useful might be debug: option, which will turn on
89
111
  extensive amount of debugging.
90
112
 
91
113
  ```ruby
92
- activate :spellcheck, debug: 1
114
+ activate :spellcheck, lang: "en", debug: 1
93
115
  ```
94
116
 
117
+ If there are some words that you would like to be allowed you can pass them to the allow option as an array. **Depricated - Please see the "Fixing spelling mistakes" section for now prefered way to include allowed words
118
+
119
+ ```ruby
120
+ activate :spellcheck, allow: ["Gooby", "pls"]
121
+ ```
122
+
123
+ You can also pass a regex to the `ignore_regex` option. Any match will be ignored.
124
+ For example to remove words in quotes
125
+ ```ruby
126
+ activate :spellcheck, lang: "en", ignore_regex: /\s('|")\w*('|")(\s|\.|,)/
127
+ ```
128
+
129
+ ## Fixing spelling mistakes & false positives
130
+
131
+ The `middleman-spellchecker` extension is likely to generate large number
132
+ of false-positives, e.g.: words which the spellchecker will consider
133
+ incorrect (not present in a dictionary), which yet may have a valid meaning
134
+ in the article's context. Common problems are acronyms, technical terms and
135
+ names. To solve this, `middleman-spellcheck` offers two solutions:
136
+
137
+ 1. The `spellcheck_allow_file` file, which points to the path with a file
138
+ containing words considered correct. Author of the website may decide which
139
+ words are allowed to be used site-wide. Example: if you write a lot about
140
+ IBM products, this file would have names such as "IBM", "AIX" or "DB/2".
141
+ Add the words one word per line without quotes.
142
+
143
+ To set the global file, use the following clause in your `config.rb`:
144
+
145
+ ```set :spellcheck_allow_file, "./data/words_allowed.txt"```
146
+
147
+ 2. The `spellcheck-allow` keyword in a frontmatter, which will work in the
148
+ context of this particular article, but not other articles. Example: your
149
+ blog is about IBM, but 1 article is about AirBnB. You'd put `AirBnB` into
150
+ your front-matter.
151
+
152
+
153
+ To use 2nd solution, add the following to your frontmatter:
154
+
155
+ ```
156
+ title: "Blog about IBM"
157
+ ...
158
+ spellcheck-allow:
159
+ - "AirBnB"```
160
+
161
+ Another example
162
+
163
+ ```
164
+ title: "Some time ago"
165
+ ...
166
+ spellcheck-allowed:
167
+ - GitHub
168
+ - Linux
169
+ ```
170
+
171
+ The `middleman-spellcheck` also comes with a simple CLI for fixing many
172
+ problems in your articles. To invoke:
173
+
174
+ ```middleman spellcheck source/blog/2015-11-01-nginx-on-travis-ci.md --fix```
175
+
176
+ This will pull up simple CLI menu and for each misspelled word, you'll have
177
+ a following choice
178
+
179
+ | Key to press | Effect |
180
+ |--------------|--------|
181
+ | g | Add the word to the `spellcheck_allow_file` |
182
+ | f | Add the word to this article's front-matter |
183
+ | i | Ignore the word for now and deal with it later |
184
+
185
+
186
+ After the run is finished, `middleman-spellchecker` will write a fixed file
187
+ to `source/blog/2015-11-01-nginx-on-travis-ci.md.fixed`. This is a safe
188
+ choice for not creating damage. If you don't want to fiddle with it, the
189
+ `--inplace` switch will make changes dynamically, and the input file will
190
+ get overwritten.
191
+
95
192
  ## Contributing
96
193
 
97
194
  1. Fork it
@@ -1,10 +1,75 @@
1
1
  module Middleman
2
2
  module Cli
3
- # This class provides an "spellchecl" command for the middleman CLI.
3
+ # This class provides a "spellcheck" command for the middleman CLI.
4
4
  class Spellcheck < Thor
5
5
  include Thor::Actions
6
+
7
+ check_unknown_options!
8
+
9
+ namespace :spellcheck
10
+
11
+ no_commands {
12
+ def misspell_ask(misspell, allow_file)
13
+ if not options[:fix]
14
+ return false
15
+ end
16
+
17
+ print "-" * 70, "\n"
18
+ print "'#{misspell[:word]}' is misspelled. What to do?:\n"
19
+ print "g\tadd allowed word to '#{allow_file}'\n" if allow_file
20
+ print "f\tadd allowed word to frontmatter\n"
21
+ print "i\tignore word (deal with it later)\n"
22
+
23
+ print "Select option and press ENTER:\n"
24
+ STDIN.gets()[0]
25
+ end
26
+
27
+ def misspell_fixes_global(resource, words_allow_global, allow_file)
28
+ open(allow_file, 'a') { |f|
29
+ words_allow_global.each do |w|
30
+ f.puts "#{w}\t#\t#{resource.source_file}\n"
31
+ end
32
+ }
33
+ end
34
+
35
+ def misspell_fixes_frontmatter(resource, words_allow_frontmatter)
36
+ data = File.read(resource.source_file)
37
+ if options[:inplace] then fn_ext = "" else ".fixed" end
38
+ fn_fixed = "#{resource.source_file}#{fn_ext}"
39
+ fixed = File.open(fn_fixed, "w")
40
+ sep_tag_cnt = 0
41
+ had_spellcheck_tag = false
42
+ data.each_line do |line|
43
+ if line =~ /^\-\-\-$/ then
44
+ sep_tag_cnt += 1
45
+ end
46
+ if line =~ /spellcheck-allow:/ then
47
+ had_spellcheck_tag = true
48
+ end
49
+
50
+ if sep_tag_cnt == 2 then
51
+ if had_spellcheck_tag == false then
52
+ fixed.puts "spellcheck-allow:\n"
53
+ end
54
+ words_allow_frontmatter.each do |w|
55
+ fixed.puts "- \"#{w}\"\n"
56
+ end
57
+ fixed.puts "---\n"
58
+ sep_tag_cnt = nil
59
+ else
60
+ fixed.puts line
61
+ end
62
+ end
63
+ fixed.close()
64
+ print "Fixed spellchecked file written to #{fn_fixed}\n"
65
+ end
66
+ }
67
+
6
68
  namespace :spellcheck
7
69
  desc "spellcheck FILE", "Run spellcheck on given file or path"
70
+ method_option "fix", :type => :boolean, :aliases => "-f", :desc => "Fix spelling error interactively"
71
+ method_option "inplace", :type => :boolean, :aliases => "-i", :desc => "Modify files in place (dangerous)"
72
+
8
73
  def spellcheck(*paths)
9
74
  app = ::Middleman::Application.server.inst
10
75
 
@@ -14,18 +79,40 @@ module Middleman
14
79
  }
15
80
  }
16
81
  if resources.empty?
17
- $stderr.puts "File / Directory #{path} not exist"
82
+ $stderr.puts "File / Directory #{paths} not exist"
18
83
  exit 1
19
84
  end
20
85
  ext = app.extensions[:spellcheck]
86
+
87
+ allow_file = app.config.defines_setting?(:spellcheck_allow_file) ?
88
+ app.config[:spellcheck_allow_file] : nil
89
+ if options[:fix] then
90
+ print "Spellchecker fix mode on! Will attempt to white-list some words\n"
91
+ end
21
92
  resources.each do |resource|
22
- say_status :spellcheck, "Running spell checker for #{resource.url}", :blue
93
+ say_status :spellcheck, "Running spell checker for #{resource.source_file}", :blue
23
94
  current_misspelled = ext.spellcheck_resource(resource)
95
+
96
+ words_allow_frontmatter = []
97
+ words_allow_global = []
24
98
  current_misspelled.each do |misspell|
25
- say_status :misspell, ext.error_message(misspell), :red
99
+ fix = misspell_ask(misspell, allow_file)
100
+ was_fixed = true
101
+ if fix == 'g' then words_allow_global << misspell[:word]
102
+ elsif fix == 'f' then words_allow_frontmatter << misspell[:word]
103
+ else was_fixed = false end
104
+
105
+ if was_fixed
106
+ say_status :spellcheck, "Fixed word #{misspell[:word]}"
107
+ else
108
+ say_status :misspell, ext.error_message(misspell), :red
109
+ end
26
110
  end
111
+ misspell_fixes_global(resource, words_allow_global, allow_file) unless words_allow_global.empty?
112
+ misspell_fixes_frontmatter(resource, words_allow_frontmatter) unless words_allow_frontmatter.empty?
27
113
  end
28
114
  end
115
+
29
116
  end
30
117
  end
31
118
  end
@@ -6,14 +6,17 @@ module Middleman
6
6
  module Spellcheck
7
7
  class SpellcheckExtension < Extension
8
8
  REJECTED_EXTS = %w(.css .js .coffee)
9
+ ALLOWED_WORDS = []
9
10
  option :page, "/*", "Run only pages that match the regex through the spellchecker"
10
11
  option :tags, [], "Run spellcheck only on some tags from the output"
11
12
  option :allow, [], "Allow specific words to be misspelled"
12
13
  option :ignored_exts, [], "Ignore specific extensions (ex: '.xml')"
14
+ option :ignore_regex, false, "Ignore regex matches"
15
+ option :ignore_selector, false, "Ignore nodes with a css selector"
13
16
  option :lang, "en", "Language for spellchecking"
14
17
  option :cmdargs, "", "Pass alternative command line arguments"
15
18
  option :debug, 0, "Enable debugging (for developers only)"
16
- option :dontfail, 0, "Don't fail when misspelled words are found"
19
+ option :dontfail, false, "Don't fail because misspelled words are found"
17
20
  option :run_after_build, true, "Run Spellcheck after build"
18
21
 
19
22
  def after_build(builder)
@@ -32,13 +35,14 @@ module Middleman
32
35
  total_misspelled += current_misspelled
33
36
  end
34
37
 
35
- unless total_misspelled.empty?
36
- estr = "Build failed. There are spelling errors."
38
+ builder.say_status :spellcheck, "Spellchecks done. #{total_misspelled.length} misspelling(s) found.", :blue
39
+
40
+ unless total_misspelled.empty?
37
41
  if options.dontfail
38
- print "== :dontfail set! Will issue warning only, but not fail.\n"
39
- print estr, "\n"
42
+ builder.say_status :spellcheck, "dontfail is set! Builder will ignore misspellings.", :yellow
40
43
  else
41
- raise Thor::Error, estr
44
+ desc = "Build failed. There are spelling errors."
45
+ raise Thor::Error, desc
42
46
  end
43
47
  end
44
48
  end
@@ -48,6 +52,10 @@ module Middleman
48
52
  doc = Nokogiri::HTML.fragment(rendered_resource)
49
53
  doc.search('code,style,script').each(&:remove)
50
54
 
55
+ if options.ignore_selector
56
+ doc.css(options.ignore_selector).each(&:remove)
57
+ end
58
+
51
59
  if options.tags.empty?
52
60
  doc.text
53
61
  else
@@ -55,6 +63,14 @@ module Middleman
55
63
  end
56
64
  end
57
65
 
66
+ def regex_filter_content(text)
67
+ if options.ignore_regex
68
+ text.to_s.gsub options.ignore_regex , ' '
69
+ else
70
+ text
71
+ end
72
+ end
73
+
58
74
  def option_tags
59
75
  if options.tags.is_a? Array
60
76
  options.tags
@@ -85,26 +101,58 @@ module Middleman
85
101
  else
86
102
  options.lang
87
103
  end
88
- run_check(select_content(resource), lang)
104
+ run_check(resource, lang)
89
105
  end
90
106
 
91
- def run_check(text, lang)
107
+ def run_check(resource, lang)
108
+ text = select_content(resource)
109
+ text = regex_filter_content(text)
92
110
  results = Spellchecker.check(text, lang)
93
- results = exclude_allowed(results)
111
+ results = exclude_allowed(resource, results)
94
112
  results.reject { |entry| entry[:correct] }
95
113
  end
96
114
 
97
- def exclude_allowed(results)
98
- results.reject { |entry| option_allowed.include? entry[:word].downcase }
115
+ def exclude_allowed(resource, results)
116
+ results.reject { |entry| allowed_words(resource).include? entry[:word].downcase }
99
117
  end
100
118
 
101
- def option_allowed
102
- allowed = if options.allow.is_a? Array
119
+ def allowed_words(resource)
120
+ words_ok = if options.allow.is_a? Array
103
121
  options.allow
104
122
  else
105
123
  [options.allow]
106
124
  end
107
- allowed.map(&:downcase)
125
+ words_ok += allowed_words_frontmatter(resource)
126
+ words_ok += allowed_words_file
127
+ words_ok.map(&:downcase)
128
+ end
129
+
130
+ def allowed_words_frontmatter(resource)
131
+ words_ok = []
132
+ if resource.data.include?("spellcheck-allow") then
133
+ allowed_tmp = resource.data["spellcheck-allow"]
134
+ words_ok += if allowed_tmp.is_a? Array
135
+ allowed_tmp
136
+ else
137
+ [allowed_tmp]
138
+ end
139
+ end
140
+ words_ok
141
+ end
142
+
143
+ def allowed_words_file
144
+ allow_file = nil
145
+ if app.config.defines_setting?(:spellcheck_allow_file)
146
+ allow_file = app.config[:spellcheck_allow_file]
147
+ end
148
+ if ALLOWED_WORDS.empty? && allow_file != nil
149
+ lines = File.read(allow_file)
150
+ lines.split("\n").each do |line|
151
+ next if line =~ /^#/ or line =~ /^$/
152
+ ALLOWED_WORDS << line.partition('#').first.strip
153
+ end
154
+ end
155
+ ALLOWED_WORDS
108
156
  end
109
157
 
110
158
  def option_ignored_exts
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  class Spellchecker
2
4
  @@aspell_path = "aspell"
3
5
  @@aspell_cmdargs = ""
@@ -76,7 +78,8 @@ class Spellchecker
76
78
  text.gsub! '’', '\''
77
79
  sdbg "self.check got raw text:\n#{text}\n"
78
80
 
79
- words = text.split(/[^\p{L}']+/).select { |s|
81
+ #Split words and
82
+ words = text.split(/'?[^\p{L}']+'?/).select { |s|
80
83
  s != "" and s != "'s" and s != "'"
81
84
  }.uniq
82
85
  sdbg "self.check word array:\n#{words}\n"
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module Spellcheck
3
- VERSION = "0.9.0"
3
+ VERSION = "0.9.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-spellcheck
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Zarea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-03 00:00:00.000000000 Z
11
+ date: 2016-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman-core
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  version: '0'
128
128
  requirements: []
129
129
  rubyforge_project:
130
- rubygems_version: 2.2.2
130
+ rubygems_version: 2.4.8
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Run spell checks as a build phase in middleman