neruda 0.2.4 → 0.2.6
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 +4 -4
- data/lib/neruda/version.rb +1 -1
- metadata +24 -219
- data/LICENSE +0 -14
- data/bin/pablo +0 -193
- data/lib/neruda/config/lisp_config.rb +0 -260
- data/lib/neruda/config/org-config.el +0 -17
- data/lib/neruda/config/ox-neruda.el +0 -114
- data/lib/neruda/config.rb +0 -137
- data/lib/neruda/emacs.rb +0 -37
- data/lib/neruda/index/atom_generator.rb +0 -86
- data/lib/neruda/index/org_generator.rb +0 -114
- data/lib/neruda/index.rb +0 -130
- data/lib/neruda/org_file/class_methods.rb +0 -72
- data/lib/neruda/org_file/extracter.rb +0 -72
- data/lib/neruda/org_file/htmlizer.rb +0 -43
- data/lib/neruda/org_file.rb +0 -299
- data/lib/neruda/preview.rb +0 -55
- data/lib/neruda/templater.rb +0 -118
- data/lib/neruda/utils.rb +0 -214
- data/lib/tasks/org.rake +0 -91
- data/lib/tasks/site.rake +0 -55
- data/lib/tasks/sync.rake +0 -34
- data/lib/tasks/tags.rake +0 -19
- data/locales/en.yml +0 -38
- data/locales/fr.yml +0 -38
data/lib/neruda/org_file.rb
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'time'
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
# neruda/config is required by htmlizer
|
|
6
|
-
require 'neruda/org_file/htmlizer'
|
|
7
|
-
require 'neruda/org_file/extracter'
|
|
8
|
-
require 'neruda/org_file/class_methods'
|
|
9
|
-
require 'neruda/index'
|
|
10
|
-
require 'neruda/version'
|
|
11
|
-
|
|
12
|
-
module Neruda
|
|
13
|
-
# Handles org files.
|
|
14
|
-
#
|
|
15
|
-
# This class is responsible for reading or writing existing or new org
|
|
16
|
-
# files, and formating their content to be used on the generated
|
|
17
|
-
# website.
|
|
18
|
-
class OrgFile
|
|
19
|
-
# @return [String] the title of the current org document, taken from
|
|
20
|
-
# the ~#+title:~ header.
|
|
21
|
-
attr_reader :title
|
|
22
|
-
|
|
23
|
-
# @return [String] the subtitle of the current org document, taken
|
|
24
|
-
# from the ~#+subtitle:~ header.
|
|
25
|
-
attr_reader :subtitle
|
|
26
|
-
|
|
27
|
-
# @return [DateTime] the date and time of the current org document,
|
|
28
|
-
# taken from the ~#+date:~ header.
|
|
29
|
-
attr_reader :date
|
|
30
|
-
|
|
31
|
-
# @return [Boolean] wether a time has been extracted from the
|
|
32
|
-
# current org document ~#+date:~ header.
|
|
33
|
-
attr_reader :notime
|
|
34
|
-
|
|
35
|
-
# The author of the current org document, taken from the ~#+author:~
|
|
36
|
-
# header.
|
|
37
|
-
#
|
|
38
|
-
# If the current document doesn't have any authorship information,
|
|
39
|
-
# the one from the ~config.yml~ file will be used instead
|
|
40
|
-
#
|
|
41
|
-
# @return [String] the author name
|
|
42
|
-
attr_reader :author
|
|
43
|
-
|
|
44
|
-
# @return [Array] the keywords list of the current org document,
|
|
45
|
-
# taken from the ~#+keywords:~ header.
|
|
46
|
-
attr_reader :keywords
|
|
47
|
-
|
|
48
|
-
# @return [String] the description of this org document, taken from
|
|
49
|
-
# the ~#+description:~ header.
|
|
50
|
-
attr_reader :excerpt
|
|
51
|
-
|
|
52
|
-
# The locale of the current org document, taken from the
|
|
53
|
-
# ~#+language:~ header.
|
|
54
|
-
#
|
|
55
|
-
# If the current document doesn't have any language information, the
|
|
56
|
-
# one from the ~config.yml~ file will be used instead, or "en" by
|
|
57
|
-
# default.
|
|
58
|
-
#
|
|
59
|
-
# @return [String] the document lang
|
|
60
|
-
attr_reader :lang
|
|
61
|
-
|
|
62
|
-
# @return [String] the relative path to the source of this document.
|
|
63
|
-
attr_reader :file
|
|
64
|
-
|
|
65
|
-
# @return [String] the relative path to the generated html file of
|
|
66
|
-
# this document.
|
|
67
|
-
attr_reader :html_file
|
|
68
|
-
|
|
69
|
-
# @return [String] the url of this document, build from the ~domain~
|
|
70
|
-
# settings and the above {#html_file @html_file} attribute.
|
|
71
|
-
attr_reader :url
|
|
72
|
-
|
|
73
|
-
# @return [String] the project owning this document.
|
|
74
|
-
attr_reader :project
|
|
75
|
-
|
|
76
|
-
extend Neruda::OrgFileClassMethods
|
|
77
|
-
|
|
78
|
-
include Neruda::OrgFileExtracter
|
|
79
|
-
include Neruda::OrgFileHtmlizer
|
|
80
|
-
|
|
81
|
-
# Prepares the file named by ~file_name~ for read and write
|
|
82
|
-
# operations.
|
|
83
|
-
#
|
|
84
|
-
# If the file ~file_name~ does not exist, the new instance may be
|
|
85
|
-
# populated by data given in the ~opts~ parameter.
|
|
86
|
-
#
|
|
87
|
-
# @example
|
|
88
|
-
# File.exist? './test.org'
|
|
89
|
-
# => true
|
|
90
|
-
# o = Neruda::OrgFile.new('./test.org')
|
|
91
|
-
# => #<Neruda::OrgFile @file='./test.org'...>
|
|
92
|
-
# o.title
|
|
93
|
-
# => "This is an existing test file"
|
|
94
|
-
# File.exist? '/tmp/does_not_exist.org'
|
|
95
|
-
# => false
|
|
96
|
-
# o = Neruda::OrgFile.new('/tmp/does_not_exist.org')
|
|
97
|
-
# => #<Neruda::OrgFile @file='/tmp/does_not_exist.org'...>
|
|
98
|
-
# o.title
|
|
99
|
-
# => ""
|
|
100
|
-
# File.exist? '/tmp/other.org'
|
|
101
|
-
# => false
|
|
102
|
-
# o = Neruda::OrgFile.new('/tmp/other.org', title: 'New file')
|
|
103
|
-
# => #<Neruda::OrgFile @file='/tmp/other.org'...>
|
|
104
|
-
# o.title
|
|
105
|
-
# => "New file"
|
|
106
|
-
#
|
|
107
|
-
# @param file_name [String] path to the corresponding Org file
|
|
108
|
-
# @param opts [Hash] optional data to initialize new Org file
|
|
109
|
-
# @option opts [String] title ('') the title of the new Org file
|
|
110
|
-
# @option opts [String] author (system user or '') the author of the
|
|
111
|
-
# document
|
|
112
|
-
# @option opts [Boolean] verbose (false) if the
|
|
113
|
-
# {Neruda::OrgFileHtmlizer#publish publish} method should output
|
|
114
|
-
# emacs process messages
|
|
115
|
-
# @option opts [String] project the project owning this file
|
|
116
|
-
# must be stored
|
|
117
|
-
# @return [Neruda::OrgFile] the new instance of Neruda::OrgFile
|
|
118
|
-
def initialize(file_name, opts = {})
|
|
119
|
-
file_name = nil if file_name == ''
|
|
120
|
-
@file = file_name
|
|
121
|
-
@html_file = nil
|
|
122
|
-
@url = nil
|
|
123
|
-
@project = opts.delete :project
|
|
124
|
-
@options = opts
|
|
125
|
-
build_html_file_and_url
|
|
126
|
-
if @file && File.exist?(@file)
|
|
127
|
-
extract_data
|
|
128
|
-
else
|
|
129
|
-
init_empty_file
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Returns a String representation of the document date, which aims
|
|
134
|
-
# to be used to sort several OrgFiles.
|
|
135
|
-
#
|
|
136
|
-
# The format used for the key is ~%Y%m%d%H%M%S~. If the current
|
|
137
|
-
# OrgFile instance does not have a date, this mehod return
|
|
138
|
-
# ~00000000000000~. If the current OrgFile instance does not have
|
|
139
|
-
# time information, the date is padded with zeros.
|
|
140
|
-
#
|
|
141
|
-
# @example with the org header ~#+date: <2019-07-03 Wed 20:52:49>~
|
|
142
|
-
# org_file.date
|
|
143
|
-
# => #<DateTime: 2019-07-03T20:52:49+02:00...>
|
|
144
|
-
# org_file.timekey
|
|
145
|
-
# => "20190703205349"
|
|
146
|
-
#
|
|
147
|
-
# @example with the org header ~#+date: <2019-07-03 Wed>~
|
|
148
|
-
# org_file.date
|
|
149
|
-
# => #<DateTime: 2019-07-03T00:00:00+02:00...>
|
|
150
|
-
# org_file.timekey
|
|
151
|
-
# => "20190703000000"
|
|
152
|
-
#
|
|
153
|
-
# @example with no date header in the org file
|
|
154
|
-
# org_file.date
|
|
155
|
-
# => nil
|
|
156
|
-
# org_file.timekey
|
|
157
|
-
# => "00000000000000"
|
|
158
|
-
#
|
|
159
|
-
# @return [String] the document key
|
|
160
|
-
def timekey
|
|
161
|
-
return '00000000000000' if @date.nil?
|
|
162
|
-
@date.strftime('%Y%m%d%H%M%S')
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Returns the current OrgFile instance DateTime as a String.
|
|
166
|
-
#
|
|
167
|
-
# This method accepts three values for the ~dateformat~ parameter:
|
|
168
|
-
#
|
|
169
|
-
# - ~:full~ (or ~:long~) :: outputs a complete date and time
|
|
170
|
-
# representation, localized through R18n;
|
|
171
|
-
# - ~:short~ :: outputs a short date representation (without time),
|
|
172
|
-
# localized with R18n;
|
|
173
|
-
# - ~:rfc3339~ :: outputs the RFC 3339 date and time representation,
|
|
174
|
-
# used in atom feed.
|
|
175
|
-
#
|
|
176
|
-
# @param dateformat [Symbol] the format to use to convert DateTime
|
|
177
|
-
# into String
|
|
178
|
-
# @param year [Boolean] wether or not the ~:full~ format must
|
|
179
|
-
# contain the year
|
|
180
|
-
# @return [String] the document DateTime string representation
|
|
181
|
-
def datestring(dateformat = :full, year: true)
|
|
182
|
-
return '' if @date.nil?
|
|
183
|
-
return R18n.l @date.to_date if dateformat == :short
|
|
184
|
-
return @date.rfc3339 if dateformat == :rfc3339
|
|
185
|
-
locale = R18n.get.locale
|
|
186
|
-
long_fmt = R18n.t.neruda.index.full_date_format(
|
|
187
|
-
date: locale.format_date_full(@date, year)
|
|
188
|
-
)
|
|
189
|
-
unless @notime
|
|
190
|
-
long_fmt = R18n.t.neruda.index.full_date_with_time_format(
|
|
191
|
-
date: long_fmt, time: locale.time_format.delete('_').strip
|
|
192
|
-
)
|
|
193
|
-
end
|
|
194
|
-
locale.strftime(@date, long_fmt)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# Formats given ~string~ with values of the current OrgFile.
|
|
198
|
-
#
|
|
199
|
-
# This method expects to find percent-tags in the given ~string~ and
|
|
200
|
-
# replace them by their corresponding value.
|
|
201
|
-
#
|
|
202
|
-
# *** Format:
|
|
203
|
-
#
|
|
204
|
-
# - %a :: the raw author name
|
|
205
|
-
# - %A :: the HTML rendering of the author name, equivalent to
|
|
206
|
-
# ~<span class="author">%a</span>~
|
|
207
|
-
# - %d :: the ~:short~ date HTML representation, equivalent
|
|
208
|
-
# to ~<time datetime="%I">%i</time>~
|
|
209
|
-
# - %D :: the ~:full~ date and time HTML representation
|
|
210
|
-
# - %i :: the raw ~:short~ date and time
|
|
211
|
-
# - %I :: the raw ~:rfc3339~ date and time
|
|
212
|
-
# - %k :: the keywords separated by a comma
|
|
213
|
-
# - %K :: the HTML list rendering of the keywords
|
|
214
|
-
# - %l :: the lang of the document
|
|
215
|
-
# - %L :: the license information, taken from the
|
|
216
|
-
# {Neruda::Config#settings}
|
|
217
|
-
# - %n :: the Neruda name and version
|
|
218
|
-
# - %N :: the Neruda name and version with a link to the project
|
|
219
|
-
# home on the name
|
|
220
|
-
# - %s :: the subtitle of the document
|
|
221
|
-
# - %t :: the title of the document
|
|
222
|
-
# - %u :: the web path to the related published HTML document
|
|
223
|
-
# - %x :: the raw description (eXcerpt)
|
|
224
|
-
# - %X :: the description, enclosed in an HTML ~p~ tag, equivalent
|
|
225
|
-
# to ~<p>%x</p>~
|
|
226
|
-
#
|
|
227
|
-
# @example
|
|
228
|
-
# org_file.format("Article written by %a the %d")
|
|
229
|
-
# => "Article written by Alice Smith the Wednesday 3rd July"
|
|
230
|
-
#
|
|
231
|
-
# @return [String] the given ~string~ after replacement occurs
|
|
232
|
-
# rubocop:disable Metrics/MethodLength
|
|
233
|
-
# rubocop:disable Layout/LineLength
|
|
234
|
-
def format(string)
|
|
235
|
-
string.gsub('%a', @author)
|
|
236
|
-
.gsub('%A', author_to_html)
|
|
237
|
-
.gsub('%d', date_to_html(:short))
|
|
238
|
-
.gsub('%D', date_to_html)
|
|
239
|
-
.gsub('%i', datestring(:short))
|
|
240
|
-
.gsub('%I', datestring(:rfc3339))
|
|
241
|
-
.gsub('%k', @keywords.join(', '))
|
|
242
|
-
.gsub('%K', keywords_to_html)
|
|
243
|
-
.gsub('%l', @lang)
|
|
244
|
-
.gsub('%L', (Neruda::Config.settings['license'] || '').gsub(/\s+/, ' ').strip)
|
|
245
|
-
.gsub('%n', "Neruda #{Neruda::VERSION}")
|
|
246
|
-
.gsub('%N', "<a href=\"https://git.umaneti.net/neruda/about/\">Neruda</a> #{Neruda::VERSION}")
|
|
247
|
-
.gsub('%s', @subtitle)
|
|
248
|
-
.gsub('%t', @title)
|
|
249
|
-
.gsub('%u', @html_file || '')
|
|
250
|
-
.gsub('%x', @excerpt)
|
|
251
|
-
.gsub('%X', "<p>#{@excerpt}</p>")
|
|
252
|
-
end
|
|
253
|
-
# rubocop:enable Layout/LineLength
|
|
254
|
-
# rubocop:enable Metrics/MethodLength
|
|
255
|
-
|
|
256
|
-
# Writes the current OrgFile content to the underlying file.
|
|
257
|
-
#
|
|
258
|
-
# The intermediate parent folders are created if necessary.
|
|
259
|
-
#
|
|
260
|
-
# @return [Integer] the length written (as returned by the
|
|
261
|
-
# underlying ~IO.write~ method call)
|
|
262
|
-
def write
|
|
263
|
-
raise TypeError, 'no conversion from nil file name to path.' if @file.nil?
|
|
264
|
-
file_dir = File.dirname @file
|
|
265
|
-
FileUtils.mkdir_p file_dir unless Dir.exist? file_dir
|
|
266
|
-
IO.write @file, @content
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
private
|
|
270
|
-
|
|
271
|
-
def build_html_file_and_url
|
|
272
|
-
return if @file.nil?
|
|
273
|
-
@html_file = Neruda::OrgFile.target_for_source(
|
|
274
|
-
@file, @project, with_public_folder: false
|
|
275
|
-
)
|
|
276
|
-
@url = "#{Neruda::Config.settings['domain']}/#{@html_file}"
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def init_empty_file
|
|
280
|
-
@title = @options[:title] || ''
|
|
281
|
-
@subtitle = ''
|
|
282
|
-
@date = DateTime.now
|
|
283
|
-
@notime = false
|
|
284
|
-
@author = @options[:author] || Neruda::Config.settings['author']
|
|
285
|
-
@keywords = []
|
|
286
|
-
@lang = @options[:lang] || Neruda::Config.settings['lang']
|
|
287
|
-
@excerpt = ''
|
|
288
|
-
body = @options[:content] || ''
|
|
289
|
-
@content = @options[:raw_content] || <<~ORG
|
|
290
|
-
#+title: #{@title}
|
|
291
|
-
#+date: <#{@date.strftime('%Y-%m-%d %a. %H:%M:%S')}>
|
|
292
|
-
#+author: #{@author}
|
|
293
|
-
#+language: #{@lang}
|
|
294
|
-
|
|
295
|
-
#{body}
|
|
296
|
-
ORG
|
|
297
|
-
end
|
|
298
|
-
end
|
|
299
|
-
end
|
data/lib/neruda/preview.rb
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'webrick'
|
|
4
|
-
require 'neruda/config'
|
|
5
|
-
|
|
6
|
-
module Neruda # rubocop:disable Style/Documentation
|
|
7
|
-
# A tiny preview server, which main goal is to replace references to
|
|
8
|
-
# the target domain by localhost.
|
|
9
|
-
class PreviewServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
10
|
-
include WEBrick::HTTPUtils
|
|
11
|
-
|
|
12
|
-
def do_GET(request, response) # rubocop:disable Naming/MethodName
|
|
13
|
-
file = local_path(request.path)
|
|
14
|
-
response.body = parse_body(file, "http://#{request.host}:#{request.port}")
|
|
15
|
-
response.status = 200
|
|
16
|
-
response.content_type = mime_type(file, DefaultMimeTypes)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def local_path(requested_path)
|
|
22
|
-
routes = Neruda::Config.settings.dig('preview', 'routes') || {}
|
|
23
|
-
return routes[requested_path] if routes.has_key? requested_path
|
|
24
|
-
local_path = Neruda::Config.settings['public_folder'] + requested_path
|
|
25
|
-
if File.directory? local_path
|
|
26
|
-
local_path = format(
|
|
27
|
-
'%<path>s/index.html', path: local_path.delete_suffix('/')
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
return local_path if File.exist? local_path
|
|
31
|
-
raise WEBrick::HTTPStatus::NotFound, 'Not found.'
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def parse_body(local_path, local_host)
|
|
35
|
-
body = IO.read local_path
|
|
36
|
-
return body unless local_path.match?(/\.(?:ht|x)ml\z/)
|
|
37
|
-
domain = Neruda::Config.settings['domain']
|
|
38
|
-
return body if domain == ''
|
|
39
|
-
body.gsub(/"file:\/\//, format('"%<host>s', host: local_host))
|
|
40
|
-
.gsub(/"#{domain}/, format('"%<host>s', host: local_host))
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
class << self
|
|
45
|
-
def start_preview
|
|
46
|
-
# Inspired by ruby un.rb library, which allows normally to start a
|
|
47
|
-
# webrick server in one line: ruby -run -e httpd public_html -p 5000
|
|
48
|
-
port = Neruda::Config.settings.dig('preview', 'server_port') || 5000
|
|
49
|
-
s = WEBrick::HTTPServer.new(Port: port)
|
|
50
|
-
s.mount '/', Neruda::PreviewServlet
|
|
51
|
-
['TERM', 'QUIT', 'INT'].each { |sig| trap(sig, proc { s.shutdown }) }
|
|
52
|
-
s.start
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
data/lib/neruda/templater.rb
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'nokogiri'
|
|
4
|
-
require 'digest/md5'
|
|
5
|
-
require 'neruda/org_file'
|
|
6
|
-
|
|
7
|
-
module Neruda
|
|
8
|
-
# Insert custom part inside generated HTML files.
|
|
9
|
-
class Templater
|
|
10
|
-
def initialize(source, dom, opts = {})
|
|
11
|
-
@dom = dom
|
|
12
|
-
@org_file = source
|
|
13
|
-
@position = opts['type'] || 'after'
|
|
14
|
-
@content = extract_content opts
|
|
15
|
-
@element = @dom.css(opts['selector'])
|
|
16
|
-
digest = Digest::MD5.hexdigest(@content)
|
|
17
|
-
@check_line = " Neruda Template: #{digest} "
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def apply
|
|
21
|
-
flag_head
|
|
22
|
-
content = @org_file.format(@content)
|
|
23
|
-
@element.each do |e|
|
|
24
|
-
insert_new_node_at e, content
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def in_head?
|
|
29
|
-
@dom.xpath('//head').children.to_a.filter(&:comment?).each do |c|
|
|
30
|
-
return true if c.text == @check_line
|
|
31
|
-
end
|
|
32
|
-
false
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class << self
|
|
36
|
-
def customize_output(file_name, source = nil)
|
|
37
|
-
templates_to_apply = filter_templates(file_name)
|
|
38
|
-
return if templates_to_apply.empty?
|
|
39
|
-
if source.nil?
|
|
40
|
-
sourcepath = Neruda::OrgFile.source_for_target(file_name)
|
|
41
|
-
source = Neruda::OrgFile.new(sourcepath)
|
|
42
|
-
end
|
|
43
|
-
dom = open_dom(file_name)
|
|
44
|
-
templates_to_apply.each do |t|
|
|
45
|
-
tpl = Neruda::Templater.new(source, dom, t)
|
|
46
|
-
next if tpl.in_head?
|
|
47
|
-
tpl.apply
|
|
48
|
-
end
|
|
49
|
-
write_dom(file_name, dom)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
private
|
|
53
|
-
|
|
54
|
-
def filter_templates(file_name)
|
|
55
|
-
templates = Neruda::Config.settings['templates']
|
|
56
|
-
return [] if templates.nil? || templates.empty?
|
|
57
|
-
templates.filter { |t| check_required_keys(t, file_name) }
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def open_dom(file_name)
|
|
61
|
-
file = File.new file_name, 'r'
|
|
62
|
-
dom = Nokogiri::HTML file
|
|
63
|
-
file.close
|
|
64
|
-
dom
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def write_dom(file_name, dom)
|
|
68
|
-
file = File.new file_name, 'w'
|
|
69
|
-
dom.write_to file
|
|
70
|
-
file.close
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def check_path(file_name, pathes)
|
|
74
|
-
pub_folder = Neruda::Config.settings['public_folder']
|
|
75
|
-
if pathes.is_a?(Array)
|
|
76
|
-
pathes.each do |tp|
|
|
77
|
-
return true if File.fnmatch?("#{pub_folder}#{tp}",
|
|
78
|
-
file_name, File::FNM_DOTMATCH)
|
|
79
|
-
end
|
|
80
|
-
return false
|
|
81
|
-
end
|
|
82
|
-
File.fnmatch?("#{pub_folder}#{pathes}",
|
|
83
|
-
file_name, File::FNM_DOTMATCH)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def check_required_keys(opts, file_name)
|
|
87
|
-
return false unless opts.has_key?('selector')
|
|
88
|
-
return false unless opts.has_key?('content') || opts.has_key?('source')
|
|
89
|
-
return check_path(file_name, opts['path']) if opts.has_key?('path')
|
|
90
|
-
true
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
private
|
|
95
|
-
|
|
96
|
-
def flag_head
|
|
97
|
-
@dom.xpath('//head').first.prepend_child("<!--#{@check_line}-->\n")
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def insert_new_node_at(elem, content)
|
|
101
|
-
case @position
|
|
102
|
-
when 'before'
|
|
103
|
-
elem.add_previous_sibling content
|
|
104
|
-
when 'replace'
|
|
105
|
-
elem.replace content
|
|
106
|
-
else
|
|
107
|
-
elem.add_next_sibling content
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def extract_content(opts)
|
|
112
|
-
return opts['content'] if opts['content']
|
|
113
|
-
# If we don't have a content option, then we must have a source
|
|
114
|
-
# one.
|
|
115
|
-
@dom.css(opts['source']).unlink.to_s
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
data/lib/neruda/utils.rb
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'uri'
|
|
4
|
-
require 'rainbow'
|
|
5
|
-
require 'net/http'
|
|
6
|
-
require 'r18n-core'
|
|
7
|
-
require 'neruda/config'
|
|
8
|
-
|
|
9
|
-
module Neruda
|
|
10
|
-
# Embeds usefull methods, mainly used in rake tasks.
|
|
11
|
-
module Utils
|
|
12
|
-
# @return [Hash] the possible throbber themes
|
|
13
|
-
THROBBER_FRAMES = {
|
|
14
|
-
'basic' => '-\|/',
|
|
15
|
-
'basicdots' => '⋯⋱⋮⋰',
|
|
16
|
-
'moon' => '🌑🌒🌓🌔🌕🌖🌗🌘',
|
|
17
|
-
'clock' => '🕛🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚',
|
|
18
|
-
'bricks' => '⣷⣯⣟⡿⢿⣻⣽⣾',
|
|
19
|
-
'points' => '·⁘∷⁛∷⁘',
|
|
20
|
-
'quadrant2' => '▙▛▜▟',
|
|
21
|
-
'default' => ['⠁ ⠂ ⠄ ⡀ ⠄ ⠂ ⠁', '⠂ ⠁ ⠂ ⠄ ⡀ ⠄ ⠂', '⠄ ⠂ ⠁ ⠂ ⠄ ⡀ ⠄',
|
|
22
|
-
'⡀ ⠄ ⠂ ⠁ ⠂ ⠄ ⡀', '⠄ ⡀ ⠄ ⠂ ⠁ ⠂ ⠄', '⠂ ⠄ ⡀ ⠄ ⠂ ⠁ ⠂']
|
|
23
|
-
}.freeze
|
|
24
|
-
|
|
25
|
-
# @return [Hash] the possible ~pablo~ options and their
|
|
26
|
-
# configuration
|
|
27
|
-
PABLO_OPTIONS = {
|
|
28
|
-
'-a' => { long: 'author' },
|
|
29
|
-
'-f' => { long: 'force', boolean: true },
|
|
30
|
-
'-h' => { long: 'help', boolean: true, meth: :on_tail },
|
|
31
|
-
'-l' => { long: 'lang', keyword: 'LOCALE' },
|
|
32
|
-
'-p' => { long: 'path' },
|
|
33
|
-
'-t' => { long: 'title' },
|
|
34
|
-
'-v' => { long: 'verbose', boolean: true, meth: :on_tail },
|
|
35
|
-
'-V' => { long: 'version', boolean: true, meth: :on_tail }
|
|
36
|
-
}.freeze
|
|
37
|
-
|
|
38
|
-
# @return [Hash] the possible ~pablo~ subcommands and their
|
|
39
|
-
# configuration
|
|
40
|
-
PABLO_COMMANDS = {
|
|
41
|
-
'init' => { opts: ['-a', '-h', '-l', '-t', '-v'] },
|
|
42
|
-
'config' => { alias: 'init' },
|
|
43
|
-
'preview' => { opts: ['-h'] },
|
|
44
|
-
'open' => { opts: ['-a', '-h', '-l', '-p', '-t', '-v'] },
|
|
45
|
-
'edit' => { alias: 'open' },
|
|
46
|
-
'build' => { opts: ['-f', '-h'] },
|
|
47
|
-
'publish' => { opts: ['-h'] },
|
|
48
|
-
'help' => { opts: ['-h'] },
|
|
49
|
-
'basic' => { opts: ['-h', '-V'], label: '<command>' }
|
|
50
|
-
}.freeze
|
|
51
|
-
|
|
52
|
-
class << self
|
|
53
|
-
# Animates strings in the user console to alert him that something
|
|
54
|
-
# is running in the background.
|
|
55
|
-
#
|
|
56
|
-
# The animation is chosen among a bunch of themes, with the
|
|
57
|
-
# configuration option ~throbber~ (retrieved via
|
|
58
|
-
# {Neruda::Config#settings}).
|
|
59
|
-
#
|
|
60
|
-
# @example
|
|
61
|
-
# long_stuff = Thread.new { very_long_operation }
|
|
62
|
-
# Neruda::Utils.throbber(long_stuff, 'Computing hard stuff:')
|
|
63
|
-
#
|
|
64
|
-
# @param thread [Thread] the long-running operation to decorate
|
|
65
|
-
# @param message [String] the message to display before the throbber
|
|
66
|
-
# @return [void]
|
|
67
|
-
def throbber(thread, message)
|
|
68
|
-
frames = select_throbber_frames
|
|
69
|
-
begin
|
|
70
|
-
run_and_decorate_thread thread, message, frames
|
|
71
|
-
rescue RuntimeError => e
|
|
72
|
-
throbber_error message
|
|
73
|
-
raise e
|
|
74
|
-
else
|
|
75
|
-
done = Rainbow('done'.ljust(frames[0].length)).green
|
|
76
|
-
puts "#{message} #{done}"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Returns the short and long options specification for a given
|
|
81
|
-
# short option.
|
|
82
|
-
#
|
|
83
|
-
# This method use the {Neruda::Utils::PABLO_OPTIONS} Hash to
|
|
84
|
-
# retrieve corresponding values.
|
|
85
|
-
#
|
|
86
|
-
# @example
|
|
87
|
-
# spec = Neruda::Utils.decorate_option('-a')
|
|
88
|
-
# => ['-a AUTHOR', '--author AUTHOR']
|
|
89
|
-
#
|
|
90
|
-
# @param short [String] the short option to decorate
|
|
91
|
-
# @return [Array] the short and long specification for an option
|
|
92
|
-
def decorate_option(short)
|
|
93
|
-
opt = Neruda::Utils::PABLO_OPTIONS[short]
|
|
94
|
-
long = "--#{opt[:long]}"
|
|
95
|
-
return [short, long] if opt[:boolean]
|
|
96
|
-
key = opt[:keyword] || opt[:long].upcase
|
|
97
|
-
[short + key, format('%<long>s %<key>s', long: long, key: key)]
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Returns the ~pablo~ help summary for a given command.
|
|
101
|
-
#
|
|
102
|
-
# @param command [String] the command for which a summary
|
|
103
|
-
# should be given
|
|
104
|
-
# @return [String]
|
|
105
|
-
def summarize_command(command)
|
|
106
|
-
Neruda::Utils::PABLO_COMMANDS[command][:opts].map do |k|
|
|
107
|
-
short, long = Neruda::Utils.decorate_option(k)
|
|
108
|
-
opt = Neruda::Utils::PABLO_OPTIONS[k]
|
|
109
|
-
label = [short, long].join(', ')
|
|
110
|
-
line = [format(' %<opt>s', opt: label).ljust(30)]
|
|
111
|
-
if R18n.t.pablo.options[opt[:long]].translated?
|
|
112
|
-
line << R18n.t.pablo.options[opt[:long]]
|
|
113
|
-
end
|
|
114
|
-
line.join(' ')
|
|
115
|
-
end.join("\n")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# Returns a formatted list of available commands for ~pablo~.
|
|
119
|
-
#
|
|
120
|
-
# @return [String]
|
|
121
|
-
def list_commands
|
|
122
|
-
lines = []
|
|
123
|
-
Neruda::Utils::PABLO_COMMANDS.each do |cmd, opt|
|
|
124
|
-
next if cmd == 'basic'
|
|
125
|
-
line = [' ', cmd.ljust(10)]
|
|
126
|
-
if opt.has_key? :alias
|
|
127
|
-
line << R18n.t.pablo.commands.alias(opt[:alias])
|
|
128
|
-
else
|
|
129
|
-
line << R18n.t.pablo.commands[cmd]
|
|
130
|
-
end
|
|
131
|
-
lines << line.join(' ')
|
|
132
|
-
end
|
|
133
|
-
lines.join("\n")
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Returns the real command name for a given command, which may be
|
|
137
|
-
# an alias.
|
|
138
|
-
#
|
|
139
|
-
# @param command [String] the command to resolve
|
|
140
|
-
# @return [String]
|
|
141
|
-
def resolve_possible_alias(command)
|
|
142
|
-
return 'basic' unless Neruda::Utils::PABLO_COMMANDS.include?(command)
|
|
143
|
-
cmd_opt = Neruda::Utils::PABLO_COMMANDS[command]
|
|
144
|
-
return cmd_opt[:alias] if cmd_opt.has_key?(:alias)
|
|
145
|
-
command
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# Try to discover the current host operating system.
|
|
149
|
-
#
|
|
150
|
-
# @return [String] either apple, windows or linux (default)
|
|
151
|
-
# :nocov:
|
|
152
|
-
def current_os
|
|
153
|
-
if ENV['OS'] == 'Windows_NT' || RUBY_PLATFORM.include?('cygwin')
|
|
154
|
-
return 'windows'
|
|
155
|
-
end
|
|
156
|
-
return 'apple' if RUBY_PLATFORM.include?('darwin')
|
|
157
|
-
'linux'
|
|
158
|
-
end
|
|
159
|
-
# :nocov:
|
|
160
|
-
|
|
161
|
-
# Download latest org-mode tarball.
|
|
162
|
-
#
|
|
163
|
-
# @return [String] the downloaded org-mode version
|
|
164
|
-
def download_org
|
|
165
|
-
# :nocov:
|
|
166
|
-
return if Neruda::Config.org_last_version.nil?
|
|
167
|
-
# :nocov:
|
|
168
|
-
tarball = "org-#{Neruda::Config.org_last_version}.tar.gz"
|
|
169
|
-
# Remove version number in dest file to allow easy rake file
|
|
170
|
-
# task naming
|
|
171
|
-
dest_file = 'tmp/org.tar.gz'
|
|
172
|
-
return if File.exist?(dest_file)
|
|
173
|
-
uri = URI("https://orgmode.org/#{tarball}")
|
|
174
|
-
# Will crash on purpose if anything goes wrong
|
|
175
|
-
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
|
176
|
-
http.request(Net::HTTP::Get.new(uri)) do |response|
|
|
177
|
-
File.open(dest_file, 'w') do |io|
|
|
178
|
-
response.read_body { |chunk| io.write chunk }
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
private
|
|
185
|
-
|
|
186
|
-
def throbber_error(message)
|
|
187
|
-
warn(
|
|
188
|
-
format(
|
|
189
|
-
"%<message>s %<label>s\n%<explanation>s",
|
|
190
|
-
message: message,
|
|
191
|
-
label: Rainbow(R18n.t.neruda.error.label).bold.red,
|
|
192
|
-
explanation: Rainbow(R18n.t.neruda.error.explanation).bold
|
|
193
|
-
)
|
|
194
|
-
)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def select_throbber_frames
|
|
198
|
-
model = Neruda::Config.settings['throbber'] || 'default'
|
|
199
|
-
model = 'default' unless Neruda::Utils::THROBBER_FRAMES.has_key?(model)
|
|
200
|
-
Neruda::Utils::THROBBER_FRAMES[model]
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def run_and_decorate_thread(thread, message, frames)
|
|
204
|
-
thread.abort_on_exception = true
|
|
205
|
-
current = 0
|
|
206
|
-
while thread.alive?
|
|
207
|
-
sleep 0.1
|
|
208
|
-
print "#{message} #{frames[current % frames.length]}\r"
|
|
209
|
-
current += 1
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
end
|