Skip to content

Instantly share code, notes, and snippets.

@youchan
Created Aug 31, 2019
Embed
What would you like to do?
マンガでわかるRubyのスクリプト
require "psych"
require "redcarpet"
require_relative "./renderer"
require_relative "./toc_renderer"
module Mwr
class Generator
def initialize(workdir)
@workdir = File.expand_path(workdir)
puts @workdir
@files = Psych.load_file("articles.yaml")
@markdown = Redcarpet::Markdown.new(Renderer, autolink: true, tables: true, fenced_code_blocks: true)
end
def generate(filepath)
names = @files.map{|name| File.basename(name, ".md") }
File.open(filepath, "w") do |html|
html.write <<~HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="bw.css">
<link href="https://fonts.googleapis.com/css?family=M+PLUS+Rounded+1c" rel="stylesheet">
</head>
<body>
HTML
File.open(@workdir + "/articles/door.md", "r") do |file|
html.write(@markdown.render(file.read))
end
html.write <<~HTML
<div class="toc">
<h1>目次</h1>
#{TocRenderer.render(@files)}
</div>
<div class="page-break"></div>
HTML
@files.each do |name|
File.open(@workdir + "/" + name, "r") do |file|
html.write(@markdown.render(file.read))
end
end
html.write <<~HTML
</body>
</html>
HTML
end
end
end
end
require "redcarpet"
require "rouge"
require "rouge/plugins/redcarpet"
class Renderer < Redcarpet::Render::HTML
include Rouge::Plugins::Redcarpet
def initialize
super
@sec = 0
@ch = 0
@para = 0
end
def header(c, level)
case level
when 1
@sec += 1
@ch = 0
@para = 0
"<h1 id='sec#{@sec}'>#{c}</h1>\n\n"
when 2
@ch += 1
@para = 0
"<h2 id='ch#{@sec}-#{@ch}'>#{c}</h2>\n\n"
when 3
@para += 1
"<h3 id='para#{@sec}-#{@ch}-#{@para}'>#{c}</h3>\n\n"
when 4
"<h4>#{c}</h4>\n\n"
end
end
def paragraph(text)
case text.strip
when "[begin dialog]"
@in_dialog = true
return "<div class='dialog'>\n"
when "[end dialog]"
@in_dialog = false
return "</div>\n"
when "[page break]"
return "<div class='page-break'></div>\n"
when /\A%([a-z][a-z0-9\-]*):(.*)/m
return "<div class='#{$1}'>#{$2}</div>\n"
end
if @in_dialog
case text
when /^わかばちゃん「(.+)」$/
return <<~HTML
<div class="speech shinra">
<div class="icon"></div>
<div class="baloon">
<p>#{$1}</p>
</div>
</div>
HTML
when /^黒猫先生「(.+)」$/
return <<~HTML
<div class="speech kuroneko">
<div class="icon"></div>
<div class="baloon">
<p>#{$1}</p>
</div>
</div>
HTML
end
end
text = text.strip.gsub(/%([a-z][a-z0-9\-]*){(.*)}/, "<span class='\\1'>\\2</span>")
"<p>#{text.gsub(/ $/, "<br>\n")}</p>\n"
end
def image(link, title, alt_text)
name = File.basename(link, ".*")
<<~HTML
<figure>
<img src="#{link}" alt="#{alt_text}" />
<figcaption id="#{name}">#{alt_text}</figcaption>
</figure>
HTML
end
end
class TocRenderer < Redcarpet::Render::Base
def initialize
super
@sec = 0
@ch = 0
end
def header(c, level)
case level
when 1
@sec += 1
@ch = 0
"<a href='#sec#{@sec}'>#{c}</a>\n<ol>"
when 2
@ch += 1
"<li><a href='#ch#{@sec}-#{@ch}'>#{c}</a></li>\n"
end
end
def self.render(files)
renderer = TocRenderer.new
markdown = Redcarpet::Markdown.new(renderer, fenced_code_blocks: true)
toc = []
files.each do |path|
File.open(path, "r") do |file|
toc << markdown.render(file.read)
end
end
<<~TOC
<nav class="toc">
<ol>
#{toc.map{|c| "<li>#{c}</li>\n</ol>"}.join("\n")}
</ol>
</nav>
TOC
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment