neruda 0.0.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/bin/pablo +135 -238
  3. data/lib/neruda/config.rb +137 -0
  4. data/lib/neruda/config/lisp_config.rb +254 -0
  5. data/lib/neruda/config/org-config.el +18 -0
  6. data/lib/neruda/config/ox-neruda.el +114 -0
  7. data/lib/neruda/emacs.rb +44 -0
  8. data/lib/neruda/index.rb +122 -0
  9. data/lib/neruda/index/atom_generator.rb +86 -0
  10. data/lib/neruda/index/org_generator.rb +115 -0
  11. data/lib/neruda/org_file.rb +299 -0
  12. data/lib/neruda/org_file/class_methods.rb +72 -0
  13. data/lib/neruda/org_file/extracter.rb +72 -0
  14. data/lib/neruda/org_file/htmlizer.rb +53 -0
  15. data/lib/neruda/preview.rb +55 -0
  16. data/lib/neruda/templater.rb +112 -0
  17. data/lib/neruda/utils.rb +212 -0
  18. data/lib/neruda/version.rb +6 -0
  19. data/lib/tasks/org.rake +84 -0
  20. data/lib/tasks/site.rake +86 -0
  21. data/lib/tasks/sync.rake +34 -0
  22. data/lib/tasks/tags.rake +19 -0
  23. data/locales/en.yml +37 -0
  24. data/locales/fr.yml +37 -0
  25. data/themes/default/css/htmlize.css +346 -0
  26. data/themes/default/css/style.css +153 -0
  27. data/themes/default/img/bottom.png +0 -0
  28. data/themes/default/img/tic.png +0 -0
  29. data/themes/default/img/top.png +0 -0
  30. metadata +153 -43
  31. data/README.md +0 -98
  32. data/docs/Rakefile.example +0 -4
  33. data/docs/config.yml.example +0 -17
  34. data/lib/assets/chapter.slim +0 -14
  35. data/lib/assets/index.slim +0 -13
  36. data/lib/assets/layout.slim +0 -17
  37. data/lib/assets/style.css +0 -199
  38. data/lib/neruda.rb +0 -106
  39. data/lib/neruda/chapter.rb +0 -26
  40. data/lib/neruda/url.rb +0 -14
  41. data/lib/tasks/book.rake +0 -60
  42. data/lib/tasks/capistrano/chapters.rake +0 -60
  43. data/lib/tasks/capistrano/sinatra.rake +0 -18
  44. data/lib/tasks/chapters.rake +0 -132
  45. data/lib/tasks/sinatra.rake +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e3101ba04a16de9562d4834ebde5c9034103d14d
4
- data.tar.gz: f50ebe738e0771b75ed532319e84cfe1027bea25
2
+ SHA256:
3
+ metadata.gz: bf44dce40376682ca2835d1472ccd7eb2ea47d5e7b892623da09350077bf4a10
4
+ data.tar.gz: fcabfb117f2ac44a76fc325a84982be6dd6e389872f4fb6bfbd10bf05924d882
5
5
  SHA512:
6
- metadata.gz: c3ca902065a455800fdd16b9b9ee0d81921b7971d4a25b9aa8e5bf0327ab05f97ddd39b7d710ab7937cee1b11a1b61e33b51ee04a140d31ad0418584de15c95d
7
- data.tar.gz: 011f3df145a513b3b780fbf543db6eb5a76cd6c89acb8342428799bd32b3bfef21a38efc5019de9b686f4517bc642649fadbbd99864eb015b14e4bb957549a10
6
+ metadata.gz: 7113b65a71b026c419a6de56d7ba2b84cdf9fbf6b02a977736dbad0484a225c2d97acb4df906c957e51a9c3b968b3260fb748856630fc534c4f30a7d5aa280d7
7
+ data.tar.gz: 1e478aa7c7c9ac80cb9293fb873baeadbfa25864cffb81460ac5e727b46360228f5eeb0f525116e88b35a537a2ae07c94f5b373e037095168c1b929ccc07bb9b
data/bin/pablo CHANGED
@@ -1,279 +1,176 @@
1
1
  #!/usr/bin/env ruby
2
- # coding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
- require 'yaml'
6
- require 'rainbow'
4
+ require 'rake'
7
5
  require 'optparse'
8
- require 'fileutils'
9
-
10
- # Methods used to play with bundler
11
- module BundlerHelper
12
- def bundler_is_present?
13
- return false unless File.exist?('Gemfile')
14
- ENV['PATH'].split(':').each do |folder|
15
- return true if File.exist? File.join(folder, 'bundle')
6
+ require 'r18n-core'
7
+ require 'neruda/utils'
8
+ require 'neruda/version'
9
+
10
+ R18n.default_places = File.expand_path('../locales', __dir__)
11
+ R18n.set Neruda::Config.settings['lang']
12
+
13
+ # Pablo commands
14
+ module PabloCommands
15
+ def pablo_init
16
+ cnf = @options.merge
17
+ cnf.delete(:verbose)
18
+ cnf.delete(:directory)
19
+ cnf.transform_keys!(&:to_s)
20
+ Neruda::Config.save(Neruda::Config.settings.merge(cnf))
21
+ @rake.options.build_all = true
22
+ @rake.invoke_task('org:install')
23
+ return if File.exist? 'src/index.org'
24
+ Neruda::OrgFile.new('src/index.org', @options).write
25
+ end
26
+ alias_method :pablo_config, :pablo_init
27
+
28
+ def pablo_build(file = ARGV[0])
29
+ @rake.options.build_all = true
30
+ if file.nil?
31
+ @rake.invoke_task('site:build')
32
+ else
33
+ @rake.invoke_task("site:build:one[#{file}]")
16
34
  end
17
- false
18
- end
19
-
20
- def rake_or_bundle_run(cmd, use_system = false)
21
- cmd.insert(1, '-s') unless @options[:verbose]
22
- cmd = ['bundle', 'exec'] + cmd if bundler_is_present?
23
- joined_cmd = cmd.join(' ')
24
- puts Rainbow(joined_cmd).blue if @options[:verbose]
25
- return system(joined_cmd) if use_system
26
- exec(*cmd)
27
35
  end
28
36
 
29
- def capify
30
- unless File.exist? 'Capfile'
31
- STDERR.puts Rainbow('ERROR: Capfile does not exist.').red
32
- exit 1
37
+ def pablo_preview
38
+ Thread.new do
39
+ sleep 1
40
+ port = Neruda::Config.settings.dig('preview', 'server_port') || 5000
41
+ uri = "http://127.0.0.1:#{port}/"
42
+ current_os = Neruda::Utils.current_os
43
+ case current_os
44
+ when 'windows'
45
+ system 'start', uri
46
+ when 'apple'
47
+ system 'open', uri
48
+ else
49
+ system 'gio', 'open', uri
50
+ end
33
51
  end
34
-
35
- capfile = File.new('Capfile', 'a')
36
- capfile.write <<~CAPFILE
37
- neruda_spec = Gem::Specification.find_by_name 'neruda'
38
- Dir.glob("\#{neruda_spec.gem_dir}/lib/tasks/*.rake").each { |r| import r }
39
- Dir.glob("\#{neruda_spec.gem_dir}/lib/tasks/capistrano/*.rake").each { |r| import r }
40
- CAPFILE
52
+ @rake.invoke_task('site:preview')
41
53
  end
42
- end
43
54
 
44
- # Methods used with pablo init method
45
- module PabloInit
46
- def init_path
47
- FileUtils.mkdir_p 'config'
48
- FileUtils.mkdir_p 'public'
49
- FileUtils.mkdir_p 'tmp/pids'
50
- FileUtils.mkdir_p 'private/characters'
51
- FileUtils.mkdir_p 'private/sceneries'
52
- FileUtils.mkdir_p 'private/chapters'
53
- FileUtils.mkdir_p 'private/notes'
54
- FileUtils.mkdir_p 'private/epubs'
55
+ def pablo_open
56
+ filename = new_file_name(ARGV[0])
57
+ FileUtils.mkdir_p File.dirname(filename)
58
+ o = Neruda::OrgFile.new(filename, @options)
59
+ o.write unless File.exist? filename
60
+ editor = ENV['EDITOR'] || ENV['VISUAL'] || 'emacs'
61
+ cmd = [editor, '+6', filename]
62
+ system(*cmd)
55
63
  end
64
+ alias_method :pablo_edit, :pablo_open
56
65
 
57
- def init_config
58
- config = {}
59
- print 'Name of your website: '
60
- config['title'] = STDIN.gets.strip
61
- print 'Your author name: '
62
- config['author'] = STDIN.gets.strip
63
- print 'Main language of your website [en_US]: '
64
- lang = STDIN.gets.strip
65
- lang = 'en_US' if lang == ''
66
- config['lang'] = lang
67
-
68
- main_title = config['title'].tr(' ', '_').downcase.gsub(/[^a-z0-9_]/, '')
69
- print "Filename of the main generated epub [#{main_title}]: "
70
- epub = STDIN.gets.strip
71
- if epub == ''
72
- epub = main_title
73
- else
74
- epub = File.basename(epub, '.epub')
75
- end
76
- config['book_filename'] = epub
77
- config['chapters'] = []
78
-
79
- IO.write 'config/config.yml', config.to_yaml
66
+ def pablo_publish
67
+ @rake.invoke_task('sync:push')
80
68
  end
81
69
 
82
- def init_assets
83
- unless Dir.exist? 'views'
84
- FileUtils.cp_r File.join(__dir__, '../lib/assets'), 'views'
70
+ def pablo_help(command = 'basic', error: false)
71
+ warn R18n.t.pablo.error.no_command if error
72
+ cmd = Neruda::Utils.resolve_possible_alias(command)
73
+ cmd_opt = Neruda::Utils::PABLO_COMMANDS[cmd]
74
+ label = cmd_opt[:label] || command
75
+ warn format("%<label>s\n\n", label: R18n.t.pablo.usage(label))
76
+ if R18n.t.pablo.commands[cmd].translated?
77
+ warn format("%<label>s\n\n", label: R18n.t.pablo.commands[cmd])
85
78
  end
86
-
87
- return if File.exist? 'public/style.css'
88
- FileUtils.mv 'views/style.css', 'public/style.css'
89
- end
90
-
91
- def init_rackup
92
- unless File.exist? 'Rakefile'
93
- FileUtils.copy File.join(__dir__, '../docs/Rakefile.example'), 'Rakefile'
94
- end
95
-
96
- return if File.exist? 'config.ru'
97
- IO.write 'config.ru', <<~CONFIG
98
- # frozen_string_literal: true
99
-
100
- require 'neruda'
101
- run Neruda::App
102
- CONFIG
79
+ warn help_command_body(cmd).join("\n")
80
+ exit 1 if error
81
+ exit
103
82
  end
104
83
 
105
- def init_bundler
106
- return if File.exist? 'Gemfile'
107
- puts ''
108
- puts 'Bundler has been detected in your path.'
109
- # puts ''
110
- # print 'Do you want to use [o]rg files, [m]arkdown files or [b]oth' \
111
- # ' (default is org): '
112
- # markup = STDIN.gets.strip.downcase
113
- # if markup == 'm'
114
- # markup_gem = 'gem \'kramdown\''
115
- # elsif markup == 'b'
116
- # markup_gem = "gem 'kramdown'\ngem 'org-ruby'"
117
- # else
118
- # markup_gem = 'gem \'org-ruby\''
119
- # end
120
- markup_gem = 'gem \'org-ruby\''
121
-
122
- IO.write 'Gemfile', <<~GEMFILE
123
- # frozen_string_literal: true
124
-
125
- source 'https://rubygems.org'
126
-
127
- gem 'neruda'
128
- #{markup_gem}
129
-
130
- group :development do
131
- gem 'capistrano'
132
- gem 'capistrano-bundler'
133
- gem 'capistrano-rvm'
134
- gem 'rubocop'
135
- end
136
- GEMFILE
137
- puts ''
138
- puts 'To complete this installation, you must now run: ' +
139
- Rainbow('bundle install').yellow
140
- end
84
+ private
141
85
 
142
- def setup
143
- puts Rainbow('Creating main folders…').blue
144
- init_path
145
- puts Rainbow('Populating config file…').blue
146
- init_config
147
- puts Rainbow('Copying template files…').blue
148
- init_assets
149
- puts Rainbow('Installing rake files…').blue
150
- init_rackup
151
- puts ''
152
- puts Rainbow('Neruda has been successfully installed.').green
153
- init_bundler if bundler_is_present?
86
+ def new_file_name(title)
87
+ title ||= @options[:title]
88
+ title = 'new' if title.nil? || title == ''
89
+ filename = Neruda::OrgFile.slug title
90
+ return "#{filename}.org" unless @options[:directory]
91
+ "#{filename}/index.org"
92
+ end
93
+
94
+ def help_command_body(command)
95
+ body = [
96
+ R18n.t.pablo.options.cmd_title,
97
+ Neruda::Utils.summarize_command(command)
98
+ ]
99
+ return body unless command == 'basic'
100
+ body + [
101
+ '',
102
+ R18n.t.pablo.commands.cmd_title,
103
+ Neruda::Utils.list_commands
104
+ ]
154
105
  end
155
106
  end
156
107
 
157
108
  # Main pablo class
158
109
  class Pablo
159
- def initialize
160
- @options = {
161
- verbose: false
162
- }
163
- @available_commands = ['capify', 'list', 'start', 'edit',
164
- 'setup', 'stop', 'compile']
165
-
166
- parse_options
167
- # Be sure required directories are always there
168
- init_path unless @arg == 'setup'
169
- route_command
110
+ def initialize(opts = {})
111
+ @options = { verbose: false }.merge(opts)
112
+ init_rake
170
113
  end
171
114
 
172
- def route_command
173
- if @arg == 'stop'
174
- rake_or_bundle_run ['rake', 'sinatra:stop']
175
- return
176
- end
177
-
178
- ARGV.shift
179
- send @arg
180
- end
115
+ include PabloCommands
181
116
 
182
117
  private
183
118
 
184
- def parse_options
185
- optparse = OptionParser.new do |opts|
186
- opts.banner = <<~HELP
187
- Usage:
188
- pablo -h
189
- pablo [ -v ] command
190
-
191
- HELP
192
- opts.on('-v', '--verbose', 'Output more information') do
193
- @options[:verbose] = true
194
- end
195
- opts.on('-h', '--help', 'Display this screen') do
196
- STDERR.puts opts
197
- STDERR.puts
198
- pablo_help
199
- end
200
- end
119
+ def init_rake
120
+ init_rakefile unless File.exist?('Rakefile')
121
+ @rake = Rake.application
122
+ Rake.verbose(false) unless @options[:verbose]
123
+ @rake.raw_load_rakefile
124
+ end
201
125
 
202
- optparse.parse!
126
+ def init_rakefile
127
+ rakefile = <<~RAKE
128
+ # frozen_string_literal: true
203
129
 
204
- @arg = ARGV[0]
205
- if @arg == 'new'
206
- @arg = 'edit'
207
- elsif @arg == 'run'
208
- @arg = 'start'
209
- elsif @arg == 'init'
210
- @arg = 'setup'
211
- end
130
+ require 'neruda/config'
131
+ require 'r18n-core'
212
132
 
213
- if !File.exist?('config/config.yml') && @arg != 'setup'
214
- STDERR.puts Rainbow('ERROR: please run pablo setup before all').red
215
- exit 1
216
- end
217
- return if @available_commands.include?(@arg)
218
- STDERR.puts Rainbow('ERROR: no or unknown command given.').red
219
- STDERR.puts Rainbow('Run pablo -h for options and available ' \
220
- 'commands').red
221
- exit 1
222
- end
223
-
224
- include BundlerHelper
225
- include PabloInit
133
+ neruda_spec = Gem::Specification.find_by_name 'neruda'
134
+ R18n.default_places = "\#{neruda_spec.gem_dir}/locales"
135
+ R18n.set(Neruda::Config.settings['lang'] || 'en')
136
+ R18n::Filters.on(:named_variables)
226
137
 
227
- def pablo_help
228
- STDERR.puts <<~HELP
229
- Book Commands:
230
- new [title] Begin to write a new chapter
231
- edit [title] Continue the writing of a chapter
232
- compile Generate the epubs files
233
- list [elements] List various book elements
234
- (chapters, characters, notes, sceneries)
138
+ Dir.glob("\#{neruda_spec.gem_dir}/lib/tasks/*.rake").each { |r| import r }
235
139
 
236
- System Commands
237
- setup Initialize your Neruda instance
238
- (you just need to do it once).
239
- start Start a test web server
240
- stop Stop the web server
241
- HELP
242
- exit
140
+ task default: 'site:build'
141
+ RAKE
142
+ IO.write 'Rakefile', rakefile
243
143
  end
144
+ end
244
145
 
245
- def compile
246
- rake_or_bundle_run ['rake', 'chapters:build_epubs'], true
247
- rake_or_bundle_run ['rake', 'book:make'], true
248
- end
146
+ optparser = OptionParser.new
147
+ optparser.version = Neruda::VERSION
249
148
 
250
- def start
251
- compile
149
+ Neruda::Utils::PABLO_OPTIONS.each do |k, opt|
150
+ optparser.send(opt[:meth] || :on, *Neruda::Utils.decorate_option(k))
151
+ end
252
152
 
253
- loc_env = ENV['APP_ENV'] || 'development'
254
- if loc_env != 'production'
255
- puts Rainbow("Neruda is run in #{loc_env} environment").green
256
- else
257
- puts Rainbow('>> Neruda is run in production environment <<').yellow
258
- end
259
- puts ''
260
- rake_or_bundle_run ['rake', 'sinatra:start']
261
- end
153
+ params = {}
154
+ optparser.parse!(into: params)
262
155
 
263
- def edit
264
- if ARGV[0].nil?
265
- print 'Title: '
266
- title = STDIN.gets.strip
267
- else
268
- title = ARGV.join(' ')
269
- end
270
- rake_or_bundle_run ['rake', "chapters:create_or_edit[#{title}]"]
271
- end
156
+ if params[:version]
157
+ warn optparser.ver
158
+ exit
159
+ end
272
160
 
273
- def list
274
- list_type = ARGV[0] || 'chapters'
275
- rake_or_bundle_run ['rake', "book:list[#{list_type}]"]
276
- end
161
+ if ARGV[0] == 'help'
162
+ params[:help] = true
163
+ ARGV.shift
164
+ end
165
+ pablo = Pablo.new(params)
166
+ command = "pablo_#{ARGV[0]}".to_sym
167
+ cmd_err = !pablo.respond_to?(command)
168
+ if params[:help] || cmd_err
169
+ cmd_err = false if params[:help] && !ARGV[0]
170
+ pablo.pablo_help(ARGV[0], error: cmd_err)
277
171
  end
172
+ ARGV.shift
278
173
 
279
- Pablo.new
174
+ init_cmds = [:pablo_init, :pablo_config]
175
+ pablo.pablo_init unless File.exist?('config.yml') || init_cmds.include?(command)
176
+ pablo.send command
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'neruda/config/lisp_config'
5
+
6
+ module Neruda
7
+ # Wrapper for configuration
8
+ #
9
+ # This class is a singleton interface, which share the static website
10
+ # being build settings among different steps or tasks.
11
+ #
12
+ # It expects the website author to holds their custom settings in a
13
+ # YAML file named ~config.yml~ available at the root of their
14
+ # project.
15
+ #
16
+ # For example, with the given config file:
17
+ #
18
+ # #+begin_src
19
+ # ---
20
+ # title: My website
21
+ # author: Alice Doe
22
+ # #+end_src
23
+ #
24
+ # Settings will be available like this:
25
+ #
26
+ # #+begin_src
27
+ # Neruda::Config.settings['author']
28
+ # => "Alice Doe"
29
+ # #+end_src
30
+ class Config
31
+ extend Neruda::LispConfig
32
+
33
+ class << self
34
+ # Access the current website settings
35
+ #
36
+ # If the settings have not been loaded yet, this method is
37
+ # responsible for calling the one, which actually loads them.
38
+ #
39
+ # @return [Hash] the website settings
40
+ def settings
41
+ return load_settings unless @config
42
+ @config
43
+ end
44
+
45
+ # Save the settings given as a parameter to the ~config.yml~ file.
46
+ #
47
+ # Not only this method overwrite the old settings, but it replace
48
+ # the current shared settings with the ones given in
49
+ # parameter. Later call to
50
+ # {file:Neruda/Config.html#settings-class_method settings}
51
+ # will, obviously, use these new settings.
52
+ #
53
+ # @param new_config [Hash] the settings to save
54
+ # @return [Hash] the new settings after save
55
+ def save(new_config)
56
+ # Do not save obvious default config values. We'll always try to
57
+ # save author and lang as they default on system variables,
58
+ # which may be different from a system to another. Thus it may
59
+ # be confusing if one use neruda on two different computer and
60
+ # these params always change.
61
+ new_config.delete_if do |k, v|
62
+ ['domain', 'public_folder', 'templates', 'theme'].include?(k) \
63
+ && v == default_settings[k]
64
+ end
65
+ IO.write 'config.yml', new_config.to_yaml
66
+ load_settings # Reload config, taking default settings into account
67
+ end
68
+
69
+ # Load the given settings as if they comes from the ~config.yml~ file.
70
+ #
71
+ # This method is handy for testing purpose. Later call to
72
+ # {file:Neruda/Config.html#settings-class_method settings} will
73
+ # use these new settings.
74
+ #
75
+ # @param config [Hash] the settings to artificially load
76
+ # @return [Hash] the new settings
77
+ def load_test(config)
78
+ @sources = nil # Reset sources
79
+ @config = default_settings.merge config
80
+ end
81
+
82
+ # Return the qualified projects sources list.
83
+ #
84
+ # @return [Array] the fully qualified projects sources list
85
+ def sources
86
+ return @sources if @sources
87
+ default_sources = [{ 'path' => 'src', 'target' => '.' }]
88
+ @sources = (settings['sources'] || default_sources).map do |s|
89
+ build_source(s)
90
+ end.compact
91
+ end
92
+
93
+ private
94
+
95
+ def load_settings
96
+ @sources = nil
97
+ conf_file = 'config.yml'
98
+ if File.exist? conf_file
99
+ @config = default_settings.merge(YAML.load_file(conf_file)).freeze
100
+ else
101
+ @config = default_settings
102
+ end
103
+ end
104
+
105
+ def extract_lang_from_env(default)
106
+ (ENV['LANG'] || default).split('_', 2).first
107
+ end
108
+
109
+ def default_settings
110
+ return @default_settings if @default_settings
111
+ @default_settings = {
112
+ 'author' => (ENV['USER'] || ''),
113
+ 'domain' => '',
114
+ 'lang' => extract_lang_from_env('en'),
115
+ 'public_folder' => 'public_html',
116
+ 'templates' => [],
117
+ 'theme' => 'default'
118
+ }.freeze
119
+ end
120
+
121
+ def build_source(seed)
122
+ opts = { 'recursive' => true, 'is_blog' => false }
123
+ case seed
124
+ when String
125
+ opts['path'] = seed
126
+ when Hash
127
+ opts.merge! seed
128
+ end
129
+ return nil unless opts.has_key?('path')
130
+ opts['path'] = File.expand_path(opts['path'])
131
+ opts['name'] ||= File.basename(opts['path']).sub(/^\./, '')
132
+ opts['target'] ||= opts['name']
133
+ opts
134
+ end
135
+ end
136
+ end
137
+ end