geb 0.1.11
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 +7 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +37 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE +21 -0
- data/README.md +384 -0
- data/Rakefile +21 -0
- data/bin/geb +21 -0
- data/lib/geb/cli.rb +40 -0
- data/lib/geb/commands/build.rb +59 -0
- data/lib/geb/commands/init.rb +70 -0
- data/lib/geb/commands/release.rb +54 -0
- data/lib/geb/commands/remote.rb +48 -0
- data/lib/geb/commands/server.rb +77 -0
- data/lib/geb/commands/upload.rb +48 -0
- data/lib/geb/commands/version.rb +36 -0
- data/lib/geb/config.rb +103 -0
- data/lib/geb/defaults.rb +44 -0
- data/lib/geb/git.rb +112 -0
- data/lib/geb/page.rb +217 -0
- data/lib/geb/partial.rb +150 -0
- data/lib/geb/samples/basic/assets/css/site.css +7 -0
- data/lib/geb/samples/basic/assets/images/android-chrome-192x192.png +0 -0
- data/lib/geb/samples/basic/assets/images/android-chrome-512x512.png +0 -0
- data/lib/geb/samples/basic/assets/images/apple-touch-icon.png +0 -0
- data/lib/geb/samples/basic/assets/images/favicon-16x16.png +0 -0
- data/lib/geb/samples/basic/assets/images/favicon-32x32.png +0 -0
- data/lib/geb/samples/basic/assets/images/favicon.ico +0 -0
- data/lib/geb/samples/basic/assets/images/hero.png +0 -0
- data/lib/geb/samples/basic/assets/images/og-thumb.png +0 -0
- data/lib/geb/samples/basic/assets/images/twitter-thumb.png +0 -0
- data/lib/geb/samples/basic/assets/js/site.js +5 -0
- data/lib/geb/samples/basic/geb.config.yml +70 -0
- data/lib/geb/samples/basic/index.html +11 -0
- data/lib/geb/samples/basic/page.html +11 -0
- data/lib/geb/samples/basic/shared/partials/_analytics.html +9 -0
- data/lib/geb/samples/basic/shared/partials/_footer.html +3 -0
- data/lib/geb/samples/basic/shared/partials/_global_assets.html +19 -0
- data/lib/geb/samples/basic/shared/partials/_header.html +0 -0
- data/lib/geb/samples/basic/shared/partials/_meta_tags.html +34 -0
- data/lib/geb/samples/basic/shared/templates/_blog_post.html +0 -0
- data/lib/geb/samples/basic/shared/templates/_site.html +19 -0
- data/lib/geb/samples/basic/site.webmanifest +1 -0
- data/lib/geb/samples/bootstrap_jquery/assets/css/site.css +7 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/android-chrome-192x192.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/android-chrome-512x512.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/apple-touch-icon.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/favicon-16x16.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/favicon-32x32.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/favicon.ico +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/hero.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/og-thumb.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/images/twitter-thumb.png +0 -0
- data/lib/geb/samples/bootstrap_jquery/assets/js/site.js +5 -0
- data/lib/geb/samples/bootstrap_jquery/blog/blog_post_1.html +35 -0
- data/lib/geb/samples/bootstrap_jquery/blog/blog_post_2.html +35 -0
- data/lib/geb/samples/bootstrap_jquery/blog/blog_post_3.html +35 -0
- data/lib/geb/samples/bootstrap_jquery/blog/index.html +17 -0
- data/lib/geb/samples/bootstrap_jquery/geb.config.yml +69 -0
- data/lib/geb/samples/bootstrap_jquery/index.html +11 -0
- data/lib/geb/samples/bootstrap_jquery/page.html +11 -0
- data/lib/geb/samples/bootstrap_jquery/shared/partials/_analytics.html +9 -0
- data/lib/geb/samples/bootstrap_jquery/shared/partials/_footer.html +3 -0
- data/lib/geb/samples/bootstrap_jquery/shared/partials/_global_assets.html +19 -0
- data/lib/geb/samples/bootstrap_jquery/shared/partials/_header.html +0 -0
- data/lib/geb/samples/bootstrap_jquery/shared/partials/_meta_tags.html +34 -0
- data/lib/geb/samples/bootstrap_jquery/shared/templates/_blog_post.html +0 -0
- data/lib/geb/samples/bootstrap_jquery/shared/templates/_site.html +19 -0
- data/lib/geb/samples/bootstrap_jquery/site.webmanifest +1 -0
- data/lib/geb/samples/geb.config.yml +70 -0
- data/lib/geb/server.rb +138 -0
- data/lib/geb/site/build.rb +189 -0
- data/lib/geb/site/core.rb +229 -0
- data/lib/geb/site/release.rb +70 -0
- data/lib/geb/site/remote.rb +142 -0
- data/lib/geb/site/template.rb +208 -0
- data/lib/geb/site.rb +83 -0
- data/lib/geb/template.rb +166 -0
- data/lib/geb/utilities.rb +110 -0
- data/lib/geb.rb +36 -0
- data/lib/seth.rb +50 -0
- data/sig/geb.rbs +4 -0
- data/test/api tests/test_cli.rb +200 -0
- data/test/api tests/test_config.rb +330 -0
- data/test/api tests/test_defaults.rb +62 -0
- data/test/api tests/test_git.rb +105 -0
- data/test/api tests/test_page.rb +320 -0
- data/test/api tests/test_partial.rb +152 -0
- data/test/api tests/test_server.rb +416 -0
- data/test/api tests/test_site.rb +1315 -0
- data/test/api tests/test_template.rb +249 -0
- data/test/api tests/test_utilities.rb +162 -0
- data/test/command tests/test_geb_build.rb +199 -0
- data/test/command tests/test_geb_init.rb +312 -0
- data/test/command tests/test_geb_release.rb +166 -0
- data/test/command tests/test_geb_remote.rb +66 -0
- data/test/command tests/test_geb_server.rb +122 -0
- data/test/command tests/test_geb_upload.rb +96 -0
- data/test/command tests/test_geb_version.rb +58 -0
- data/test/support/geb_api_test.rb +37 -0
- data/test/support/geb_cli_test.rb +275 -0
- data/test/support/geb_minitest_ext.rb +35 -0
- data/test/support/geb_test_helpers.rb +84 -0
- data/test/support/geb_web_server_proxy.rb +128 -0
- data/test/test_helper.rb +61 -0
- metadata +301 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Build command definition, based on Dry::CLI framework
|
|
4
|
+
# Builds the site, this is the core of what Geb does
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Build Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
12
|
+
|
|
13
|
+
module Geb
|
|
14
|
+
module CLI
|
|
15
|
+
module Commands
|
|
16
|
+
|
|
17
|
+
# Define build command
|
|
18
|
+
class Build < Dry::CLI::Command
|
|
19
|
+
|
|
20
|
+
# Command description, usage and examples
|
|
21
|
+
desc "Build the full site, includes pages and assets"
|
|
22
|
+
example [" ", "--skip_assets", "--skip_pages"]
|
|
23
|
+
|
|
24
|
+
# Define command options
|
|
25
|
+
option :skip_assets, type: :boolean, default: false, desc: "Skip building assets (images, css, js)"
|
|
26
|
+
option :skip_pages, type: :boolean, default: false, desc: "Skip building pages"
|
|
27
|
+
|
|
28
|
+
# Call method for the build command
|
|
29
|
+
def call(**options)
|
|
30
|
+
|
|
31
|
+
# initialise a new site and load the site from the current directory
|
|
32
|
+
site = Geb::Site.new
|
|
33
|
+
site.load(Dir.pwd)
|
|
34
|
+
|
|
35
|
+
# build the pages unless the skip_pages option is set
|
|
36
|
+
# it is important to build assets first as there may be pages in the assets directory
|
|
37
|
+
Geb.log "Skipping building pages as told." if options[:skip_pages]
|
|
38
|
+
site.build_pages unless options[:skip_pages]
|
|
39
|
+
|
|
40
|
+
# build the assets (images, css, js) unless the skip_assets option is set
|
|
41
|
+
Geb.log "Skipping building assets as told." if options[:skip_assets]
|
|
42
|
+
site.build_assets unless options[:skip_assets]
|
|
43
|
+
|
|
44
|
+
# put a smartarse message to the console if both options are set
|
|
45
|
+
Geb.log "You told me to skip everything, so I did." if options[:skip_assets] && options[:skip_pages]
|
|
46
|
+
|
|
47
|
+
rescue Geb::Error => e
|
|
48
|
+
|
|
49
|
+
# print error message
|
|
50
|
+
puts
|
|
51
|
+
warn e.message
|
|
52
|
+
|
|
53
|
+
end # def call
|
|
54
|
+
|
|
55
|
+
end # class Build < Dry::CLI::Command
|
|
56
|
+
|
|
57
|
+
end # module Commands
|
|
58
|
+
end # module CLI
|
|
59
|
+
end # module Geb
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Init command definition, based on Dry::CLI framework
|
|
4
|
+
# Initializes the site, creates a basic folder structure and git repository
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Init Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
12
|
+
|
|
13
|
+
# include the required libraries
|
|
14
|
+
require 'fileutils'
|
|
15
|
+
|
|
16
|
+
module Geb
|
|
17
|
+
module CLI
|
|
18
|
+
module Commands
|
|
19
|
+
|
|
20
|
+
# define init command
|
|
21
|
+
class Init < Dry::CLI::Command
|
|
22
|
+
|
|
23
|
+
# command description, usage and examples
|
|
24
|
+
desc "Initialise geb site, creates folder locations, git repository and initial file structures"
|
|
25
|
+
example ["new_site ", "new_site [options]", "new_site --skip_template --skip_git"]
|
|
26
|
+
|
|
27
|
+
# define project name command argument
|
|
28
|
+
argument :site_path, type: :string, required: true, desc: "Path to the site folder / site name"
|
|
29
|
+
|
|
30
|
+
# define command options
|
|
31
|
+
option :template, type: :string, required: false, desc: "Template site, either a path to a folder or one of the following: #{Geb::Defaults::AVAILABLE_TEMPLATES.join(", ")}. Default: #{Geb::Defaults::AVAILABLE_TEMPLATES.first}"
|
|
32
|
+
option :skip_template, type: :boolean, default: false, desc: "Skip generating a site from template, ignores the template option."
|
|
33
|
+
option :skip_git, type: :boolean, default: false, desc: "Skip initialising git repository"
|
|
34
|
+
option :force, type: :boolean, default: false, desc: "Force overwrite of existing files and git repository. Use with caution."
|
|
35
|
+
|
|
36
|
+
# call method for the init command
|
|
37
|
+
def call(site_path:, **options)
|
|
38
|
+
|
|
39
|
+
# initialize a new site object, this does all sorts of validations and checks, raises errors if something is wrong
|
|
40
|
+
new_site = Geb::Site.new
|
|
41
|
+
|
|
42
|
+
# validate the site
|
|
43
|
+
new_site.validate(site_path, options[:template], options[:skip_template], options[:force])
|
|
44
|
+
|
|
45
|
+
# validate proposed git repository in the site path if we are not skipping git, will raise error if git situation is unacceptable
|
|
46
|
+
Geb.log "Skipping git repository validation as told." if options[:skip_git]
|
|
47
|
+
Geb::Git.validate_git_repo(site_path) unless options[:skip_git]
|
|
48
|
+
|
|
49
|
+
# create the site folder and populate it with the template if we are not skipping the whole process
|
|
50
|
+
new_site.create
|
|
51
|
+
|
|
52
|
+
# create the git repository if we are not skipping git
|
|
53
|
+
Geb.log "Skipping git repository creation as told." if options[:skip_git]
|
|
54
|
+
Geb::Git.create_git_repo(site_path) unless options[:skip_git]
|
|
55
|
+
|
|
56
|
+
rescue Geb::Error => e
|
|
57
|
+
|
|
58
|
+
# print error message
|
|
59
|
+
puts
|
|
60
|
+
warn e.message
|
|
61
|
+
|
|
62
|
+
end # def call
|
|
63
|
+
|
|
64
|
+
# ::: Methods ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
65
|
+
|
|
66
|
+
end # class Init < Dry::CLI::Command
|
|
67
|
+
|
|
68
|
+
end # module Commands
|
|
69
|
+
end # module CLI
|
|
70
|
+
end # module Geb
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Release command definition, based on Dry::CLI framework
|
|
4
|
+
# Builds the site into the release directory with optional template archive
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Release Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @todo Consider some option or check to see if the release would override previous release --with_template
|
|
12
|
+
#
|
|
13
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
14
|
+
|
|
15
|
+
module Geb
|
|
16
|
+
module CLI
|
|
17
|
+
module Commands
|
|
18
|
+
|
|
19
|
+
# Define release command
|
|
20
|
+
class Release < Dry::CLI::Command
|
|
21
|
+
|
|
22
|
+
# Command description, usage and examples
|
|
23
|
+
desc "Builds the release version of the site (pages and assets)"
|
|
24
|
+
example [" ", "--with_template"]
|
|
25
|
+
|
|
26
|
+
# Define command options
|
|
27
|
+
option :with_template, type: :boolean, default: false, desc: "Build the release site with a template archive so you can share it."
|
|
28
|
+
|
|
29
|
+
# Call method for the release command
|
|
30
|
+
def call(**options)
|
|
31
|
+
|
|
32
|
+
# initialise a new site and load the site from the current directory
|
|
33
|
+
site = Geb::Site.new
|
|
34
|
+
site.load(Dir.pwd)
|
|
35
|
+
|
|
36
|
+
# create a new release for the site
|
|
37
|
+
site.release()
|
|
38
|
+
|
|
39
|
+
# bundle the site with a template archive if the with_template option is set
|
|
40
|
+
site.bundle_template() if options[:with_template]
|
|
41
|
+
|
|
42
|
+
rescue Geb::Error => e
|
|
43
|
+
|
|
44
|
+
# print error message
|
|
45
|
+
puts
|
|
46
|
+
warn e.message
|
|
47
|
+
|
|
48
|
+
end # def call
|
|
49
|
+
|
|
50
|
+
end # class Release < Dry::CLI::Command
|
|
51
|
+
|
|
52
|
+
end # module Commands
|
|
53
|
+
end # module CLI
|
|
54
|
+
end # module Geb
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Remote command definition, based on Dry::CLI framework
|
|
4
|
+
# Just a proxy for the ssh command
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Remote Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
12
|
+
|
|
13
|
+
module Geb
|
|
14
|
+
module CLI
|
|
15
|
+
module Commands
|
|
16
|
+
|
|
17
|
+
# Define remote command
|
|
18
|
+
class Remote < Dry::CLI::Command
|
|
19
|
+
|
|
20
|
+
# Command description, usage and examples
|
|
21
|
+
desc "Launch remote ssh session using the config file settings"
|
|
22
|
+
example [" "]
|
|
23
|
+
|
|
24
|
+
# Define command options
|
|
25
|
+
|
|
26
|
+
# Call method for the remote command
|
|
27
|
+
def call(*)
|
|
28
|
+
|
|
29
|
+
# initialise a new site and load the site from the current directory
|
|
30
|
+
site = Geb::Site.new
|
|
31
|
+
site.load(Dir.pwd)
|
|
32
|
+
|
|
33
|
+
# launch the remote session
|
|
34
|
+
site.launch_remote()
|
|
35
|
+
|
|
36
|
+
rescue Geb::Error => e
|
|
37
|
+
|
|
38
|
+
# print error message
|
|
39
|
+
puts
|
|
40
|
+
warn e.message
|
|
41
|
+
|
|
42
|
+
end # def call
|
|
43
|
+
|
|
44
|
+
end # class Remote < Dry::CLI::Command
|
|
45
|
+
|
|
46
|
+
end # module Commands
|
|
47
|
+
end # module CLI
|
|
48
|
+
end # module Geb
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Build command definition, based on Dry::CLI framework
|
|
4
|
+
# Run a webrick http server to view the site output, it optionally monitors
|
|
5
|
+
# for file changes and rebuilds the site when a file changes.
|
|
6
|
+
#
|
|
7
|
+
# @title Geb - Remote Command
|
|
8
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
9
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
10
|
+
# @license MIT
|
|
11
|
+
#
|
|
12
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
13
|
+
|
|
14
|
+
module Geb
|
|
15
|
+
module CLI
|
|
16
|
+
module Commands
|
|
17
|
+
|
|
18
|
+
# Define server command
|
|
19
|
+
class Server < Dry::CLI::Command
|
|
20
|
+
|
|
21
|
+
# Command description, usage and examples
|
|
22
|
+
desc "Start a local server to view the site output (runs build first), uses webrick"
|
|
23
|
+
example [" ", "--port 8080", "--skip_auto_build", "--skip_build"]
|
|
24
|
+
|
|
25
|
+
# Define command options
|
|
26
|
+
option :port, type: :int, default: 0, desc: "Port to run the server on, otherwise it will use config file setting"
|
|
27
|
+
option :skip_build, type: :boolean, default: false, desc: "Skip building the site before starting the server"
|
|
28
|
+
option :skip_auto_build, type: :boolean, default: false, desc: "Don't automatically rebuild the site when a file changes"
|
|
29
|
+
|
|
30
|
+
# Call method for the server command
|
|
31
|
+
# @param options [Hash] the options hash for the command
|
|
32
|
+
def call(**options)
|
|
33
|
+
|
|
34
|
+
# initialise a site and load it from the current directory
|
|
35
|
+
site = Geb::Site.new
|
|
36
|
+
site.load(Dir.pwd)
|
|
37
|
+
|
|
38
|
+
# build the site if the skip_build option is not set
|
|
39
|
+
site.build() unless options[:skip_build]
|
|
40
|
+
|
|
41
|
+
# start a new queue for the shutdown signal (instead of using trap to shutdown the server and file watcher directly)
|
|
42
|
+
@shutdown_queue = Queue.new
|
|
43
|
+
trap('INT') { @shutdown_queue << :shutdown }
|
|
44
|
+
|
|
45
|
+
# get the server port from the options, site configuration or auto generated (0), in that order
|
|
46
|
+
server_port = options[:port] || site.site_config.local_port || 0
|
|
47
|
+
|
|
48
|
+
# initialize the server
|
|
49
|
+
server = Geb::Server.new(site, server_port, !options[:skip_auto_build])
|
|
50
|
+
|
|
51
|
+
# start the server
|
|
52
|
+
server.start()
|
|
53
|
+
|
|
54
|
+
# wait for the shutdown signal
|
|
55
|
+
@shutdown_queue.pop
|
|
56
|
+
|
|
57
|
+
# stop the server
|
|
58
|
+
server.stop()
|
|
59
|
+
|
|
60
|
+
rescue Geb::Error => e
|
|
61
|
+
|
|
62
|
+
# print error message
|
|
63
|
+
puts
|
|
64
|
+
warn e.message
|
|
65
|
+
|
|
66
|
+
end # def call
|
|
67
|
+
|
|
68
|
+
# Force shutdown of the server
|
|
69
|
+
def force_shutdown
|
|
70
|
+
@shutdown_queue << :shutdown if @shutdown_queue
|
|
71
|
+
end # force_shutdown
|
|
72
|
+
|
|
73
|
+
end # class Server < Dry::CLI::Command
|
|
74
|
+
|
|
75
|
+
end # module Commands
|
|
76
|
+
end # module CLI
|
|
77
|
+
end # module Geb
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Upload command definition, based on Dry::CLI framework
|
|
4
|
+
# Upload the site to a remote server
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Upload Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
12
|
+
|
|
13
|
+
module Geb
|
|
14
|
+
module CLI
|
|
15
|
+
module Commands
|
|
16
|
+
|
|
17
|
+
# Define upload command
|
|
18
|
+
class Upload < Dry::CLI::Command
|
|
19
|
+
|
|
20
|
+
# Command description, usage and examples
|
|
21
|
+
desc "Upload the site to the remote server"
|
|
22
|
+
example [" "]
|
|
23
|
+
|
|
24
|
+
# Define command options
|
|
25
|
+
|
|
26
|
+
# Call method for the remote command
|
|
27
|
+
def call(*)
|
|
28
|
+
|
|
29
|
+
# initialise a new site and load the site from the current directory
|
|
30
|
+
site = Geb::Site.new
|
|
31
|
+
site.load(Dir.pwd)
|
|
32
|
+
|
|
33
|
+
# check if the site has been released before uploading
|
|
34
|
+
site.upload_release_to_remote()
|
|
35
|
+
|
|
36
|
+
rescue Geb::Error => e
|
|
37
|
+
|
|
38
|
+
# print error message
|
|
39
|
+
puts
|
|
40
|
+
warn e.message
|
|
41
|
+
|
|
42
|
+
end # def call
|
|
43
|
+
|
|
44
|
+
end # class Upload < Dry::CLI::Upload
|
|
45
|
+
|
|
46
|
+
end # module Commands
|
|
47
|
+
end # module CLI
|
|
48
|
+
end # module Geb
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Version command definition, based on Dry::CLI framework
|
|
4
|
+
# Prints the current version of the Geb
|
|
5
|
+
#
|
|
6
|
+
# @title Geb - Version Command
|
|
7
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
8
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
9
|
+
# @license MIT
|
|
10
|
+
#
|
|
11
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
12
|
+
|
|
13
|
+
module Geb
|
|
14
|
+
module CLI
|
|
15
|
+
module Commands
|
|
16
|
+
|
|
17
|
+
# Define version command
|
|
18
|
+
class Version < Dry::CLI::Command
|
|
19
|
+
|
|
20
|
+
# Command description, usage and examples
|
|
21
|
+
desc "Print version"
|
|
22
|
+
example [" "]
|
|
23
|
+
|
|
24
|
+
# Call method for the version command
|
|
25
|
+
def call(*)
|
|
26
|
+
|
|
27
|
+
# Print the version
|
|
28
|
+
puts "Geb version #{Geb::VERSION}"
|
|
29
|
+
|
|
30
|
+
end # def call
|
|
31
|
+
|
|
32
|
+
end # class Version < Dry::CLI::Command
|
|
33
|
+
|
|
34
|
+
end # module Commands
|
|
35
|
+
end # module CLI
|
|
36
|
+
end # module Geb
|
data/lib/geb/config.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Geb configuration. It merges the geb.yml configuration file with the defaults.
|
|
4
|
+
#
|
|
5
|
+
# @title Geb - Command Registry
|
|
6
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
7
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
8
|
+
# @license MIT
|
|
9
|
+
#
|
|
10
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
11
|
+
|
|
12
|
+
# include the required libraries
|
|
13
|
+
require 'yaml'
|
|
14
|
+
|
|
15
|
+
module Geb
|
|
16
|
+
class Config
|
|
17
|
+
|
|
18
|
+
class ConfigFileNotFound < Geb::Error
|
|
19
|
+
MESSAGE = "Could not find geb config file.".freeze
|
|
20
|
+
def initialize(e = ""); super(e, MESSAGE); end
|
|
21
|
+
end # class ConfigFileNotFound < Geb::Error
|
|
22
|
+
|
|
23
|
+
# check if the site directory specified has the required geb.config.yml file
|
|
24
|
+
def self.site_directory_has_config?(site_path)
|
|
25
|
+
File.exist?(File.join(site_path, Geb::Defaults::SITE_CONFIG_FILENAME))
|
|
26
|
+
end # def self.site_directory_has_config?
|
|
27
|
+
|
|
28
|
+
# initialize the site configuration\
|
|
29
|
+
# @param site [Geb::Site] the site object
|
|
30
|
+
# @raise ConfigFileNotFound if the site directory has no geb.config.yml file
|
|
31
|
+
def initialize(site)
|
|
32
|
+
|
|
33
|
+
# set the site path
|
|
34
|
+
@site = site
|
|
35
|
+
|
|
36
|
+
# make sure the site directory has the required geb.config.yml file
|
|
37
|
+
raise ConfigFileNotFound.new("Site path [#{@site.site_path}] has no geb configuration.") unless Geb::Config.site_directory_has_config?(@site.site_path)
|
|
38
|
+
|
|
39
|
+
# load the site configuration, if no configuration is found in the file, set it to an empty hash
|
|
40
|
+
@config = YAML.load_file(File.join(@site.site_path, Geb::Defaults::SITE_CONFIG_FILENAME))
|
|
41
|
+
@config ||= {}
|
|
42
|
+
|
|
43
|
+
end # def initialize
|
|
44
|
+
|
|
45
|
+
# get the configured site name, if not set, use the site directory name
|
|
46
|
+
# @return [String] the site name
|
|
47
|
+
def site_name
|
|
48
|
+
return @config['site_name'] || File.basename(@site.site_path)
|
|
49
|
+
end # def site_name
|
|
50
|
+
|
|
51
|
+
# get the configured remote uri
|
|
52
|
+
# @return [String] the remote uri
|
|
53
|
+
def remote_uri
|
|
54
|
+
return @config['remote_uri'] || nil
|
|
55
|
+
end # def remote_uri
|
|
56
|
+
|
|
57
|
+
# get the configured remote path
|
|
58
|
+
# @return [String] the remote path
|
|
59
|
+
def remote_path
|
|
60
|
+
return @config['remote_path'] || nil
|
|
61
|
+
end # def remote_path
|
|
62
|
+
|
|
63
|
+
# get the configured local port
|
|
64
|
+
# @return [Integer] the local port
|
|
65
|
+
def local_port
|
|
66
|
+
return @config['local_port'] || nil
|
|
67
|
+
end # def local_port
|
|
68
|
+
|
|
69
|
+
# get the configured output directory
|
|
70
|
+
# @return [String] the output directory
|
|
71
|
+
# @note the assets directory is relative to the site root
|
|
72
|
+
def output_dir
|
|
73
|
+
return @config['output_dir'] || Geb::Defaults::OUTPUT_DIR
|
|
74
|
+
end # def output_dir
|
|
75
|
+
|
|
76
|
+
# get the configured assets directory
|
|
77
|
+
# @return [String] the assets directory
|
|
78
|
+
# @note the assets directory is relative to the site root
|
|
79
|
+
def assets_dir
|
|
80
|
+
return @config['assets_dir'] || Geb::Defaults::ASSETS_DIR
|
|
81
|
+
end # def assets_dir
|
|
82
|
+
|
|
83
|
+
# get the configured page extensions
|
|
84
|
+
# @return [Array] the page extensions
|
|
85
|
+
def page_extensions
|
|
86
|
+
return @config['page_extensions'] || Geb::Defaults::PAGE_EXTENSIONS
|
|
87
|
+
end # def page_extensions
|
|
88
|
+
|
|
89
|
+
# get the configured template and partial identifier
|
|
90
|
+
# @return [Regexp] the template and partial identifier
|
|
91
|
+
def template_and_partial_identifier
|
|
92
|
+
return @config['template_and_partial_identifier'] || Geb::Defaults::TEMPLATE_AND_PARTIAL_IDENTIFIER
|
|
93
|
+
end # def template_and_partial_identifier
|
|
94
|
+
|
|
95
|
+
# get the configured template paths
|
|
96
|
+
# @return [Array] the template paths
|
|
97
|
+
# @note the template paths are relative to the site root
|
|
98
|
+
def template_paths
|
|
99
|
+
return @config['template_paths'] || []
|
|
100
|
+
end # def template_paths
|
|
101
|
+
|
|
102
|
+
end # class Config
|
|
103
|
+
end # module Geb
|
data/lib/geb/defaults.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# A simple list of defaults for the Geb gem
|
|
4
|
+
#
|
|
5
|
+
# @title Geb - Defaults
|
|
6
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
7
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
8
|
+
# @license MIT
|
|
9
|
+
#
|
|
10
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
11
|
+
|
|
12
|
+
# include the required libraries
|
|
13
|
+
require 'fileutils'
|
|
14
|
+
|
|
15
|
+
module Geb
|
|
16
|
+
module Defaults
|
|
17
|
+
|
|
18
|
+
# default values for site templates
|
|
19
|
+
TEMPLATE_ARCHIVE_FILENAME = 'geb-template.tar.gz' # default the template archive filename
|
|
20
|
+
AVAILABLE_TEMPLATES = # list of bundled templates (first one is the default template)
|
|
21
|
+
['bootstrap_jquery', 'basic']
|
|
22
|
+
SITE_CONFIG_FILENAME = 'geb.config.yml' # site config file name
|
|
23
|
+
HTTP_TEMPLATE_CONTENT_TYPES = # acceptable remote template content types
|
|
24
|
+
['application/x-gzip', 'application/gzip', 'application/octet-stream']
|
|
25
|
+
BUNDLED_TEMPLATES_DIR = # bundled template directory
|
|
26
|
+
File.join(__dir__, 'samples')
|
|
27
|
+
DEFAULT_TEMPLATE_DIR = # default template directory
|
|
28
|
+
File.join(BUNDLED_TEMPLATES_DIR, AVAILABLE_TEMPLATES.first)
|
|
29
|
+
DEFAULT_TEMPLATE = # default template
|
|
30
|
+
AVAILABLE_TEMPLATES.first
|
|
31
|
+
|
|
32
|
+
# default values for site configuration (all paths are relative to the site root)
|
|
33
|
+
OUTPUT_DIR = 'output' # output directory (relative to site root)
|
|
34
|
+
LOCAL_OUTPUT_DIR = 'local' # local output directory (relative to output directory)
|
|
35
|
+
RELEASE_OUTPUT_DIR = 'release' # release output directory (relative to output directory)
|
|
36
|
+
ASSETS_DIR = 'assets' # location for assets (images, js and css)
|
|
37
|
+
|
|
38
|
+
# default values for site pages
|
|
39
|
+
PAGE_EXTENSIONS = # list of file extention to treat as pages
|
|
40
|
+
['.md', '.markdown', '.html', '.htm', '.txt', '.js', '.css']
|
|
41
|
+
TEMPLATE_AND_PARTIAL_IDENTIFIER = /^_/ # filename pattern for templates or partials
|
|
42
|
+
|
|
43
|
+
end # module Defaults
|
|
44
|
+
end # module Geb
|
data/lib/geb/git.rb
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Simple set of git utilities used by the cli commands
|
|
4
|
+
#
|
|
5
|
+
# @title Geb - Git
|
|
6
|
+
# @author Edin Mustajbegovic <edin@actiontwelve.com>
|
|
7
|
+
# @copyright 2024 Edin Mustajbegovic
|
|
8
|
+
# @license MIT
|
|
9
|
+
#
|
|
10
|
+
# @see https://github.com/mainfram-work/geb for more information
|
|
11
|
+
|
|
12
|
+
# include the required libraries
|
|
13
|
+
require 'tmpdir'
|
|
14
|
+
require 'open3'
|
|
15
|
+
require 'shellwords'
|
|
16
|
+
|
|
17
|
+
module Geb
|
|
18
|
+
module Git
|
|
19
|
+
|
|
20
|
+
class FailedValidationError < Geb::Error
|
|
21
|
+
MESSAGE = "Could not evaluate if the specified SITE_PATH is within a git repository, please choose a different location or use the --skip_git option.".freeze
|
|
22
|
+
def initialize(e = ""); super(e, MESSAGE); end
|
|
23
|
+
end # class FailedValidationError < Geb::Error
|
|
24
|
+
|
|
25
|
+
class InsideGitRepoError < Geb::Error
|
|
26
|
+
MESSAGE = "You are already inside a git repository, please choose a different location or use the --skip_git option.".freeze
|
|
27
|
+
def initialize(e = ""); super(e, MESSAGE); end
|
|
28
|
+
end # class InsideGitRepoError < Geb::Error
|
|
29
|
+
|
|
30
|
+
class GitError < Geb::Error
|
|
31
|
+
MESSAGE = "An error occurred while executing a git command.".freeze
|
|
32
|
+
def initialize(e = ""); super(e, MESSAGE); end
|
|
33
|
+
end # class GitError < Geb
|
|
34
|
+
|
|
35
|
+
# ::: Class Methods ::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
36
|
+
|
|
37
|
+
# validate if the proposed directory is a git repository, raise an error if it is
|
|
38
|
+
# or if the directory is inside a git repository
|
|
39
|
+
# @param site_directory [String] the proposed site directory
|
|
40
|
+
# @raise [FailedValidationError] if the directory could not be evaluated
|
|
41
|
+
# @raise [InsideGitRepoError] if the directory is inside a git repository
|
|
42
|
+
# @raise [GitError] if an error occurred while executing the git command
|
|
43
|
+
# @return [void]
|
|
44
|
+
def self.validate_git_repo(site_directory)
|
|
45
|
+
|
|
46
|
+
Geb.log_start "Validating proposed site path as a git repository ... "
|
|
47
|
+
|
|
48
|
+
# initialize the closest directory to the site directory that actually exists
|
|
49
|
+
closest_existing_directory = site_directory
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# find the closest existing directory
|
|
53
|
+
until Dir.exist?(closest_existing_directory)
|
|
54
|
+
closest_existing_directory = File.dirname(closest_existing_directory)
|
|
55
|
+
end # until
|
|
56
|
+
|
|
57
|
+
# raise an error if we reached the root directory
|
|
58
|
+
raise FailedValidationError if closest_existing_directory == '/'
|
|
59
|
+
|
|
60
|
+
# perform the git check in the closest existing directory
|
|
61
|
+
_, stderr, status = Open3.capture3("cd #{Shellwords.shellescape(closest_existing_directory)} && git rev-parse --is-inside-work-tree")
|
|
62
|
+
|
|
63
|
+
# check if the error message is that the directory is not in a git repository
|
|
64
|
+
raise InsideGitRepoError if status.success?
|
|
65
|
+
|
|
66
|
+
# the above git command will fail if the directory is not in a git repository (we want that)
|
|
67
|
+
# raise error for all other errors
|
|
68
|
+
raise FailedValidationError.new(stderr.chomp) unless stderr.include?("not a git repository")
|
|
69
|
+
|
|
70
|
+
Geb.log "done."
|
|
71
|
+
|
|
72
|
+
end # def self.validate_git_repo(site_directory)
|
|
73
|
+
|
|
74
|
+
# Create a new git repository in the specified folder. It also creates a .gitignore file
|
|
75
|
+
# @param site_directory [String] the proposed site directory
|
|
76
|
+
# @raise [GitError] if an error occurred while executing the git command
|
|
77
|
+
# @return [void]
|
|
78
|
+
def self.create_git_repo(site_directory)
|
|
79
|
+
|
|
80
|
+
Geb.log_start "Initialising git repository ... "
|
|
81
|
+
|
|
82
|
+
# initialize the git repository
|
|
83
|
+
_, stderr, status = Open3.capture3("git -C #{Shellwords.shellescape(site_directory)} init")
|
|
84
|
+
|
|
85
|
+
# raise an error if the git command failed
|
|
86
|
+
raise GitError.new(stderr.chomp) unless status.success?
|
|
87
|
+
|
|
88
|
+
# attempt to create a .gitignore file
|
|
89
|
+
begin
|
|
90
|
+
|
|
91
|
+
# create a .gitignore file
|
|
92
|
+
File.open(File.join(site_directory, '.gitignore'), 'w') do |f|
|
|
93
|
+
|
|
94
|
+
# ignore everything withint the output folder
|
|
95
|
+
f.puts "/output"
|
|
96
|
+
f.puts "/.DS_Store"
|
|
97
|
+
|
|
98
|
+
end # File.open
|
|
99
|
+
|
|
100
|
+
rescue StandardError => e
|
|
101
|
+
|
|
102
|
+
# raise an error if the gitignore file could not be created
|
|
103
|
+
raise GitError.new("Could not create .gitignore file: #{e.message}")
|
|
104
|
+
|
|
105
|
+
end # begin ... rescue
|
|
106
|
+
|
|
107
|
+
Geb.log "done."
|
|
108
|
+
|
|
109
|
+
end # def self.create_git_repo
|
|
110
|
+
|
|
111
|
+
end # module Git
|
|
112
|
+
end # module Geb
|