mint 0.7.4 → 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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +23 -14
  3. data/LICENSE +22 -0
  4. data/README.md +68 -79
  5. data/bin/mint +47 -10
  6. data/bin/mint-epub +1 -4
  7. data/config/templates/base/style.css +187 -0
  8. data/config/templates/default/layout.erb +10 -0
  9. data/config/templates/default/style.css +237 -0
  10. data/config/templates/garden/layout.erb +38 -0
  11. data/config/templates/garden/style.css +303 -0
  12. data/config/templates/nord/layout.erb +11 -0
  13. data/config/templates/nord/style.css +339 -0
  14. data/config/templates/nord-dark/layout.erb +11 -0
  15. data/config/templates/nord-dark/style.css +339 -0
  16. data/config/templates/zen/layout.erb +11 -0
  17. data/config/templates/zen/style.css +114 -0
  18. data/lib/mint/command_line.rb +253 -111
  19. data/lib/mint/css.rb +11 -4
  20. data/lib/mint/css_parser.rb +76 -0
  21. data/lib/mint/css_template.rb +37 -0
  22. data/lib/mint/document.rb +203 -43
  23. data/lib/mint/helpers.rb +50 -10
  24. data/lib/mint/layout.rb +2 -3
  25. data/lib/mint/markdown_template.rb +47 -0
  26. data/lib/mint/mint.rb +181 -114
  27. data/lib/mint/plugin.rb +3 -3
  28. data/lib/mint/plugins/epub.rb +1 -2
  29. data/lib/mint/resource.rb +19 -9
  30. data/lib/mint/style.rb +10 -14
  31. data/lib/mint/version.rb +1 -1
  32. data/lib/mint.rb +1 -0
  33. data/man/mint.1 +135 -0
  34. data/spec/cli/README.md +99 -0
  35. data/spec/cli/argument_parsing_spec.rb +237 -0
  36. data/spec/cli/bin_integration_spec.rb +348 -0
  37. data/spec/cli/configuration_management_spec.rb +363 -0
  38. data/spec/cli/full_workflow_integration_spec.rb +527 -0
  39. data/spec/cli/publish_workflow_spec.rb +368 -0
  40. data/spec/cli/template_management_spec.rb +300 -0
  41. data/spec/css_parser_spec.rb +149 -0
  42. data/spec/css_spec.rb +1 -1
  43. data/spec/document_spec.rb +102 -69
  44. data/spec/helpers_spec.rb +42 -42
  45. data/spec/mint_spec.rb +104 -80
  46. data/spec/plugin_spec.rb +141 -143
  47. data/spec/run_cli_tests.rb +95 -0
  48. data/spec/spec_helper.rb +8 -1
  49. data/spec/style_spec.rb +18 -16
  50. data/spec/support/cli_helpers.rb +169 -0
  51. data/spec/support/fixtures/content-2.md +16 -0
  52. data/spec/support/matchers.rb +1 -1
  53. metadata +116 -224
  54. data/config/syntax.yaml +0 -71
  55. data/config/templates/base/style.sass +0 -144
  56. data/config/templates/default/css/style.css +0 -158
  57. data/config/templates/default/layout.haml +0 -8
  58. data/config/templates/default/style.sass +0 -36
  59. data/config/templates/protocol/layout.haml +0 -7
  60. data/config/templates/protocol/style.sass +0 -20
  61. data/config/templates/zen/css/style.css +0 -145
  62. data/config/templates/zen/layout.haml +0 -7
  63. data/config/templates/zen/style.sass +0 -24
  64. data/features/config.feature +0 -21
  65. data/features/plugins/epub.feature +0 -23
  66. data/features/publish.feature +0 -73
  67. data/features/support/env.rb +0 -15
  68. data/features/templates.feature +0 -79
  69. data/spec/command_line_spec.rb +0 -87
  70. data/spec/plugins/epub_spec.rb +0 -242
@@ -0,0 +1,527 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Full CLI Workflow Integration" do
4
+ describe "complete user workflows" do
5
+ context "in isolated environment" do
6
+ around(:each) do |example|
7
+ in_temp_dir do |dir|
8
+ @test_dir = dir
9
+ example.run
10
+ end
11
+ end
12
+
13
+ describe "new user getting started" do
14
+ it "can set up a new project from scratch" do
15
+ # 1. Initialize configuration
16
+ expect {
17
+ Mint::CommandLine.set("author", "Test User", :local)
18
+ Mint::CommandLine.set("layout", "clean", :local)
19
+ }.not_to raise_error
20
+
21
+ # 2. Create a custom template
22
+ layout_content = <<~HTML
23
+ <!DOCTYPE html>
24
+ <html lang="en">
25
+ <head>
26
+ <meta charset="UTF-8">
27
+ <title>My Site</title>
28
+ <% if style %>
29
+ <link rel="stylesheet" href="<%= style %>">
30
+ <% end %>
31
+ </head>
32
+ <body>
33
+ <header>
34
+ <h1>My Site</h1>
35
+ </header>
36
+ <main>
37
+ <%= content %>
38
+ </main>
39
+ <footer>
40
+ <p>&copy; 2024 Test User</p>
41
+ </footer>
42
+ </body>
43
+ </html>
44
+ HTML
45
+
46
+ create_template_file("my-layout.erb", :layout, layout_content)
47
+ Mint::CommandLine.install("my-layout.erb", "clean", :local)
48
+
49
+ # 3. Create some content
50
+ create_markdown_file("index.md", <<~MARKDOWN
51
+ # Welcome to My Site
52
+
53
+ This is the homepage of my new site.
54
+
55
+ ## Features
56
+
57
+ - Clean design
58
+ - Easy to maintain
59
+ - Fast loading
60
+
61
+ Check out my [about page](about.html).
62
+ MARKDOWN
63
+ )
64
+
65
+ create_markdown_file("about.md", <<~MARKDOWN
66
+ # About Me
67
+
68
+ I'm a developer who loves simple, clean websites.
69
+
70
+ ## Contact
71
+
72
+ - Email: test@example.com
73
+ - GitHub: @testuser
74
+ MARKDOWN
75
+ )
76
+
77
+ # 4. Publish the site
78
+ expect {
79
+ Mint::CommandLine.publish!(["index.md", "about.md"], {})
80
+ }.not_to raise_error
81
+
82
+ # 5. Verify everything worked
83
+ expect(File.exist?("index.html")).to be true
84
+ expect(File.exist?("about.html")).to be true
85
+
86
+ index_content = File.read("index.html")
87
+ expect(index_content).to include("<h1>My Site</h1>") # header
88
+ expect(index_content).to include("Welcome to My Site") # content
89
+ expect(index_content).to include("Test User") # footer
90
+ expect(index_content).to include("about.html") # link
91
+
92
+ about_content = File.read("about.html")
93
+ expect(about_content).to include("About Me")
94
+ expect(about_content).to include("test@example.com")
95
+ end
96
+ end
97
+
98
+ describe "documentation site workflow" do
99
+ it "can build a multi-page documentation site" do
100
+ # Create a documentation structure
101
+ FileUtils.mkdir_p("docs/guides")
102
+ FileUtils.mkdir_p("docs/api")
103
+ FileUtils.mkdir_p("build")
104
+
105
+ # Create navigation template
106
+ nav_layout = <<~ERB
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head>
110
+ <title>Documentation</title>
111
+ <style>
112
+ body { font-family: sans-serif; margin: 0; }
113
+ .container { display: flex; }
114
+ .sidebar { width: 200px; background: #f5f5f5; padding: 1rem; }
115
+ .content { flex: 1; padding: 1rem; }
116
+ .nav-link { display: block; margin: 0.5rem 0; }
117
+ </style>
118
+ </head>
119
+ <body>
120
+ <div class="container">
121
+ <nav class="sidebar">
122
+ <h3>Documentation</h3>
123
+ <% if defined?(all_files) && all_files %>
124
+ <% all_files.each do |file| %>
125
+ <% name = File.basename(file, '.md') %>
126
+ <% path = file.gsub('.md', '.html') %>
127
+ <a href="<%= path %>" class="nav-link"><%= name.tr('-', ' ').capitalize %></a>
128
+ <% end %>
129
+ <% end %>
130
+ </nav>
131
+ <main class="content">
132
+ <%= content %>
133
+ </main>
134
+ </div>
135
+ </body>
136
+ </html>
137
+ ERB
138
+
139
+ FileUtils.mkdir_p(".mint/templates/docs")
140
+ File.write(".mint/templates/docs/layout.erb", nav_layout)
141
+
142
+ # Create documentation content
143
+ create_markdown_file("docs/index.md", <<~MARKDOWN
144
+ # Project Documentation
145
+
146
+ Welcome to our comprehensive documentation.
147
+
148
+ ## Getting Started
149
+
150
+ See our [installation guide](guides/installation.html) to get up and running.
151
+ MARKDOWN
152
+ )
153
+
154
+ create_markdown_file("docs/guides/installation.md", <<~MARKDOWN
155
+ # Installation Guide
156
+
157
+ ## Prerequisites
158
+
159
+ - Ruby 2.7+
160
+ - Git
161
+
162
+ ## Steps
163
+
164
+ 1. Clone the repository
165
+ 2. Run `bundle install`
166
+ 3. Run `mint publish`
167
+ MARKDOWN
168
+ )
169
+
170
+ create_markdown_file("docs/api/overview.md", <<~MARKDOWN
171
+ # API Overview
172
+
173
+ Our API provides REST endpoints for all major operations.
174
+
175
+ ## Authentication
176
+
177
+ All requests require an API key in the header.
178
+ MARKDOWN
179
+ )
180
+
181
+ # Configure for documentation
182
+ Mint::CommandLine.set("layout", "docs", :local)
183
+ Mint::CommandLine.set("destination", "build", :local)
184
+
185
+ # Publish all documentation
186
+ files = ["docs/index.md", "docs/guides/installation.md", "docs/api/overview.md"]
187
+ Mint::CommandLine.publish!(files, { recursive: false })
188
+
189
+ # Verify the documentation site
190
+ expect(File.exist?("build/docs/index.html")).to be true
191
+ expect(File.exist?("build/docs/guides/installation.html")).to be true
192
+ expect(File.exist?("build/docs/api/overview.html")).to be true
193
+
194
+ index_content = File.read("build/docs/index.html")
195
+ expect(index_content).to include("Documentation") # nav
196
+ expect(index_content).to include("installation") # nav link
197
+ expect(index_content).to include("Project Documentation") # content
198
+ end
199
+ end
200
+
201
+ describe "blog workflow" do
202
+ it "can manage a simple blog" do
203
+ # Create blog structure
204
+ FileUtils.mkdir_p("posts")
205
+ FileUtils.mkdir_p("output")
206
+
207
+ # Create blog template
208
+ blog_layout = <<~ERB
209
+ <!DOCTYPE html>
210
+ <html>
211
+ <head>
212
+ <title>My Blog</title>
213
+ <meta name="viewport" content="width=device-width, initial-scale=1">
214
+ <style>
215
+ body {
216
+ max-width: 800px;
217
+ margin: 0 auto;
218
+ padding: 2rem;
219
+ font-family: Georgia, serif;
220
+ line-height: 1.6;
221
+ }
222
+ .header { border-bottom: 1px solid #eee; margin-bottom: 2rem; }
223
+ .post-meta { color: #666; font-size: 0.9em; margin-bottom: 1rem; }
224
+ .back-link { margin-top: 2rem; }
225
+ </style>
226
+ </head>
227
+ <body>
228
+ <header class="header">
229
+ <h1><a href="index.html">My Blog</a></h1>
230
+ </header>
231
+ <article>
232
+ <%= content %>
233
+ </article>
234
+ <div class="back-link">
235
+ <a href="index.html">&larr; Back to all posts</a>
236
+ </div>
237
+ </body>
238
+ </html>
239
+ ERB
240
+
241
+ FileUtils.mkdir_p(".mint/templates/blog")
242
+ File.write(".mint/templates/blog/layout.erb", blog_layout)
243
+
244
+ # Create blog posts
245
+ create_markdown_file("posts/2024-01-15-first-post.md", <<~MARKDOWN
246
+ # My First Blog Post
247
+
248
+ <div class="post-meta">January 15, 2024</div>
249
+
250
+ Welcome to my new blog! I'm excited to share my thoughts on:
251
+
252
+ - Web development
253
+ - Ruby programming
254
+ - Life and code
255
+
256
+ Stay tuned for more posts!
257
+ MARKDOWN
258
+ )
259
+
260
+ create_markdown_file("posts/2024-01-20-learning-mint.md", <<~MARKDOWN
261
+ # Learning Mint for Static Sites
262
+
263
+ <div class="post-meta">January 20, 2024</div>
264
+
265
+ I've been exploring Mint for generating static sites. Here's what I've learned:
266
+
267
+ ## Why Static Sites?
268
+
269
+ - Fast loading
270
+ - Easy hosting
271
+ - Version control friendly
272
+
273
+ ## Getting Started with Mint
274
+
275
+ The process is straightforward...
276
+ MARKDOWN
277
+ )
278
+
279
+ # Create an index page
280
+ create_markdown_file("index.md", <<~MARKDOWN
281
+ # Welcome to My Blog
282
+
283
+ Recent posts:
284
+
285
+ - [Learning Mint for Static Sites](posts/2024-01-20-learning-mint.html) - January 20, 2024
286
+ - [My First Blog Post](posts/2024-01-15-first-post.html) - January 15, 2024
287
+ MARKDOWN
288
+ )
289
+
290
+ # Configure and publish
291
+ Mint::CommandLine.configure({
292
+ "layout" => "blog",
293
+ "destination" => "output"
294
+ }, :local)
295
+
296
+ # Publish all content
297
+ files = Dir.glob("posts/*.md") + ["index.md"]
298
+ Mint::CommandLine.publish!(files, {})
299
+
300
+ # Verify blog structure
301
+ expect(File.exist?("output/index.html")).to be true
302
+ expect(File.exist?("output/posts/2024-01-15-first-post.html")).to be true
303
+ expect(File.exist?("output/posts/2024-01-20-learning-mint.html")).to be true
304
+
305
+ # Check content
306
+ index_content = File.read("output/index.html")
307
+ expect(index_content).to include("My Blog")
308
+ expect(index_content).to include("Recent posts")
309
+
310
+ post_content = File.read("output/posts/2024-01-15-first-post.html")
311
+ expect(post_content).to include("My First Blog Post")
312
+ expect(post_content).to include("January 15, 2024")
313
+ expect(post_content).to include("Back to all posts")
314
+ end
315
+ end
316
+
317
+ describe "team collaboration workflow" do
318
+ it "supports shared templates and configuration" do
319
+ # Simulate a team setup with shared templates
320
+
321
+ # 1. Set up shared template (simulating user scope)
322
+ shared_template = <<~ERB
323
+ <!DOCTYPE html>
324
+ <html>
325
+ <head>
326
+ <title>Company Documentation</title>
327
+ <style>
328
+ body { font-family: 'Helvetica', sans-serif; }
329
+ .company-header { background: #003366; color: white; padding: 1rem; }
330
+ .content { padding: 2rem; }
331
+ </style>
332
+ </head>
333
+ <body>
334
+ <header class="company-header">
335
+ <h1>Acme Corp Documentation</h1>
336
+ </header>
337
+ <div class="content">
338
+ <%= content %>
339
+ </div>
340
+ </body>
341
+ </html>
342
+ ERB
343
+
344
+ # Create company template
345
+ FileUtils.mkdir_p(".mint/templates/company")
346
+ File.write(".mint/templates/company/layout.erb", shared_template)
347
+
348
+ # 2. Individual developer customizes local config
349
+ Mint::CommandLine.configure({
350
+ "layout" => "company",
351
+ "author" => "Alice Developer",
352
+ "destination" => "team-docs"
353
+ }, :local)
354
+
355
+ # 3. Create team documentation
356
+ FileUtils.mkdir_p("team-docs")
357
+
358
+ create_markdown_file("project-overview.md", <<~MARKDOWN
359
+ # Project Overview
360
+
361
+ ## Architecture
362
+
363
+ Our system consists of three main components:
364
+
365
+ 1. Frontend (React)
366
+ 2. Backend (Rails API)
367
+ 3. Database (PostgreSQL)
368
+
369
+ ## Deployment
370
+
371
+ We use Docker for containerization and deploy to AWS.
372
+ MARKDOWN
373
+ )
374
+
375
+ # 4. Publish with team template
376
+ Mint::CommandLine.publish!(["project-overview.md"], {})
377
+
378
+ # 5. Verify team branding is applied
379
+ expect(File.exist?("team-docs/project-overview.html")).to be true
380
+
381
+ content = File.read("team-docs/project-overview.html")
382
+ expect(content).to include("Acme Corp Documentation")
383
+ expect(content).to include("company-header")
384
+ expect(content).to include("Project Overview")
385
+ end
386
+ end
387
+
388
+ describe "migration and maintenance workflows" do
389
+ it "can migrate templates and preserve content" do
390
+ # Start with old template
391
+ old_template = "<html><body><%= content %></body></html>"
392
+ create_template_file("old.erb", :layout, old_template)
393
+ Mint::CommandLine.install("old.erb", "v1", :local)
394
+
395
+ # Create content with old template
396
+ create_markdown_file("document.md", "# My Document\n\nContent here.")
397
+ Mint::CommandLine.publish!(["document.md"], { layout: "v1" })
398
+
399
+ old_content = File.read("document.html")
400
+ expect(old_content).to include("My Document")
401
+
402
+ # Create new, improved template
403
+ new_template = <<~ERB
404
+ <!DOCTYPE html>
405
+ <html lang="en">
406
+ <head>
407
+ <meta charset="UTF-8">
408
+ <title>Documentation</title>
409
+ </head>
410
+ <body>
411
+ <div class="container">
412
+ <%= content %>
413
+ </div>
414
+ </body>
415
+ </html>
416
+ ERB
417
+
418
+ create_template_file("new.erb", :layout, new_template)
419
+ Mint::CommandLine.install("new.erb", "v2", :local)
420
+
421
+ # Migrate to new template
422
+ Mint::CommandLine.publish!(["document.md"], { layout: "v2" })
423
+
424
+ new_content = File.read("document.html")
425
+ expect(new_content).to include("My Document") # content preserved
426
+ expect(new_content).to include("<!DOCTYPE html>") # new template features
427
+ expect(new_content).to include("container") # new styling
428
+ end
429
+ end
430
+
431
+ describe "error recovery workflows" do
432
+ it "can recover from and fix common mistakes" do
433
+ # 1. Try to use non-existent template (common mistake)
434
+ create_markdown_file("test.md", "# Test")
435
+
436
+ expect {
437
+ Mint::CommandLine.publish!(["test.md"], { layout: "nonexistent" })
438
+ }.to raise_error(Mint::TemplateNotFoundException)
439
+
440
+ # 2. Create the missing template
441
+ allow(STDIN).to receive(:gets).and_return("y\n") # auto-create
442
+ silence_output do
443
+ mock_editor do
444
+ Mint::CommandLine.edit("nonexistent", :layout, :local)
445
+ end
446
+ end
447
+
448
+ # 3. Now publishing should work
449
+ expect {
450
+ Mint::CommandLine.publish!(["test.md"], { layout: "nonexistent" })
451
+ }.not_to raise_error
452
+
453
+ expect(File.exist?("test.html")).to be true
454
+ end
455
+
456
+ it "handles corrupted configuration gracefully" do
457
+ # Create corrupted config
458
+ FileUtils.mkdir_p(".mint")
459
+ File.write(".mint/config.yaml", "invalid: yaml: content: [")
460
+
461
+ # Should still be able to set new config
462
+ expect {
463
+ Mint::CommandLine.set("layout", "recovery", :local)
464
+ }.not_to raise_error
465
+
466
+ # Config should now be valid
467
+ config = YAML.load_file(".mint/config.yaml")
468
+ expect(config["layout"]).to eq("recovery")
469
+ end
470
+ end
471
+
472
+ describe "performance with large projects" do
473
+ it "handles many files efficiently" do
474
+ # Create a larger number of files
475
+ FileUtils.mkdir_p("large-project")
476
+ setup_basic_config
477
+ create_template_directory("default")
478
+
479
+ files = []
480
+ 20.times do |i|
481
+ file = "large-project/page-#{i.to_s.rjust(3, '0')}.md"
482
+ content = <<~MARKDOWN
483
+ # Page #{i}
484
+
485
+ This is page number #{i} in our large project.
486
+
487
+ ## Content
488
+
489
+ #{'Lorem ipsum dolor sit amet. ' * 10}
490
+
491
+ ## Links
492
+
493
+ - [Previous](page-#{'%03d' % (i-1)}.html) #{i > 0 ? '' : '(none)'}
494
+ - [Next](page-#{'%03d' % (i+1)}.html) #{i < 19 ? '' : '(none)'}
495
+ MARKDOWN
496
+
497
+ create_markdown_file(file, content)
498
+ files << file
499
+ end
500
+
501
+ # Publish all files and measure time
502
+ start_time = Time.now
503
+
504
+ expect {
505
+ Mint::CommandLine.publish!(files, {})
506
+ }.not_to raise_error
507
+
508
+ end_time = Time.now
509
+ duration = end_time - start_time
510
+
511
+ # Verify all files were created
512
+ 20.times do |i|
513
+ expect(File.exist?("large-project/page-#{'%03d' % i}.html")).to be true
514
+ end
515
+
516
+ # Should complete in reasonable time (adjust as needed)
517
+ expect(duration).to be < 10.0
518
+
519
+ # Verify content quality isn't compromised
520
+ sample_content = File.read("large-project/page-010.html")
521
+ expect(sample_content).to include("Page 10")
522
+ expect(sample_content).to include("Lorem ipsum")
523
+ end
524
+ end
525
+ end
526
+ end
527
+ end