Skip to content

Instantly share code, notes, and snippets.

@atuyosi
Created September 9, 2018 13:46
Show Gist options
  • Save atuyosi/b338a31c88815e1f35e8b62981859276 to your computer and use it in GitHub Desktop.
Save atuyosi/b338a31c88815e1f35e8b62981859276 to your computer and use it in GitHub Desktop.
Pandocで生成したepubファイルの目次情報と章番号を修正するRubyスクリプト
#! /usr/bin/env ruby
require 'nokogiri'
require 'pathname'
# na.xhtml
# nav.xhtml専用
def modify_appendix_header(node, ns, prefix_letter='A')
# 付録を特別扱いすためのメソッド
# puts node.name
chapter_node = node.xpath('./xmlns:a')
prev_section_number = chapter_node.children[0].text # span tag
chapter_node.children[0].content = "付録" + prefix_letter
title = chapter_node.children[1].text.gsub(/付録.?\s+(.+)/, '\1')
chapter_node.children[0]['class'] = 'appendix-header-number'
chapter_node.children[1].content = title
for n in node.xpath(".//xmlns:span[@class='section-header-number']") do
new_section_header = n.text.gsub(/#{prev_section_number}\.(\d+?)/, "#{prefix_letter}." + '\1' )
n.content = new_section_header
end
end
def modify_nav_chapter_header(node)
chapter_node = node.xpath('./xmlns:a')
if chapter_node.children[0].name != 'span' then
return
else
chapter_number = chapter_node.children[0].text
chapter_node.children[0].content = "第#{chapter_number}章"
end
# mn = node.text.strip.match(/^(\d)\s+?(.+)/)
end
def modify_nav_xhtml()
nav_xml = Nokogiri::XML(open('_temp/EPUB/nav.xhtml').read)
ns = nav_xml.namespaces
letter = 'A'
for node in nav_xml.xpath('//xmlns:nav/xmlns:ol/xmlns:li') do
if node.text =~ /付録/ then
modify_appendix_header(node, ns, prefix_letter=letter)
letter = letter.succ
else
modify_nav_chapter_header(node)
end
end
File.write('_temp/EPUB/nav.xhtml', nav_xml)
end
################################################################
# toc.ncx
def modify_toc_ncx()
ncx_xml = Nokogiri::XML(open('_temp/EPUB/toc.ncx').read)
replace_section_numbers = []
prefix_letters = ['A', 'B', 'C', 'D', 'F', 'G' ]
for text_node in ncx_xml.xpath('//xmlns:navLabel/xmlns:text') do
if not text_node.text =~ /付録/
mc = text_node.text.strip.match(/^(\d)\s+?(.+)/)
if mc then
text_node.content = "第#{mc[1]}章 #{mc[2]}"
end
else
# 付録の章見出しには番号は不要
mo = text_node.text.strip.match(/(\d)\s+?(.+)/)
if mo then
replace_section_numbers.push(mo[1])
text_node.content = mo[2].to_s
end
end
end
for sub_text_node in ncx_xml.xpath('//xmlns:navLabel/xmlns:text') do
for number, letter in replace_section_numbers.zip(prefix_letters) do
if sub_text_node .text.strip =~ /^#{number}\.(\d+?)/ then
new_label_text = sub_text_node.text.strip.gsub(/^#{number}\.(\d+?)/, "#{letter}." + '\1' )
sub_text_node.content = new_label_text
end
end
end
File.write('_temp/EPUB/toc.ncx', ncx_xml.to_xml)
end
################################################################
# for each ch_xxx.xhtml
def modify_chapter(file, prefix_letter='A')
xhtml = Nokogiri::XML(open(file))
md = xhtml.xpath('//xmlns:h1').children[1].text.strip.match(/(付録.*?)\s+?(.+)/)
prev_chapter_number = xhtml.xpath('//xmlns:h1//xmlns:span[@class="header-section-number"]').first.text
if md then
#xhtml.xpath('//xmlns:h1//xmlns:span[@class="header-section-number"]').children[0].content = md[1]
xhtml.xpath('//xmlns:h1').children[0].content = md[1]
xhtml.xpath('//xmlns:h1').children[1].content = " #{md[2]}"
xhtml.xpath('//xmlns:h1').children[0]['class'] = 'appendix-header-number'
for section_node in xhtml.xpath('//xmlns:span[@class="header-section-number"]') do
section_node.content = section_node.text.strip.gsub( /^#{prev_chapter_number}(.+)/ , prefix_letter + '\1')
end
File.write(file, xhtml)
end
end
def modify_appendix_chapter_files()
appendix_files = []
chapter_files = Pathname.glob('_temp/EPUB/text/ch???.xhtml').sort()
for file in chapter_files do
xhtml = Nokogiri::XML(file.open())
if xhtml.xpath('//xmlns:title').text =~ /付録/ then
appendix_files.push(file)
end
end
prefix_letters = ['A', 'B', 'C', 'D', 'F', 'G' ]
for apx, letter in appendix_files.zip(prefix_letters) do
modify_chapter(apx.to_s,prefix_letter=letter)
end
end
# main
modify_nav_xhtml()
modify_toc_ncx()
modify_appendix_chapter_files()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment