integtest/spec/helper/source.rb (77 lines of code) (raw):
# frozen_string_literal: true
require 'pathname'
require 'yaml'
require_relative 'book'
require_relative 'repo'
##
# Helper class for setting up source files for tests.
class Source
attr_reader :books
attr_accessor :toc_extra
def initialize(tmp)
@root = File.expand_path 'src', tmp
Dir.mkdir @root
@repos = Hash.new { |hash, name| hash[name] = Repo.new name, path(name) }
@books = {}
@toc_extra = nil
end
##
# Create a source repo and return it. You should add files to be converted.
def repo(name)
@repos[name]
end
##
# Write a source file and return the absolute path to that file.
def write(source_relative_path, text)
realpath = path source_relative_path
dir = File.expand_path '..', realpath
FileUtils.mkdir_p dir
File.open(realpath, 'w:UTF-8') do |f|
f.write text
end
realpath
end
##
# Transform path fragment for a source file into the path that that file
# should have.
def path(source_relative_path)
File.expand_path(source_relative_path, @root)
end
##
# Create a new book and return it. The prefix should default to the title,
# lowercased, with whitespace replaced with `-`.
def book(title, prefix: title.downcase.gsub(/\s/, '-'))
@books[title] || (@books[title] = Book.new title, prefix)
end
##
# Create a repository containing a file and commit that. Returns the repo.
def repo_with_file(name, file, content)
repo(name).tap do |repo|
repo.write file, content
repo.commit 'init'
end
end
##
# Create a repository with an index file that includes headings that make
# docbook happy and commit that file. Returns the repo.
def repo_with_index(name, index_content)
repo_with_file name, 'index.asciidoc', <<~ASCIIDOC
= Title
[[chapter]]
== Chapter
#{index_content}
ASCIIDOC
end
##
# Create a repo with an index.asciidoc file and a book that uses it as
# a source.
def book_and_repo(repo_name, book_name, index_content)
repo = repo_with_index repo_name, index_content
book(book_name).source repo, 'index.asciidoc'
end
##
# Create two repos and a book. The first repo contains an index that includes
# a file in the second repo. The book is configured to use both repos as a
# source so that it'll build properly.
def simple_include
book_and_repo 'repo1', 'Test', <<~ASCIIDOC
Include between here
include::../repo2/included.asciidoc[]
and here.
ASCIIDOC
repo2 = repo_with_file 'repo2', 'included.asciidoc', 'included text'
book('Test').source repo2, 'included.asciidoc'
end
##
# Build the config file that can build all books declared in this source.
def conf(relative_path: false)
path = write 'conf.yaml', build_conf
return path unless relative_path
Pathname.new(path)
.relative_path_from(Pathname.new(Dir.getwd))
.to_s
end
private
def build_conf
conf = {
contents_title: 'Test',
toc_extra: @toc_extra,
repos: @repos.values.map { |repo| [repo.name, repo.root] }.to_h,
contents: @books.values.map(&:conf),
}.compact
conf = desymbolize_keys conf
conf.to_yaml
end
end