static-site-builder 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 34651b912c8819f93ee3dd7dda4209674306e91ff9040d8343671412ba4a9873
4
+ data.tar.gz: 32ac2a4ce16874db16d7990607dbc557ab18fa0235670681377aabb0baf78684
5
+ SHA512:
6
+ metadata.gz: 96ace8067d05e208f9d26061962558fc9bfef30196e703be13249573612fb674ab496e6e052522e5c8ab6006b39b6825108d89a360323b5c4e6d2e9c02badc96
7
+ data.tar.gz: 2656f4592bf359cd186284ebbba773e83772fda781121e9515cee27d9f72b7fa7e6520c23858464842da95c9fab197782c7a4b510ef2b7cf3cbb0b2e7207be8d
data/ARCHITECTURE.md ADDED
@@ -0,0 +1,61 @@
1
+ # Architecture
2
+
3
+ This project is a **generator tool**, similar to `rails new`. It creates static site projects that use standard Ruby gems.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ static-site-generator/
9
+ ├── lib/
10
+ │ └── generator.rb # Main generator logic
11
+ ├── bin/
12
+ │ └── generate # CLI entry point
13
+ ├── exe/
14
+ │ └── static-site-generator # Gem executable
15
+ └── templates/ # Template files (future)
16
+ ```
17
+
18
+ ## How It Works
19
+
20
+ 1. **Generator** (`static-site-generator` gem)
21
+ - Creates project structure
22
+ - Generates Gemfile with dependencies
23
+ - Creates config files
24
+ - Sets up build tasks
25
+
26
+ 2. **Builder Gem** (`static-site-builder` gem) - **Separate gem**
27
+ - Handles ERB/Phlex compilation
28
+ - Manages asset copying
29
+ - Generates importmap JSON
30
+ - Outputs static HTML
31
+
32
+ 3. **Standard Gems** - Used by generated sites
33
+ - `importmap-rails` - Importmap support
34
+ - `phlex-rails` - Phlex components
35
+ - `static-site-builder` - Core builder functionality
36
+
37
+ ## Generated Site Structure
38
+
39
+ ```
40
+ my-site/
41
+ ├── Gemfile # Dependencies
42
+ ├── package.json # JS dependencies (if needed)
43
+ ├── Rakefile # Build tasks
44
+ ├── config/
45
+ │ └── importmap.rb # Importmap config
46
+ ├── app/
47
+ │ ├── views/
48
+ │ ├── javascript/
49
+ │ └── assets/
50
+ └── lib/
51
+ └── site_builder.rb # Thin wrapper using static-site-builder gem
52
+ ```
53
+
54
+ ## Separation of Concerns
55
+
56
+ - **Generator** - Creates projects (this repo)
57
+ - **Builder** - Compiles sites (`static-site-builder` gem)
58
+ - **Standard Gems** - Provide functionality (importmap-rails, etc.)
59
+
60
+ This keeps the generator lightweight and maintainable.
61
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.0.1] - 2025-11-21
9
+
10
+ ### Added
11
+ - Initial release of static-site-builder gem
12
+ - Generator for creating new static site projects
13
+ - Builder for compiling ERB templates to static HTML
14
+ - Support for multiple template engines (ERB, Phlex)
15
+ - Support for multiple JavaScript bundlers (Importmap, ESBuild, Webpack, Vite, None)
16
+ - Support for multiple CSS frameworks (TailwindCSS, shadcn/ui, Plain CSS)
17
+ - Support for multiple JavaScript frameworks (Stimulus, React, Vue, Alpine.js, Vanilla)
18
+ - Frontmatter parsing for ERB pages
19
+ - Layout support with nested layouts
20
+ - Importmap JSON generation
21
+ - Asset copying (JavaScript, CSS, vendor files, static files)
22
+ - Comprehensive test suite
23
+ - YARD documentation
24
+ - CI/CD setup (GitHub Actions)
25
+
26
+ ### Changed
27
+ - Vendor JavaScript files are automatically copied directly from `node_modules` to `dist/assets/javascripts/` during build
28
+ - Removed requirement for `vendor/javascript/` folder - vendor files are copied automatically based on importmap configuration
29
+ - Generator no longer creates vendor files during project generation
30
+
31
+ ### Fixed
32
+ - Added warning messages when vendor files cannot be found in `node_modules`
33
+ - Updated base64 dependency comments to clarify requirement for Ruby 3.4+
34
+
35
+ [0.0.1]: https://github.com/Ancez/static-site-builder/releases/tag/v0.0.1
36
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Static Site Builder Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,482 @@
1
+ # Static Site Builder
2
+
3
+ A Ruby-based generator and builder for creating static HTML sites with working JavaScript. **No backend required** - just compile your templates to static HTML and deploy anywhere.
4
+
5
+ ## Main Objective
6
+
7
+ Generate static HTML pages with JavaScript files that work. Choose your own stack:
8
+
9
+ - **Template Engine**: ERB or Phlex
10
+ - **JavaScript Bundler**: Importmap, ESBuild, Webpack, Vite, or none
11
+ - **CSS Framework**: TailwindCSS, shadcn/ui, or plain CSS
12
+ - **JavaScript Framework**: Stimulus, React, Vue, Alpine.js, or vanilla JS
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ gem install static-site-builder
18
+ # or
19
+ git clone https://github.com/Ancez/static-site-builder
20
+ cd static-site-builder
21
+ bundle install
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Option 1: Install as a gem
27
+ ```bash
28
+ gem install static-site-builder
29
+ static-site-builder new my-site
30
+ ```
31
+
32
+ ### Option 2: Use directly from repo
33
+ ```bash
34
+ git clone https://github.com/Ancez/static-site-builder
35
+ cd static-site-builder
36
+ bundle install
37
+ ruby bin/generate my-site
38
+ ```
39
+
40
+ You'll be prompted to choose your stack using an interactive menu with arrow key navigation. Generated sites use:
41
+ - `static-site-builder` gem for compilation
42
+ - Standard gems (importmap-rails, phlex-rails, etc.) for functionality
43
+ - npm packages for JS bundlers and frameworks
44
+
45
+ ## What Gets Generated
46
+
47
+ A clean project structure that depends on gems:
48
+
49
+ ```
50
+ my-site/
51
+ ├── Gemfile # Dependencies (static-site-builder, importmap-rails, etc.)
52
+ ├── package.json # JS dependencies (if needed)
53
+ ├── Rakefile # Build tasks
54
+ ├── config/
55
+ │ └── importmap.rb # Importmap config (if using importmap)
56
+ ├── app/
57
+ │ ├── views/
58
+ │ │ ├── layouts/
59
+ │ │ ├── pages/
60
+ │ │ └── components/ # Reusable components/partials
61
+ │ ├── javascript/
62
+ │ └── assets/
63
+ └── lib/
64
+ └── site_builder.rb # Compiles your site
65
+ ```
66
+
67
+ ## How It Works
68
+
69
+ 1. **Generator** (`static-site-generator`) - Creates the project structure
70
+ 2. **Builder Gem** (`static-site-builder`) - Handles ERB/Phlex compilation
71
+ 3. **Standard Gems** - importmap-rails, phlex-rails, etc. for functionality
72
+ 4. **Build Tools** - Rake tasks that use the builder gem
73
+
74
+ ## Features
75
+
76
+ - 🎯 **Static HTML output** - No server-side rendering needed
77
+ - 🔧 **Flexible stack** - Choose what works for you
78
+ - 📦 **Gem-based** - Uses existing Ruby gems, not custom code
79
+ - 🚀 **Fast builds** - Compile once, deploy everywhere
80
+ - 🎨 **Component support** - ERB or Phlex components
81
+ - 📱 **Modern JS** - ES modules, importmaps, or bundlers
82
+
83
+ ## Supported Stacks
84
+
85
+ ### Template Engines
86
+ - **ERB** - Ruby's embedded Ruby templates
87
+ - **Phlex** - Ruby component library (via phlex-rails gem)
88
+
89
+ ### JavaScript Bundlers
90
+ - **Importmap** - No bundling, use ES modules directly (via importmap-rails gem)
91
+ - **ESBuild** - Fast JavaScript bundler
92
+ - **Webpack** - Powerful bundler with plugins
93
+ - **Vite** - Next-generation frontend tooling
94
+ - **None** - Vanilla JavaScript, no bundling
95
+
96
+ ### CSS Frameworks
97
+ - **TailwindCSS** - Utility-first CSS framework
98
+ - **shadcn/ui** - Re-usable components built with Tailwind
99
+ - **Plain CSS** - Write your own styles
100
+
101
+ ### JavaScript Frameworks
102
+ - **Stimulus** - Modest JavaScript framework
103
+ - **React** - Popular UI library
104
+ - **Vue** - Progressive JavaScript framework
105
+ - **Alpine.js** - Minimal framework for HTML
106
+ - **Vanilla JS** - No framework
107
+
108
+ ## Building Powerful Websites
109
+
110
+ ### Using ERB Templates
111
+
112
+ Create pages in `app/views/pages/` with frontmatter:
113
+
114
+ ```erb
115
+ ---
116
+ title: My Page
117
+ description: A great page
118
+ ---
119
+
120
+ <h1><%= @title %></h1>
121
+ <p><%= @description %></p>
122
+ ```
123
+
124
+ Use layouts in `app/views/layouts/application.html.erb`:
125
+
126
+ ```erb
127
+ <!DOCTYPE html>
128
+ <html>
129
+ <head>
130
+ <title><%= @title || "My Site" %></title>
131
+ </head>
132
+ <body>
133
+ <%= yield %>
134
+ </body>
135
+ </html>
136
+ ```
137
+
138
+ ### Using Phlex Components
139
+
140
+ Create reusable components in `app/views/components/`:
141
+
142
+ ```ruby
143
+ class Button < Phlex::HTML
144
+ def initialize(text:, href:, variant: "primary")
145
+ @text = text
146
+ @href = href
147
+ @variant = variant
148
+ end
149
+
150
+ def template
151
+ a(href: @href, class: "btn btn-#{@variant}") { @text }
152
+ end
153
+ end
154
+ ```
155
+
156
+ Use in pages:
157
+
158
+ ```ruby
159
+ class HomePage < Phlex::HTML
160
+ def template
161
+ div do
162
+ h1 { "Welcome" }
163
+ render Button.new(text: "Get Started", href: "/about")
164
+ end
165
+ end
166
+ end
167
+ ```
168
+
169
+ ### JavaScript with Importmap
170
+
171
+ No bundling needed - use ES modules directly:
172
+
173
+ ```javascript
174
+ // app/javascript/application.js
175
+ import { Application } from "@hotwired/stimulus"
176
+ import HelloController from "./controllers/hello_controller"
177
+
178
+ window.Stimulus = Application.start()
179
+ Stimulus.register("hello", HelloController)
180
+ ```
181
+
182
+ ### JavaScript with Bundlers
183
+
184
+ Use ESBuild, Webpack, or Vite for modern tooling:
185
+
186
+ ```javascript
187
+ // app/javascript/index.js
188
+ import React from 'react'
189
+ import { createRoot } from 'react-dom/client'
190
+
191
+ function App() {
192
+ return <h1>Hello from React!</h1>
193
+ }
194
+
195
+ const root = createRoot(document.getElementById('app'))
196
+ root.render(<App />)
197
+ ```
198
+
199
+ ### CSS with TailwindCSS
200
+
201
+ Use utility classes directly in templates:
202
+
203
+ ```erb
204
+ <div class="container mx-auto px-4">
205
+ <h1 class="text-4xl font-bold text-gray-900">Hello World</h1>
206
+ </div>
207
+ ```
208
+
209
+ ### CSS with shadcn/ui
210
+
211
+ Install components and use them in your templates:
212
+
213
+ ```bash
214
+ npx shadcn-ui@latest add button
215
+ ```
216
+
217
+ ## Examples
218
+
219
+ ### ERB + Importmap + Stimulus + TailwindCSS
220
+ ```bash
221
+ static-site-builder new my-site
222
+ # Choose: ERB, Importmap, TailwindCSS, Stimulus
223
+ ```
224
+
225
+ ### Phlex + ESBuild + React + shadcn
226
+ ```bash
227
+ static-site-builder new my-site
228
+ # Choose: Phlex, ESBuild, shadcn/ui, React
229
+ ```
230
+
231
+ ## Requirements
232
+
233
+ ### For Importmap Projects
234
+
235
+ When using **Importmap** as your JavaScript bundler:
236
+
237
+ 1. **Install npm dependencies**:
238
+ ```bash
239
+ npm install
240
+ ```
241
+
242
+ 2. **Build your site** - vendor files are automatically copied from `node_modules` to `dist/assets/javascripts/` during the build:
243
+ ```bash
244
+ rake build:all
245
+ ```
246
+
247
+ The build process automatically copies required vendor JavaScript files directly from `node_modules` to `dist/assets/javascripts/` based on your importmap configuration. No intermediate `vendor/javascript/` folder is needed.
248
+
249
+ ## Development
250
+
251
+ ### Running Your Site Locally
252
+
253
+ After generating a site, you can run it locally with auto-rebuild and live reload:
254
+
255
+ ```bash
256
+ cd my-site
257
+ bundle install
258
+ npm install # Required for importmap projects and JS frameworks
259
+
260
+ # Start development server (auto-rebuilds on file changes)
261
+ rake dev:server
262
+ ```
263
+
264
+ This will:
265
+ - Build your site to `dist/`
266
+ - Start a web server at `http://localhost:3000`
267
+ - Watch for file changes and rebuild automatically
268
+ - Auto-refresh your browser when files change
269
+
270
+ You can change the port with:
271
+ ```bash
272
+ PORT=8080 rake dev:server
273
+ ```
274
+
275
+ ### Building for Production
276
+
277
+ ```bash
278
+ # Build everything (assets + HTML)
279
+ rake build:all
280
+
281
+ # Or just HTML
282
+ rake build:html
283
+
284
+ # Output is in dist/ directory
285
+ ```
286
+
287
+ ## Deployment
288
+
289
+ The `dist/` directory contains your complete static site and can be deployed to any static hosting provider.
290
+
291
+ ### Cloudflare Pages
292
+
293
+ 1. **Connect your repository** to Cloudflare Pages in the Cloudflare dashboard
294
+
295
+ 2. **Build settings**:
296
+ - **Build command**: `bundle install && npm install && bundle exec rake build:all`
297
+ - **Build output directory**: `dist`
298
+ - **Root directory**: (leave empty or set to repository root)
299
+
300
+ 3. **Environment variables** (if needed):
301
+ - `RUBY_VERSION`: Set to your Ruby version (e.g., `3.4`)
302
+ - `NODE_VERSION`: Set to your Node.js version (e.g., `24`)
303
+
304
+ 4. **Deploy**: Cloudflare Pages will automatically build and deploy on every push to your main branch
305
+
306
+ **Note**: Cloudflare Pages supports Ruby and Node.js builds. Ensure your `Gemfile` and `package.json` are properly configured.
307
+
308
+ ### Vercel
309
+
310
+ 1. **Install Vercel CLI** (optional):
311
+ ```bash
312
+ npm i -g vercel
313
+ ```
314
+
315
+ 2. **Deploy**:
316
+ ```bash
317
+ # Build locally first
318
+ bundle install && npm install && bundle exec rake build:all
319
+
320
+ # Deploy
321
+ vercel --prod
322
+ ```
323
+
324
+ Or connect your repository in the Vercel dashboard with these settings:
325
+ - **Build Command**: `bundle install && npm install && bundle exec rake build:all`
326
+ - **Output Directory**: `dist`
327
+ - **Install Command**: `bundle install && npm install`
328
+
329
+ 3. **Configuration file** (optional `vercel.json`):
330
+ ```json
331
+ {
332
+ "buildCommand": "bundle install && npm install && bundle exec rake build:all",
333
+ "outputDirectory": "dist",
334
+ "installCommand": "bundle install && npm install"
335
+ }
336
+ ```
337
+
338
+ ### Netlify
339
+
340
+ 1. **Create `netlify.toml`** in your project root:
341
+ ```toml
342
+ [build]
343
+ command = "bundle install && npm install && bundle exec rake build:all"
344
+ publish = "dist"
345
+
346
+ [build.environment]
347
+ RUBY_VERSION = "3.4"
348
+ NODE_VERSION = "24"
349
+ ```
350
+
351
+ 2. **Deploy**:
352
+ - Connect your repository in Netlify dashboard
353
+ - Netlify will automatically detect `netlify.toml` and use those settings
354
+ - Or use Netlify CLI: `netlify deploy --prod`
355
+
356
+ ### GitHub Pages
357
+
358
+ 1. **Using GitHub Actions** (recommended):
359
+
360
+ Create `.github/workflows/deploy.yml`:
361
+ ```yaml
362
+ name: Deploy to GitHub Pages
363
+
364
+ on:
365
+ push:
366
+ branches: [ main ]
367
+
368
+ jobs:
369
+ deploy:
370
+ runs-on: ubuntu-latest
371
+ steps:
372
+ - uses: actions/checkout@v4
373
+
374
+ - name: Set up Ruby
375
+ uses: ruby/setup-ruby@v1
376
+ with:
377
+ ruby-version: 3.4
378
+ bundler-cache: true
379
+
380
+ - name: Set up Node.js
381
+ uses: actions/setup-node@v4
382
+ with:
383
+ node-version: '24'
384
+ cache: 'npm'
385
+
386
+ - name: Install dependencies
387
+ run: |
388
+ bundle install
389
+ npm install
390
+
391
+ - name: Build site
392
+ run: bundle exec rake build:all
393
+ # Note: Vendor files will be automatically copied from node_modules during build
394
+
395
+ - name: Deploy to GitHub Pages
396
+ uses: peaceiris/actions-gh-pages@v4
397
+ with:
398
+ github_token: ${{ secrets.GITHUB_TOKEN }}
399
+ publish_dir: ./dist
400
+ ```
401
+
402
+ 2. **Enable GitHub Pages** in your repository settings:
403
+ - Go to Settings → Pages
404
+ - Source: GitHub Actions
405
+
406
+ ### Other Static Hosts
407
+
408
+ For any static hosting provider (AWS S3, Azure Static Web Apps, etc.):
409
+
410
+ 1. **Build locally**:
411
+ ```bash
412
+ bundle install
413
+ npm install
414
+ bundle exec rake build:all
415
+ ```
416
+
417
+ 2. **Upload `dist/` directory** to your hosting provider
418
+
419
+ 3. **Configure** your host to serve from the `dist` directory
420
+
421
+ ### CI/CD Considerations
422
+
423
+ - **Vendor files**: Vendor files are automatically copied from `node_modules` to `dist/` during build - no vendor folder needed
424
+ - **Dependencies**: Both Ruby (`Gemfile`) and Node.js (`package.json`) dependencies are needed for the build
425
+ - **Build order**: Install dependencies → Build assets → Build HTML
426
+ - **Ruby/Node versions**: Specify versions in your CI/CD configuration to ensure consistent builds
427
+
428
+ ### Generator Development
429
+
430
+ ```bash
431
+ # Clone the repo
432
+ git clone https://github.com/Ancez/static-site-builder
433
+ cd static-site-builder
434
+
435
+ # Install dependencies
436
+ bundle install
437
+
438
+ # Run tests
439
+ bundle exec rspec
440
+
441
+ # Build the gem
442
+ gem build static-site-builder.gemspec
443
+ ```
444
+
445
+ ## Testing
446
+
447
+ The project includes comprehensive test coverage:
448
+
449
+ - Unit tests for Generator and Builder classes
450
+ - Integration tests for full build workflows
451
+ - End-to-end tests for complete workflows
452
+ - Tests for all stack combinations
453
+
454
+ Run tests with:
455
+ ```bash
456
+ bundle exec rspec
457
+ ```
458
+
459
+ View coverage report:
460
+ ```bash
461
+ open coverage/index.html
462
+ ```
463
+
464
+ ## Architecture
465
+
466
+ This generator follows the Rails pattern:
467
+ - **Generator gem** - Creates project structure
468
+ - **Builder gem** - Handles compilation (separate gem: `static-site-builder`)
469
+ - **Standard gems** - Reuse existing Ruby gems
470
+ - **Generated code** - Minimal, uses gem dependencies
471
+
472
+ ## Contributing
473
+
474
+ Contributions welcome! Especially:
475
+ - New template engine support
476
+ - New bundler integrations
477
+ - New CSS framework setups
478
+ - Documentation improvements
479
+
480
+ ## License
481
+
482
+ MIT
data/bin/generate ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/static_site_builder"
5
+ require "tty-prompt"
6
+
7
+ def main
8
+ if ARGV.empty?
9
+ puts "Usage: ruby bin/generate <app-name>"
10
+ puts " or: static-site-builder new <app-name>"
11
+ exit 1
12
+ end
13
+
14
+ app_name = ARGV[0]
15
+
16
+ if Dir.exist?(app_name)
17
+ puts "Error: Directory '#{app_name}' already exists"
18
+ exit 1
19
+ end
20
+
21
+ puts "Generating static site: #{app_name}"
22
+ puts "=" * 50
23
+
24
+ prompt = TTY::Prompt.new
25
+
26
+ template_engine = prompt.select(
27
+ "Template engine?",
28
+ StaticSiteBuilder::Generator::TEMPLATE_ENGINES.map(&:capitalize),
29
+ default: 1
30
+ ).downcase
31
+
32
+ js_bundler = prompt.select(
33
+ "JavaScript bundler?",
34
+ StaticSiteBuilder::Generator::JS_BUNDLERS.map(&:capitalize),
35
+ default: 1
36
+ ).downcase
37
+
38
+ css_framework = prompt.select(
39
+ "CSS framework?",
40
+ StaticSiteBuilder::Generator::CSS_FRAMEWORKS.map(&:capitalize),
41
+ default: 1
42
+ ).downcase
43
+
44
+ js_framework = prompt.select(
45
+ "JavaScript framework?",
46
+ StaticSiteBuilder::Generator::JS_FRAMEWORKS.map(&:capitalize),
47
+ default: 1
48
+ ).downcase
49
+
50
+ options = {
51
+ template_engine: template_engine,
52
+ js_bundler: js_bundler,
53
+ css_framework: css_framework,
54
+ js_framework: js_framework
55
+ }
56
+
57
+ generator = StaticSiteBuilder::Generator.new(app_name, options)
58
+ generator.generate
59
+ rescue Interrupt
60
+ puts "\n\nGeneration cancelled."
61
+ exit 1
62
+ end
63
+
64
+ main if __FILE__ == $PROGRAM_NAME