Class: Frontman::CLI

Inherits:
Thor
  • Object
show all
Defined in:
lib/frontman/commands/init.rb,
lib/frontman/commands/build.rb,
lib/frontman/commands/serve.rb

Instance Method Summary collapse

Instance Method Details

#buildObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/frontman/commands/build.rb', line 19

def build
  Frontman::Config.set(:mode, 'build')
  Frontman::Bootstrapper.bootstrap_app(Frontman::App.instance)

  assets_pipeline = Frontman::Builder::AssetPipeline.new(
    Frontman::App.instance
      .asset_pipelines
      .filter { |p| %i[all build].include?(p[:mode]) }
  )

  assets_pipeline.run!(:before)

  enable_parallel = options[:parallel]

  Frontman::Config.set(:parallel, enable_parallel)

  timer = Frontman::Toolbox::Timer.start

  current_build_files = Dir.glob(Dir.pwd + '/build/**/*').reject do |f|
    File.directory? f
  end

  public_dir = Frontman::Config.get(:public_dir, fallback: 'public/')
  assets_to_build = Dir.glob(File.join(public_dir, '**/*')).reject do |f|
    File.directory? f
  end

  mapping_path = Dir.pwd + '/_build.json'
  mapping = Frontman::Builder::Mapping.new(mapping_path)
  mapping.delete_file

  build_directory = Dir.pwd + '/build/'
  builder = Frontman::Builder::Builder.new
  builder.build_directory = build_directory
  builder.current_build_files = current_build_files

  builder.on('created, updated, deleted, unchanged', ->(build_file) {
    mapping.add_from_build_file(build_file)
  })

  assets = builder.build_assets(assets_to_build)
  redirects = builder.build_redirects

  resources_paths = builder.build_from_resources(
    Frontman::SitemapTree.resources
  )

  new_files = assets + redirects + resources_paths

  builder.delete_files(current_build_files - new_files)
  mapping.save_file

  assets_pipeline.run!(:after)

  Builder::StatisticsCollector.output(builder, mapping, timer, new_files)
end

#init(path) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/frontman/commands/init.rb', line 11

def init(path)
  template = options[:template] || 'default'

  raise "Template #{template} does not exist!" unless template_exists?(template)

  target_dir = File.join(Dir.pwd, path == '.' ? '' : path)

  unless allowed_to_modify_dir?(target_dir)
    say 'Not bootstrapping new Frontman project'
    return
  end

  copy_template(template, target_dir)

  command = path == '.' ? '' : "cd #{path} && "
  command += 'bundle exec frontman serve'

  say "Your project is ready. Run `#{command}` and start developing!"
end

#serveObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/frontman/commands/serve.rb', line 18

def serve
  Frontman::Config.set(:mode, 'serve')
  app = Frontman::App.instance
  Frontman::Bootstrapper.bootstrap_app(app)

  assets_pipeline = Frontman::Builder::AssetPipeline.new(
    app
      .asset_pipelines
      .filter { |p| %i[all serve].include?(p[:mode]) }
  )
  processes = assets_pipeline.run_in_background!(:before)

  helpers_dir = Frontman::Config.get(:helpers_dir, fallback: 'helpers')
  content_dir = Frontman::Config.get(:content_dir, fallback: 'source/')
  listen_to_dirs = Frontman::Config.get(:observe_dirs, fallback:
    [
      Frontman::Config.get(:layout_dir, fallback: 'views/layouts'),
      Frontman::Config.get(:partial_dir, fallback: 'views/partials'),
      content_dir,
      helpers_dir
    ]).filter { |dir| Dir.exist?(dir) }
  app.refresh_data_files = true

  listener = Listen.to(*listen_to_dirs) do |modified, added|
    (added + modified).each do |m|
      resource_path = m.sub("#{Dir.pwd}/", '')
      begin
        if resource_path.start_with?(helpers_dir)
          helper_name = File.basename(resource_path).gsub('.rb', '')
          load("./#{resource_path}")
          app.register_helpers(
            [{
              path: File.join(Dir.pwd, resource_path),
              name: helper_name.split('_').collect(&:capitalize).join
            }]
          )
        elsif resource_path.start_with?(*listen_to_dirs)
          r = Frontman::Resource.from_path(resource_path)

          if resource_path.start_with?(content_dir)
            exists = app.sitemap_tree.from_resource(r)
            app.sitemap_tree.add(r) unless exists
          end

          r&.parse_resource(true)
        elsif resource_path.end_with?('.rb')
          load("./#{resource_path}")
        end
      rescue Error
        # We ignore all errors to prevent the listener from crashing.
        # Errors will be surfaced by the server instead.
      end
    end
  end

  listener.start

  FrontmanServer.set :public_folder, Frontman::Config.get(
    :public_dir, fallback: 'public'
  )

  port = Frontman::Config.get(:port, fallback: 4568)
  num_retries = Frontman::Config.get(:port_retries, fallback: 3)

  port_retry_strategy = Frontman::Config.get(:port_retry_strategy, fallback: ->(p) {
    port_in_use = false

    (1 + num_retries).times do
      begin
        port_in_use = Socket.tcp('localhost', p, connect_timeout: 3) { true }
      rescue StandardError
        port_in_use = false
      end

      break unless port_in_use

      p += 1
    end

    raise Frontman::ServerPortError if port_in_use

    p
  })

  FrontmanServer.set(:port, port_retry_strategy.call(port))
  FrontmanServer.set(:bind, Frontman::Config.get(:host, fallback: 'localhost'))

  FrontmanServer.run! do
    hostname = FrontmanServer.settings.bind
    host = "http://#{hostname}:#{FrontmanServer.settings.port}"
    print "== View your site at \"#{host}/\"\n"
    processes += assets_pipeline.run_in_background!(:after)
    at_exit { processes.each { |pid| Process.kill(0, pid) } }
  end
end