Skip to content

Instantly share code, notes, and snippets.

@AliSoftware
Last active February 9, 2019 16:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AliSoftware/b36b4ff089929f340ffdc458b9cccf4a to your computer and use it in GitHub Desktop.
Save AliSoftware/b36b4ff089929f340ffdc458b9cccf4a to your computer and use it in GitHub Desktop.
Runs SwiftLint on all code snippets found in a markdown file
#!/usr/bin/env ruby
require 'tmpdir'
require 'open3'
# The first parameter is supposed to be the path to the markdown file
input_file = ARGV.first
config_file = ARGV[1] || '.swiftlint.yml'
config_param = File.exist?(config_file) ? " --config #{File.realpath(config_file)}" : ''
Dir.mktmpdir('snippets') do |tmpdir|
buffer = nil
offsets = {}
snippet_index = 0
# Read the markdown file line by line, and extract each snippet into its own file
File.foreach(input_file).each_with_index do |line, line_number|
if line.chomp == '```' && !buffer.nil?
# end of snippet
path = "#{tmpdir}/snippet-#{snippet_index}.swift"
File.write(path, buffer)
buffer = nil
elsif line =~ /^```(.*)$/
# beginning of snippet
unless $1.empty? || $1 == 'swift' # skip non-swift snippets
puts "Snippet found on line #{line_number} but not swift (#{$1})"
next
end
snippet_index += 1
offsets[snippet_index] = line_number + 1
buffer = ''
elsif !buffer.nil?
# inside snippet
buffer += line
end
end
# Run Swiftlint and dump the output
Open3.popen3("swiftlint lint --path #{tmpdir}#{config_param}") do |stdin, stdout, stderr|
# Print "Linting …" while processing
while line = stderr.gets
STDERR.puts line
end
puts '-----'
# Order the lint violation messages, as Swiftlint doesn't
# guarantee to lint files in alphabetical order
ordered_errors = Array.new(snippet_index) { [] }
stdout.each_line do |line|
if line =~ %r{^#{tmpdir}/snippet-([0-9]+)\.swift:([0-9]+):(.*)$}
new_line_number = $2.to_i + offsets[$1.to_i]
line = "#{input_file}:#{new_line_number}:#{$3}"
end
ordered_errors[$1.to_i - 1] << line
end
STDOUT.puts ordered_errors.flatten
end
end
@AliSoftware
Copy link
Author

Example output:

$ ./lint_snippets_in_markdown.rb README.md
Loading configuration from '/Users/[…]/[…]/.swiftlint.yml'
Linting Swift files at path /var/folders/ng/98cn3mbs14sbflfdm0dl8frmym018y/T/snippets20190115-28364-1obh28
Linting 'snippet-15.swift' (1/18)
Linting 'snippet-17.swift' (2/18)
Linting 'snippet-13.swift' (3/18)
Linting 'snippet-11.swift' (4/18)
Linting 'snippet-9.swift' (5/18)
Linting 'snippet-16.swift' (6/18)
Linting 'snippet-14.swift' (7/18)
Linting 'snippet-10.swift' (8/18)
Linting 'snippet-8.swift' (9/18)
Linting 'snippet-12.swift' (10/18)
Linting 'snippet-6.swift' (11/18)
Linting 'snippet-4.swift' (12/18)
Linting 'snippet-18.swift' (13/18)
Linting 'snippet-2.swift' (14/18)
Linting 'snippet-5.swift' (15/18)
Linting 'snippet-7.swift' (16/18)
Linting 'snippet-3.swift' (17/18)
Linting 'snippet-1.swift' (18/18)
Done linting! Found 9 violations, 0 serious in 18 files.
-----
README.md:80: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:95: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:98: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:127: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:129: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:150: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
README.md:190:39: warning: Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. (colon)
README.md:376:3: warning: Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'vc' (identifier_name)
README.md:416: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment