Class: WikiPromoter::Migrator

Inherits:
Object
  • Object
show all
Defined in:
lib/wiki_promoter/migrator.rb

Overview

Mechanizes the flatten + relink transform for converting hierarchical markdown research/planning trees into GitHub Wiki format. GitHub wikis route pages by basename only (ignoring directory structure), so every file gets a directory-prefixed, cased, and numbered page title (e.g. "77.a.i. Raw Experiment Data"). This groups and orders them logically in the sidebar. Internal relative links are rewritten to reference the new cased, numbered page titles.

Constant Summary collapse

ENTRY_SLUG_RE =
%r{\A(?:.*/)?(\d+)-(.+)\z}
/\[([^\]]*)\]\(([^)\s]+)\)/
MAX_TITLE_LENGTH =
120
SUBDIR_STYLES =
[:alpha, :roman, :numeric]
FILE_STYLES =
[:numeric, :roman, :numeric]
CollisionError =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(docs_path, entry_page_name: nil) ⇒ Migrator

Returns a new instance of Migrator.

Raises:

  • (ArgumentError)


48
49
50
51
52
53
54
55
56
# File 'lib/wiki_promoter/migrator.rb', line 48

def initialize(docs_path, entry_page_name: nil)
  @docs_path = docs_path.chomp("/")
  match = ENTRY_SLUG_RE.match(File.basename(@docs_path))
  raise ArgumentError, "#{docs_path} doesn't look like a docs/<issue>-<slug> tree" unless match

  @issue_number = match[1]
  @entry_page_name = entry_page_name || ENV["ENTRY_PAGE_NAME"] || match[2]
  @metadata = nil
end

Instance Attribute Details

#docs_pathObject (readonly)

Returns the value of attribute docs_path.



46
47
48
# File 'lib/wiki_promoter/migrator.rb', line 46

def docs_path
  @docs_path
end

#entry_page_nameObject (readonly)

Returns the value of attribute entry_page_name.



46
47
48
# File 'lib/wiki_promoter/migrator.rb', line 46

def entry_page_name
  @entry_page_name
end

#issue_numberObject (readonly)

Returns the value of attribute issue_number.



46
47
48
# File 'lib/wiki_promoter/migrator.rb', line 46

def issue_number
  @issue_number
end

Instance Method Details

#clean_title(h1_title) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/wiki_promoter/migrator.rb', line 84

def clean_title(h1_title)
  return nil if h1_title.nil?
  title = h1_title
    .gsub(/[`"'\/\\:*?<>|]/, "")
    .gsub(/\s+/, " ")
    .strip

  if title.length > MAX_TITLE_LENGTH
    truncated = title[0, MAX_TITLE_LENGTH - 1].rstrip
    return "#{truncated}"
  end

  title
end

#entry_wiki_nameObject

The flattened wiki page name for the tree's root entry document. GitHub wikis derive the entry page from the root README.md; a tree without one has no entry page, so fail loudly rather than with a bare KeyError.



78
79
80
81
82
# File 'lib/wiki_promoter/migrator.rb', line 78

def entry_wiki_name
  wiki_names.fetch("README.md") do
    raise ArgumentError, "#{docs_path} has no root README.md to serve as the wiki entry page"
  end
end

#h1(content) ⇒ Object



71
72
73
# File 'lib/wiki_promoter/migrator.rb', line 71

def h1(content)
  content[/^#\s+(.+)$/, 1]&.strip
end

#pagesObject

=> rewritten_markdown_content



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/wiki_promoter/migrator.rb', line 100

def pages
  check_collisions!

  titles = source_files.each_with_object({}) do |path, memo|
    rel = relative_path(path)
    build_metadata! unless @metadata
    memo[rel] = @metadata.fetch(rel).fetch(:raw_h1) || @metadata.fetch(rel).fetch(:title)
  end

  source_files.each_with_object({}) do |path, memo|
    rel = relative_path(path)
    content = rewrite_links(File.read(path), rel, titles)
    memo["#{wiki_names.fetch(rel)}.md"] = content
  end
end

#source_filesObject



58
59
60
# File 'lib/wiki_promoter/migrator.rb', line 58

def source_files
  @source_files ||= Dir.glob(File.join(docs_path, "**", "*.md")).sort
end

#wiki_namesObject

=> flattened_wiki_filename_without_extension



63
64
65
66
67
68
69
# File 'lib/wiki_promoter/migrator.rb', line 63

def wiki_names
  build_metadata! unless @metadata
  @wiki_names ||= source_files.each_with_object({}) do |path, memo|
    rel = relative_path(path)
    memo[rel] = @metadata.fetch(rel).fetch(:wiki_name)
  end
end