flame 5.0.0.rc4 → 5.0.0.rc7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +929 -0
- data/LICENSE.txt +19 -0
- data/README.md +135 -0
- data/lib/flame/application.rb +47 -46
- data/lib/flame/config.rb +73 -0
- data/lib/flame/controller/actions.rb +122 -0
- data/lib/flame/{dispatcher → controller}/cookies.rb +8 -3
- data/lib/flame/controller/path_to.rb +34 -10
- data/lib/flame/controller.rb +45 -78
- data/lib/flame/dispatcher/request.rb +22 -6
- data/lib/flame/dispatcher/routes.rb +22 -14
- data/lib/flame/dispatcher/static.rb +13 -9
- data/lib/flame/dispatcher.rb +15 -18
- data/lib/flame/errors/argument_not_assigned_error.rb +3 -8
- data/lib/flame/errors/config_file_not_found_error.rb +17 -0
- data/lib/flame/errors/controller_not_found_error.rb +19 -0
- data/lib/flame/errors/route_arguments_order_error.rb +3 -10
- data/lib/flame/errors/route_extra_arguments_error.rb +7 -20
- data/lib/flame/errors/route_not_found_error.rb +4 -9
- data/lib/flame/errors/template_not_found_error.rb +2 -8
- data/lib/flame/path.rb +36 -18
- data/lib/flame/render.rb +13 -5
- data/lib/flame/router/controller_finder.rb +56 -0
- data/lib/flame/router/route.rb +9 -0
- data/lib/flame/router/routes.rb +56 -9
- data/lib/flame/router/routes_refine/mounting.rb +57 -0
- data/lib/flame/router/routes_refine.rb +144 -0
- data/lib/flame/router.rb +7 -157
- data/lib/flame/validators.rb +14 -10
- data/lib/flame/version.rb +1 -1
- data/lib/flame.rb +12 -5
- metadata +107 -96
- data/bin/flame +0 -16
- data/lib/flame/application/config.rb +0 -49
- data/template/.editorconfig +0 -15
- data/template/.gitignore +0 -28
- data/template/.rubocop.yml +0 -14
- data/template/Gemfile +0 -55
- data/template/Rakefile +0 -824
- data/template/application.rb.erb +0 -10
- data/template/config/config.rb.erb +0 -56
- data/template/config/database.example.yml +0 -5
- data/template/config/deploy.example.yml +0 -2
- data/template/config/puma.rb +0 -56
- data/template/config/sequel.rb.erb +0 -22
- data/template/config/server.example.yml +0 -32
- data/template/config/session.example.yml +0 -7
- data/template/config.ru.erb +0 -72
- data/template/controllers/_controller.rb.erb +0 -14
- data/template/controllers/site/_controller.rb.erb +0 -18
- data/template/controllers/site/index_controller.rb.erb +0 -12
- data/template/db/.keep +0 -0
- data/template/filewatchers.yml +0 -12
- data/template/helpers/.keep +0 -0
- data/template/lib/.keep +0 -0
- data/template/locales/en.yml +0 -0
- data/template/models/.keep +0 -0
- data/template/public/.keep +0 -0
- data/template/server +0 -200
- data/template/services/.keep +0 -0
- data/template/views/.keep +0 -0
- data/template/views/site/index.html.erb.erb +0 -1
- data/template/views/site/layout.html.erb.erb +0 -10
data/template/application.rb.erb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
## Module for Application configuration
|
4
|
-
module <%= @module_name %>
|
5
|
-
## Constants
|
6
|
-
SITE_NAME = '<%= @module_name %>'
|
7
|
-
ORGANIZATION_NAME = '<%= @module_name %> LLC'
|
8
|
-
::<%= @short_module_name %> = ::<%= @module_name %>
|
9
|
-
|
10
|
-
## Helpers
|
11
|
-
def self.logger
|
12
|
-
<%= @short_module_name %>::Application.config[:logger]
|
13
|
-
end
|
14
|
-
|
15
|
-
## Configuration for application
|
16
|
-
module Config
|
17
|
-
def self.included(app)
|
18
|
-
## Translations
|
19
|
-
# app.include Flame::R18n::Configuration
|
20
|
-
|
21
|
-
## Mail
|
22
|
-
# app.include Config::Mail
|
23
|
-
|
24
|
-
## Sentry
|
25
|
-
# app.include Config::Sentry
|
26
|
-
|
27
|
-
## Threads (for mails)
|
28
|
-
Thread.abort_on_exception = true
|
29
|
-
|
30
|
-
## Currencies rates
|
31
|
-
# Money.default_bank = Money::Bank::GoogleCurrency.new
|
32
|
-
### https://github.com/RubyMoney/money#troubleshooting
|
33
|
-
# I18n.enforce_available_locales = false
|
34
|
-
|
35
|
-
## Required configs
|
36
|
-
load_configs(app, :server, require: true)
|
37
|
-
|
38
|
-
## Not-required configs
|
39
|
-
# load_configs(app, :google_maps_api)
|
40
|
-
|
41
|
-
## Mails directory
|
42
|
-
# app.config[:mails_dir] = proc { File.join config[:views_dir], 'mail' }
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.load_configs(app, *keys, require: false)
|
46
|
-
keys.each do |key|
|
47
|
-
begin
|
48
|
-
app.config.load_yaml key
|
49
|
-
rescue => exception
|
50
|
-
next unless require
|
51
|
-
raise exception
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
data/template/config/puma.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
#!/usr/bin/env puma
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'yaml'
|
5
|
-
config = YAML.load_file(File.join(__dir__, 'server.yml'))
|
6
|
-
|
7
|
-
environment = ENV['RACK_ENV'] || config[:environment]
|
8
|
-
env_config = config[environment]
|
9
|
-
|
10
|
-
root_dir = File.join(__dir__, '..')
|
11
|
-
directory root_dir
|
12
|
-
|
13
|
-
prune_bundler
|
14
|
-
|
15
|
-
rackup 'config.ru'
|
16
|
-
|
17
|
-
require 'fileutils'
|
18
|
-
|
19
|
-
raise 'Unknown directory for pid files!' unless env_config[:pids_dir]
|
20
|
-
pids_dir = File.join root_dir, env_config[:pids_dir]
|
21
|
-
FileUtils.mkdir_p pids_dir
|
22
|
-
|
23
|
-
pidfile File.join pids_dir, env_config[:pid_file]
|
24
|
-
state_path File.join pids_dir, 'puma.state'
|
25
|
-
|
26
|
-
raise 'Unknown directory for log files!' unless env_config[:logs_dir]
|
27
|
-
log_dir = File.join root_dir, env_config[:logs_dir]
|
28
|
-
FileUtils.mkdir_p log_dir
|
29
|
-
|
30
|
-
if env_config[:daemonize]
|
31
|
-
stdout_redirect(
|
32
|
-
File.join(log_dir, 'stdout'),
|
33
|
-
File.join(log_dir, 'stderr'),
|
34
|
-
true # append to file
|
35
|
-
)
|
36
|
-
end
|
37
|
-
|
38
|
-
environment environment
|
39
|
-
|
40
|
-
# preload_app! if config['environment'] != 'production'
|
41
|
-
|
42
|
-
cores = Etc.nprocessors
|
43
|
-
workers_count = env_config[:workers_count] || (cores < 2 ? 1 : 2)
|
44
|
-
|
45
|
-
workers workers_count
|
46
|
-
worker_timeout env_config[:daemonize] ? 15 : 1_000_000
|
47
|
-
threads 0, env_config[:threads_count] || 4
|
48
|
-
daemonize env_config[:daemonize]
|
49
|
-
|
50
|
-
# bind 'unix://tmp/sockets/puma.sock'
|
51
|
-
env_config[:binds].each do |type, value|
|
52
|
-
value = "#{value[:host]}:#{value[:port]}" if type == :tcp
|
53
|
-
FileUtils.mkdir_p File.join(root_dir, File.dirname(value)) if type == :unix
|
54
|
-
bind "#{type}://#{value}"
|
55
|
-
end
|
56
|
-
# activate_control_app 'tcp://0.0.0.0:3000'
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
## Database initialize for Sequel
|
6
|
-
module <%= @module_name %>
|
7
|
-
database_config_file = File.join(__dir__, 'database.yml')
|
8
|
-
if File.exist?(database_config_file)
|
9
|
-
Sequel::Model.plugin :timestamps
|
10
|
-
Sequel::Model.plugin :json_serializer
|
11
|
-
Sequel::Model.raise_on_save_failure = false
|
12
|
-
|
13
|
-
database_config = YAML.load_file(database_config_file)
|
14
|
-
env_db_name = ENV['DB_NAME']
|
15
|
-
database_config[:database] = env_db_name if env_db_name
|
16
|
-
DB = Sequel.connect database_config
|
17
|
-
|
18
|
-
|
19
|
-
# DB.extension :pg_enum
|
20
|
-
DB.extension :error_sql
|
21
|
-
end
|
22
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
:environment: development
|
2
|
-
# :environment: production
|
3
|
-
|
4
|
-
:default: &default
|
5
|
-
:binds:
|
6
|
-
:tcp:
|
7
|
-
:host: '0.0.0.0'
|
8
|
-
:port: 3000
|
9
|
-
# :unix: 'tmp/sockets/puma.sock'
|
10
|
-
:daemonize: false
|
11
|
-
:pids_dir: tmp/pids
|
12
|
-
:logs_dir: log
|
13
|
-
:pid_file: puma.pid
|
14
|
-
# :workers_count: 1
|
15
|
-
# :threads_count: 4
|
16
|
-
|
17
|
-
development: &development
|
18
|
-
<<: *default
|
19
|
-
:workers_count: 1
|
20
|
-
:threads_count: 4
|
21
|
-
|
22
|
-
test: &test
|
23
|
-
<<: *default
|
24
|
-
:daemonize: false
|
25
|
-
|
26
|
-
production: &production
|
27
|
-
<<: *default
|
28
|
-
:binds:
|
29
|
-
# :tcp:
|
30
|
-
# :host: '0.0.0.0'
|
31
|
-
# :port: 3000
|
32
|
-
:unix: 'tmp/sockets/puma.sock'
|
data/template/config.ru.erb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
environment = ENV['RACK_ENV'].to_sym
|
4
|
-
|
5
|
-
is_development = environment == :development
|
6
|
-
|
7
|
-
## Require gems
|
8
|
-
require 'bundler'
|
9
|
-
Bundler.require :default, environment
|
10
|
-
|
11
|
-
## Require libs
|
12
|
-
# require 'money/bank/google_currency'
|
13
|
-
|
14
|
-
## Require dirs
|
15
|
-
Flame::Application.require_dirs(
|
16
|
-
%w[config lib models helpers exports mailers services controllers]
|
17
|
-
)
|
18
|
-
|
19
|
-
## Require application
|
20
|
-
require './application'
|
21
|
-
|
22
|
-
## Use session middleware
|
23
|
-
if <%= @short_module_name %>::Application.config[:session]
|
24
|
-
use Rack::Session::Cookie, <%= @short_module_name %>::Application.config[:session][:cookie]
|
25
|
-
end
|
26
|
-
|
27
|
-
## Logger
|
28
|
-
require 'logger'
|
29
|
-
logs_dir = File.join(
|
30
|
-
__dir__,
|
31
|
-
<%= @short_module_name %>::Application.config[:server][environment.to_s][:logs_dir]
|
32
|
-
)
|
33
|
-
|
34
|
-
<%= @short_module_name %>::Application.config[:logger] = Logger.new(
|
35
|
-
is_development ? $stdout : File.join(logs_dir, 'stdout'),
|
36
|
-
'weekly'
|
37
|
-
)
|
38
|
-
|
39
|
-
## Access Logger
|
40
|
-
unless is_development
|
41
|
-
use Rack::CommonLogger, Logger.new(
|
42
|
-
File.join(logs_dir, 'access'),
|
43
|
-
'weekly'
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
if <%= @short_module_name %>.const_defined?(:DB)
|
48
|
-
## SQL Logger
|
49
|
-
if is_development
|
50
|
-
<%= @short_module_name %>::DB.loggers <<
|
51
|
-
if ENV['RACK_CONSOLE_INTRO']
|
52
|
-
Logger.new($stdout)
|
53
|
-
else
|
54
|
-
<%= @short_module_name %>.logger
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
## Freeze DB (not for `rake console`)
|
59
|
-
<%= @short_module_name %>::DB.freeze unless ENV['RACK_CONSOLE_INTRO']
|
60
|
-
end
|
61
|
-
|
62
|
-
## Remove invalid UTF-8 characters from requests
|
63
|
-
use Rack::UTF8Sanitizer
|
64
|
-
|
65
|
-
## Remove trailing slashes from request path (and redirect)
|
66
|
-
# use Rack::RemoveTrailingSlashes
|
67
|
-
|
68
|
-
## CSRF
|
69
|
-
# use Rack::Csrf, raise: is_development
|
70
|
-
|
71
|
-
## Run application
|
72
|
-
run <%= @short_module_name %>::Application
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module <%= @module_name %>
|
4
|
-
## Base controller for any others controllers
|
5
|
-
class Controller < Flame::Controller
|
6
|
-
# include Flame::R18n::Initialization
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def logger
|
11
|
-
<%= @short_module_name %>.logger
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module <%= @module_name %>
|
4
|
-
module Site
|
5
|
-
## Base controller for site-section
|
6
|
-
class Controller < <%= @short_module_name %>::Controller
|
7
|
-
# include Flame::Flash
|
8
|
-
# include Flame::R18n::LocaleInPath
|
9
|
-
|
10
|
-
protected
|
11
|
-
|
12
|
-
def execute(method)
|
13
|
-
response.headers[Rack::CONTENT_TYPE] = 'text/html; charset=utf-8'
|
14
|
-
super
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/template/db/.keep
DELETED
File without changes
|
data/template/filewatchers.yml
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
- :pattern: '**/{Gemfile,*.{rb,ru,yml}}'
|
2
|
-
:exclude: '**/{spec/**/*,config/**/*.example*}'
|
3
|
-
:command: bundle exec pumactl restart -F config/puma.rb
|
4
|
-
|
5
|
-
# - :pattern: 'assets/styles/**/*'
|
6
|
-
# :command: rake assets:build:styles
|
7
|
-
#
|
8
|
-
# - :pattern: '{assets/scripts/**/*,{.babelrc,webpack.config.js}}'
|
9
|
-
# :command: rake assets:build:scripts
|
10
|
-
#
|
11
|
-
# - :pattern: 'package.json'
|
12
|
-
# :command: yarn install && rake assets:build:scripts
|
data/template/helpers/.keep
DELETED
File without changes
|
data/template/lib/.keep
DELETED
File without changes
|
data/template/locales/en.yml
DELETED
File without changes
|
data/template/models/.keep
DELETED
File without changes
|
data/template/public/.keep
DELETED
File without changes
|
data/template/server
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# frozen_string_literal: true
|
4
|
-
|
5
|
-
require 'shellwords'
|
6
|
-
require 'yaml'
|
7
|
-
|
8
|
-
## Functons
|
9
|
-
def show_usage
|
10
|
-
puts <<~USAGE
|
11
|
-
Usage: ./server COMMAND
|
12
|
-
|
13
|
-
COMMAND is one of:
|
14
|
-
start - Start server
|
15
|
-
stop - Stop server
|
16
|
-
kill - Kill server (and filewatcher)
|
17
|
-
restart - Restart server
|
18
|
-
monitor - Show log
|
19
|
-
devel - Restart and monitor server
|
20
|
-
ps - Show processes of server
|
21
|
-
USAGE
|
22
|
-
end
|
23
|
-
|
24
|
-
def bash(command, print: true)
|
25
|
-
puts command if print
|
26
|
-
system bash_command(command)
|
27
|
-
end
|
28
|
-
|
29
|
-
def bash_command(command)
|
30
|
-
escaped_command = Shellwords.escape(command)
|
31
|
-
"bash -c #{escaped_command}"
|
32
|
-
end
|
33
|
-
|
34
|
-
def bash_spawn(command)
|
35
|
-
puts "spawn #{command}"
|
36
|
-
spawn bash_command command
|
37
|
-
end
|
38
|
-
|
39
|
-
def server(command)
|
40
|
-
if %i[start restart].include?(command) &&
|
41
|
-
!(dependencies_check && assets_build)
|
42
|
-
exit
|
43
|
-
end
|
44
|
-
if %i[stop restart].include?(command)
|
45
|
-
kill_each read_filewatcher_pids
|
46
|
-
delete_filewatcher_pids_file
|
47
|
-
end
|
48
|
-
web_server(command)
|
49
|
-
end
|
50
|
-
|
51
|
-
def web_server(command)
|
52
|
-
pumactl_command = "bundle exec pumactl #{command} -F #{puma_config_file}"
|
53
|
-
if environment == 'production' || command != :restart
|
54
|
-
waiting_mailing_lock if %i[stop restart].include?(command)
|
55
|
-
return bash pumactl_command
|
56
|
-
end
|
57
|
-
development_restart pumactl_command
|
58
|
-
end
|
59
|
-
|
60
|
-
def development_restart(pumactl_command)
|
61
|
-
filewatcher_pids =
|
62
|
-
development_filewatchers.map { |command| bash_spawn command }
|
63
|
-
dump_filewatcher_pids filewatcher_pids
|
64
|
-
# web_server :stop if File.exist? puma_pid_file
|
65
|
-
# web_server :start
|
66
|
-
File.exist?(puma_pid_file) ? bash(pumactl_command) : web_server(:start)
|
67
|
-
rescue SystemExit, Interrupt
|
68
|
-
kill_each filewatcher_pids
|
69
|
-
delete_filewatcher_pids_file
|
70
|
-
end
|
71
|
-
|
72
|
-
def kill_each(pids)
|
73
|
-
Array(pids).each do |pid|
|
74
|
-
bash "kill #{pid}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def filewatcher_command(pattern, execute, exclude: nil)
|
79
|
-
<<-CMD.split.join(' ')
|
80
|
-
bundle exec "
|
81
|
-
filewatcher
|
82
|
-
'#{pattern}'
|
83
|
-
#{"--exclude '#{exclude}'" unless exclude.nil?}
|
84
|
-
'#{execute}'
|
85
|
-
"
|
86
|
-
CMD
|
87
|
-
end
|
88
|
-
|
89
|
-
def development_filewatchers
|
90
|
-
YAML.load_file(File.join(__dir__, 'filewatchers.yml')).map do |args|
|
91
|
-
filewatcher_command args[:pattern], args[:command], exclude: args[:exclude]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def dump_filewatcher_pids(filewatcher_pids)
|
96
|
-
FileUtils.mkdir_p server_config_pids_dir
|
97
|
-
File.write(
|
98
|
-
filewatcher_pids_file,
|
99
|
-
filewatcher_pids.join($RS)
|
100
|
-
)
|
101
|
-
end
|
102
|
-
|
103
|
-
def read_filewatcher_pids
|
104
|
-
return unless File.exist?(filewatcher_pids_file)
|
105
|
-
File.read(filewatcher_pids_file).split($RS)
|
106
|
-
end
|
107
|
-
|
108
|
-
def delete_filewatcher_pids_file
|
109
|
-
return unless File.exist?(filewatcher_pids_file)
|
110
|
-
File.delete filewatcher_pids_file
|
111
|
-
end
|
112
|
-
|
113
|
-
def server_config
|
114
|
-
@server_config ||= YAML.load_file(File.join(__dir__, 'config/server.yml'))
|
115
|
-
end
|
116
|
-
|
117
|
-
def puma_config_file
|
118
|
-
@puma_config_file ||= File.join(__dir__, 'config/puma.rb')
|
119
|
-
end
|
120
|
-
|
121
|
-
def puma_pid_file
|
122
|
-
File.join(
|
123
|
-
__dir__, *server_config[environment].values_at(:pids_dir, :pid_file)
|
124
|
-
)
|
125
|
-
end
|
126
|
-
|
127
|
-
def server_config_pids_dir
|
128
|
-
server_config[environment][:pids_dir]
|
129
|
-
end
|
130
|
-
|
131
|
-
def filewatcher_pids_file
|
132
|
-
File.join server_config_pids_dir, 'filewatcher.pids'
|
133
|
-
end
|
134
|
-
|
135
|
-
def environment
|
136
|
-
ENV['RACK_ENV'] || server_config[:environment]
|
137
|
-
end
|
138
|
-
|
139
|
-
def log_files
|
140
|
-
File.join(__dir__, 'log/{stdout,stderr}')
|
141
|
-
end
|
142
|
-
|
143
|
-
def waiting_mailing_lock
|
144
|
-
while Dir[File.join(__dir__, 'tmp/mailing_*')].any?
|
145
|
-
puts "\e[31m\e[1mMails sending in progress!\e[22m\e[0m\nWaiting..."
|
146
|
-
sleep 1
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def monitor_server
|
151
|
-
bash "tail -f #{log_files}"
|
152
|
-
end
|
153
|
-
|
154
|
-
def dependencies_check
|
155
|
-
bash('bundle check || bundle install') # && bash('yarn install')
|
156
|
-
end
|
157
|
-
|
158
|
-
def assets_build
|
159
|
-
bash 'rake assets:build', print: false
|
160
|
-
end
|
161
|
-
|
162
|
-
def ps_with_grep(pattern)
|
163
|
-
bash "ps aux | grep #{pattern} --color", print: false
|
164
|
-
end
|
165
|
-
|
166
|
-
## Runtime
|
167
|
-
case ARGV[0]
|
168
|
-
when 'start'
|
169
|
-
server :start
|
170
|
-
when 'stop'
|
171
|
-
server :stop
|
172
|
-
when 'restart'
|
173
|
-
server :restart
|
174
|
-
when 'kill'
|
175
|
-
server :stop
|
176
|
-
bash 'pkill -f filewatcher'
|
177
|
-
bash 'pkill -f puma'
|
178
|
-
when 'monitor'
|
179
|
-
monitor_server
|
180
|
-
when 'devel'
|
181
|
-
server :restart
|
182
|
-
if environment == 'production'
|
183
|
-
puts 'Waiting for logs...'
|
184
|
-
sleep 1.5
|
185
|
-
monitor_server
|
186
|
-
end
|
187
|
-
when 'ps'
|
188
|
-
puts
|
189
|
-
puts 'Filewatcher:'
|
190
|
-
puts
|
191
|
-
ps_with_grep '[f]ilewatcher'
|
192
|
-
puts
|
193
|
-
puts 'Puma:'
|
194
|
-
puts
|
195
|
-
ps_with_grep '[p]uma[\ :]'
|
196
|
-
else
|
197
|
-
puts "Unknown command #{ARGV[0]}"
|
198
|
-
puts
|
199
|
-
show_usage
|
200
|
-
end
|
data/template/services/.keep
DELETED
File without changes
|
data/template/views/.keep
DELETED
File without changes
|
@@ -1 +0,0 @@
|
|
1
|
-
<h1>Hello, world!</h1>
|