mint 0.8.0 → 0.8.1

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: 70a879d8b2c0b7150b6535b2c2c00c366d3e8484c499c7c0065e76bd5454b768
4
- data.tar.gz: a2595df94714597a9937a232115b963c096b6b71acbe373878a700181653adb4
3
+ metadata.gz: 49d66d53b189d1897ab9938358279f7dc0c4ede1d44926eba5f1b9b6f7d8344b
4
+ data.tar.gz: '08b1882ec1972dbedd02c87e0e6a4cf1f61ca0a631c7f56bca20b4dfeb1ea36b'
5
5
  SHA512:
6
- metadata.gz: 1ca15ee5ad05556ca6d7aef47d2f74f048a2f2cd7c11fc78931ffd6af7a36417dc65c04dae0661b53a71c9515dcdef09557d7538e0607da161a424061e3049f6
7
- data.tar.gz: 4d2b342e58022fde932ad266825bfed9d2b08ba029c0b0469868560a7d87e69383d8c0eab5fa3b28e63630283a33e808cb6319fd4ae9f0bc9734ca93dbea2598
6
+ metadata.gz: 3acb8ce3fc1856014e0efe3aa94d3720faeb8f677e2f9e3a46c541ecc8bd62f65a187558421ac10acc0599f813a8d161bed142bf44c75b51e6bc8f140351cc7f
7
+ data.tar.gz: 3851e818c5bad026bfde0302c8fe3184dfe4d79e93ca87479e85590015bb3fd082926fe88f7397144b8fbbb4163ae9e602bbb510bf23da009d20943b334896c2
data/README.md CHANGED
@@ -1,137 +1,100 @@
1
- # What is Mint?
1
+ # Mint
2
2
 
3
- Mint transforms your plain text documents into beautiful documents. It makes the process simple but customizable.
3
+ Transform your plain text documents into beautiful HTML documents with customizable styling and templates.
4
4
 
5
- Why would you want to keep all of your documents as plain text?
5
+ ## Installation
6
6
 
7
- - To focus on words and structure when you write
8
- - To control style with a single command, independently of document structure
9
- - To keep your text and formatting under version control
10
- - To make your text amenable to scripting--for example, text analysis
7
+ ```bash
8
+ gem install mint
9
+ ```
11
10
 
12
- What does Mint create from these source files? Beautiful, styled HTML ready to print, e-mail, export, and present.
11
+ ## Quick Start
13
12
 
14
- In a few words: *Mint processes words so you don't have to.*
13
+ Transform a Markdown document into styled HTML:
15
14
 
16
- ## The mint command
15
+ ```bash
16
+ mint publish Document.md
17
+ ```
17
18
 
18
- If you have a plain text document formatted in Markdown or Textile or almost any other templating
19
- language, you're ready to go.
19
+ This creates `Document.html` in your current directory with beautiful default styling.
20
20
 
21
- The easiest Mint command doesn't require configuration. It transforms a document into HTML and links
22
- it to the default stylesheet, which I've designed for you.
21
+ ## Usage
23
22
 
24
- Simply type:
23
+ ### Basic Commands
25
24
 
26
- mint publish Document.md
25
+ ```bash
26
+ # Publish a single document
27
+ mint publish Document.md
27
28
 
28
- And voilà, Minimalism.html will show up next to Document.md.
29
+ # Publish with a template
30
+ mint publish Document.md --template nord
29
31
 
30
- Opening Minimalism.html with your favorite web browser--[Firefox is best for typography][Firefox
31
- typography], but Webkit-based browsers (Chrome, Safari) work, too--will show what looks like a
32
- word-processed document, complete with big bold headers, italic emphasis, automatically indented
33
- and numbered lists, and bullets. If you're in a modern browser, you'll even see ligatures and
34
- proper kerning. The page will be on a white canvas that looks like a page, even though you are in a
35
- browser.
32
+ # Publish to a specific directory
33
+ mint publish Document.md --destination public
36
34
 
37
- Sending that page to a printer is as easy as clicking "Print" from your browser. What comes out of
38
- your printer will have a 12 pt base font, normal margins, and a not-too-cramped baseline. (Ah the
39
- wonder of print stylesheets.)
35
+ # Publish multiple files
36
+ mint publish *.md --destination final-drafts
40
37
 
41
- You can throw as many files as you'd like in. Any commandline argument *not* preceded by an option
42
- (e.g., `--template`) or in the `mint` command vocabulary (more on that in a minute) will be
43
- interpreted as a file name:
38
+ # Publish a digital garden, with linked navigation
39
+ mint publish content/**/*.md --template garden --destination public
40
+ ```
44
41
 
45
- mint publish Document.md Proposal.md
42
+ ### Common Options
46
43
 
47
- This command can be tweaked with options and arguments to be more flexible:
44
+ | Flag | Description |
45
+ |------|-------------|
46
+ | `-t, --template TEMPLATE` | Use a built-in template (combines layout + style) |
47
+ | `-l, --layout LAYOUT` | Specify only the layout |
48
+ | `-s, --style STYLE` | Specify only the style |
49
+ | `-d, --destination DIR` | Output directory |
50
+ | `-o, --output-file FORMAT` | Custom output filename format |
51
+ | `--style-mode MODE` | How styles are included (inline, external, original) |
52
+ | `--style-destination PATH` | Create external stylesheet and link it (sets mode to external) |
53
+ | `-r, --recursive` | Find all Markdown files in any directories specified |
48
54
 
49
- mint publish Document.md --template resume # specifies a style template
50
- mint publish Document.md --style-destination styles # creates external stylesheet in styles directory
51
- mint publish Document.md --style-destination styles/custom.css # creates external stylesheet at specific path
55
+ ### Style modes
52
56
 
53
- For a listing of mint options, take [a look at the tutorial][tutorial] or the [full API](http://www.rubydoc.info/github/davejacobs/mint).
57
+ Mint offers three ways to include styles in your HTML output:
54
58
 
55
- ## A basic Mint document
59
+ - **`inline`** (default) CSS is embedded directly in the HTML document as `<style>` tags
60
+ - **`external`** – CSS is compiled and saved as separate files, linked with `<link>` tags
61
+ - **`original`** – Links directly to original CSS template files without processing (for live editing)
56
62
 
57
- Mint is loaded with smart defaults, so if you don't want to configure something--say, the basic HTML
58
- skeleton of your document or the output directory--you don't have to. You'll probably be surprised
59
- at how easy it is to use out of the box, and how configurable it is.
63
+ The `original` mode is particularly useful for template development, as it allows you to edit CSS files and see changes immediately without republishing. Only `.css` files are supported in this mode, and `@import` statements in CSS files will be included as additional `<link>` tags.
60
64
 
61
- document = Mint::Document.new("Document.md")
62
- document.publish!
65
+ ### Built-in templates
63
66
 
64
- If you want to customize your document, though--and that's why I built this library--Mint makes that
65
- easy with explicit parameters:
67
+ - `default` Clean, minimal styling
68
+ - `nord` Clean, uses Nord color scheme
69
+ - `nord-dark` – Dark version of Nord
70
+ - `garden` – For digital gardens; includes navigation
66
71
 
67
- # Create a document with external stylesheet
68
- document = Mint::Document.new("Document.md",
69
- style_destination: "css",
70
- template: "zen")
71
- document.publish!
72
+ ## Documentation
72
73
 
73
- # Create with specific layout and style
74
- document = Mint::Document.new("Resume.md",
75
- destination: "output",
76
- layout: "resume",
77
- style: "professional")
78
- document.publish!
74
+ - **Complete usage guide:** [TUTORIAL.md](doc/TUTORIAL.md)
75
+ - **Man page:** `man mint` (after installation)
76
+ - **API documentation:** [RubyDoc](http://www.rubydoc.info/github/davejacobs/mint)
79
77
 
80
- To understand Mint's flexibility, you'll want to [take a look at the API][API].
78
+ ## Why Mint?
81
79
 
82
- [Firefox typography]: http://opentype.info/blog/2008/06/14/kerning-and-opentype-features-in-firefox-3/ "Firefox 3 supports
83
- kerning and automatic ligatures"
80
+ - **Focus on writing** Keep documents as plain text
81
+ - **Version control friendly** – Text files work great with Git
82
+ - **Scriptable** – Automate document processing
83
+ - **Beautiful output** – Professional-looking HTML ready for print or web
84
+ - **Highly customizable** – Create your own templates and styles
84
85
 
85
- ## Templates
86
+ ## Templates and customization
86
87
 
87
- Templates can be written in any format accepted by the Tilt template interface library. (See [the
88
- Tilt TEMPLATES file][Tilt templates] for more information.)
88
+ Mint supports layouts written in HAML or ERB and stylesheets can be written in CSS, SCSS, or SASS.
89
89
 
90
- In a template layouts, Ruby calls are sparse but necessary.
90
+ ## Contributing
91
91
 
92
- If you're designing a layout, you need to indicate where Mint should place your content. For that
93
- simple reason, raw HTML files cannot be layouts. Instead, if you want to use HTML templates, you
94
- should use the ERB format. These files are essentially HTML with the possibility for Ruby calls. You
95
- can even use the .html extension for your files. Just code the dynamic portion using ERB syntax.
92
+ 1. Fork the repository
93
+ 2. Create a feature branch
94
+ 3. Make your changes
95
+ 4. Run the tests: `rspec`
96
+ 5. Submit a pull request
96
97
 
97
- Inside your template, use the `content` method to place your source's content.
98
+ ## License
98
99
 
99
- For stylesheets, use the `stylesheet_tag` method, which automatically handles both inline and external stylesheets based on the document's style mode:
100
-
101
- So if you're writing your layout using Haml, the template might look like this:
102
-
103
- !!!
104
- %html
105
- %head
106
- = stylesheet_tag
107
- %body
108
- #container= content
109
-
110
- The `stylesheet_tag` method will generate either:
111
- - `<style>...</style>` tags with inlined CSS for inline mode (default)
112
- - `<link rel="stylesheet" href="...">` tags for external stylesheets
113
-
114
- You can create template stylesheets using [CSS][] or [SCSS][].
115
-
116
- Mint comes preloaded with a few templates to get you started.
117
-
118
- 1. Default
119
- 2. Zen
120
- 3. Nord
121
- 4. Nord Dark
122
-
123
- ## Plugins: A work in progress
124
-
125
- I've designed the beginnings of a plugin system. With this system, you can implement a callback or
126
- two and have full control over document creation and sharing. I'll get documentation going soon. For
127
- now, look to lib/mint/plugins/epub.rb and bin/mint-epub for an example of how to build one. It's not
128
- complete and I'm open to API suggestions.
129
-
130
- This is going to be useful for things like creating actual office documents or e-books or even bound
131
- novels. I'm actually thinking that half the power of this library is its plugin system.
132
-
133
- [tutorial]: http://github.com/davejacobs/mint/tree/master/doc/API.md
134
- [Tilt templates]: http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md "A listing of all templates supported by Tilt."
135
- [CSS]: http://en.wikipedia.org/wiki/Cascading_Style_Sheets
136
- [SASS/SCSS]: http://sass-lang.com/
137
- [Less]: http://lesscss.org/
100
+ MIT License. See [LICENSE](LICENSE) for details.
@@ -41,8 +41,8 @@ module Mint
41
41
  parsed_options[:destination] = d
42
42
  end
43
43
 
44
- cli.on "--inline-style", "Inline CSS into the HTML document (default)" do
45
- parsed_options[:style_mode] = :inline
44
+ cli.on "--style-mode MODE", ["inline", "external", "original"], "Specify how styles are included (inline, external, original)" do |mode|
45
+ parsed_options[:style_mode] = mode.to_sym
46
46
  end
47
47
 
48
48
  cli.on "--style-destination DESTINATION", "Create stylesheet at specified directory or file path and link it" do |destination|
@@ -58,7 +58,7 @@ module Mint
58
58
  parsed_options[:scope] = :user
59
59
  end
60
60
 
61
- cli.on "-l", "--local", "Specify config changes on a project-specific level" do
61
+ cli.on "--local", "Specify config changes on a project-specific level" do
62
62
  parsed_options[:scope] = :local
63
63
  end
64
64
 
@@ -71,7 +71,7 @@ module Mint
71
71
  parser.parse! transient_argv
72
72
 
73
73
  if parsed_options[:style_mode] == :inline && parsed_options[:style_destination]
74
- raise ArgumentError, "--inline-style and --style-destination cannot be used together"
74
+ raise ArgumentError, "--style-mode inline and --style-destination cannot be used together"
75
75
  end
76
76
 
77
77
  default_options = Mint.default_options.merge(destination: Dir.getwd)
@@ -0,0 +1,76 @@
1
+ require "pathname"
2
+
3
+ module Mint
4
+ # Parses CSS files to extract @import statements and calculate relative paths
5
+ class CssParser
6
+
7
+ # Extracts @import statements from CSS content
8
+ #
9
+ # @param [String] css_content the CSS content to parse
10
+ # @return [Array<String>] array of imported file paths
11
+ def self.extract_imports(css_content)
12
+ imports = []
13
+
14
+ # Match @import statements with various formats:
15
+ # @import "file.css";
16
+ # @import 'file.css';
17
+ # @import url("file.css");
18
+ # @import url('file.css');
19
+ css_content.scan(/@import\s+(?:url\()?['"]([^'"]+)['"](?:\))?;?/i) do |match|
20
+ imports << match[0]
21
+ end
22
+
23
+ imports
24
+ end
25
+
26
+ # Resolves all CSS files (main + imports) and calculates their paths relative to HTML output
27
+ #
28
+ # @param [String] main_css_path absolute path to the main CSS file
29
+ # @param [String] html_output_path absolute path to the HTML output file
30
+ # @return [Array<String>] array of relative paths from HTML to CSS files
31
+ def self.resolve_css_files(main_css_path, html_output_path)
32
+ css_files = []
33
+ main_css_file = Pathname.new(main_css_path)
34
+ html_file = Pathname.new(html_output_path)
35
+
36
+ # Add the main CSS file
37
+ css_files << main_css_file.relative_path_from(html_file.dirname).to_s
38
+
39
+ # Only process if main CSS file exists and is a .css file
40
+ return css_files unless main_css_file.exist? && main_css_file.extname == '.css'
41
+
42
+ begin
43
+ css_content = File.read(main_css_path)
44
+ imports = extract_imports(css_content)
45
+
46
+ imports.each do |import_path|
47
+ # Resolve import path relative to the main CSS file's directory
48
+ import_file = main_css_file.dirname + import_path
49
+
50
+ # Only include if it's a .css file and exists
51
+ if import_file.exist? && import_file.extname == '.css'
52
+ # Calculate path relative to HTML output
53
+ relative_import = import_file.relative_path_from(html_file.dirname).to_s
54
+ css_files << relative_import
55
+ end
56
+ end
57
+
58
+ rescue => e
59
+ # If we can't read the CSS file, just return the main file
60
+ # This allows the system to gracefully handle missing or unreadable files
61
+ end
62
+
63
+ css_files
64
+ end
65
+
66
+ # Generates HTML link tags for CSS files
67
+ #
68
+ # @param [Array<String>] css_file_paths array of relative paths to CSS files
69
+ # @return [String] HTML link tags
70
+ def self.generate_link_tags(css_file_paths)
71
+ css_file_paths.map do |css_path|
72
+ %Q{<link rel="stylesheet" href="#{css_path}">}
73
+ end.join("\n ")
74
+ end
75
+ end
76
+ end
data/lib/mint/document.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "mint/resource"
2
2
  require "mint/layout"
3
3
  require "mint/style"
4
+ require "mint/css_parser"
4
5
 
5
6
  module Mint
6
7
  class Document < Resource
@@ -245,11 +246,28 @@ module Mint
245
246
  case @style_mode
246
247
  when :external
247
248
  "<link rel=\"stylesheet\" href=\"#{stylesheet}\">".html_safe
249
+ when :original
250
+ original_stylesheet_tags.html_safe
248
251
  else # :inline (default)
249
252
  "<style>#{self.style.render}</style>".html_safe
250
253
  end
251
254
  end
252
255
 
256
+ # Generates stylesheet link tags for original mode
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
+
253
271
  # Parses styles defined in YAML metadata in content, including it
254
272
  # in output CSS style
255
273
  #
data/lib/mint/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mint
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.1"
3
3
  end
data/man/mint.1 CHANGED
@@ -18,16 +18,16 @@ Transform one or more source files into HTML documents
18
18
  .BR \-d ", " \-\-destination " " \fIDIRECTORY\fR
19
19
  Specify a destination directory, relative to the root
20
20
  .TP
21
- .BR \-\-inline\-style
22
- Inline CSS into the HTML document (default behavior)
21
+ .BR \-\-style\-mode " " \fIMODE\fR
22
+ Specify how styles are included (inline, external, original). Default is inline.
23
23
  .TP
24
24
  .BR \-\-style\-destination " " \fIDESTINATION\fR
25
- Create stylesheet at specified directory or file path and link it. This option is mutually exclusive with --inline-style.
25
+ Create stylesheet at specified directory or file path and link it. This sets style mode to external.
26
26
  .TP
27
27
  .BR \-\-template " " \fITEMPLATE\fR
28
28
  Specify a template to use for both layout and styling
29
29
  .TP
30
- .BR \-\-layout " " \fILAYOUT\fR
30
+ .BR \-l ", " \-\-layout " " \fILAYOUT\fR
31
31
  Specify a specific layout template
32
32
  .TP
33
33
  .BR \-\-style " " \fISTYLE\fR
@@ -39,7 +39,7 @@ Specify config changes on a global level
39
39
  .BR \-u ", " \-\-user
40
40
  Specify config changes on a user-wide level
41
41
  .TP
42
- .BR \-l ", " \-\-local
42
+ .BR \-\-local
43
43
  Specify config changes on a local level (default)
44
44
  .TP
45
45
  .BR \-r ", " \-\-recursive
data/spec/cli/README.md CHANGED
@@ -6,17 +6,17 @@ This directory contains a comprehensive test suite for the Mint command-line int
6
6
 
7
7
  ### Core test files
8
8
 
9
- - **`argument_parsing_spec.rb`** - Tests command-line argument parsing and option handling
10
- - **`template_management_spec.rb`** - Tests template installation, uninstallation, editing, and listing
11
- - **`publish_workflow_spec.rb`** - Tests markdown publishing, file discovery, and output generation
12
- - **`configuration_management_spec.rb`** - Tests configuration setting, reading, and scope management
13
- - **`bin_integration_spec.rb`** - Tests actual `bin/mint` executable integration
14
- - **`full_workflow_integration_spec.rb`** - End-to-end workflow tests for common user scenarios
9
+ - **`argument_parsing_spec.rb`** Tests command-line argument parsing and option handling
10
+ - **`template_management_spec.rb`** Tests template installation, uninstallation, editing, and listing
11
+ - **`publish_workflow_spec.rb`** Tests markdown publishing, file discovery, and output generation
12
+ - **`configuration_management_spec.rb`** Tests configuration setting, reading, and scope management
13
+ - **`bin_integration_spec.rb`** Tests actual `bin/mint` executable integration
14
+ - **`full_workflow_integration_spec.rb`** End-to-end workflow tests for common user scenarios
15
15
 
16
16
  ### Support files
17
17
 
18
- - **`../support/cli_helpers.rb`** - Helper methods for CLI testing (temp directories, file creation, output capture)
19
- - **`run_cli_tests.rb`** - Custom test runner with better output formatting
18
+ - **`../support/cli_helpers.rb`** Helper methods for CLI testing (temp directories, file creation, output capture)
19
+ - **`run_cli_tests.rb`** Custom test runner with better output formatting
20
20
 
21
21
  ## Running tests
22
22
 
@@ -79,9 +79,9 @@ end
79
79
  ## Debugging failed tests
80
80
 
81
81
  ### Common issues
82
- 1. **Missing templates** - Tests create minimal templates; check `create_template_directory`
83
- 2. **File paths** - All paths should be relative within temp directory
84
- 3. **Configuration** - Use `setup_basic_config` to establish minimal config
82
+ 1. **Missing templates** Tests create minimal templates; check `create_template_directory`
83
+ 2. **File paths** All paths should be relative within temp directory
84
+ 3. **Configuration** Use `setup_basic_config` to establish minimal config
85
85
 
86
86
  ### Debug helpers
87
87
 
@@ -29,6 +29,13 @@ RSpec.describe "CLI Argument Parsing" do
29
29
  expect(result[:options][:layout_or_style_or_template]).to eq([:layout, "custom"])
30
30
  end
31
31
 
32
+ it "parses -l option for layout" do
33
+ result = Mint::CommandLine.parse(["-l", "custom", "file.md"])
34
+
35
+ expect(result[:argv]).to eq(["file.md"])
36
+ expect(result[:options][:layout_or_style_or_template]).to eq([:layout, "custom"])
37
+ end
38
+
32
39
  it "parses --style option" do
33
40
  result = Mint::CommandLine.parse(["--style", "minimal", "file.md"])
34
41
 
@@ -107,9 +114,6 @@ RSpec.describe "CLI Argument Parsing" do
107
114
 
108
115
  result = Mint::CommandLine.parse(["-u"])
109
116
  expect(result[:options][:scope]).to eq(:user)
110
-
111
- result = Mint::CommandLine.parse(["-l"])
112
- expect(result[:options][:scope]).to eq(:local)
113
117
  end
114
118
  end
115
119
 
@@ -203,5 +207,31 @@ RSpec.describe "CLI Argument Parsing" do
203
207
  end
204
208
  end
205
209
  end
210
+
211
+ context "with style mode options" do
212
+ it "parses --style-mode inline" do
213
+ result = Mint::CommandLine.parse(["--style-mode", "inline", "file.md"])
214
+
215
+ expect(result[:options][:style_mode]).to eq(:inline)
216
+ end
217
+
218
+ it "parses --style-mode external" do
219
+ result = Mint::CommandLine.parse(["--style-mode", "external", "file.md"])
220
+
221
+ expect(result[:options][:style_mode]).to eq(:external)
222
+ end
223
+
224
+ it "parses --style-mode original" do
225
+ result = Mint::CommandLine.parse(["--style-mode", "original", "file.md"])
226
+
227
+ expect(result[:options][:style_mode]).to eq(:original)
228
+ end
229
+
230
+ it "defaults to inline style mode" do
231
+ result = Mint::CommandLine.parse(["file.md"])
232
+
233
+ expect(result[:options][:style_mode]).to eq(:inline)
234
+ end
235
+ end
206
236
  end
207
237
  end
@@ -0,0 +1,149 @@
1
+ require "spec_helper"
2
+ require "mint/css_parser"
3
+ require "tempfile"
4
+ require "pathname"
5
+
6
+ describe Mint::CssParser do
7
+ describe ".extract_imports" do
8
+ it "extracts @import statements with double quotes" do
9
+ css = '@import "reset.css"; body { margin: 0; }'
10
+ imports = Mint::CssParser.extract_imports(css)
11
+ expect(imports).to eq(["reset.css"])
12
+ end
13
+
14
+ it "extracts @import statements with single quotes" do
15
+ css = "@import 'normalize.css'; .class { color: red; }"
16
+ imports = Mint::CssParser.extract_imports(css)
17
+ expect(imports).to eq(["normalize.css"])
18
+ end
19
+
20
+ it "extracts @import url() statements" do
21
+ css = '@import url("fonts.css"); @import url(\'colors.css\');'
22
+ imports = Mint::CssParser.extract_imports(css)
23
+ expect(imports).to eq(["fonts.css", "colors.css"])
24
+ end
25
+
26
+ it "extracts multiple @import statements" do
27
+ css = <<~CSS
28
+ @import "reset.css";
29
+ @import 'normalize.css';
30
+ @import url("fonts.css");
31
+ body { margin: 0; }
32
+ CSS
33
+ imports = Mint::CssParser.extract_imports(css)
34
+ expect(imports).to eq(["reset.css", "normalize.css", "fonts.css"])
35
+ end
36
+
37
+ it "returns empty array when no imports found" do
38
+ css = "body { margin: 0; color: blue; }"
39
+ imports = Mint::CssParser.extract_imports(css)
40
+ expect(imports).to eq([])
41
+ end
42
+ end
43
+
44
+ describe ".resolve_css_files" do
45
+ let(:temp_dir) { Dir.mktmpdir }
46
+
47
+ after do
48
+ FileUtils.rm_rf(temp_dir)
49
+ end
50
+
51
+ it "resolves main CSS file path relative to HTML output" do
52
+ # Create directory structure:
53
+ # temp_dir/
54
+ # css/
55
+ # main.css
56
+ # output/
57
+ # index.html (output file)
58
+
59
+ css_dir = File.join(temp_dir, "css")
60
+ output_dir = File.join(temp_dir, "output")
61
+ FileUtils.mkdir_p([css_dir, output_dir])
62
+
63
+ main_css = File.join(css_dir, "main.css")
64
+ html_output = File.join(output_dir, "index.html")
65
+
66
+ File.write(main_css, "body { margin: 0; }")
67
+
68
+ css_files = Mint::CssParser.resolve_css_files(main_css, html_output)
69
+ expect(css_files).to eq(["../css/main.css"])
70
+ end
71
+
72
+ it "resolves main CSS and imported files" do
73
+ # Create directory structure:
74
+ # temp_dir/
75
+ # css/
76
+ # main.css (imports reset.css)
77
+ # reset.css
78
+ # output/
79
+ # index.html
80
+
81
+ css_dir = File.join(temp_dir, "css")
82
+ output_dir = File.join(temp_dir, "output")
83
+ FileUtils.mkdir_p([css_dir, output_dir])
84
+
85
+ main_css = File.join(css_dir, "main.css")
86
+ reset_css = File.join(css_dir, "reset.css")
87
+ html_output = File.join(output_dir, "index.html")
88
+
89
+ File.write(main_css, '@import "reset.css"; body { margin: 0; }')
90
+ File.write(reset_css, "* { box-sizing: border-box; }")
91
+
92
+ css_files = Mint::CssParser.resolve_css_files(main_css, html_output)
93
+ expect(css_files).to eq(["../css/main.css", "../css/reset.css"])
94
+ end
95
+
96
+ it "ignores non-existent imported files" do
97
+ css_dir = File.join(temp_dir, "css")
98
+ output_dir = File.join(temp_dir, "output")
99
+ FileUtils.mkdir_p([css_dir, output_dir])
100
+
101
+ main_css = File.join(css_dir, "main.css")
102
+ html_output = File.join(output_dir, "index.html")
103
+
104
+ File.write(main_css, '@import "nonexistent.css"; body { margin: 0; }')
105
+
106
+ css_files = Mint::CssParser.resolve_css_files(main_css, html_output)
107
+ expect(css_files).to eq(["../css/main.css"])
108
+ end
109
+
110
+ it "only processes .css files" do
111
+ scss_dir = File.join(temp_dir, "scss")
112
+ output_dir = File.join(temp_dir, "output")
113
+ FileUtils.mkdir_p([scss_dir, output_dir])
114
+
115
+ main_scss = File.join(scss_dir, "main.scss")
116
+ html_output = File.join(output_dir, "index.html")
117
+
118
+ File.write(main_scss, '@import "reset"; body { margin: 0; }')
119
+
120
+ css_files = Mint::CssParser.resolve_css_files(main_scss, html_output)
121
+ expect(css_files).to eq(["../scss/main.scss"])
122
+ end
123
+ end
124
+
125
+ describe ".generate_link_tags" do
126
+ it "generates HTML link tags for CSS files" do
127
+ css_paths = ["../css/main.css", "../css/reset.css"]
128
+
129
+ html = Mint::CssParser.generate_link_tags(css_paths)
130
+
131
+ expected = <<~HTML.strip
132
+ <link rel="stylesheet" href="../css/main.css">
133
+ <link rel="stylesheet" href="../css/reset.css">
134
+ HTML
135
+
136
+ expect(html).to eq(expected)
137
+ end
138
+
139
+ it "handles empty array" do
140
+ html = Mint::CssParser.generate_link_tags([])
141
+ expect(html).to eq("")
142
+ end
143
+
144
+ it "handles single CSS file" do
145
+ html = Mint::CssParser.generate_link_tags(["styles.css"])
146
+ expect(html).to eq('<link rel="stylesheet" href="styles.css">')
147
+ end
148
+ end
149
+ end
data/spec/plugin_spec.rb CHANGED
@@ -188,21 +188,21 @@ describe Mint do
188
188
  end
189
189
 
190
190
  # TODO: Document expected document functionality changes related to plugins
191
- describe Mint::Document do
192
- context "when plugins are registered with Mint" do
193
- describe "#content=" do
194
- it "applies each registered plugin's before_render filter"
195
- end
196
-
197
- describe "#render" do
198
- it "applies each registered plugin's after_render filter"
199
- end
200
-
201
- describe "#publish!" do
202
- it "applies each registered plugin's after_publish filter"
203
- end
204
- end
205
- end
191
+ # describe Mint::Document do
192
+ # context "when plugins are registered with Mint" do
193
+ # describe "#content=" do
194
+ # it "applies each registered plugin's before_render filter"
195
+ # end
196
+
197
+ # describe "#render" do
198
+ # it "applies each registered plugin's after_render filter"
199
+ # end
200
+
201
+ # describe "#publish!" do
202
+ # it "applies each registered plugin's after_publish filter"
203
+ # end
204
+ # end
205
+ # end
206
206
 
207
207
  describe Mint::Plugin do
208
208
  # We have to instantiate these plugins in a before block,
@@ -217,7 +217,7 @@ describe Mint do
217
217
  describe ".underscore" do
218
218
  let(:plugin) { Class.new(Mint::Plugin) }
219
219
 
220
- it "when anonymous, returns a random identifier"
220
+ # it "when anonymous, returns a random identifier"
221
221
 
222
222
  it "when named, returns its name, underscored" do
223
223
  expect(plugin).to receive(:name).and_return("EPub")
@@ -255,7 +255,7 @@ describe Mint do
255
255
  end
256
256
  end
257
257
 
258
- it "returns a hash of options the plugin can take, including constraints"
258
+ # it "returns a hash of options the plugin can take, including constraints"
259
259
  end
260
260
 
261
261
  context "plugin callbacks" do
@@ -328,47 +328,47 @@ describe Mint do
328
328
  expect(File.exist?("second-half.html")).to be_truthy
329
329
  end
330
330
 
331
- it "allows changes to the style file" do
332
- pending "figure out a better strategy for style manipulation"
333
- document = Mint::Document.new "content.md", style: "style.css"
334
-
335
- plugin.instance_eval do
336
- def after_publish(document)
337
- # I'd like to take document.style_destination_file,
338
- # but the current Mint API doesn't allow for this
339
- # if we're setting the style via a concrete
340
- # stylesheet in our current directory
341
- style_source = document.style.source_file
342
- style = File.read style_source
343
- File.open style_source, "w" do |file|
344
- file << style.gsub(/#/, ".")
345
- end
346
- end
347
- end
348
-
349
- document.publish! :plugins => [plugin]
350
-
351
- File.read(document.style.source_file).should =~ /\#container/
352
- end
353
-
354
- context "when the output is in the default directory" do
355
- it "doesn't allow changes to the document directory" do
356
- pending "figuring out the best way to prevent directory manipulation"
357
- document = Mint::Document.new "content.md"
358
- plugin.instance_eval do
359
- def after_publish
360
- original = document.destination_directory
361
- new = File.expand_path "invalid"
362
- FileUtils.mv original, new
363
- document.destination = "invalid"
364
- end
365
-
366
- expect do
367
- document.publish! :plugins => [plugin]
368
- end.to raise_error(InvalidPluginAction)
369
- end
370
- end
371
- end
331
+ # it "allows changes to the style file" do
332
+ # pending "figure out a better strategy for style manipulation"
333
+ # document = Mint::Document.new "content.md", style: "style.css"
334
+
335
+ # plugin.instance_eval do
336
+ # def after_publish(document)
337
+ # # I'd like to take document.style_destination_file,
338
+ # # but the current Mint API doesn't allow for this
339
+ # # if we're setting the style via a concrete
340
+ # # stylesheet in our current directory
341
+ # style_source = document.style.source_file
342
+ # style = File.read style_source
343
+ # File.open style_source, "w" do |file|
344
+ # file << style.gsub(/#/, ".")
345
+ # end
346
+ # end
347
+ # end
348
+
349
+ # document.publish! :plugins => [plugin]
350
+
351
+ # File.read(document.style.source_file).should =~ /\#container/
352
+ # end
353
+
354
+ # context "when the output is in the default directory" do
355
+ # it "doesn't allow changes to the document directory" do
356
+ # pending "figuring out the best way to prevent directory manipulation"
357
+ # document = Mint::Document.new "content.md"
358
+ # plugin.instance_eval do
359
+ # def after_publish
360
+ # original = document.destination_directory
361
+ # new = File.expand_path "invalid"
362
+ # FileUtils.mv original, new
363
+ # document.destination = "invalid"
364
+ # end
365
+
366
+ # expect do
367
+ # document.publish! :plugins => [plugin]
368
+ # end.to raise_error(InvalidPluginAction)
369
+ # end
370
+ # end
371
+ # end
372
372
 
373
373
  context "when the output is a new directory" do
374
374
  it "allows changes to the document directory" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Jacobs
@@ -182,24 +182,21 @@ files:
182
182
  - bin/mint
183
183
  - bin/mint-epub
184
184
  - config/templates/base/style.css
185
- - config/templates/default/css/style.css
186
185
  - config/templates/default/layout.erb
187
186
  - config/templates/default/style.css
188
187
  - config/templates/garden/layout.erb
189
188
  - config/templates/garden/style.css
190
- - config/templates/newspaper/layout.erb
191
189
  - config/templates/nord-dark/layout.erb
192
190
  - config/templates/nord-dark/style.css
193
191
  - config/templates/nord/layout.erb
194
192
  - config/templates/nord/style.css
195
- - config/templates/protocol/layout.erb
196
- - config/templates/protocol/style.css
197
193
  - config/templates/reset.css
198
194
  - config/templates/zen/layout.erb
199
195
  - config/templates/zen/style.css
200
196
  - lib/mint.rb
201
197
  - lib/mint/command_line.rb
202
198
  - lib/mint/css.rb
199
+ - lib/mint/css_parser.rb
203
200
  - lib/mint/css_template.rb
204
201
  - lib/mint/document.rb
205
202
  - lib/mint/exceptions.rb
@@ -225,6 +222,7 @@ files:
225
222
  - spec/cli/full_workflow_integration_spec.rb
226
223
  - spec/cli/publish_workflow_spec.rb
227
224
  - spec/cli/template_management_spec.rb
225
+ - spec/css_parser_spec.rb
228
226
  - spec/css_spec.rb
229
227
  - spec/document_spec.rb
230
228
  - spec/helpers_spec.rb
@@ -271,6 +269,7 @@ test_files:
271
269
  - spec/cli/full_workflow_integration_spec.rb
272
270
  - spec/cli/publish_workflow_spec.rb
273
271
  - spec/cli/template_management_spec.rb
272
+ - spec/css_parser_spec.rb
274
273
  - spec/css_spec.rb
275
274
  - spec/document_spec.rb
276
275
  - spec/helpers_spec.rb
@@ -1,205 +0,0 @@
1
- @import '../reset.css';
2
- body {
3
- font-family: Ubuntu, "Hoefler Text", "Grandesign Neue Serif", Ubuntu, Georgia, FreeSerif, serif, Georgia, serif;
4
- }
5
-
6
- h1, h2 {
7
- line-height: 1.3;
8
- }
9
-
10
- h2, h3, h4, h5, h6 {
11
- line-height: 22.5px;
12
- }
13
-
14
- h1, h2, h3, h4, h5, h6 {
15
- font-family: "Hoefler Text", Garamond, Georgia;
16
- font-weight: normal;
17
- }
18
-
19
- h1 {
20
- font-size: 22.5px;
21
- margin-top: 22.5px;
22
- margin-bottom: 22.5px;
23
- }
24
-
25
- h2 {
26
- font-size: 18px;
27
- margin-top: 33.75px;
28
- margin-bottom: 11.25px;
29
- }
30
-
31
- h3 {
32
- font-size: 16.5px;
33
- margin-top: 39.375px;
34
- margin-bottom: 5.625px;
35
- }
36
-
37
- h4 {
38
- font-size: 15.75px;
39
- margin-top: 19.6875px;
40
- margin-bottom: 2.8125px;
41
- }
42
-
43
- h5, h6 {
44
- font-size: 15px;
45
- margin-top: 19.6875px;
46
- margin-bottom: 2.8125px;
47
- }
48
-
49
- ul {
50
- list-style-type: square;
51
- }
52
- ul ul {
53
- list-style-type: circle;
54
- }
55
-
56
- ul, ol {
57
- margin: 5.625px 0 0 11.25px;
58
- padding-left: 27px;
59
- }
60
- ul li p, ol li p {
61
- text-indent: 0 !important;
62
- }
63
- ul li + li, ol li + li {
64
- margin-top: 5.625px;
65
- }
66
-
67
- p {
68
- margin: 11.25px 0;
69
- }
70
-
71
- ul + p, ol + p, blockquote + p, pre + p {
72
- text-indent: 0;
73
- }
74
-
75
- a:link, a:visited, a:active {
76
- color: #cb0018;
77
- text-decoration: none;
78
- }
79
- a:hover {
80
- text-decoration: underline;
81
- }
82
-
83
- code {
84
- font-family: Monaco, Menlo, Mensch, Consolas, Monotype, mono;
85
- font-style: normal;
86
- }
87
-
88
- pre, blockquote {
89
- display: block;
90
- margin-left: 22.5px;
91
- margin-right: 45px;
92
- padding: 7.5px 22.5px;
93
- padding-left: 16.875px;
94
- white-space: pre;
95
- }
96
- pre p, blockquote p {
97
- margin: 0;
98
- line-height: 1.35;
99
- }
100
-
101
- img {
102
- display: block;
103
- }
104
-
105
- @media screen {
106
- body {
107
- font-size: 15px;
108
- line-height: 22.5px;
109
- background-color: #666;
110
- color: #333;
111
- }
112
- #container {
113
- display: block;
114
- border: solid 1px #999;
115
- width: 780px;
116
- padding: 40px 60px;
117
- margin: 11.25px auto;
118
- background-color: #fff;
119
- box-sizing: border-box;
120
- -moz-box-sizing: border-box;
121
- -webkit-box-sizing: border-box;
122
- }
123
- code {
124
- font-size: 13.125px;
125
- }
126
- pre {
127
- white-space: pre-wrap;
128
- white-space: -moz-pre-wrap;
129
- white-space: -o-pre-wrap;
130
- word-wrap: break-word;
131
- }
132
- pre code {
133
- font-size: 11.25px;
134
- }
135
- }
136
- @media print {
137
- @page {
138
- margin-left: 1in;
139
- margin-right: 1in;
140
- margin-top: 1in;
141
- margin-bottom: 1in;
142
- }
143
- body {
144
- font-size: 12pt;
145
- line-height: 15.6pt;
146
- width: auto;
147
- margin: 0;
148
- padding: 0;
149
- }
150
- code {
151
- font-size: 10.5pt;
152
- }
153
- pre code {
154
- font-size: 9pt;
155
- }
156
- h1, h2, h3, h4, h5, h6, li, blockquote {
157
- page-break-inside: avoid;
158
- }
159
- p {
160
- widows: 3;
161
- orphans: 3;
162
- }
163
- }
164
- body {
165
- text-rendering: optimizeLegibility;
166
- }
167
-
168
- h1 {
169
- font-size: 25.5px;
170
- border-bottom: solid 2px #666;
171
- }
172
-
173
- h2 {
174
- font-size: 19.5px;
175
- }
176
-
177
- h3 {
178
- font-size: 18px;
179
- font-style: italic;
180
- }
181
-
182
- h4 {
183
- font-variant: small-caps;
184
- }
185
-
186
- h5, h6 {
187
- font-weight: bold;
188
- }
189
-
190
- p + p {
191
- text-indent: 22.5px;
192
- }
193
-
194
- pre, blockquote {
195
- border-left: solid 2px #ddd;
196
- background-color: #fdffe8;
197
- }
198
-
199
- blockquote {
200
- font-style: italic;
201
- }
202
-
203
- code {
204
- font-family: "Ubuntu Mono";
205
- }
@@ -1,16 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <link rel="preconnect" href="https://fonts.googleapis.com">
7
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
8
- <link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&family=Old+Standard+TT:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
9
- <%= stylesheet_tag %>
10
- </head>
11
- <body>
12
- <main id="container">
13
- <div class="newspaper-columns"><%= content %></div>
14
- </main>
15
- </body>
16
- </html>
@@ -1,9 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <%= stylesheet_tag %>
5
- </head>
6
- <body>
7
- <div id="container"><%= content %></div>
8
- </body>
9
- </html>
@@ -1,25 +0,0 @@
1
- :root {
2
- --screen-font-size: 16px;
3
- --screen-line-height: calc(var(--screen-font-size) * 1.3);
4
- --screen-unit: var(--screen-line-height);
5
-
6
- --print-font-size: 12pt;
7
- --print-line-height: calc(var(--print-font-size) * 1.3);
8
- --print-unit: var(--print-line-height);
9
-
10
- --link-color: #cb0018;
11
- }
12
-
13
- @import "../base/style.css";
14
-
15
- body {
16
- font-family: ScalaSansPro, "Helvetica Neue";
17
- }
18
-
19
- p + h2, p + h3, p + h4, p + h5, p + h6 {
20
- margin-top: calc(var(--screen-unit) * 1.5);
21
- }
22
-
23
- p {
24
- line-height: 1.25;
25
- }