mint 0.8.1 → 0.10.0
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 +4 -4
- data/Gemfile +1 -26
- data/README.md +117 -37
- data/bin/mint +2 -81
- data/config/templates/base/navigation.css +136 -0
- data/config/templates/base/print.css +152 -0
- data/config/templates/{reset.css → base/reset.css} +1 -1
- data/config/templates/base/style.css +117 -137
- data/config/templates/base/utilities.css +136 -0
- data/config/templates/base/variables.css +124 -0
- data/config/templates/basic/style.css +151 -0
- data/config/templates/default/layout.erb +33 -3
- data/config/templates/default/style.css +95 -164
- data/config/templates/magazine/style.css +383 -0
- data/config/templates/nord/style.css +105 -220
- data/config/templates/nord-dark/style.css +82 -263
- data/lib/mint/commandline/parse.rb +144 -0
- data/lib/mint/commandline/publish.rb +46 -0
- data/lib/mint/commandline/run.rb +30 -0
- data/lib/mint/config.rb +162 -0
- data/lib/mint/{css.rb → css_dsl.rb} +9 -9
- data/lib/mint/css_parser.rb +45 -25
- data/lib/mint/document.rb +250 -365
- data/lib/mint/document_tree.rb +163 -0
- data/lib/mint/exceptions.rb +2 -3
- data/lib/mint/helpers.rb +23 -180
- data/lib/mint/layout.rb +26 -9
- data/lib/mint/renderers/css_renderer.rb +32 -0
- data/lib/mint/renderers/erb_renderer.rb +11 -0
- data/lib/mint/renderers/markdown_renderer.rb +45 -0
- data/lib/mint/style.rb +21 -31
- data/lib/mint/template.rb +30 -0
- data/lib/mint/version.rb +1 -1
- data/lib/mint/workspace.rb +171 -0
- data/lib/mint.rb +44 -12
- data/man/mint.1 +85 -44
- data/spec/cli/README.md +2 -2
- data/spec/cli/argument_parsing_spec.rb +89 -147
- data/spec/cli/bin_integration_spec.rb +23 -243
- data/spec/cli/full_workflow_integration_spec.rb +99 -442
- data/spec/cli/original_style_integration_spec.rb +58 -0
- data/spec/cli/publish_workflow_spec.rb +72 -70
- data/spec/commandline_path_integration_spec.rb +230 -0
- data/spec/config_file_integration_spec.rb +362 -0
- data/spec/{css_spec.rb → css_dsl_spec.rb} +7 -3
- data/spec/css_parser_spec.rb +59 -1
- data/spec/document_spec.rb +37 -242
- data/spec/flattened_path_spec.rb +150 -0
- data/spec/layout_spec.rb +42 -3
- data/spec/mint_spec.rb +22 -217
- data/spec/path_handling_spec.rb +237 -0
- data/spec/run_cli_tests.rb +1 -1
- data/spec/spec_helper.rb +3 -10
- data/spec/style_spec.rb +31 -56
- data/spec/support/cli_helpers.rb +7 -10
- data/spec/support/matchers.rb +1 -1
- data/spec/template_spec.rb +31 -0
- data/spec/workspace_spec.rb +177 -0
- metadata +75 -89
- data/bin/mint-epub +0 -20
- data/config/templates/garden/layout.erb +0 -38
- data/config/templates/garden/style.css +0 -303
- data/config/templates/nord/layout.erb +0 -11
- data/config/templates/nord-dark/layout.erb +0 -11
- data/config/templates/zen/layout.erb +0 -11
- data/config/templates/zen/style.css +0 -114
- data/lib/mint/command_line.rb +0 -360
- data/lib/mint/css_template.rb +0 -37
- data/lib/mint/markdown_template.rb +0 -47
- data/lib/mint/mint.rb +0 -313
- data/lib/mint/plugin.rb +0 -136
- data/lib/mint/plugins/epub.rb +0 -293
- data/lib/mint/resource.rb +0 -101
- data/plugins/templates/epub/layouts/container.haml +0 -5
- data/plugins/templates/epub/layouts/content.haml +0 -35
- data/plugins/templates/epub/layouts/layout.haml +0 -6
- data/plugins/templates/epub/layouts/title.haml +0 -11
- data/plugins/templates/epub/layouts/toc.haml +0 -26
- data/spec/cli/configuration_management_spec.rb +0 -363
- data/spec/cli/template_management_spec.rb +0 -300
- data/spec/helpers_spec.rb +0 -249
- data/spec/plugin_spec.rb +0 -449
- data/spec/resource_spec.rb +0 -135
data/lib/mint/document.rb
CHANGED
@@ -1,403 +1,288 @@
|
|
1
|
-
require "
|
2
|
-
require "
|
3
|
-
require "
|
4
|
-
|
1
|
+
require "pathname"
|
2
|
+
require "yaml"
|
3
|
+
require "active_support/core_ext/string/output_safety"
|
4
|
+
|
5
|
+
require_relative "./renderers/markdown_renderer"
|
6
|
+
require_relative "./renderers/erb_renderer"
|
7
|
+
require_relative "./renderers/css_renderer"
|
8
|
+
require_relative "./helpers"
|
9
|
+
require_relative "./document_tree"
|
5
10
|
|
6
11
|
module Mint
|
7
|
-
class Document
|
12
|
+
class Document
|
8
13
|
METADATA_DELIM = "\n\n"
|
14
|
+
|
15
|
+
attr_reader :title, :destination_path
|
16
|
+
|
17
|
+
# @param [Pathname] working_directory path by which relative links should be resolved
|
18
|
+
# @param [Pathname] source_path path to markdown file (relative to working_directory)
|
19
|
+
# @param [Pathname] destination_path path to output file (relative to destination_directory_path)
|
20
|
+
# @param [Pathname] destination_directory_path path to destination directory
|
21
|
+
# @param [Pathname] layout_path path to layout file (relative to working_directory)
|
22
|
+
# @param [Pathname] style_path path to style file (relative to working_directory)
|
23
|
+
# @param [Pathname] style_destination_path path to style destination file
|
24
|
+
# @param [Symbol] style_mode style mode (:inline, :external, :original)
|
25
|
+
# @param [Boolean] insert_title_heading whether to inject title as H1 heading
|
26
|
+
# @param [Boolean] show_navigation whether to show navigation
|
27
|
+
# @param [Integer] navigation_depth navigation depth (optional)
|
28
|
+
# @param [Array<Hash>] navigation_data array of navigation items with :path and :title
|
29
|
+
# @param [String] navigation_title title for navigation panel (optional)
|
30
|
+
# @param [Proc] transform_links proc to transform link basenames; yields the basename of the link
|
31
|
+
# @param [Boolean] render_style whether to render style
|
32
|
+
def initialize(working_directory:,
|
33
|
+
source_path:,
|
34
|
+
destination_path:,
|
35
|
+
destination_directory_path:,
|
36
|
+
layout_path:,
|
37
|
+
style_path:,
|
38
|
+
style_destination_path:,
|
39
|
+
style_mode:,
|
40
|
+
insert_title_heading:,
|
41
|
+
transform_links: Proc.new,
|
42
|
+
render_style: true)
|
43
|
+
@working_directory = working_directory
|
44
|
+
@source_path = source_path
|
45
|
+
@destination_path = destination_path
|
46
|
+
@destination_directory_path = destination_directory_path
|
47
|
+
@layout_path = layout_path
|
48
|
+
@style_path = style_path
|
49
|
+
@style_destination_path = style_destination_path
|
50
|
+
@style_mode = style_mode
|
51
|
+
@insert_title_heading = insert_title_heading
|
52
|
+
@transform_links = transform_links
|
53
|
+
@render_style = render_style
|
54
|
+
@title = guess_title
|
55
|
+
end
|
9
56
|
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
57
|
+
# Publishes the markdown document to HTML
|
58
|
+
#
|
59
|
+
# Reads the markdown source file, transforms links, renders to HTML,
|
60
|
+
# applies the layout template, and writes to the destination directory.
|
61
|
+
# The destination path is resolved at publish time by combining
|
62
|
+
# destination_directory_path + destination_path.
|
63
|
+
#
|
64
|
+
# @return [Pathname] the destination path relative to working_directory
|
65
|
+
def publish!(show_navigation: nil, navigation: nil, navigation_depth: nil, navigation_title: nil)
|
66
|
+
if @style_mode == :external && @render_style
|
67
|
+
create_external_stylesheet
|
68
|
+
end
|
69
|
+
|
70
|
+
# Read and parse Markdown into metadata + content
|
71
|
+
source_content = File.read(@source_path)
|
72
|
+
metadata, body = parse_metadata_from(source_content)
|
26
73
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
74
|
+
# Transform Markdown links, taking output format into account
|
75
|
+
body_with_rewritten_links = transform_markdown_links(body, &@transform_links)
|
76
|
+
|
77
|
+
# Render Markdown to HTML
|
78
|
+
rendered_content = Renderers::Markdown.render(body_with_rewritten_links)
|
79
|
+
|
80
|
+
# Create layout variables, for use in the layout template
|
81
|
+
layout_variables = {
|
82
|
+
working_directory: @working_directory,
|
83
|
+
current_path: @source_path.to_s,
|
84
|
+
metadata: metadata,
|
85
|
+
title: @title,
|
86
|
+
insert_title_heading: @insert_title_heading,
|
87
|
+
content: rendered_content.html_safe,
|
88
|
+
stylesheet_tag: render_stylesheet_tag(@style_path, @style_mode),
|
89
|
+
files: navigation ? generate_navigation_tree(navigation: navigation) : [],
|
90
|
+
show_navigation: show_navigation,
|
91
|
+
navigation_title: navigation_title
|
92
|
+
}
|
93
|
+
|
94
|
+
# Render the layout
|
95
|
+
layout_content = File.read(@layout_path)
|
96
|
+
rendered_content = Renderers::Erb.render(layout_content, layout_variables)
|
97
|
+
|
98
|
+
# Write the rendered content to the destination path
|
99
|
+
full_destination_path = @destination_directory_path.absolute? ?
|
100
|
+
@destination_directory_path + @destination_path :
|
101
|
+
@working_directory + @destination_directory_path + @destination_path
|
102
|
+
|
103
|
+
full_destination_path.dirname.mkpath
|
104
|
+
full_destination_path.open("w+") do |f|
|
105
|
+
f << rendered_content
|
51
106
|
end
|
52
107
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# Yield self to block after all other parameters are loaded,
|
61
|
-
# so we only have to tweak. (We don't have to give up our
|
62
|
-
# defaults or re-test blocks beyond them being tweaked.)
|
63
|
-
yield self if block
|
64
|
-
end
|
65
|
-
|
66
|
-
# Renders content in the context of layout and returns as a String.
|
67
|
-
def render(args={})
|
68
|
-
intermediate_content = layout.render self, args
|
69
|
-
Mint.after_render(intermediate_content, {})
|
70
|
-
end
|
71
|
-
|
72
|
-
# Writes all rendered content where a) possible, b) required,
|
73
|
-
# and c) specified. Outputs to specified file.
|
74
|
-
def publish!(opts={})
|
75
|
-
options = { :render_style => true }.merge(opts)
|
76
|
-
super
|
77
|
-
|
78
|
-
if @style_mode == :external && options[:render_style]
|
79
|
-
FileUtils.mkdir_p style_destination_directory
|
80
|
-
File.open(self.style_destination_file, "w+") do |f|
|
81
|
-
f << self.style.render
|
82
|
-
end
|
108
|
+
# Return the destination path used, for use in verbose output
|
109
|
+
begin
|
110
|
+
full_destination_path.relative_path_from(@working_directory)
|
111
|
+
rescue ArgumentError
|
112
|
+
# If, for some reason, the paths don't share a common prefix,
|
113
|
+
# return the full path to avoid an error
|
114
|
+
full_destination_path
|
83
115
|
end
|
84
|
-
|
85
|
-
Mint.after_publish(self, opts)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Implicit readers are paired with explicit accessors. This
|
89
|
-
# allows for processing variables before storing them.
|
90
|
-
attr_reader :metadata, :layout, :style
|
91
|
-
|
92
|
-
# Returns HTML content marked as safe for template rendering
|
93
|
-
def content
|
94
|
-
@content.html_safe
|
95
116
|
end
|
96
|
-
|
97
|
-
#
|
98
|
-
# the Document's content
|
117
|
+
|
118
|
+
# Transforms Markdown links from .md extensions
|
99
119
|
#
|
100
|
-
# @param [
|
101
|
-
#
|
102
|
-
# @return [
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
120
|
+
# @param [String] text the Markdown text containing links to Markdown documents
|
121
|
+
# @yield [String] block used to transform the basename of each Markdown link found
|
122
|
+
# @return [String] the text with transformed links
|
123
|
+
def transform_markdown_links(text, &block)
|
124
|
+
text.gsub(/(\[([^\]]*)\]\(([^)]*\.md)\))/) do |match|
|
125
|
+
link_text = $2
|
126
|
+
link_url = $3
|
127
|
+
|
128
|
+
# Only transform relative links (not absolute URLs)
|
129
|
+
if link_url !~ /^https?:\/\//
|
130
|
+
# Preserve directory structure in links
|
131
|
+
dirname = File.dirname(link_url)
|
132
|
+
basename = File.basename(link_url, ".*")
|
133
|
+
|
134
|
+
new_filename = yield basename
|
135
|
+
|
136
|
+
new_url = if dirname == "."
|
137
|
+
new_filename
|
138
|
+
else
|
139
|
+
File.join(dirname, new_filename)
|
140
|
+
end
|
141
|
+
|
142
|
+
"[#{link_text}](#{new_url})"
|
143
|
+
else
|
144
|
+
match
|
145
|
+
end
|
113
146
|
end
|
114
|
-
|
115
|
-
@renderer = Mint.renderer tempfile
|
116
|
-
@content = @renderer.render
|
117
147
|
end
|
118
148
|
|
119
|
-
#
|
149
|
+
# Generates navigation tree data for use in layout templates
|
120
150
|
#
|
121
|
-
# @
|
122
|
-
#
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
151
|
+
# @return [Array<Hash>] array of navigation items with keys:
|
152
|
+
# - :title (String) - display title for the item
|
153
|
+
# - :html_path (String) - path to the HTML file (for files) or nil (for directories)
|
154
|
+
# - :source_path (String) - path to the source file relative to working directory
|
155
|
+
# - :depth (Integer) - nesting depth in the tree
|
156
|
+
# - :is_directory (Boolean) - true if this is a directory entry (optional key)
|
157
|
+
def generate_navigation_tree(navigation:)
|
158
|
+
# Build DocumentTree with documents (path + title pairs)
|
159
|
+
document_tree = DocumentTree.new(navigation)
|
160
|
+
reoriented_tree = document_tree.reorient(@destination_path)
|
161
|
+
|
162
|
+
# Serialize to flat array for ERB template consumption
|
163
|
+
reoriented_tree.serialize(max_depth: @navigation_depth)
|
132
164
|
end
|
133
165
|
|
134
|
-
|
135
|
-
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
166
|
+
private
|
167
|
+
|
168
|
+
# Calculates the relative path of a target pathname to a reference pathname; this is an
|
169
|
+
# extension of Pathname#relative_path_from that handles the case where the reference pathname
|
170
|
+
# is a file and the target pathname is a directory. In this case, the relative path should be
|
171
|
+
# the target pathname.
|
172
|
+
#
|
173
|
+
# @param [Pathname] target_pathname the pathname to calculate the relative path for
|
174
|
+
# @param [Pathname] reference_pathname the pathname to use as the reference
|
175
|
+
# @return [Pathname] the relative path of the target pathname to the reference pathname
|
176
|
+
def calculate_relative_path(target_pathname, reference_pathname)
|
177
|
+
# Determine if reference is a file based on extension (since the file may not exist on disk yet)
|
178
|
+
reference_is_file = !reference_pathname.extname.empty?
|
179
|
+
reference_dir = reference_is_file ? reference_pathname.dirname : reference_pathname
|
180
|
+
|
181
|
+
begin
|
182
|
+
relative_path = target_pathname.relative_path_from(reference_dir)
|
183
|
+
|
184
|
+
# Prepend './' to relative paths that don't start with '../'
|
185
|
+
# to make it clear they are relative paths within the same directory tree
|
186
|
+
relative_str = relative_path.to_s
|
187
|
+
if relative_str.start_with?('../')
|
188
|
+
relative_path
|
143
189
|
else
|
144
|
-
|
145
|
-
Style.new(style_file, root: self.root, destination: self.destination, context: self.context)
|
190
|
+
Pathname.new("./#{relative_str}")
|
146
191
|
end
|
147
|
-
|
148
|
-
|
149
|
-
# Overrides layout and style settings with named template.
|
150
|
-
#
|
151
|
-
# @param [String] template the name of the template to set as
|
152
|
-
# layout and string
|
153
|
-
def template=(template)
|
154
|
-
if template
|
155
|
-
self.layout = template
|
156
|
-
self.style = template
|
192
|
+
rescue
|
193
|
+
target_pathname
|
157
194
|
end
|
158
195
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
# I'm going to maintain a document's official style_destination
|
163
|
-
# outside of its style object. If a document has no
|
164
|
-
# style_destination defined when it needs one, the document will
|
165
|
-
# use the original style's source directory.
|
166
|
-
#
|
167
|
-
# This decision eliminates edge cases, including the case where
|
168
|
-
# we want to generate, but not move, a document's style. It also
|
169
|
-
# lets us keep style information separate from document-specific
|
170
|
-
# information. (Without this separation, funky things happen when
|
171
|
-
# you assign a new style template to an existing document -- if
|
172
|
-
# you had specified a custom style_destination before changing
|
173
|
-
# the template, that custom destination would be overridden.)
|
174
|
-
#
|
175
|
-
# The style_destination attribute is lazy. It's exposed via
|
176
|
-
# virtual attributes like #style_destination_file.
|
177
|
-
attr_reader :style_destination, :style_mode
|
178
|
-
|
179
|
-
# @param [Symbol] style_mode how styles should be incorporated (:inline or :external)
|
180
|
-
# @return [void]
|
181
|
-
def style_mode=(style_mode)
|
182
|
-
@style_mode = style_mode
|
183
|
-
end
|
184
|
-
|
185
|
-
# @param [String] style_destination the subdirectory into
|
186
|
-
# which styles will be rendered or copied
|
187
|
-
# @return [void]
|
188
|
-
def style_destination=(style_destination)
|
189
|
-
@style_destination = style_destination
|
196
|
+
|
197
|
+
def metadata_chunk(text)
|
198
|
+
text.split(METADATA_DELIM).first
|
190
199
|
end
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
dir = path.absolute? ?
|
199
|
-
path : destination_directory_path + path
|
200
|
-
dir + style.name
|
200
|
+
|
201
|
+
def metadata_from(text)
|
202
|
+
raw_metadata = YAML.load(metadata_chunk(text))
|
203
|
+
|
204
|
+
case raw_metadata
|
205
|
+
when String, false, nil
|
206
|
+
{}
|
201
207
|
else
|
202
|
-
|
208
|
+
raw_metadata
|
203
209
|
end
|
210
|
+
rescue Psych::SyntaxError, Exception
|
211
|
+
{}
|
204
212
|
end
|
205
213
|
|
206
|
-
#
|
207
|
-
#
|
208
|
-
# @
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
style_destination_file_path.dirname
|
218
|
-
end
|
219
|
-
|
220
|
-
# Exposes style_destination directory as a String.
|
221
|
-
#
|
222
|
-
# @return [String]
|
223
|
-
def style_destination_directory
|
224
|
-
style_destination_directory_path.to_s
|
225
|
-
end
|
226
|
-
|
227
|
-
# Convenience methods for views
|
228
|
-
|
229
|
-
# Returns a relative path from the document to its stylesheet. Can
|
230
|
-
# be called directly from inside a layout template.
|
231
|
-
def stylesheet
|
232
|
-
tmp_style_dir = Mint.path_for_scope(:user) + "tmp"
|
233
|
-
tmp_style_file = tmp_style_dir + File.basename(style.name)
|
234
|
-
Helpers.normalize_path(tmp_style_file.to_s,
|
235
|
-
self.destination_directory).to_s
|
236
|
-
end
|
237
|
-
|
238
|
-
# Returns the rendered CSS content for inline inclusion
|
239
|
-
def inline_stylesheet
|
240
|
-
self.style.render
|
241
|
-
end
|
242
|
-
|
243
|
-
# Returns either inline CSS or stylesheet link based on style mode
|
244
|
-
# Use this helper in layouts instead of stylesheet or inline_stylesheet directly
|
245
|
-
def stylesheet_tag
|
246
|
-
case @style_mode
|
214
|
+
# Renders a stylesheet tag (either <style> or <link>) based on the style mode
|
215
|
+
#
|
216
|
+
# @param [Pathname] style_path the path to the style file
|
217
|
+
# @param [Symbol] style_mode the style mode (:inline, :external, :original)
|
218
|
+
# @return [String] the stylesheet tag
|
219
|
+
def render_stylesheet_tag(style_path, style_mode)
|
220
|
+
return "" unless style_path&.exist?
|
221
|
+
|
222
|
+
case style_mode
|
223
|
+
when :inline
|
224
|
+
"<style>#{Renderers::Css.render_file(style_path)}</style>"
|
247
225
|
when :external
|
248
|
-
|
226
|
+
full_destination_path = @destination_directory_path.absolute? ?
|
227
|
+
@destination_directory_path + @destination_path :
|
228
|
+
@working_directory + @destination_directory_path + @destination_path
|
229
|
+
absolute_stylesheet_path = external_stylesheet_destination_path
|
230
|
+
unless absolute_stylesheet_path.absolute?
|
231
|
+
absolute_stylesheet_path = @working_directory + absolute_stylesheet_path
|
232
|
+
end
|
233
|
+
relative_path_to_stylesheet = absolute_stylesheet_path.relative_path_from(full_destination_path.dirname)
|
234
|
+
"<link rel=\"stylesheet\" href=\"#{relative_path_to_stylesheet}\">"
|
249
235
|
when :original
|
250
|
-
|
251
|
-
|
252
|
-
|
236
|
+
full_destination_path = @destination_directory_path.absolute? ?
|
237
|
+
@destination_directory_path + @destination_path :
|
238
|
+
@working_directory + @destination_directory_path + @destination_path
|
239
|
+
absolute_style_path = style_path.absolute? ? style_path : @working_directory + style_path
|
240
|
+
relative_path_to_original = absolute_style_path.relative_path_from(full_destination_path.dirname)
|
241
|
+
"<link rel=\"stylesheet\" href=\"#{relative_path_to_original}\">"
|
242
|
+
else
|
243
|
+
style_content = Renderers::Css.render_file(style_path)
|
244
|
+
"<style>#{style_content}</style>"
|
253
245
|
end
|
254
246
|
end
|
255
|
-
|
256
|
-
#
|
257
|
-
# Links directly to original CSS files without processing
|
258
|
-
def original_stylesheet_tags
|
259
|
-
return "" unless self.style&.template_path
|
260
|
-
|
261
|
-
main_css_path = self.style.template_path
|
262
|
-
html_output_path = self.output_file
|
263
|
-
|
264
|
-
# Only process .css files
|
265
|
-
return "" unless File.extname(main_css_path) == '.css'
|
266
|
-
|
267
|
-
css_file_paths = CssParser.resolve_css_files(main_css_path, html_output_path)
|
268
|
-
CssParser.generate_link_tags(css_file_paths)
|
269
|
-
end
|
270
|
-
|
271
|
-
# Parses styles defined in YAML metadata in content, including it
|
272
|
-
# in output CSS style
|
247
|
+
|
248
|
+
# Returns the destination path for the external stylesheet
|
273
249
|
#
|
274
|
-
#
|
275
|
-
def
|
276
|
-
|
250
|
+
# @return [Pathname] the destination path for the external stylesheet
|
251
|
+
def external_stylesheet_destination_path
|
252
|
+
@style_destination_path + "style.css"
|
277
253
|
end
|
278
|
-
|
279
|
-
#
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
# Calculate where the current file will actually be placed
|
288
|
-
current_source_path = Pathname.new(source_file_path).expand_path
|
289
|
-
current_relative_to_source = current_source_path.relative_path_from(source_base_dir)
|
290
|
-
current_html_filename = current_relative_to_source.to_s.gsub(/\.(#{Mint::MARKDOWN_EXTENSIONS.join('|')})$/i, '.html')
|
291
|
-
|
292
|
-
dest_base = Pathname.new(root_directory_path).expand_path
|
293
|
-
if destination && !destination.empty?
|
294
|
-
dest_base = dest_base + destination
|
254
|
+
|
255
|
+
# Creates an external stylesheet if the style mode is :external
|
256
|
+
def create_external_stylesheet
|
257
|
+
return unless @style_mode == :external
|
258
|
+
style_output_file = external_stylesheet_destination_path
|
259
|
+
style_output_file.dirname.mkpath
|
260
|
+
style_output_file.open("w+") do |f|
|
261
|
+
f << Renderers::Css.render_file(@style_path)
|
295
262
|
end
|
296
|
-
|
297
|
-
current_full_path = dest_base + current_html_filename
|
298
|
-
current_destination_dir = current_full_path.dirname
|
299
|
-
|
300
|
-
@all_files.map do |file|
|
301
|
-
title = extract_title_from_file(file)
|
302
|
-
|
303
|
-
# Calculate where this target file will be placed
|
304
|
-
file_path = Pathname.new(file).expand_path
|
305
|
-
relative_to_source = file_path.relative_path_from(source_base_dir)
|
306
|
-
html_filename = relative_to_source.to_s.gsub(/\.(#{Mint::MARKDOWN_EXTENSIONS.join('|')})$/i, '.html')
|
307
|
-
|
308
|
-
target_full_path = dest_base + html_filename
|
309
|
-
|
310
|
-
# Calculate the relative path from the current file's destination directory to the target file
|
311
|
-
relative_link = target_full_path.relative_path_from(current_destination_dir)
|
312
|
-
|
313
|
-
{
|
314
|
-
source_path: relative_to_source.to_s,
|
315
|
-
html_path: relative_link.to_s,
|
316
|
-
title: title,
|
317
|
-
depth: relative_to_source.to_s.count('/')
|
318
|
-
}
|
319
|
-
end.sort_by {|f| f[:source_path] }
|
320
263
|
end
|
321
|
-
|
322
|
-
#
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
content = File.read(file)
|
329
|
-
|
330
|
-
if content =~ /^#\s+(.+)$/
|
331
|
-
return $1.strip
|
332
|
-
end
|
333
|
-
|
334
|
-
File.basename(file, '.*').tr('_-', ' ').split.map(&:capitalize).join(' ')
|
335
|
-
rescue
|
336
|
-
File.basename(file, '.*').tr('_-', ' ').split.map(&:capitalize).join(' ')
|
264
|
+
|
265
|
+
# Extracts title from Markdown file name
|
266
|
+
#
|
267
|
+
# @param [Pathname] file_path path to Markdown file
|
268
|
+
# @return [String] extracted title
|
269
|
+
def guess_title
|
270
|
+
Helpers.extract_title_from_file(@source_path)
|
337
271
|
end
|
338
|
-
|
339
|
-
#
|
340
|
-
#
|
341
|
-
# @param [String]
|
342
|
-
# @
|
343
|
-
def
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
relative_dir = relative_path.dirname
|
350
|
-
filename = relative_path.basename
|
351
|
-
|
352
|
-
# Set destination to preserve directory structure
|
353
|
-
if relative_dir.to_s != "."
|
354
|
-
# Combine base destination with relative directory structure
|
355
|
-
base_destination = destination || ""
|
356
|
-
if base_destination.empty?
|
357
|
-
destination = relative_dir.to_s
|
358
|
-
else
|
359
|
-
destination = File.join(base_destination, relative_dir.to_s)
|
360
|
-
end
|
272
|
+
|
273
|
+
# Parse YAML metadata from markdown content
|
274
|
+
#
|
275
|
+
# @param [String] text markdown content
|
276
|
+
# @return [Array] array of [metadata_hash, content_without_metadata]
|
277
|
+
def parse_metadata_from(text)
|
278
|
+
metadata = metadata_from(text)
|
279
|
+
new_text = if !metadata.empty?
|
280
|
+
text.sub(metadata_chunk(text) + METADATA_DELIM, "")
|
281
|
+
else
|
282
|
+
text
|
361
283
|
end
|
362
284
|
|
363
|
-
|
364
|
-
end
|
365
|
-
|
366
|
-
class << self
|
367
|
-
def metadata_chunk(text)
|
368
|
-
text.split(METADATA_DELIM).first
|
369
|
-
end
|
370
|
-
|
371
|
-
def metadata_from(text)
|
372
|
-
raw_metadata = YAML.load metadata_chunk(text)
|
373
|
-
|
374
|
-
case raw_metadata
|
375
|
-
when String
|
376
|
-
{}
|
377
|
-
when false
|
378
|
-
{}
|
379
|
-
when nil
|
380
|
-
{}
|
381
|
-
else
|
382
|
-
raw_metadata
|
383
|
-
end
|
384
|
-
rescue Psych::SyntaxError
|
385
|
-
{}
|
386
|
-
rescue Exception
|
387
|
-
{}
|
388
|
-
end
|
389
|
-
|
390
|
-
def parse_metadata_from(text)
|
391
|
-
metadata = metadata_from text
|
392
|
-
new_text =
|
393
|
-
if !metadata.empty?
|
394
|
-
text.sub metadata_chunk(text) + METADATA_DELIM, ""
|
395
|
-
else
|
396
|
-
text
|
397
|
-
end
|
398
|
-
|
399
|
-
[metadata, new_text]
|
400
|
-
end
|
285
|
+
[metadata, new_text]
|
401
286
|
end
|
402
287
|
end
|
403
|
-
end
|
288
|
+
end
|