Class: Mint::Document

Inherits:
Object
  • Object
show all
Defined in:
lib/mint/document.rb

Constant Summary collapse

METADATA_DELIM =
"\n\n"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(working_directory:, source_path:, destination_path:, destination_directory_path:, layout_path:, style_path:, style_destination_path:, style_mode:, insert_title_heading:, transform_links: Proc.new, render_style: true) ⇒ Document

Returns a new instance of Document.

Parameters:

  • working_directory (Pathname)

    path by which relative links should be resolved

  • source_path (Pathname)

    path to markdown file (relative to working_directory)

  • destination_path (Pathname)

    path to output file (relative to destination_directory_path)

  • destination_directory_path (Pathname)

    path to destination directory

  • layout_path (Pathname)

    path to layout file (relative to working_directory)

  • style_path (Pathname)

    path to style file (relative to working_directory)

  • style_destination_path (Pathname)

    path to style destination file

  • style_mode (Symbol)

    style mode (:inline, :external, :original)

  • insert_title_heading (Boolean)

    whether to inject title as H1 heading

  • show_navigation (Boolean)

    whether to show navigation

  • navigation_depth (Integer)

    navigation depth (optional)

  • navigation_data (Array<Hash>)

    array of navigation items with :path and :title

  • navigation_title (String)

    title for navigation panel (optional)

  • transform_links (Proc) (defaults to: Proc.new)

    proc to transform link basenames; yields the basename of the link

  • render_style (Boolean) (defaults to: true)

    whether to render style



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/mint/document.rb', line 32

def initialize(working_directory:,
               source_path:,
               destination_path:,
               destination_directory_path:,
               layout_path:,
               style_path:,
               style_destination_path:,
               style_mode:,
               insert_title_heading:,
               transform_links: Proc.new,
               render_style: true)
  @working_directory = working_directory
  @source_path = source_path
  @destination_path = destination_path
  @destination_directory_path = destination_directory_path
  @layout_path = layout_path
  @style_path = style_path
  @style_destination_path = style_destination_path
  @style_mode = style_mode
  @insert_title_heading = insert_title_heading
  @transform_links = transform_links
  @render_style = render_style
  @title = guess_title
end

Instance Attribute Details

#destination_pathObject (readonly)

Returns the value of attribute destination_path.



15
16
17
# File 'lib/mint/document.rb', line 15

def destination_path
  @destination_path
end

#titleObject (readonly)

Returns the value of attribute title.



15
16
17
# File 'lib/mint/document.rb', line 15

def title
  @title
end

Instance Method Details

#generate_navigation_tree(navigation:) ⇒ Array<Hash>

Generates navigation tree data for use in layout templates

Returns:

  • (Array<Hash>)

    array of navigation items with keys:

    • :title (String) - display title for the item

    • :html_path (String) - path to the HTML file (for files) or nil (for directories)

    • :source_path (String) - path to the source file relative to working directory

    • :depth (Integer) - nesting depth in the tree

    • :is_directory (Boolean) - true if this is a directory entry (optional key)



157
158
159
160
161
162
163
164
# File 'lib/mint/document.rb', line 157

def generate_navigation_tree(navigation:)
  # Build DocumentTree with documents (path + title pairs)
  document_tree = DocumentTree.new(navigation)
  reoriented_tree = document_tree.reorient(@destination_path)
  
  # Serialize to flat array for ERB template consumption
  reoriented_tree.serialize(max_depth: @navigation_depth)
end

#publish!(show_navigation: nil, navigation: nil, navigation_depth: nil, navigation_title: nil) ⇒ Pathname

Publishes the markdown document to HTML

Reads the markdown source file, transforms links, renders to HTML, applies the layout template, and writes to the destination directory. The destination path is resolved at publish time by combining destination_directory_path + destination_path.

Returns:

  • (Pathname)

    the destination path relative to working_directory



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/mint/document.rb', line 65

def publish!(show_navigation: nil, navigation: nil, navigation_depth: nil, navigation_title: nil)
  if @style_mode == :external && @render_style
    create_external_stylesheet
  end

  # Read and parse Markdown into metadata + content
  source_content = File.read(@source_path)
  , body = (source_content)
  
  # Transform Markdown links, taking output format into account
  body_with_rewritten_links = transform_markdown_links(body, &@transform_links)
  
  # Render Markdown to HTML
  rendered_content = Renderers::Markdown.render(body_with_rewritten_links)
  
  # Create layout variables, for use in the layout template
  layout_variables = {
    working_directory: @working_directory,
    current_path: @source_path.to_s,
    metadata: ,
    title: @title,
    insert_title_heading: @insert_title_heading,
    content: rendered_content.html_safe,
    stylesheet_tag: render_stylesheet_tag(@style_path, @style_mode),
    files: navigation ? generate_navigation_tree(navigation: navigation) : [],
    show_navigation: show_navigation,
    navigation_title: navigation_title
  }
  
  # Render the layout
  layout_content = File.read(@layout_path)
  rendered_content = Renderers::Erb.render(layout_content, layout_variables)
  
  # Write the rendered content to the destination path
  full_destination_path = @destination_directory_path.absolute? ? 
    @destination_directory_path + @destination_path : 
    @working_directory + @destination_directory_path + @destination_path
  
  full_destination_path.dirname.mkpath
  full_destination_path.open("w+") do |f|
    f << rendered_content
  end

  # Return the destination path used, for use in verbose output
  begin
    full_destination_path.relative_path_from(@working_directory)
  rescue ArgumentError
    # If, for some reason, the paths don't share a common prefix,
    # return the full path to avoid an error
    full_destination_path
  end
end

Transforms Markdown links from .md extensions

Parameters:

  • text (String)

    the Markdown text containing links to Markdown documents

Yields:

  • (String)

    block used to transform the basename of each Markdown link found

Returns:

  • (String)

    the text with transformed links



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/mint/document.rb', line 123

def transform_markdown_links(text, &block)
  text.gsub(/(\[([^\]]*)\]\(([^)]*\.md)\))/) do |match|
    link_text = $2
    link_url = $3
    
    # Only transform relative links (not absolute URLs)
    if link_url !~ /^https?:\/\//
      # Preserve directory structure in links
      dirname = File.dirname(link_url)
      basename = File.basename(link_url, ".*")
      
      new_filename = yield basename
      
      new_url = if dirname == "."
        new_filename
      else
        File.join(dirname, new_filename)
      end
      
      "[#{link_text}](#{new_url})"
    else
      match
    end
  end
end