marcdouane 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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +109 -0
- data/Rakefile +12 -0
- data/bin/marcdouane +67 -0
- data/lib/marcdouane/file_checker.rb +54 -0
- data/lib/marcdouane/rules/consistent_header_style.rb +35 -0
- data/lib/marcdouane/rules/ensure_headers_cascade.rb +27 -0
- data/lib/marcdouane/rules/line_length.rb +30 -0
- data/lib/marcdouane/rules/no_consecutive_blank_lines.rb +22 -0
- data/lib/marcdouane/rules/rule.rb +52 -0
- data/lib/marcdouane/rules/start_with_top_level_header.rb +19 -0
- data/lib/marcdouane/rules.rb +9 -0
- data/lib/marcdouane/version.rb +5 -0
- data/lib/marcdouane.rb +17 -0
- data/logo.jpeg +0 -0
- data/sig/marcdouane.rbs +4 -0
- metadata +116 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1ac5051e1dda30d1dd98035ba682431ac8e32788b4187772eea00e1306f5ca1d
|
|
4
|
+
data.tar.gz: 2b60396b0e783bf920602fd49c2d04e4288e2c9b35e1485f85e7a94a5653d046
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e054ef7079b1bf87c8203d3db165a43c3b26ffa7fc7fd1301a346060b0b25e60b7868f82550972992291b16875a5ce22512784417f489f990a673aa49fb1f501
|
|
7
|
+
data.tar.gz: 3982749d76b7e586a67b6ed6a5b8ef13bcc3ecea6c0877166ac6fe00605979fd2904c5c069d9b1a0d16da9bbac9e98f186c2a21264038f7849648d78166d426e
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stéphane Maniaci
|
|
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,109 @@
|
|
|
1
|
+
# Marc d'Ouane
|
|
2
|
+
|
|
3
|
+
a beautiful, epic Markdown linter
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bundle add marcdouane
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gem install marcdouane
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Checking a file with default rules:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
marcdouane check some-file.md
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For the complete tour just use
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
marcdouane
|
|
33
|
+
marcdouane check --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
Some rules have settings (see `lib/marcdouane/rules.rb` for
|
|
39
|
+
now). These settings can be overriden with a YAML config file that
|
|
40
|
+
resembles the Rubocop config:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
LineLength:
|
|
44
|
+
maximum_line_length: 90 # which is utter madness
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
I'm doing it
|
|
50
|
+
|
|
51
|
+
## Contributing
|
|
52
|
+
|
|
53
|
+
A rule must inherit `Marcdouane::Rule`. It must answer to `check!` and
|
|
54
|
+
raise a `Marcdouane::Error` with an `ERROR_MESSAGE` and a line
|
|
55
|
+
number. Example:
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
class CheckAnglois < Marcdouane::Rule
|
|
59
|
+
ERROR_MESSAGE = "Do not mention the English"
|
|
60
|
+
|
|
61
|
+
def check!
|
|
62
|
+
File
|
|
63
|
+
.read(file)
|
|
64
|
+
.lines
|
|
65
|
+
.each_with_index(line, index) do
|
|
66
|
+
raise Marcdouane:Error.new(ERROR_MESSAGE, index + 1) if line =~ /anglois/
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
It is then expected to be tested throughout the Cucumber feature tests
|
|
73
|
+
like such:
|
|
74
|
+
|
|
75
|
+
```feature
|
|
76
|
+
Feature: Built-in Markdown Rules
|
|
77
|
+
# [...]
|
|
78
|
+
|
|
79
|
+
Rule: Don't mention the English
|
|
80
|
+
Example: It fails when the English are mentioned
|
|
81
|
+
Given a file named "foo.md" with:
|
|
82
|
+
"""
|
|
83
|
+
# Tout va bien
|
|
84
|
+
Pas d'anglois à l'horizon
|
|
85
|
+
"""
|
|
86
|
+
When I run `marcdouane check "foo.md"`
|
|
87
|
+
Then it should fail with:
|
|
88
|
+
"""
|
|
89
|
+
foo.md:2: Don't mention the English
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
Example: It passes when the English are not mentioned
|
|
93
|
+
Given a file named "foo.md" with:
|
|
94
|
+
"""
|
|
95
|
+
# Tout va bien
|
|
96
|
+
Quelques voix dans la tête mais tranquille
|
|
97
|
+
"""
|
|
98
|
+
When I run `marcdouane check "foo.md"`
|
|
99
|
+
Then it should pass
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
104
|
+
https://github.com/freesteph/marcdouane.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
The gem is available as open source under the terms of the [MIT
|
|
109
|
+
License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/marcdouane
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "dry/cli"
|
|
6
|
+
require "marcdouane"
|
|
7
|
+
|
|
8
|
+
module Marcdouane
|
|
9
|
+
module CLI
|
|
10
|
+
module Commands
|
|
11
|
+
extend Dry::CLI::Registry
|
|
12
|
+
|
|
13
|
+
class Version < Dry::CLI::Command
|
|
14
|
+
desc "Print version"
|
|
15
|
+
|
|
16
|
+
def call(*)
|
|
17
|
+
puts Marcdouane::VERSION
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Check < Dry::CLI::Command
|
|
22
|
+
desc "Check the Markdown of one or more file"
|
|
23
|
+
|
|
24
|
+
option :verbose,
|
|
25
|
+
type: :boolean,
|
|
26
|
+
default: false,
|
|
27
|
+
desc: "Verbose output"
|
|
28
|
+
|
|
29
|
+
option :config,
|
|
30
|
+
type: :string,
|
|
31
|
+
required: false,
|
|
32
|
+
desc: "Configuration file"
|
|
33
|
+
|
|
34
|
+
argument :files,
|
|
35
|
+
type: :array,
|
|
36
|
+
required: true,
|
|
37
|
+
desc: "Files to check against"
|
|
38
|
+
|
|
39
|
+
def call(files: [], **options)
|
|
40
|
+
if files.empty?
|
|
41
|
+
puts "No files provided."
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
exit_code = 0
|
|
46
|
+
|
|
47
|
+
files.each do |file|
|
|
48
|
+
if !File.exist?(file)
|
|
49
|
+
$stderr.puts "`#{file}' is missing, or not a valid file."
|
|
50
|
+
exit_code = 1
|
|
51
|
+
else
|
|
52
|
+
exit_code = Marcdouane::FileChecker.call(file, options)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
exit(exit_code)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
register "version", Version, aliases: ["v", "-v", "--version"]
|
|
62
|
+
register "check", Check
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Dry::CLI.new(Marcdouane::CLI::Commands).call
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "debug"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
require_relative "rules"
|
|
7
|
+
|
|
8
|
+
module Marcdouane
|
|
9
|
+
class FileChecker
|
|
10
|
+
class << self
|
|
11
|
+
def call(file, options)
|
|
12
|
+
verbose = options.fetch(:verbose)
|
|
13
|
+
|
|
14
|
+
parse_config!(options[:config])
|
|
15
|
+
|
|
16
|
+
puts "Checking `#{file}'..." if verbose
|
|
17
|
+
|
|
18
|
+
exit_code = 0
|
|
19
|
+
|
|
20
|
+
rules.each do |rule|
|
|
21
|
+
rule.new(file, options).check!
|
|
22
|
+
rescue Marcdouane::Error => e
|
|
23
|
+
$stderr.puts("#{file}:#{e.line_number}: #{e.message}")
|
|
24
|
+
|
|
25
|
+
exit_code = 1
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
puts "Done." if verbose
|
|
29
|
+
|
|
30
|
+
exit_code
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def parse_config!(path)
|
|
34
|
+
return if path.nil?
|
|
35
|
+
|
|
36
|
+
config = YAML.load_file(path)
|
|
37
|
+
|
|
38
|
+
config.each do |klass, hash|
|
|
39
|
+
hash.each do |key, value|
|
|
40
|
+
rule_class = "Marcdouane::Rules::#{klass}"
|
|
41
|
+
|
|
42
|
+
const_get(rule_class).class_eval do
|
|
43
|
+
self.config[key.to_sym] = value
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def rules
|
|
50
|
+
Marcdouane::Rules::Rule.subclasses
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marcdouane
|
|
4
|
+
module Rules
|
|
5
|
+
class ConsistentHeaderStyle < Rule
|
|
6
|
+
ERROR_MESSAGE = "Use a unique, consistent header style"
|
|
7
|
+
|
|
8
|
+
def check!
|
|
9
|
+
reference_style, style = nil
|
|
10
|
+
|
|
11
|
+
source = @markdown.source.lines.dup
|
|
12
|
+
|
|
13
|
+
@markdown.on(:heading) do |header|
|
|
14
|
+
line_number = line_number_from_byte_range(header.byte_range)
|
|
15
|
+
|
|
16
|
+
raw_line = source[line_number]
|
|
17
|
+
|
|
18
|
+
if raw_line.start_with?("#")
|
|
19
|
+
style = :normal
|
|
20
|
+
else
|
|
21
|
+
style = :underline
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
reference_style ||= style
|
|
25
|
+
|
|
26
|
+
if reference_style != style
|
|
27
|
+
error!(line_number)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@markdown.walk
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marcdouane
|
|
4
|
+
module Rules
|
|
5
|
+
# Ensure that every child header is always a direct descendant of
|
|
6
|
+
# the previous header (i.e its level increments by 1).
|
|
7
|
+
class EnsureHeadersCascade < Rule
|
|
8
|
+
ERROR_MESSAGE = "Header levels should increment one at a time"
|
|
9
|
+
|
|
10
|
+
def check!
|
|
11
|
+
previous_level = nil
|
|
12
|
+
|
|
13
|
+
@markdown.on(:heading) do |header|
|
|
14
|
+
previous_level ||= header.level
|
|
15
|
+
|
|
16
|
+
if header.level > previous_level && header.level != previous_level + 1
|
|
17
|
+
error!(line_number_from_byte_range(header.byte_range))
|
|
18
|
+
else
|
|
19
|
+
previous_level = header.level
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@markdown.walk
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
URI_REGEXP = URI::RFC2396_PARSER.make_regexp
|
|
6
|
+
|
|
7
|
+
module Marcdouane
|
|
8
|
+
module Rules
|
|
9
|
+
# Ensure the line-length does not go over the default (80)
|
|
10
|
+
# character limit. Link references are not accounted for.
|
|
11
|
+
class LineLength < Rule
|
|
12
|
+
ERROR_MESSAGE = "Line-length is over %s characters"
|
|
13
|
+
|
|
14
|
+
setting :maximum_line_length, default: 80, reader: true
|
|
15
|
+
|
|
16
|
+
def check!
|
|
17
|
+
@markdown.source.lines.each_with_index do |line, index|
|
|
18
|
+
if line.match?(/^\[.*\]: #{URI_REGEXP}$/)
|
|
19
|
+
next
|
|
20
|
+
elsif line.length > self.class.maximum_line_length
|
|
21
|
+
error!(
|
|
22
|
+
index,
|
|
23
|
+
ERROR_MESSAGE % self.class.maximum_line_length
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marcdouane
|
|
4
|
+
module Rules
|
|
5
|
+
# Ensure there are no consecutive blank lines
|
|
6
|
+
class NoConsecutiveBlankLines < Rule
|
|
7
|
+
ERROR_MESSAGE = "Consecutive blank lines"
|
|
8
|
+
|
|
9
|
+
def check!
|
|
10
|
+
@markdown
|
|
11
|
+
.source
|
|
12
|
+
.lines
|
|
13
|
+
.each_cons(2)
|
|
14
|
+
.each_with_index do |pair, index|
|
|
15
|
+
if pair.map(&:strip).all?(&:empty?)
|
|
16
|
+
error!(index + 2)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/configurable"
|
|
4
|
+
require "inkmark"
|
|
5
|
+
|
|
6
|
+
module Marcdouane
|
|
7
|
+
module Rules
|
|
8
|
+
# Rule is the base class to regroup all rules. It is initialized
|
|
9
|
+
# with a file path and some options forwarded from the CLI
|
|
10
|
+
# invocation.
|
|
11
|
+
#
|
|
12
|
+
# Subclasses must implement `check!` and provide an
|
|
13
|
+
# ERROR_MESSAGE when the check fails.
|
|
14
|
+
class Rule
|
|
15
|
+
extend Dry::Configurable
|
|
16
|
+
|
|
17
|
+
attr_reader :file, :options, :markdown
|
|
18
|
+
|
|
19
|
+
def initialize(file, options)
|
|
20
|
+
@file = file
|
|
21
|
+
@options = options
|
|
22
|
+
@markdown = Inkmark.new(
|
|
23
|
+
File.read(file),
|
|
24
|
+
options: {
|
|
25
|
+
frontmatter: true
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def line_number_from_byte_range(range)
|
|
31
|
+
File.binread(file, range.first).count("\n")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def identifier
|
|
35
|
+
self.class.to_s.split("::").last
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Produces an error that will be collected and output by the
|
|
39
|
+
# CLI. It must be called with the 0-indexed line-number, and an
|
|
40
|
+
# optional `message` override instead of the class's
|
|
41
|
+
# ERROR_MESSAGE.
|
|
42
|
+
def error!(machine_line_number, message = nil)
|
|
43
|
+
msg = message || self.class.const_get("ERROR_MESSAGE")
|
|
44
|
+
|
|
45
|
+
raise Marcdouane::Error.new(
|
|
46
|
+
"[#{identifier}] #{msg}",
|
|
47
|
+
machine_line_number + 1
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Marcdouane
|
|
4
|
+
module Rules
|
|
5
|
+
# Ensure the first line, frontmatter or not, is a top-level
|
|
6
|
+
# header.
|
|
7
|
+
class StartWithTopLevelHeader < Rule
|
|
8
|
+
ERROR_MESSAGE = "The file should start with a top-level header"
|
|
9
|
+
|
|
10
|
+
def check!
|
|
11
|
+
sections = @markdown.chunks_by_heading
|
|
12
|
+
|
|
13
|
+
if sections.empty? || sections.first[:level] != 1
|
|
14
|
+
error!(0)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "rules/rule"
|
|
4
|
+
|
|
5
|
+
require_relative "rules/ensure_headers_cascade"
|
|
6
|
+
require_relative "rules/line_length"
|
|
7
|
+
require_relative "rules/no_consecutive_blank_lines"
|
|
8
|
+
require_relative "rules/start_with_top_level_header"
|
|
9
|
+
require_relative "rules/consistent_header_style"
|
data/lib/marcdouane.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "marcdouane/version"
|
|
4
|
+
require_relative "marcdouane/file_checker"
|
|
5
|
+
|
|
6
|
+
module Marcdouane
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
attr_reader :msg, :line_number
|
|
9
|
+
|
|
10
|
+
def initialize(msg, line_number)
|
|
11
|
+
@msg = msg
|
|
12
|
+
@line_number = line_number
|
|
13
|
+
|
|
14
|
+
super(@msg)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/logo.jpeg
ADDED
|
Binary file
|
data/sig/marcdouane.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: marcdouane
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Stéphane Maniaci
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: dry-cli
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.4'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.4'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: dry-configurable
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.4'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.4'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: inkmark
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.1.3
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.1.3
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: yaml
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.4'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.4'
|
|
68
|
+
description: Marcdouane lints Markdown files and can be easily extended to fit your
|
|
69
|
+
needs.
|
|
70
|
+
email:
|
|
71
|
+
- stephane.maniaci@gmail.com
|
|
72
|
+
executables:
|
|
73
|
+
- marcdouane
|
|
74
|
+
extensions: []
|
|
75
|
+
extra_rdoc_files: []
|
|
76
|
+
files:
|
|
77
|
+
- LICENSE.txt
|
|
78
|
+
- README.md
|
|
79
|
+
- Rakefile
|
|
80
|
+
- bin/marcdouane
|
|
81
|
+
- lib/marcdouane.rb
|
|
82
|
+
- lib/marcdouane/file_checker.rb
|
|
83
|
+
- lib/marcdouane/rules.rb
|
|
84
|
+
- lib/marcdouane/rules/consistent_header_style.rb
|
|
85
|
+
- lib/marcdouane/rules/ensure_headers_cascade.rb
|
|
86
|
+
- lib/marcdouane/rules/line_length.rb
|
|
87
|
+
- lib/marcdouane/rules/no_consecutive_blank_lines.rb
|
|
88
|
+
- lib/marcdouane/rules/rule.rb
|
|
89
|
+
- lib/marcdouane/rules/start_with_top_level_header.rb
|
|
90
|
+
- lib/marcdouane/version.rb
|
|
91
|
+
- logo.jpeg
|
|
92
|
+
- sig/marcdouane.rbs
|
|
93
|
+
homepage: https://github.com/freesteph/marcdouane
|
|
94
|
+
licenses:
|
|
95
|
+
- MIT
|
|
96
|
+
metadata:
|
|
97
|
+
homepage_uri: https://github.com/freesteph/marcdouane
|
|
98
|
+
source_code_uri: https://github.com/freesteph/marcdouane
|
|
99
|
+
rdoc_options: []
|
|
100
|
+
require_paths:
|
|
101
|
+
- lib
|
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '4.0'
|
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
112
|
+
requirements: []
|
|
113
|
+
rubygems_version: 4.0.10
|
|
114
|
+
specification_version: 4
|
|
115
|
+
summary: Marcdouane is a pretty Markdown linter
|
|
116
|
+
test_files: []
|