fronde 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ext/r18n.rb +20 -0
- data/lib/ext/time.rb +6 -16
- data/lib/ext/time_no_time.rb +23 -0
- data/lib/fronde/cli/commands.rb +16 -12
- data/lib/fronde/cli/data/gitignore +0 -1
- data/lib/fronde/cli/opt_parse.rb +4 -7
- data/lib/fronde/cli/throbber.rb +24 -13
- data/lib/fronde/cli.rb +3 -2
- data/lib/fronde/config/data/org-config.el +3 -2
- data/lib/fronde/config/data/ox-fronde.el +72 -35
- data/lib/fronde/config/data/themes/umaneti/css/htmlize.css +364 -0
- data/lib/fronde/config/data/themes/umaneti/css/style.css +250 -0
- data/lib/fronde/config/data/themes/umaneti/img/bottom.png +0 -0
- data/lib/fronde/config/data/themes/umaneti/img/content.png +0 -0
- data/lib/fronde/config/data/themes/umaneti/img/tic.png +0 -0
- data/lib/fronde/config/data/themes/umaneti/img/top.png +0 -0
- data/lib/fronde/config/helpers.rb +0 -18
- data/lib/fronde/config/lisp.rb +13 -3
- data/lib/fronde/config.rb +40 -26
- data/lib/fronde/emacs.rb +1 -1
- data/lib/fronde/index/data/all_tags.org +6 -1
- data/lib/fronde/index/data/template.org +8 -4
- data/lib/fronde/index/org_generator.rb +2 -0
- data/lib/fronde/index.rb +12 -15
- data/lib/fronde/org/file.rb +39 -27
- data/lib/fronde/org/file_extracter.rb +15 -12
- data/lib/fronde/org.rb +11 -9
- data/lib/fronde/slug.rb +39 -12
- data/lib/fronde/source/gemini.rb +0 -5
- data/lib/fronde/source/html.rb +5 -5
- data/lib/fronde/source.rb +13 -8
- data/lib/fronde/sync/neocities.rb +220 -0
- data/lib/fronde/sync/rsync.rb +46 -0
- data/lib/fronde/sync.rb +32 -0
- data/lib/fronde/templater.rb +18 -11
- data/lib/fronde/version.rb +1 -1
- data/lib/tasks/org.rake +12 -17
- data/lib/tasks/site.rake +10 -13
- data/lib/tasks/sync.rake +13 -36
- data/lib/tasks/tags.rake +2 -2
- data/locales/en.yml +1 -0
- data/locales/fr.yml +1 -0
- metadata +49 -10
data/lib/fronde/config.rb
CHANGED
@@ -39,16 +39,16 @@ module Fronde
|
|
39
39
|
|
40
40
|
def initialize
|
41
41
|
@default_settings = {
|
42
|
-
'author' =>
|
42
|
+
'author' => ENV['USER'] || '',
|
43
43
|
'domain' => '',
|
44
44
|
'lang' => Fronde::Config::Helpers.extract_lang_from_env('en'),
|
45
45
|
'html_public_folder' => 'public_html',
|
46
46
|
'gemini_public_folder' => 'public_gmi',
|
47
47
|
'templates' => [], 'theme' => 'default'
|
48
48
|
}.freeze
|
49
|
-
@org_version = @sources = nil
|
50
|
-
@config = load_settings
|
51
49
|
# Do not load sources now to avoid dependency loop on config
|
50
|
+
@sources = nil
|
51
|
+
@config = load_settings
|
52
52
|
end
|
53
53
|
|
54
54
|
include Fronde::Config::Lisp
|
@@ -93,7 +93,7 @@ module Fronde
|
|
93
93
|
def reset
|
94
94
|
# Reload config, taking default settings into account
|
95
95
|
@config = load_settings
|
96
|
-
@
|
96
|
+
@sources = nil
|
97
97
|
@sources = load_sources
|
98
98
|
end
|
99
99
|
|
@@ -109,7 +109,7 @@ module Fronde
|
|
109
109
|
# @return [Fronde::Config::Store] self
|
110
110
|
def load_test(config)
|
111
111
|
@config = @default_settings.merge config
|
112
|
-
@
|
112
|
+
@sources = nil
|
113
113
|
@sources = load_sources
|
114
114
|
self
|
115
115
|
end
|
@@ -148,26 +148,48 @@ module Fronde
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
+
def check_duplicate_and_warn(collection, source, type)
|
152
|
+
path = source['path']
|
153
|
+
return path unless collection[type].has_key?(path)
|
154
|
+
|
155
|
+
warn(
|
156
|
+
R18n.t.fronde.error.source.duplicate(
|
157
|
+
source: source['name'], type: type
|
158
|
+
)
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
151
162
|
def remove_duplicate(sources)
|
152
163
|
check_paths = {}
|
153
164
|
sources.each do |source|
|
154
165
|
type = source.type
|
155
166
|
check_paths[type] ||= {}
|
156
|
-
path = source
|
167
|
+
path = check_duplicate_and_warn check_paths, source, type
|
157
168
|
# Avoid duplicate
|
158
|
-
|
159
|
-
|
160
|
-
R18n.t.fronde.error.source.duplicate(
|
161
|
-
source: source['name'], type: type
|
162
|
-
)
|
163
|
-
)
|
164
|
-
next
|
165
|
-
end
|
169
|
+
next unless path
|
170
|
+
|
166
171
|
check_paths[type][path] = source
|
167
172
|
end
|
168
173
|
check_paths
|
169
174
|
end
|
170
175
|
|
176
|
+
def filter_possible_matchs(path, other_paths_list)
|
177
|
+
other_paths_list.select do |other_path|
|
178
|
+
path != other_path && other_path.start_with?(path)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def warn_on_existing_inclusion(type, other, possible_matchs, sources)
|
183
|
+
possible_matchs.each do |match|
|
184
|
+
warn(
|
185
|
+
R18n.t.fronde.error.source.inclusion(
|
186
|
+
source: sources[match]['title'],
|
187
|
+
other_source: other, type: type
|
188
|
+
)
|
189
|
+
)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
171
193
|
def remove_inclusion(check_paths)
|
172
194
|
check_paths.map do |type, sources_by_path|
|
173
195
|
skip_paths = []
|
@@ -183,21 +205,13 @@ module Fronde
|
|
183
205
|
next source unless source.recursive?
|
184
206
|
|
185
207
|
# Ensure that the current source does not embed another one
|
186
|
-
possible_matchs =
|
187
|
-
path != other_path && other_path.start_with?(path)
|
188
|
-
end
|
208
|
+
possible_matchs = filter_possible_matchs path, sorted_paths
|
189
209
|
next source if possible_matchs.empty?
|
190
210
|
|
191
211
|
skip_paths += possible_matchs
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
R18n.t.fronde.error.source.inclusion(
|
196
|
-
source: other_source['title'], type: type,
|
197
|
-
other_source: source['title']
|
198
|
-
)
|
199
|
-
)
|
200
|
-
end
|
212
|
+
warn_on_existing_inclusion(
|
213
|
+
type, source['title'], possible_matchs, sources_by_path
|
214
|
+
)
|
201
215
|
end
|
202
216
|
end.flatten
|
203
217
|
end
|
data/lib/fronde/emacs.rb
CHANGED
@@ -4,11 +4,16 @@
|
|
4
4
|
{% for index in indexes %}
|
5
5
|
* {{ index.title }}
|
6
6
|
:PROPERTIES:
|
7
|
-
|
7
|
+
{%- if project_type == 'html' %}
|
8
|
+
:HTML_CONTAINER_CLASS: index-tags{% endif %}
|
8
9
|
:UNNUMBERED: notoc
|
9
10
|
:END:
|
10
11
|
|
11
12
|
{% for tag in index.tags -%}
|
13
|
+
{%- if project_type == 'gemini' -%}
|
14
|
+
[[{{ domain }}{{ project_path }}tags/{{ tag.slug }}.gmi][{{ tag.title }} ({{ tag.weight }})]]
|
15
|
+
{%- else -%}
|
12
16
|
- [[{{ domain }}{{ project_path }}tags/{{ tag.slug }}.html][{{ tag.title }}]] ({{ tag.weight }})
|
17
|
+
{%- endif %}
|
13
18
|
{% endfor %}
|
14
19
|
{%- endfor -%}
|
@@ -1,22 +1,26 @@
|
|
1
1
|
#+title: {{ title }}
|
2
2
|
#+author: {{ author }}
|
3
3
|
#+language: {{ lang }}
|
4
|
-
{%-
|
4
|
+
{%- if project_type == 'html' and slug != '__HOME_PAGE__' %}
|
5
5
|
#+html_head_extra: <link rel="alternate" type="application/atom+xml" title="{{ title }}" href="{{ domain }}{{ project_path }}feeds/{{ slug }}.xml" />
|
6
|
-
{%
|
6
|
+
{% endif -%}
|
7
7
|
{%- assign last_year = 0 -%}
|
8
8
|
{% for article in entries %}
|
9
9
|
{% assign cur_year = article.timekey | slice: 0, 4 %}
|
10
10
|
{%- unless cur_year == last_year %}
|
11
11
|
* {% if cur_year == "0000" %}{{ unsorted }}{% else %}{{ cur_year }}{% endif %}
|
12
12
|
:PROPERTIES:
|
13
|
-
|
13
|
+
{%- if project_type == 'html' %}
|
14
|
+
:HTML_CONTAINER_CLASS: index-year{% endif %}
|
14
15
|
:UNNUMBERED: notoc
|
15
16
|
:END:
|
16
17
|
{% assign last_year = cur_year %}
|
17
18
|
{% endunless -%}
|
19
|
+
{%- if project_type == 'gemini' -%}
|
20
|
+
[[{{ article.url }}][{% if article.published != '' %}{{ article.published_gemini_index }} {% endif %}{{ article.title }}]]
|
21
|
+
{%- else -%}
|
18
22
|
- *[[{{ article.url }}][{{ article.title }}]]*
|
19
23
|
{%- if article.published != '' %} / {{ article.published }}{% endif -%}
|
20
24
|
{%- if article.excerpt != '' %} \\
|
21
|
-
{{ article.excerpt }}{% endif %}
|
25
|
+
{{ article.excerpt }}{% endif %}{% endif %}
|
22
26
|
{%- endfor %}
|
@@ -56,6 +56,7 @@ module Fronde
|
|
56
56
|
'title' => title,
|
57
57
|
'slug' => slug,
|
58
58
|
'project_path' => @project.public_absolute_path,
|
59
|
+
'project_type' => @project.type,
|
59
60
|
'domain' => Fronde::CONFIG.get('domain'),
|
60
61
|
'lang' => Fronde::CONFIG.get('lang'),
|
61
62
|
'author' => Fronde::CONFIG.get('author'),
|
@@ -81,6 +82,7 @@ module Fronde
|
|
81
82
|
'author' => Fronde::CONFIG.get('author'),
|
82
83
|
'domain' => Fronde::CONFIG.get('domain'),
|
83
84
|
'project_path' => @project.public_absolute_path,
|
85
|
+
'project_type' => @project.type,
|
84
86
|
'indexes' => indexes
|
85
87
|
)
|
86
88
|
end
|
data/lib/fronde/index.rb
CHANGED
@@ -30,26 +30,23 @@ module Fronde
|
|
30
30
|
|
31
31
|
def sort_by(kind)
|
32
32
|
accepted_values = %i[name weight]
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@tags_names[tag] + " (#{@index[tag].length})"
|
39
|
-
end.reverse
|
33
|
+
unless accepted_values.include?(kind)
|
34
|
+
error_msg = R18n.t.fronde.error.index.wrong_sort_kind(
|
35
|
+
kind: kind, accepted_values: accepted_values.inspect
|
36
|
+
)
|
37
|
+
raise ArgumentError, error_msg
|
40
38
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
sort_tags_by_name_and_weight[:"by_#{kind}"].map do |tag|
|
40
|
+
@tags_names[tag] + " (#{@index[tag].length})"
|
41
|
+
end.reverse
|
42
|
+
# Reverse in order to have most important or A near next prompt
|
43
|
+
# and avoid to scroll to find the beginning of the list.
|
45
44
|
end
|
46
45
|
|
47
46
|
class << self
|
48
|
-
def
|
47
|
+
def all_blog_index(&block)
|
49
48
|
all_blogs = CONFIG.sources.filter_map do |project|
|
50
|
-
|
51
|
-
|
52
|
-
Index.new(project)
|
49
|
+
Index.new(project) if project.blog?
|
53
50
|
end
|
54
51
|
return all_blogs unless block
|
55
52
|
|
data/lib/fronde/org/file.rb
CHANGED
@@ -118,41 +118,53 @@ module Fronde
|
|
118
118
|
#
|
119
119
|
# *** Format:
|
120
120
|
#
|
121
|
-
# - %a :: the raw author name
|
121
|
+
# - %a :: the raw author name.
|
122
122
|
# - %A :: the HTML rendering of the author name, equivalent to
|
123
|
-
# ~<span class="author">%a</span
|
123
|
+
# ~<span class="author">%a</span>~.
|
124
124
|
# - %d :: the ~:short~ date HTML representation, equivalent
|
125
|
-
# to ~<time datetime="%I">%i</time
|
126
|
-
# - %D :: the ~:full~ date and time HTML representation
|
127
|
-
# - %
|
128
|
-
#
|
129
|
-
# - %
|
130
|
-
#
|
131
|
-
# - %
|
125
|
+
# to ~<time datetime="%I">%i</time>~.
|
126
|
+
# - %D :: the ~:full~ date and time HTML representation.
|
127
|
+
# - %F :: the ~link~ HTML tag for the main Atom feed of the
|
128
|
+
# current file source.
|
129
|
+
# - %h :: the declared host/domain name, taken from the
|
130
|
+
# {Fronde::Config#settings}.
|
131
|
+
# - %i :: the raw ~:short~ date and time.
|
132
|
+
# - %I :: the raw ~:iso8601~ date and time.
|
133
|
+
# - %k :: the document keywords separated by commas.
|
134
|
+
# - %K :: the HTML list rendering of the keywords.
|
135
|
+
# - %l :: the lang of the document.
|
132
136
|
# - %L :: the license information, taken from the
|
133
|
-
# {Fronde::Config#settings}
|
134
|
-
# - %n :: the
|
135
|
-
# - %N :: the
|
136
|
-
# home on the name
|
137
|
-
# - %
|
138
|
-
# - %
|
139
|
-
# - %
|
140
|
-
# - %
|
137
|
+
# {Fronde::Config#settings}.
|
138
|
+
# - %n :: the fronde name and version.
|
139
|
+
# - %N :: the fronde name and version with a link to the project
|
140
|
+
# home on the name.
|
141
|
+
# - %o :: the theme name (~o~ as in Outfit) of the current file source.
|
142
|
+
# - %s :: the subtitle of the document (from ~#+subtitle:~).
|
143
|
+
# - %t :: the title of the document (from ~#+title:~).
|
144
|
+
# - %u :: the URL to the related published HTML document.
|
145
|
+
# - %x :: the raw description (~x~ as in eXcerpt) of the document
|
146
|
+
# (from ~#+description:~).
|
141
147
|
# - %X :: the description, enclosed in an HTML ~p~ tag, equivalent
|
142
|
-
# to ~<p>%x</p
|
148
|
+
# to ~<p>%x</p>~.
|
143
149
|
#
|
144
150
|
# @example
|
145
151
|
# org_file.format("Article written by %a the %d")
|
146
152
|
# => "Article written by Alice Smith the Wednesday 3rd July"
|
147
153
|
#
|
148
154
|
# @return [String] the given ~string~ after replacement occurs
|
149
|
-
# rubocop:disable Metrics/MethodLength
|
150
155
|
# rubocop:disable Layout/LineLength
|
151
156
|
def format(string)
|
157
|
+
project_data = @project.to_h
|
158
|
+
# NOTE: The following keycode are reserved by Org itself:
|
159
|
+
# %a (author), %c (creator), %C (input-file), %d (date),
|
160
|
+
# %e (email), %s (subtitle), %t (title), %T (timestamp),
|
161
|
+
# %v (html validation link)
|
152
162
|
string.gsub('%a', @data[:author])
|
153
163
|
.gsub('%A', "<span class=\"author\">#{@data[:author]}</span>")
|
154
164
|
.gsub('%d', @data[:date].l18n_short_date_html)
|
155
165
|
.gsub('%D', @data[:date].l18n_long_date_html)
|
166
|
+
.gsub('%F', project_data['atom_feed'] || '')
|
167
|
+
.gsub('%h', project_data['domain'] || '')
|
156
168
|
.gsub('%i', @data[:date].l18n_short_date_string)
|
157
169
|
.gsub('%I', @data[:date].xmlschema)
|
158
170
|
.gsub('%k', @data[:keywords].join(', '))
|
@@ -161,6 +173,7 @@ module Fronde
|
|
161
173
|
.gsub('%L', Fronde::CONFIG.get('license', '').gsub(/\s+/, ' ').strip)
|
162
174
|
.gsub('%n', "Fronde #{Fronde::VERSION}")
|
163
175
|
.gsub('%N', "<a href=\"https://git.umaneti.net/fronde/about/\">Fronde</a> #{Fronde::VERSION}")
|
176
|
+
.gsub('%o', project_data['theme'] || '')
|
164
177
|
.gsub('%s', @data[:subtitle])
|
165
178
|
.gsub('%t', @data[:title])
|
166
179
|
.gsub('%u', @data[:url] || '')
|
@@ -168,7 +181,6 @@ module Fronde
|
|
168
181
|
.gsub('%X', "<p>#{@data[:excerpt]}</p>")
|
169
182
|
end
|
170
183
|
# rubocop:enable Layout/LineLength
|
171
|
-
# rubocop:enable Metrics/MethodLength
|
172
184
|
|
173
185
|
# Writes the current Org::File content to the underlying file.
|
174
186
|
#
|
@@ -215,6 +227,7 @@ module Fronde
|
|
215
227
|
data['published_body'] = extract_published_body
|
216
228
|
pub_date = @data[:date]
|
217
229
|
data['published'] = pub_date.l18n_long_date_string(with_year: false)
|
230
|
+
data['published_gemini_index'] = pub_date.strftime('%Y-%m-%d')
|
218
231
|
data['published_xml'] = pub_date.xmlschema
|
219
232
|
data['updated_xml'] = @data[:updated]&.xmlschema
|
220
233
|
data
|
@@ -228,8 +241,10 @@ module Fronde
|
|
228
241
|
else
|
229
242
|
source = find_source_for_publication_file
|
230
243
|
end
|
231
|
-
|
232
|
-
|
244
|
+
return source if source
|
245
|
+
|
246
|
+
short_file = @file.sub(/^#{Dir.pwd}/, '.')
|
247
|
+
warn R18n.t.fronde.error.org_file.no_project(file: short_file)
|
233
248
|
end
|
234
249
|
|
235
250
|
def find_source_for_org_file
|
@@ -250,20 +265,17 @@ module Fronde
|
|
250
265
|
def init_empty_file
|
251
266
|
@data = {
|
252
267
|
title: @options[:title] || '', subtitle: '', excerpt: '',
|
253
|
-
date: Time.now,
|
254
268
|
author: @options[:author] || Fronde::CONFIG.get('author'),
|
255
|
-
keywords: [],
|
256
269
|
lang: @options[:lang] || Fronde::CONFIG.get('lang'),
|
257
|
-
pub_file: nil, url: nil
|
270
|
+
date: Time.now, keywords: [], pub_file: nil, url: nil
|
258
271
|
}
|
259
|
-
body = @options[:content] || ''
|
260
272
|
@data[:content] = @options[:raw_content] || <<~ORG
|
261
273
|
#+title: #{@data[:title]}
|
262
274
|
#+date: <#{@data[:date].strftime('%Y-%m-%d %a. %H:%M:%S')}>
|
263
275
|
#+author: #{@data[:author]}
|
264
276
|
#+language: #{@data[:lang]}
|
265
277
|
|
266
|
-
#{
|
278
|
+
#{@options[:content]}
|
267
279
|
ORG
|
268
280
|
end
|
269
281
|
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
using TimePatch
|
4
4
|
|
5
|
+
require_relative '../../ext/time_no_time'
|
6
|
+
|
5
7
|
module Fronde
|
6
8
|
module Org
|
7
9
|
# This module holds extracter methods for the {Fronde::Org::File}
|
@@ -14,7 +16,7 @@ module Fronde
|
|
14
16
|
def extract_data
|
15
17
|
@data = { content: ::File.read(@file), pub_file: nil, url: nil }
|
16
18
|
%i[title subtitle date author keywords lang excerpt].each do |param|
|
17
|
-
@data[param] = send("extract_#{param}"
|
19
|
+
@data[param] = send(:"extract_#{param}")
|
18
20
|
end
|
19
21
|
return unless @project
|
20
22
|
|
@@ -29,22 +31,19 @@ module Fronde
|
|
29
31
|
match = daterx.match(@data[:content])
|
30
32
|
return NilTime.new if match.nil?
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
date = Time.strptime("#{match[1]} #{time}", '%Y-%m-%d %H:%M:%S')
|
39
|
-
date.no_time = notime
|
40
|
-
date
|
34
|
+
return TimeNoTime.parse_no_time(match[1]) if match[2].nil?
|
35
|
+
|
36
|
+
Time.strptime(
|
37
|
+
"#{match[1]} #{match[2]}:#{match[3] || '00'}",
|
38
|
+
'%Y-%m-%d %H:%M:%S'
|
39
|
+
)
|
41
40
|
end
|
42
41
|
|
43
42
|
def extract_title
|
44
43
|
match = /^#\+title:(.+)$/i.match(@data[:content])
|
45
44
|
if match.nil?
|
46
45
|
# Avoid to leak absolute path
|
47
|
-
project_relative_path = @file.sub
|
46
|
+
project_relative_path = @file.sub %r{^#{Dir.pwd}/}, ''
|
48
47
|
return project_relative_path
|
49
48
|
end
|
50
49
|
match[1].strip
|
@@ -81,13 +80,17 @@ module Fronde
|
|
81
80
|
# Always return something, even when not published yet
|
82
81
|
return @data[:excerpt] unless pub_file && @project
|
83
82
|
|
84
|
-
project_type = @project
|
83
|
+
project_type = @project.type
|
85
84
|
pub_folder = Fronde::CONFIG.get("#{project_type}_public_folder")
|
86
85
|
file_name = pub_folder + pub_file
|
87
86
|
return @data[:excerpt] unless ::File.exist? file_name
|
88
87
|
|
89
88
|
return ::File.read(file_name) if project_type == 'gemini'
|
90
89
|
|
90
|
+
read_html_body file_name
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_html_body(file_name)
|
91
94
|
dom = ::File.open(file_name, 'r') { |file| Nokogiri::HTML file }
|
92
95
|
body = dom.css('div#content')
|
93
96
|
body.css('header').unlink # Remove the main title
|
data/lib/fronde/org.rb
CHANGED
@@ -55,23 +55,25 @@ module Fronde
|
|
55
55
|
# @param destination [String] where to save the org-mode tarball
|
56
56
|
# @return [String] the downloaded org-mode version
|
57
57
|
def download(destination = 'var/tmp')
|
58
|
-
# Remove version number in dest file to allow easy rake file
|
59
|
-
# task naming
|
60
|
-
dest_file = ::File.expand_path('org.tar.gz', destination)
|
61
58
|
org_last_version = last_version(force: false, cookie_dir: destination)
|
62
59
|
tarball = "org-mode-release_#{org_last_version}.tar.gz"
|
63
60
|
uri = URI("https://git.savannah.gnu.org/cgit/emacs/org-mode.git/snapshot/#{tarball}")
|
64
61
|
# Will crash on purpose if anything goes wrong
|
65
62
|
Net::HTTP.start(uri.host) do |http|
|
66
|
-
|
63
|
+
fetch_org_tarball http, Net::HTTP::Get.new(uri), destination
|
64
|
+
end
|
65
|
+
org_last_version
|
66
|
+
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
def fetch_org_tarball(http, request, destination)
|
69
|
+
# Remove version number in dest file to allow easy rake file
|
70
|
+
# task naming
|
71
|
+
dest_file = ::File.expand_path('org.tar.gz', destination)
|
72
|
+
http.request request do |response|
|
73
|
+
::File.open(dest_file, 'w') do |io|
|
74
|
+
response.read_body { |chunk| io.write chunk }
|
72
75
|
end
|
73
76
|
end
|
74
|
-
org_last_version
|
75
77
|
end
|
76
78
|
|
77
79
|
def make_org_cmd(org_dir, target, verbose: false)
|
data/lib/fronde/slug.rb
CHANGED
@@ -5,23 +5,50 @@ module Fronde
|
|
5
5
|
module Slug
|
6
6
|
class << self
|
7
7
|
def slug(title)
|
8
|
-
title.downcase
|
8
|
+
title.downcase
|
9
9
|
.encode('ascii', fallback: ->(k) { translit(k) })
|
10
|
-
.
|
10
|
+
.encode('utf-8') # Convert back to utf-8 string
|
11
|
+
.gsub(/[^\w-]/, '-')
|
12
|
+
.squeeze('-')
|
13
|
+
.delete_suffix('-')
|
11
14
|
end
|
12
15
|
|
16
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
13
18
|
def translit(char)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'
|
19
|
+
case char
|
20
|
+
when 'á', 'à', 'â', 'ä', 'ǎ', 'ã', 'å'
|
21
|
+
'a'
|
22
|
+
when 'é', 'è', 'ê', 'ë', 'ě', 'ẽ', '€'
|
23
|
+
'e'
|
24
|
+
when 'í', 'ì', 'î', 'ï', 'ǐ', 'ĩ'
|
25
|
+
'i'
|
26
|
+
when 'ó', 'ò', 'ô', 'ö', 'ǒ', 'õ', 'ø'
|
27
|
+
'o'
|
28
|
+
when 'ú', 'ù', 'û', 'ü', 'ǔ', 'ũ'
|
29
|
+
'u'
|
30
|
+
when 'ý', 'ỳ', 'ŷ', 'ÿ', 'ỹ'
|
31
|
+
'y'
|
32
|
+
when 'ç', '©', '🄯'
|
33
|
+
'c'
|
34
|
+
when 'ñ'
|
35
|
+
'n'
|
36
|
+
when 'ß'
|
37
|
+
'ss'
|
38
|
+
when 'œ'
|
39
|
+
'oe'
|
40
|
+
when 'æ'
|
41
|
+
'ae'
|
42
|
+
when '®'
|
43
|
+
'r'
|
44
|
+
when '™'
|
45
|
+
'tm'
|
46
|
+
else
|
47
|
+
'-'
|
48
|
+
end
|
24
49
|
end
|
50
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
51
|
+
# rubocop:enable Metrics/MethodLength
|
25
52
|
end
|
26
53
|
end
|
27
54
|
end
|
data/lib/fronde/source/gemini.rb
CHANGED
data/lib/fronde/source/html.rb
CHANGED
@@ -40,12 +40,12 @@ module Fronde
|
|
40
40
|
super
|
41
41
|
end
|
42
42
|
|
43
|
-
def org_default_options
|
43
|
+
def org_default_options
|
44
44
|
defaults = {
|
45
45
|
'publishing-function' => 'org-html-publish-to-html',
|
46
46
|
'html-head-include-default-style' => 't',
|
47
47
|
'html-head-include-scripts' => 't',
|
48
|
-
'html-head' => '
|
48
|
+
'html-head' => '%F',
|
49
49
|
'html-postamble' => Html.org_default_postamble
|
50
50
|
}
|
51
51
|
return defaults if @config['theme'] == 'default'
|
@@ -55,10 +55,10 @@ module Fronde
|
|
55
55
|
'html-head-include-scripts' => 'nil',
|
56
56
|
'html-head' => <<~HTMLHEAD
|
57
57
|
<link rel="stylesheet" type="text/css" media="screen"
|
58
|
-
href="
|
58
|
+
href="%h/assets/%o/css/style.css">
|
59
59
|
<link rel="stylesheet" type="text/css" media="screen"
|
60
|
-
href="
|
61
|
-
|
60
|
+
href="%h/assets/%o/css/htmlize.css">
|
61
|
+
%F
|
62
62
|
HTMLHEAD
|
63
63
|
)
|
64
64
|
end
|
data/lib/fronde/source.rb
CHANGED
@@ -147,7 +147,7 @@ module Fronde
|
|
147
147
|
|
148
148
|
def clean_config
|
149
149
|
fill_in_specific_config
|
150
|
-
@config['name'] ||= @config['path'].sub(
|
150
|
+
@config['name'] ||= @config['path'].sub(%r{^[.~]*/}, '').tr('/.', '-')
|
151
151
|
@config['title'] ||= @config['path']
|
152
152
|
@config['target'] ||= File.basename(@config['path']).delete_prefix '.'
|
153
153
|
@config['target'] = '' if @config['target'] == '.'
|
@@ -168,12 +168,16 @@ module Fronde
|
|
168
168
|
end
|
169
169
|
|
170
170
|
def render_heading
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
171
|
+
%w[head head-extra preamble postamble].each do |kind|
|
172
|
+
heading_key = "#{@config['type']}-#{kind}"
|
173
|
+
heading = @config.dig 'org-options', heading_key
|
174
|
+
next unless heading
|
175
|
+
|
176
|
+
@config['org-options'][heading_key] =
|
177
|
+
heading.gsub('%F', @config['atom_feed'])
|
178
|
+
.gsub('%h', @config['domain'])
|
179
|
+
.gsub('%o', @config['theme'])
|
180
|
+
end
|
177
181
|
end
|
178
182
|
|
179
183
|
def org_project_config
|
@@ -181,7 +185,8 @@ module Fronde
|
|
181
185
|
'base-directory' => @config['path'],
|
182
186
|
'base-extension' => 'org',
|
183
187
|
'publishing-directory' => publication_path,
|
184
|
-
'recursive' => @config['recursive']
|
188
|
+
'recursive' => @config['recursive'],
|
189
|
+
'fronde-base-uri' => "#{@config['domain']}#{public_absolute_path}"
|
185
190
|
}.merge(@config['org-options'])
|
186
191
|
exclude = @config['exclude']
|
187
192
|
attributes['exclude'] = exclude if exclude
|