-
-
Save Pysis868/6a42c95cfb410d5f384c2e8a97ce44f9 to your computer and use it in GitHub Desktop.
Offline renderer for GitHub flavoured markdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
# Renders Markdown content offline by converting it to HTML using GitHub's own redcarpet renderer software, and their additional CSS. | |
# Does require a download of the additional GitHub CSS to a local cache. | |
# Replaces grip for preferred offline functionality: https://github.com/joeyespo/grip/issues/35 | |
# Dependencies: redcarpet | |
require 'optparse' | |
options = { | |
cache: false, | |
replace: false | |
} | |
OptionParser.new do |opts| | |
opts.banner = 'Usage: [cat <file.md> |] gfm-render [options] <file.md>' | |
opts.on('-c', '--cache', 'Only checks to locally cache the additional GitHub CSS file, if it does not exist already.') do | |
options[:cache] = true | |
end | |
opts.on('-f', '--force', 'Sames as -r|--replace.') do | |
options[:replace] = true | |
end | |
opts.on('-h', '--help', "Displays this usage text.") do | |
puts opts | |
exit | |
end | |
opts.on('-r', '--replace', 'Forces a re-download of the additional GitHub CSS file.') do | |
options[:replace] = true | |
end | |
end.parse!(ARGV) | |
gh_markdown_css_filename = File.join(ENV["XDG_CACHE_HOME"] || "#{ENV['HOME']}/.cache", "gfm-render/github-markdown.css") | |
unless File.exist?(gh_markdown_css_filename) && !options[:replace] | |
require 'net/http' | |
require 'pathname' | |
CSS_URL = 'https://raw.githubusercontent.com/sindresorhus/github-markdown-css/main/github-markdown.css' | |
STDERR.puts "Downloading \"#{CSS_URL}\" to the cache at \"#{gh_markdown_css_filename}\"." | |
Pathname.new(gh_markdown_css_filename).dirname.mkpath | |
File.open(gh_markdown_css_filename, "w") do |css| | |
css.write(Net::HTTP.get(URI(CSS_URL))) | |
end | |
end | |
if options[:cache] | |
return | |
end | |
gh_markdown_css = File.read(gh_markdown_css_filename) | |
input = ARGV[0] && ARGV[0] != "-" && File.open(ARGV[0]) || STDIN | |
output = ARGV[1] && File.open(ARGV[1], "w") || STDOUT | |
File.join(ENV["XDG_CACHE_HOME"] || "#{ENV['HOME']}/.cache", "gfm-render") | |
require 'redcarpet' | |
require 'erb' | |
class RenderWithTaskLists < Redcarpet::Render::HTML | |
def list_item(text, list_type) | |
if text.start_with?("[x]", "[X]") | |
text[0..2] = %(<input type="checkbox" class="task-list-item-checkbox" disabled="" checked="checked">) | |
elsif text.start_with?("[ ]") | |
text[0..2] = %(<input type="checkbox" class="task-list-item-checkbox" disabled="">) | |
end | |
%(<li class="task-list-item">#{text}</li>) | |
end | |
end | |
markdown_renderer = Redcarpet::Markdown.new( | |
RenderWithTaskLists, | |
no_intra_emphasis: true, | |
autolink: true, | |
tables: true, | |
fenced_code_blocks: true, | |
lax_spacing: true, | |
) | |
html_output = markdown_renderer.render(input.read) | |
name = input.is_a?(File) && File.basename(input) || "<stdin>" | |
erb = ERB.new(DATA.read) | |
output.write(erb.result) | |
__END__ | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Rendered <%= name %></title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
<%= gh_markdown_css %> | |
@media (prefers-color-scheme: dark) { | |
body { | |
color: #c9d1d9; | |
background-color: #0d1117; | |
} | |
} | |
@media (prefers-color-scheme: light) { | |
body { | |
color: #24292f; | |
background-color: #ffffff; | |
} | |
} | |
.markdown-body { | |
box-sizing: border-box; | |
min-width: 200px; | |
max-width: 980px; | |
margin: 1 auto; | |
padding: 45px; | |
border: 1px solid #d0d7de; | |
border-radius: 6px; | |
} | |
@media (max-width: 767px) { | |
.markdown-body { | |
padding: 15px; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<article class="markdown-body"> | |
<%= html_output %> | |
</article> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment