neruda 0.0.9 → 0.2.0

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.
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