bhook 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 004e13098155733cadddffee89a4085b4c7dc78fafa28de82b4266cd86c95eab
4
- data.tar.gz: aa6a9773afd270b0d63f230142b3ac86a3f90719b6602a7ae26cee712b36ffff
3
+ metadata.gz: b4ef3049d516cd681eac21ac34923cf9cdd292cbb79ca238d7228e1a18a9a323
4
+ data.tar.gz: 942754c6193f0e19d1b2dc028aa13e9033e7d2e4f5a01e3edb76248ce2d1e3f6
5
5
  SHA512:
6
- metadata.gz: 757d1a3bcabc583116a5d02b41beb198f19dc891cb3ce948482614bd77f7a18ae5082ee5e3e535ee777739b030d25887ae7d1b8c3ccaa566943035e7ca51cd2e
7
- data.tar.gz: e41a385694dabe87e08d21fa51a5d0091028b7317d81f48b107e2a73797d8b9eacc1eafdf52a42715149706ecbe30c604a1aab7f3cd39e3147a767a4fc6ddb85
6
+ metadata.gz: cb421ebe8b1ea40155b8fec5139d249b99c99bdc17f44587b07d4af8824a2519ca3edba0134f1029475df2be577da5f140149a0a11d7ea05273de23734c2fcc3
7
+ data.tar.gz: 9563f8a81b32da179e8f4582f36dfa619076237fe64880fdd3047feafc7f89826bc8098e884ce8ef3c59afc35c155d882d709a74d9e41cf54936b0af2fd21862
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bhook (0.1.0)
4
+ bhook (0.1.3)
5
5
  git (~> 1.10)
6
6
  kramdown (~> 2.3)
7
7
  listen (~> 3.7)
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Bhook
2
2
 
3
- Bhook is a static bliki generator.
3
+ Bhook is a static website generator that works off a git repo containing a markdown file based wiki, like for example, the [India Startup Wiki](https://gitlab.com/india-startups/wiki).
4
+
5
+ I use this to create [HTML versions of the wiki](https://sidu.in/wiki/startups) and of [my essays](https://sidu.in/essays/) that I can publish.
4
6
 
5
7
  ## Installation
6
8
 
@@ -10,17 +12,32 @@ Install it yourself as:
10
12
 
11
13
  ## Usage
12
14
 
13
- TODO: Write usage instructions here
15
+ Getting help:
14
16
 
15
- ## Development
17
+ $ bhook --help
18
+ Bhook version 0.1.2
19
+ Usage: bhook --source /source/path --output /output/path
20
+ -s, --source=SOURCE Path to version controlled directory containing source md files
21
+ -o, --output=OUTPUT Path to directory where output files are to be generated
22
+ -w, --watch Continuously watch the source directory for changes and generate output
23
+ -v, --verbose Print detailed information about files as they are processed
24
+ -t, --theme=PATH Path to directory containing theme files to use when generating html
25
+ --generate-theme=PATH Generate a baseline theme that you can then modify to your needs
26
+ -h, --help Prints this help
27
+
28
+ How I use it:
16
29
 
17
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+ ➜ essays git:(main) bhook -s . -o /tmp/out -t /tmp/out/theme -w -v
31
+
32
+ ## Development
18
33
 
19
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+ 1. `git clone --recursive git@gitlab.com:kaiwren/bhook.git`
35
+ 2. After checking out the repo, run `bundle install` to install dependencies.
36
+ 4. Then, run `bundle exec rake` to run the specs and sorbet typechecking.
20
37
 
21
38
  ## Contributing
22
39
 
23
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bhook.
40
+ Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/kaiwren/bhook.
24
41
 
25
42
  ## License
26
43
 
data/bin/bhook CHANGED
@@ -5,7 +5,29 @@ require 'bundler/setup'
5
5
  require 'bhook'
6
6
 
7
7
  puts "Bhook version #{Bhook::VERSION}"
8
- args = Bhook::ArgsParser.new(ARGV).parse!
9
- workspace = Bhook::Workspace.new(args.source, args.output)
8
+ args = Bhook::ArgsParser.new(ARGV).parse
9
+
10
+ if args.verbose
11
+ Bhook::L.level = Logger::DEBUG
12
+ else
13
+ Bhook::L.level = Logger::INFO
14
+ end
15
+
16
+ if args.generate_theme
17
+ Bhook::ThemeGenerator.new(args.generate_theme).generate!
18
+ exit
19
+ end
20
+
21
+ workspace = Bhook::Workspace.new(args.source, args.output, args.theme)
22
+
23
+ if args.benchmark
24
+ require 'benchmark'
25
+ n = 10
26
+ Benchmark.bmbm do |bench|
27
+ Bhook::L.level = Logger::WARN
28
+ bench.report("Generate HTML #{n} times") { n.times { workspace.process! } }
29
+ end
30
+ exit
31
+ end
10
32
 
11
33
  args.watch ? workspace.watch! : workspace.process!
@@ -1,23 +1,30 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
1
4
  module Bhook
2
5
  class ArgsParser
3
- Options = Struct.new(:source, :output, :watch)
6
+ extend T::Sig
7
+
8
+ Options = Struct.new(:source, :output, :watch, :verbose, :theme, :generate_theme, :benchmark)
4
9
 
5
10
  def initialize(argv)
6
- @args = Options.new(nil, nil, false)
11
+ @args = Options.new(nil, nil, false, false, nil, nil, false)
7
12
  @argv = argv.clone
8
13
  @opt_parser = build_opt_parser
9
14
  end
10
15
 
11
- def parse!
16
+ def parse
12
17
  begin
13
- @opt_parser.parse!(@argv)
14
- rescue OptionParser::InvalidOption => e
18
+ @opt_parser.parse(@argv)
19
+ rescue OptionParser::ParseError => e
15
20
  puts
16
21
  puts "Error! #{e.message}"
17
22
  puts
23
+ puts @opt_parser
24
+ exit
18
25
  end
19
-
20
- if !@argv.empty? || (!@args.source || !@args.output)
26
+
27
+ if source_or_output_paths_missing? && generate_theme_missing?
21
28
  puts @opt_parser
22
29
  exit
23
30
  end
@@ -25,26 +32,59 @@ module Bhook
25
32
  end
26
33
 
27
34
  private
35
+
36
+ def source_or_output_paths_missing?
37
+ !@args.source || !@args.output
38
+ end
39
+
40
+ def generate_theme_missing?
41
+ !@args.generate_theme
42
+ end
43
+
28
44
  def build_opt_parser
29
45
  OptionParser.new do |opts|
30
46
  opts.banner = "Usage: bhook --source /source/path --output /output/path"
31
47
 
32
48
  opts.on("-sSOURCE", "--source=SOURCE",
33
- String, "Path to version controlled directory containing source md files") do |s|
34
- @args.source = s
49
+ String, "Path to version controlled directory containing source md files") do |source_path|
50
+ @args.source = source_path
35
51
  end
36
52
 
37
53
  opts.on("-oOUTPUT", "--output=OUTPUT",
38
- String, "Path to directory where output files are to be generated") do |o|
39
- @args.output = o
54
+ String, "Path to directory where output files are to be generated") do |out_path|
55
+ @args.output = out_path
40
56
  end
41
57
 
42
58
  opts.on("-w", "--watch",
43
59
  FalseClass,
44
- "Continuously watch the source directory for changes and generate output") do |w|
60
+ "Continuously watch the source directory for changes and generate output") do
45
61
  @args.watch = true
46
62
  end
47
63
 
64
+ opts.on("-v", "--verbose",
65
+ FalseClass,
66
+ "Print detailed information about files as they are processed") do
67
+ @args.verbose = true
68
+ end
69
+
70
+ opts.on("-tPATH", "--theme=PATH",
71
+ String,
72
+ "Path to directory containing theme files to use when generating html") do |path|
73
+ @args.theme = path
74
+ end
75
+
76
+ opts.on("--generate-theme=PATH",
77
+ String,
78
+ "Generate a baseline theme that you can then modify to your needs") do |path|
79
+ @args.generate_theme = path
80
+ end
81
+
82
+ opts.on("--benchmark",
83
+ FalseClass,
84
+ "Run a performance benchmark for the specified source") do
85
+ @args.benchmark = true
86
+ end
87
+
48
88
  opts.on("-h", "--help", "Prints this help") do
49
89
  puts opts
50
90
  exit
@@ -16,7 +16,7 @@ module Bhook
16
16
  def convert_a(el, indent)
17
17
  href_path = el.attr['href']
18
18
  if valid_relative_md_link?(href_path)
19
- puts "Found link: #{href_path}"
19
+ L.debug "Found link: #{href_path}"
20
20
  el.attr['href'].gsub!(/\.md/, '.html')
21
21
  end
22
22
  super(el, indent)
@@ -1,62 +1,61 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Bhook
5
5
  class Directory
6
+ extend T::Sig
7
+
6
8
  GIT_DIR = '.git'
7
9
  MD_EXT = '.md'
8
10
 
9
- attr_reader :sub_dirs, :md_files
10
-
11
- def initialize(src_path, git = nil)
11
+ sig { params(src_path: Pathname, out_path: Pathname, git: Git::Base).void }
12
+ def initialize(src_path, out_path, git)
12
13
  @src_path = src_path
14
+ @out_path = T.let(out_path.join(src_path.basename), Pathname)
13
15
  @git = git
14
- @sub_dirs = []
15
- @md_files = []
16
+ @sub_dirs = T.let([], T::Array[Directory])
17
+ @md_files = T.let([], T::Array[MdFile])
16
18
  build_next_level_nodes
17
19
  end
18
20
 
19
- def root_dir_for_a_commit?
20
- !@git
21
- end
22
-
23
- def write!(out_path)
24
- dir_path = if root_dir_for_a_commit?
25
- out_path
26
- else
27
- File.join(out_path, @src_path.basename)
28
- end
29
-
30
- FileUtils.mkdir_p(dir_path, verbose: true)
31
- @sub_dirs.each { |dir| dir.write!(dir_path) }
32
- @md_files.each { |file| file.write!(dir_path) }
21
+ sig { params(theme: Theme).void }
22
+ def write!(theme)
23
+ FileUtils.mkdir_p(@out_path)
24
+ L.debug("mkdir: #{@out_path}")
25
+ @sub_dirs.each { |dir| dir.write!(theme) }
26
+ @md_files.map do |file|
27
+ Thread.new { file.write!(theme) }
28
+ end.each do |thread|
29
+ thread.join
30
+ end
33
31
  end
34
-
32
+
33
+ sig { returns(T::Array[MdFile]) }
35
34
  def all_md_files
36
35
  @md_files + @sub_dirs.map(&:all_md_files).flatten
37
36
  end
38
37
 
38
+ sig { returns(String) }
39
39
  def to_s
40
40
  @src_path.to_s
41
41
  end
42
-
42
+
43
43
  private
44
44
 
45
+ sig { void }
45
46
  def build_next_level_nodes
46
- if root_dir_for_a_commit?
47
- @git = Git.open(@src_path)
48
- end
49
-
50
- @sub_dirs = @src_path.children.map do |child|
51
- if child.directory? && child.basename.to_s != GIT_DIR
52
- Directory.new(child, @git)
47
+ children = @src_path.children
48
+ children.delete(@src_path.join(GIT_DIR))
49
+
50
+ file_threads = []
51
+ children.each do |child_path|
52
+ if child_path.directory?
53
+ @sub_dirs << Directory.new(child_path, @out_path, @git)
54
+ elsif child_path.extname == MD_EXT
55
+ file_threads << Thread.new { MdFile.new(child_path, @out_path, @git) }
53
56
  end
54
- end.compact
55
- @md_files = @src_path.children.select do |child|
56
- !child.directory? && child.extname == MD_EXT
57
- end.map do |child|
58
- MdFile.new(child, @git)
59
- end.compact
57
+ end
58
+ file_threads.each { |thread| @md_files << thread.value }
60
59
  end
61
60
  end
62
61
  end
@@ -0,0 +1,8 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Bhook
5
+ L = Logger.new(STDOUT, formatter: proc {|severity, datetime, progname, msg|
6
+ "#{Thread.current.object_id} #{msg}\n"
7
+ })
8
+ end
data/lib/bhook/md_file.rb CHANGED
@@ -1,50 +1,47 @@
1
- # typed: false
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Bhook
5
5
  class MdFile
6
6
  extend T::Sig
7
- PAGE_TEMPLATE = File.read(File.join(File.dirname(__FILE__), 'theme', 'page.erb'))
8
- AFTER_H1_TEMPLATE = File.read(File.join(File.dirname(__FILE__), 'theme', '_after_h1.erb'))
9
-
10
- def initialize(src_file_path, git)
7
+
8
+ PAGE_TEMPLATE = T.let(File.read(Bhook::PAGE_TEMPLATE_PATH), String)
9
+ AFTER_H1_TEMPLATE = T.let(File.read(Bhook::AFTER_H1_TEMPLATE_PATH), String)
10
+
11
+ sig { returns(Pathname) }
12
+ attr_reader :src_file_path
13
+
14
+ sig { params(src_file_path: Pathname, out_path: Pathname, git: Git::Base).void }
15
+ def initialize(src_file_path, out_path, git)
16
+ L.debug "Reading: #{src_file_path}"
11
17
  @md = T.let(File.read(src_file_path), String)
12
- @src_file_path = src_file_path.expand_path
13
- file_meta_data = git.lib.send(:command, 'log',
14
- '-n 1',
15
- '--pretty=format:%ad|%h',
16
- '--date=short',
17
- '--',
18
- @src_file_path)
19
- @src_file_date, @src_file_sha = file_meta_data.split('|')
18
+ @src_file_path = src_file_path
19
+ @out_path = out_path
20
+ src_file_date, src_file_sha = git.lib.send(:command, 'log',
21
+ '-n 1',
22
+ '--pretty=format:%ad|%h',
23
+ '--date=short',
24
+ '--',
25
+ @src_file_path).split('|')
26
+ @src_file_date = T.let(src_file_date, T.nilable(String))
27
+ @src_file_sha = T.let(src_file_sha, T.nilable(String))
20
28
  end
21
29
 
22
- sig { returns(Pathname) }
23
- attr_reader :src_file_path
30
+ sig { params(theme: Bhook::Theme).void }
31
+ def write!(theme)
32
+ out_file_name = @src_file_path.basename.sub(/\.md$/, '.html')
33
+ out_file_path = @out_path.join(out_file_name)
24
34
 
25
- sig { params(out_path: String).void }
26
- def write!(out_path)
27
- out_file_name = File.basename(@src_file_path).gsub(/\.md$/, '.html')
28
- out_file_path = File.join(out_path, out_file_name)
29
- src_file_sha = @src_file_sha
30
- src_file_date = @src_file_date
31
- src_title = ''
32
- puts "Parsing: #{@src_file_sha} #{out_file_path}"
33
- after_h1_strategy = ->(binding_instance) { ERB.new(AFTER_H1_TEMPLATE, trim_mode: '-').result(binding_instance) }
35
+ L.debug "Processing: #{@src_file_sha || 'unversioned'} #{@src_file_path}"
36
+ rendered_page = theme.render_page(@md, @src_file_sha, @src_file_date)
34
37
 
35
- doc = Kramdown::Document.new(@md)
36
- output, warnings = Converter::Html.convert(doc.root, doc.options.merge(
37
- after_h1_strategy: after_h1_strategy,
38
- h1_callback: ->(str) { src_title = str }
39
- ))
40
- rendered_page = ERB.new(PAGE_TEMPLATE, trim_mode: '-').result(binding)
41
- puts "Writing: #{@src_file_sha} #{out_file_path}"
38
+ L.debug "Writing: #{@src_file_sha} #{out_file_path}"
42
39
  File.write(out_file_path, rendered_page)
43
40
  end
44
41
 
45
42
  sig { returns(String) }
46
43
  def to_s
47
- @src_file_path
44
+ @src_file_path.to_s
48
45
  end
49
46
  end
50
47
  end
@@ -0,0 +1,13 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Bhook
5
+ class RootDirectory < Directory
6
+ extend T::Sig
7
+
8
+ sig { params(src_path: Pathname, out_path: Pathname).void }
9
+ def initialize(src_path, out_path)
10
+ super(src_path, out_path, Git.open(src_path))
11
+ end
12
+ end
13
+ end
@@ -4,4 +4,3 @@ href="https://twitter.com/intent/tweet?text=<%= CGI.escape(src_title) -%>&via=po
4
4
  <a class="twitter-follow-button" href="https://twitter.com/ponnappa">Follow @ponnappa</a>
5
5
  <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
6
6
  </div>
7
-
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Bhook
5
+ class Theme
6
+ extend T::Sig
7
+
8
+ sig { params(theme_path: String).void }
9
+ def initialize(theme_path)
10
+ @page_template = T.let(File.read(File.join(theme_path, 'page.erb')), String)
11
+ @after_h1_template = T.let(File.read(File.join(theme_path, '_after_h1.erb')), String)
12
+ strategy = ->(binding_instance) { ERB.new(@after_h1_template, trim_mode: '-').result(binding_instance) }
13
+ @after_h1_strategy = T.let(strategy, T.proc.params(binding_instance: Binding).returns(String))
14
+ end
15
+
16
+ sig { params(md: String, src_file_sha: T.nilable(String), src_file_date: T.nilable(String)).returns(String) }
17
+ def render_page(md, src_file_sha, src_file_date)
18
+ src_title = T.let('', String)
19
+
20
+ doc = Kramdown::Document.new(md)
21
+ output, warnings = Converter::Html.convert(doc.root, doc.options.merge(
22
+ after_h1_strategy: @after_h1_strategy,
23
+ h1_callback: ->(str) { src_title = str }
24
+ ))
25
+ ERB.new(@page_template, trim_mode: '-').result(binding)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Bhook
5
+ class ThemeGenerator
6
+ extend T::Sig
7
+
8
+ sig {params(output_path: String).void}
9
+ def initialize(output_path)
10
+ @output_path = T.let(File.join(output_path, 'theme'), String)
11
+ @template_files = T.let([Bhook::PAGE_TEMPLATE_PATH,
12
+ Bhook::AFTER_H1_TEMPLATE_PATH], T::Array[String])
13
+ end
14
+
15
+ sig {void}
16
+ def generate!
17
+ FileUtils.mkdir_p(@output_path, verbose: true)
18
+ FileUtils.cp(@template_files, @output_path, verbose: true)
19
+ end
20
+ end
21
+ end
data/lib/bhook/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Bhook
5
- VERSION = '0.1.0'
5
+ VERSION = '0.1.3'
6
6
  end
@@ -5,26 +5,27 @@ module Bhook
5
5
  class Workspace
6
6
  extend T::Sig
7
7
 
8
- sig { params(src_path: String, out_path: String).void }
9
- def initialize(src_path, out_path)
10
- @src_path = src_path
11
- @out_path = out_path
8
+ sig { params(src_path: String, out_path: String, theme_path: String).void }
9
+ def initialize(src_path, out_path, theme_path)
10
+ @src_path = T.let(Pathname.new(src_path).expand_path, Pathname)
11
+ @out_path = T.let(Pathname.new(out_path).expand_path, Pathname)
12
+ @theme = T.let(Theme.new(theme_path), Bhook::Theme)
12
13
  end
13
14
 
14
15
  sig { void }
15
- def process!
16
- root = root_dir
17
- root.write!(@out_path)
16
+ def process!
17
+ root_dir.write!(@theme)
18
+ L.info "Done!"
18
19
  end
19
20
 
20
21
  sig { void }
21
22
  def watch!
22
23
  process!
23
- puts
24
- puts "Watching #{@src_path} for changes..."
25
- listener = Listen.to(@src_path, File.join(@src_path, '.git')) do |_modified, _added, _removed|
24
+
25
+ L.info "Watching: #{@src_path} for changes..."
26
+ listener = Listen.to(@src_path.to_s, File.join(@src_path.to_s, '.git')) do |_modified, _added, _removed|
27
+ L.info "Detected changes..."
26
28
  process!
27
- puts "-----\n"
28
29
  end
29
30
  listener.start
30
31
  sleep
@@ -34,12 +35,11 @@ module Bhook
34
35
  def all_md_files
35
36
  root_dir.all_md_files
36
37
  end
37
-
38
- private
39
-
40
- sig { returns(Bhook::Directory) }
38
+
39
+ private
40
+ sig { returns(Bhook::RootDirectory) }
41
41
  def root_dir
42
- Directory.new(Pathname.new(@src_path))
42
+ RootDirectory.new(@src_path, @out_path)
43
43
  end
44
44
  end
45
45
  end
data/lib/bhook.rb CHANGED
@@ -6,17 +6,29 @@ require 'fileutils'
6
6
  require 'pathname'
7
7
  require 'erb'
8
8
  require 'optparse'
9
+ require 'logger'
9
10
  require 'sorbet-runtime'
10
11
  require 'git'
11
12
  require 'kramdown'
12
13
  require 'listen'
14
+
15
+ module Bhook
16
+ extend T::Sig
17
+
18
+ THEME_DIR_PATH = T.let(File.join(File.dirname(__FILE__), 'bhook', 'theme'), String)
19
+ PAGE_TEMPLATE_PATH = T.let(File.join(THEME_DIR_PATH, 'page.erb'), String)
20
+ AFTER_H1_TEMPLATE_PATH = T.let(File.join(THEME_DIR_PATH, '_after_h1.erb'), String)
21
+
22
+ class Error < StandardError; end
23
+ end
24
+
13
25
  require_relative 'bhook/version'
26
+ require_relative 'bhook/logger'
14
27
  require_relative 'bhook/args_parser'
28
+ require_relative 'bhook/theme_generator'
29
+ require_relative 'bhook/theme'
15
30
  require_relative 'bhook/converter/html'
16
31
  require_relative 'bhook/directory'
32
+ require_relative 'bhook/root_directory'
17
33
  require_relative 'bhook/md_file'
18
34
  require_relative 'bhook/workspace'
19
-
20
- module Bhook
21
- class Error < StandardError; end
22
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bhook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sidu Ponnappa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-12 00:00:00.000000000 Z
11
+ date: 2022-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -171,9 +171,13 @@ files:
171
171
  - lib/bhook/args_parser.rb
172
172
  - lib/bhook/converter/html.rb
173
173
  - lib/bhook/directory.rb
174
+ - lib/bhook/logger.rb
174
175
  - lib/bhook/md_file.rb
176
+ - lib/bhook/root_directory.rb
177
+ - lib/bhook/theme.rb
175
178
  - lib/bhook/theme/_after_h1.erb
176
179
  - lib/bhook/theme/page.erb
180
+ - lib/bhook/theme_generator.rb
177
181
  - lib/bhook/version.rb
178
182
  - lib/bhook/workspace.rb
179
183
  - sorbet/config