fronde 0.4.0 → 0.6.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/nil_time.rb +3 -6
- data/lib/ext/time.rb +10 -17
- data/lib/ext/time_no_time.rb +27 -0
- data/lib/fronde/cli/commands.rb +18 -14
- data/lib/fronde/cli/data/fish_completion +20 -0
- data/lib/fronde/cli/data/gitignore +0 -1
- data/lib/fronde/cli/helpers.rb +0 -2
- data/lib/fronde/cli/opt_parse.rb +15 -18
- data/lib/fronde/cli/throbber.rb +35 -18
- data/lib/fronde/cli.rb +4 -3
- data/lib/fronde/config/data/org-config.el +3 -2
- data/lib/fronde/config/data/ox-fronde.el +91 -46
- 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 +1 -19
- data/lib/fronde/config/lisp.rb +14 -7
- data/lib/fronde/config.rb +47 -31
- data/lib/fronde/emacs.rb +23 -9
- data/lib/fronde/index/atom_generator.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 +10 -6
- data/lib/fronde/index.rb +19 -17
- data/lib/fronde/org/file.rb +71 -39
- data/lib/fronde/org/file_extracter.rb +23 -12
- data/lib/fronde/org.rb +14 -12
- data/lib/fronde/slug.rb +39 -12
- data/lib/fronde/source/gemini.rb +4 -9
- data/lib/fronde/source/html.rb +9 -9
- data/lib/fronde/source.rb +17 -12
- 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 +35 -51
- data/lib/fronde/version.rb +1 -1
- data/lib/tasks/cli.rake +45 -13
- data/lib/tasks/org.rake +30 -35
- data/lib/tasks/site.rake +63 -41
- data/lib/tasks/sync.rake +19 -50
- data/lib/tasks/tags.rake +2 -2
- data/locales/en.yml +143 -81
- data/locales/fr.yml +153 -89
- metadata +56 -17
- data/lib/ext/r18n.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d233f108a209e4d5a02633de060293ce6f4981393555ebf5f53f16a25f6d3d0
|
4
|
+
data.tar.gz: 9efa6cd46fc4d6d33e98bcee3e7cb1dd43a179736bafb552f6ac3e7a8c5bb8ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1c7f18af62f3fbd02be2f025c7d6305a7ea1c3751a35490eee4402de3a4aebf11c211cc3efcc4d57d0b82e99807a439ef920eb67182f0f8313905b20d89fd15
|
7
|
+
data.tar.gz: 315634038a4eb1df1c07f019894a0b86b591649f58068d771811bc0bbb92402cc03f79ada03f716caae0e8219075937d1df63ab3e6453827fadb03763203d4da
|
data/lib/ext/nil_time.rb
CHANGED
@@ -10,12 +10,9 @@ class NilTime
|
|
10
10
|
''
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def l18n_long_date_string(*)
|
18
|
-
''
|
13
|
+
%i[l18n_short_date_string l18n_long_date_string
|
14
|
+
l18n_long_date_no_year_string].each do |name|
|
15
|
+
define_method(name) { '' }
|
19
16
|
end
|
20
17
|
|
21
18
|
def l18n_short_date_html
|
data/lib/ext/time.rb
CHANGED
@@ -7,7 +7,7 @@ module TimePatch
|
|
7
7
|
#
|
8
8
|
# @return [String] the localized Time string representation
|
9
9
|
def l18n_short_date_string
|
10
|
-
|
10
|
+
I18n.l to_date
|
11
11
|
end
|
12
12
|
|
13
13
|
# Format the current Time as a HTML `time` tag showing a short date.
|
@@ -17,26 +17,19 @@ module TimePatch
|
|
17
17
|
"<time datetime=\"#{xmlschema}\">#{l18n_short_date_string}</time>"
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
# Returns the current Time instance as a localized long string.
|
21
|
+
#
|
22
|
+
# @return [String] the localized Time string representation
|
23
|
+
def l18n_long_date_string
|
24
|
+
I18n.l self, format: :long
|
22
25
|
end
|
23
26
|
|
24
|
-
# Returns the current Time instance as a localized long string
|
27
|
+
# Returns the current Time instance as a localized long string
|
28
|
+
# without year.
|
25
29
|
#
|
26
|
-
# @param with_year [Boolean] wether or not the string must contain the
|
27
|
-
# year
|
28
30
|
# @return [String] the localized Time string representation
|
29
|
-
def
|
30
|
-
|
31
|
-
long_fmt = R18n.t.fronde.index.full_date_format(
|
32
|
-
date: locale.format_date_full(self, year: with_year)
|
33
|
-
)
|
34
|
-
unless @no_time
|
35
|
-
long_fmt = R18n.t.fronde.index.full_date_with_time_format(
|
36
|
-
date: long_fmt, time: locale.time_format.delete('_').strip
|
37
|
-
)
|
38
|
-
end
|
39
|
-
locale.strftime(self, long_fmt)
|
31
|
+
def l18n_long_date_no_year_string
|
32
|
+
I18n.l self, format: :long_no_year
|
40
33
|
end
|
41
34
|
|
42
35
|
# Format the current Time as a HTML `time` tag showing a long date.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using TimePatch
|
4
|
+
|
5
|
+
# A time emulator to keep the fact that the time information was
|
6
|
+
# missing, even if it behaves as a Time object for the given date.
|
7
|
+
class TimeNoTime < Time
|
8
|
+
# Returns the current Time instance as a localized long string
|
9
|
+
# without time.
|
10
|
+
#
|
11
|
+
# @return [String] the localized Time string representation
|
12
|
+
def l18n_long_date_string
|
13
|
+
I18n.l self, format: :long_no_time
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the current Time instance as a localized long string
|
17
|
+
# without time nor year.
|
18
|
+
#
|
19
|
+
# @return [String] the localized Time string representation
|
20
|
+
def l18n_long_date_no_year_string
|
21
|
+
I18n.l self, format: :long_no_time_no_year
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse_no_time(string)
|
25
|
+
strptime("#{string} 00:00:00", '%Y-%m-%d %H:%M:%S')
|
26
|
+
end
|
27
|
+
end
|
data/lib/fronde/cli/commands.rb
CHANGED
@@ -27,13 +27,13 @@ module Fronde
|
|
27
27
|
init_rake
|
28
28
|
@rake.options.build_all = true
|
29
29
|
@rake['org:upgrade'].invoke
|
30
|
-
|
30
|
+
true
|
31
31
|
end
|
32
32
|
|
33
33
|
def fronde_build
|
34
34
|
@rake.options.build_all = true
|
35
35
|
@rake['site:build'].invoke @options[:force]
|
36
|
-
|
36
|
+
true
|
37
37
|
end
|
38
38
|
|
39
39
|
def fronde_preview
|
@@ -43,7 +43,7 @@ module Fronde
|
|
43
43
|
Helpers.launch_app_for_uri "http://127.0.0.1:#{port}/"
|
44
44
|
end
|
45
45
|
@rake['site:preview'].invoke
|
46
|
-
|
46
|
+
true
|
47
47
|
end
|
48
48
|
|
49
49
|
def fronde_open
|
@@ -58,12 +58,12 @@ module Fronde
|
|
58
58
|
cmd << '+6'
|
59
59
|
end
|
60
60
|
cmd << file_path
|
61
|
-
|
61
|
+
system(*cmd)
|
62
62
|
end
|
63
63
|
|
64
64
|
def fronde_publish
|
65
65
|
@rake['sync:push'].invoke
|
66
|
-
|
66
|
+
true
|
67
67
|
end
|
68
68
|
|
69
69
|
def fronde_help
|
@@ -71,22 +71,26 @@ module Fronde
|
|
71
71
|
@command = @argv.shift || 'basic' if @command == 'help'
|
72
72
|
cmd_opt = OptParse.command_options(@command)
|
73
73
|
label = cmd_opt[:label] || @command
|
74
|
-
|
74
|
+
output = [format_label(I18n.t('fronde.bin.usage', label:))]
|
75
75
|
cmd = cmd_opt[:name] || @command
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
warn body unless body == ''
|
81
|
-
0
|
76
|
+
output << format_label(I18n.t("fronde.bin.commands.#{cmd}"))
|
77
|
+
output << OptParse.help_command_body(cmd)
|
78
|
+
puts output.join
|
79
|
+
true
|
82
80
|
end
|
83
81
|
|
84
82
|
private
|
85
83
|
|
84
|
+
def format_label(label)
|
85
|
+
return '' if label == '' || label.start_with?('Translation missing:')
|
86
|
+
|
87
|
+
format("%<label>s\n\n", label:)
|
88
|
+
end
|
89
|
+
|
86
90
|
def file_name_from_title
|
87
|
-
title = @options[:title] ||
|
91
|
+
title = @options[:title] || I18n.t('fronde.bin.options.default_title')
|
88
92
|
# No title, nor a reliable file_path? Better abort
|
89
|
-
raise
|
93
|
+
raise I18n.t('fronde.error.bin.no_file') if title == ''
|
90
94
|
|
91
95
|
"#{Fronde::Slug.slug(title)}.org"
|
92
96
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
function __fronde_main_commands
|
2
|
+
echo {{ comcomp }}
|
3
|
+
end
|
4
|
+
|
5
|
+
function __fronde_no_command_yet
|
6
|
+
set -f cmd (__fish_print_cmd_args_without_options)
|
7
|
+
{%- for com in commands %}
|
8
|
+
{% unless forloop.first %}and {% endunless %}not contains {{ com }} $cmd
|
9
|
+
{%- endfor %}
|
10
|
+
end
|
11
|
+
|
12
|
+
complete -c fronde -e
|
13
|
+
complete -c fronde -f
|
14
|
+
complete -c fronde -x -n '__fronde_no_command_yet' -a '(__fronde_main_commands)'
|
15
|
+
complete -c fronde -n 'contains help (__fish_print_cmd_args_without_options)' -a '{{ commands | join ' ' }}'
|
16
|
+
complete -c fronde -n 'contains new (__fish_print_cmd_args_without_options)' -F
|
17
|
+
complete -c fronde -n 'contains open (__fish_print_cmd_args_without_options)' -F
|
18
|
+
{%- for compopt in details %}
|
19
|
+
complete -c fronde{% unless compopt.command == 'basic' %} -n 'contains {{ compopt.command }} (__fish_print_cmd_args_without_options)'{% endunless %} -s {{ compopt.short_no_dash }} -l {{ compopt.long_no_dash }}{% if compopt.keyword %} -r{% endif %}{% if compopt.choices %} -a '{{ compopt.choices | join ' ' }}'{% endif %} -d {% if compopt.help %}'{{ compopt.help }}'{% else %}{{ compopt.long_no_dash | capitalize }}{% endif %}
|
20
|
+
{%- endfor %}
|
data/lib/fronde/cli/helpers.rb
CHANGED
data/lib/fronde/cli/opt_parse.rb
CHANGED
@@ -10,13 +10,13 @@ module Fronde
|
|
10
10
|
'-a' => { long: 'author' },
|
11
11
|
'-f' => { long: 'force', boolean: true },
|
12
12
|
'-h' => { long: 'help', boolean: true, method: :on_tail,
|
13
|
-
help:
|
13
|
+
help: I18n.t('fronde.bin.options.help') },
|
14
14
|
'-l' => { long: 'lang', keyword: 'LOCALE' },
|
15
15
|
'-o' => { long: 'output', keyword: 'FORMAT', choices: %w[gemini html] },
|
16
16
|
'-t' => { long: 'title' },
|
17
17
|
'-v' => { long: 'verbose', boolean: true, method: :on_tail },
|
18
18
|
'-V' => { long: 'version', boolean: true, method: :on_tail,
|
19
|
-
help:
|
19
|
+
help: I18n.t('fronde.bin.options.version') }
|
20
20
|
}.freeze
|
21
21
|
|
22
22
|
# TODO: jekyll new [path] / jekyll build / jekyll clean / jekyll serve
|
@@ -28,13 +28,13 @@ module Fronde
|
|
28
28
|
FRONDE_COMMANDS = {
|
29
29
|
'new' => { opts: ['-a', '-l', '-o', '-t', '-v'], label: 'new <path>' },
|
30
30
|
'init' => { alias: 'new' },
|
31
|
-
'update' => {},
|
31
|
+
'update' => { opts: ['-v'] },
|
32
32
|
'config' => { alias: 'update' },
|
33
33
|
'preview' => {},
|
34
|
-
'open' => { opts: ['-a', '-l', '-t'
|
34
|
+
'open' => { opts: ['-a', '-l', '-t'], label: 'open <path>' },
|
35
35
|
'edit' => { alias: 'open' },
|
36
|
-
'build' => { opts: ['-f'] },
|
37
|
-
'publish' => {},
|
36
|
+
'build' => { opts: ['-f', '-v'] },
|
37
|
+
'publish' => { opts: ['-v'] },
|
38
38
|
'help' => {},
|
39
39
|
'basic' => { opts: ['-h', '-V'], label: '<command>' }
|
40
40
|
}.freeze
|
@@ -59,11 +59,10 @@ module Fronde
|
|
59
59
|
config = [short, long]
|
60
60
|
else
|
61
61
|
key = opt[:keyword] || opt[:long].upcase
|
62
|
-
config = [short, format('%<long>s %<key>s', long
|
62
|
+
config = [short, format('%<long>s %<key>s', long:, key:)]
|
63
63
|
end
|
64
|
-
config
|
65
|
-
config
|
66
|
-
config
|
64
|
+
config.push opt[:choices], opt[:help]
|
65
|
+
config.compact
|
67
66
|
end
|
68
67
|
|
69
68
|
# Returns the ~fronde~ help summary for a given command.
|
@@ -76,12 +75,10 @@ module Fronde
|
|
76
75
|
short, long = decorate_option(k)
|
77
76
|
opt = FRONDE_OPTIONS[k]
|
78
77
|
label = [short, long].join(', ')
|
79
|
-
line = [format(' %<opt>s', opt: label).ljust(30)]
|
80
|
-
help = opt[:help]
|
81
|
-
line << help if help
|
78
|
+
line = [format(' %<opt>s', opt: label).ljust(30), opt[:help]]
|
82
79
|
choices = opt[:choices]
|
83
80
|
line << "(#{choices.join(', ')})" if choices
|
84
|
-
line.join(' ')
|
81
|
+
line.compact.join(' ')
|
85
82
|
end.join("\n")
|
86
83
|
end
|
87
84
|
|
@@ -89,9 +86,9 @@ module Fronde
|
|
89
86
|
command_opts_doc = summarize_command(command)
|
90
87
|
return '' if command_opts_doc == ''
|
91
88
|
|
92
|
-
body = [
|
89
|
+
body = [I18n.t('fronde.bin.options.cmd_title'), command_opts_doc]
|
93
90
|
if command == 'basic'
|
94
|
-
body += ['',
|
91
|
+
body += ['', I18n.t('fronde.bin.commands.cmd_title'), list_commands]
|
95
92
|
end
|
96
93
|
body.join("\n")
|
97
94
|
end
|
@@ -105,9 +102,9 @@ module Fronde
|
|
105
102
|
|
106
103
|
line = [' ', cmd.ljust(10)]
|
107
104
|
if opt.has_key? :alias
|
108
|
-
line <<
|
105
|
+
line << I18n.t('fronde.bin.commands.alias', alias: opt[:alias])
|
109
106
|
else
|
110
|
-
line <<
|
107
|
+
line << I18n.t("fronde.bin.commands.#{cmd}")
|
111
108
|
end
|
112
109
|
line.join(' ')
|
113
110
|
end.join("\n")
|
data/lib/fronde/cli/throbber.rb
CHANGED
@@ -21,6 +21,7 @@ module Fronde
|
|
21
21
|
|
22
22
|
def initialize(thread, message)
|
23
23
|
@frames = select_frames
|
24
|
+
@term_width = terminal_width
|
24
25
|
@thread = thread
|
25
26
|
@thread.abort_on_exception = false
|
26
27
|
@thread.report_on_exception = false
|
@@ -28,23 +29,17 @@ module Fronde
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def run
|
31
|
-
|
32
|
-
frames_len = @frames.length
|
33
|
-
current = 0
|
34
|
-
while @thread.alive?
|
35
|
-
sleep 0.1
|
36
|
-
frame = @frames[current % frames_len]
|
37
|
-
message = "#{@message} #{frame}"
|
38
|
-
print "#{message.ljust(term_width)}\r"
|
39
|
-
current += 1
|
40
|
-
end
|
41
|
-
@thread.join # Ensure any inner exception is re-raised
|
32
|
+
thread_loop
|
42
33
|
rescue RuntimeError => e
|
43
34
|
show_error
|
44
35
|
raise e
|
36
|
+
# :nocov: not sure how to emulate a Ctrl+c in rspec
|
37
|
+
rescue Interrupt => e
|
38
|
+
show_message Rainbow(I18n.t('fronde.bin.interrupted')).red, "\n"
|
39
|
+
raise e
|
40
|
+
# :nocov:
|
45
41
|
else
|
46
|
-
|
47
|
-
puts "#{@message} #{done}".ljust(term_width)
|
42
|
+
show_message Rainbow(I18n.t('fronde.bin.done')).green, "\n"
|
48
43
|
end
|
49
44
|
|
50
45
|
class << self
|
@@ -61,15 +56,32 @@ module Fronde
|
|
61
56
|
#
|
62
57
|
# @param thread [Thread] the long-running operation to decorate
|
63
58
|
# @param message [String] the message to display before the throbber
|
59
|
+
# @param verbose [Boolean] whether the decoration should be shown
|
60
|
+
# or skipped
|
64
61
|
# @return [void]
|
65
|
-
def run(thread, message)
|
66
|
-
|
67
|
-
|
62
|
+
def run(thread, message, verbose)
|
63
|
+
if verbose
|
64
|
+
thread.join
|
65
|
+
else
|
66
|
+
throbber = new(thread, message)
|
67
|
+
throbber.run
|
68
|
+
end
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
72
|
private
|
72
73
|
|
74
|
+
def thread_loop
|
75
|
+
frames_len = @frames.length
|
76
|
+
current = 0
|
77
|
+
while @thread.alive?
|
78
|
+
sleep 0.1
|
79
|
+
show_message @frames[current % frames_len]
|
80
|
+
current += 1
|
81
|
+
end
|
82
|
+
@thread.join # Ensure any inner exception is re-raised
|
83
|
+
end
|
84
|
+
|
73
85
|
def terminal_width
|
74
86
|
# Not a tty. Docker?
|
75
87
|
return 0 unless system('test -t 0')
|
@@ -77,13 +89,18 @@ module Fronde
|
|
77
89
|
`stty size`.strip.split[1].to_i - 1
|
78
90
|
end
|
79
91
|
|
92
|
+
def show_message(suffix, end_of_line = "\r")
|
93
|
+
message = "#{@message} #{suffix}".ljust(@term_width)
|
94
|
+
print "#{message}#{end_of_line}"
|
95
|
+
end
|
96
|
+
|
80
97
|
def show_error
|
81
98
|
warn(
|
82
99
|
format(
|
83
100
|
"%<message>s %<label>s\n%<explanation>s",
|
84
101
|
message: @message,
|
85
|
-
label: Rainbow(
|
86
|
-
explanation: Rainbow(
|
102
|
+
label: Rainbow(I18n.t('fronde.error.bin.label')).bold.red,
|
103
|
+
explanation: Rainbow(I18n.t('fronde.error.bin.explanation')).bold
|
87
104
|
)
|
88
105
|
)
|
89
106
|
end
|
data/lib/fronde/cli.rb
CHANGED
@@ -21,12 +21,13 @@ module Fronde
|
|
21
21
|
|
22
22
|
if help_param_given?
|
23
23
|
return 2 if @options[:recover_from_error]
|
24
|
-
|
24
|
+
|
25
|
+
return true
|
25
26
|
end
|
26
27
|
|
27
28
|
init_rake if %w[build preview publish].include?(@command)
|
28
29
|
|
29
|
-
method = "fronde_#{@command}"
|
30
|
+
method = :"fronde_#{@command}"
|
30
31
|
return 2 if method_unknown?(method)
|
31
32
|
|
32
33
|
send method
|
@@ -50,7 +51,7 @@ module Fronde
|
|
50
51
|
def method_unknown?(method)
|
51
52
|
return false if respond_to?(method)
|
52
53
|
|
53
|
-
warn
|
54
|
+
warn I18n.t('fronde.error.bin.no_command')
|
54
55
|
fronde_help
|
55
56
|
true
|
56
57
|
end
|
@@ -4,8 +4,9 @@
|
|
4
4
|
(load-file (expand-file-name "htmlize.el" "{{ work_dir }}/lib"))
|
5
5
|
|
6
6
|
;; Current project options
|
7
|
-
(setq fronde
|
8
|
-
fronde
|
7
|
+
(setq fronde-version "{{ version }}"
|
8
|
+
fronde-current-work-dir "{{ work_dir }}"
|
9
|
+
fronde-domain "{{ domain }}"
|
9
10
|
user-mail-address "{{ author.email }}"
|
10
11
|
user-full-name "{{ author.name }}"
|
11
12
|
org-html-metadata-timestamp-format "{{ long_date_fmt }}"
|
@@ -34,87 +34,132 @@
|
|
34
34
|
|
35
35
|
;;; Function Declarations
|
36
36
|
|
37
|
-
(defvar fronde
|
38
|
-
"Version of the current fronde installation")
|
37
|
+
(defvar fronde-version ""
|
38
|
+
"Version of the current fronde installation.")
|
39
39
|
|
40
|
-
(defvar fronde
|
40
|
+
(defvar fronde-current-work-dir nil
|
41
41
|
"Location of the current fronde website base directory.")
|
42
42
|
|
43
|
-
(defvar fronde
|
44
|
-
"
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
(defvar fronde-domain ""
|
44
|
+
"Target domain with scheme of the current fronde installation.")
|
45
|
+
|
46
|
+
(defvar fronde-org-temp-dir nil
|
47
|
+
"Location of the local Org temporary directory.
|
48
|
+
This is where to place org timestamps and id locations.")
|
49
|
+
|
50
|
+
(defvar fronde--keywords-slugs-alist nil
|
51
|
+
"A list associating each keywords to its related slug.
|
52
|
+
|
53
|
+
Can be hydrated with `fronde--build-keywords-list'.")
|
54
|
+
|
55
|
+
(defun fronde--build-keywords-list ()
|
56
|
+
(let ((keywords-file (format "%s/keywords" fronde-org-temp-dir))
|
57
|
+
keywords-slugs)
|
58
|
+
(when (file-readable-p keywords-file)
|
59
|
+
(let ((content (with-temp-buffer
|
60
|
+
(insert-file-contents keywords-file)
|
61
|
+
(string-trim-right (buffer-string)))))
|
62
|
+
(mapcar
|
63
|
+
(lambda (line)
|
64
|
+
(push (split-string line "\x1f") keywords-slugs))
|
65
|
+
(split-string content "\x1e"))))
|
66
|
+
keywords-slugs))
|
67
|
+
|
68
|
+
(defun fronde--format-rich-keywords (info function)
|
69
|
+
"Extract keywords from INFO and apply FUNCTION on them.
|
70
|
+
FUNCTION is expected to format each keyword for a rich display for the
|
71
|
+
current export backend. FUNCTION must receive 3 arguments: the current
|
72
|
+
KEYWORD, its related SLUG and the current project BASE-URI."
|
73
|
+
(let ((base-uri (plist-get info :fronde-base-uri)))
|
74
|
+
(mapcar
|
75
|
+
(lambda (k)
|
76
|
+
(let ((slug (cadr (assoc k fronde--keywords-slugs-alist))))
|
77
|
+
(funcall function k slug base-uri)))
|
78
|
+
(split-string
|
79
|
+
(org-export-data (plist-get info :keywords) info)
|
80
|
+
",+ *"))))
|
81
|
+
|
82
|
+
(defun fronde--org-html-format-spec (upstream info)
|
83
|
+
"Advise UPSTREAM to return format specification for preamble and postamble.
|
49
84
|
INFO is a plist used as a communication channel."
|
50
85
|
(let ((output (funcall upstream info)))
|
51
86
|
(push `(?A . ,(format "<span class=\"author\">%s</span>"
|
52
87
|
(org-export-data (plist-get info :author) info)))
|
53
|
-
|
88
|
+
output)
|
54
89
|
(push `(?k . ,(org-export-data (plist-get info :keywords) info)) output)
|
55
|
-
(push `(?K . ,(format "<ul class=\"keywords-list\"
|
56
|
-
(
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
90
|
+
(push `(?K . ,(format "<ul class=\"keywords-list\">\n%s</ul>"
|
91
|
+
(apply #'concat
|
92
|
+
(fronde--format-rich-keywords
|
93
|
+
info
|
94
|
+
(lambda (k slug base-uri)
|
95
|
+
(format "<li class=\"keyword\"><a href=\"%stags/%s.html\">%s</a></li>\n"
|
96
|
+
base-uri slug k))))))
|
97
|
+
output)
|
61
98
|
(push `(?l . ,(org-export-data (plist-get info :language) info)) output)
|
62
|
-
(push `(?n . ,(format "Fronde %s" fronde
|
63
|
-
(push `(?N . ,(format "<a href=\"https://etienne.depar.is/fronde/\">Fronde</a> %s" fronde
|
99
|
+
(push `(?n . ,(format "Fronde %s" fronde-version)) output)
|
100
|
+
(push `(?N . ,(format "<a href=\"https://etienne.depar.is/fronde/\">Fronde</a> %s" fronde-version)) output)
|
64
101
|
(push `(?x . ,(org-export-data (plist-get info :description) info)) output)
|
65
102
|
(push `(?X . ,(format "<p>%s</p>"
|
66
103
|
(org-export-data (plist-get info :description) info)))
|
67
|
-
|
104
|
+
output)))
|
68
105
|
|
69
|
-
(defun fronde
|
70
|
-
"
|
106
|
+
(defun fronde--org-gmi-format-spec (upstream info)
|
107
|
+
"Advise UPSTREAM to return format specification for gemini postamble.
|
71
108
|
INFO is a plist used as a communication channel."
|
72
109
|
(let ((output (funcall upstream info)))
|
73
|
-
(push `(?
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
110
|
+
(push `(?K . ,(org-gmi--build-links-list
|
111
|
+
(fronde--format-rich-keywords
|
112
|
+
info
|
113
|
+
(lambda (k slug base-uri)
|
114
|
+
(list (format "%stags/%s.gmi" base-uri slug)
|
115
|
+
(format "🏷️ %s" k))))))
|
116
|
+
output)
|
117
|
+
(push `(?n . ,(format "Fronde %s" fronde-version)) output)))
|
118
|
+
|
119
|
+
(defun fronde--org-i18n-export (link description backend)
|
120
|
+
"Export the given i18n LINK with its DESCRIPTION for the current BACKEND."
|
121
|
+
(let* ((splitted-link (split-string link "::"))
|
78
122
|
(path (car splitted-link))
|
79
123
|
(desc (or description path))
|
80
124
|
(lang (cadr splitted-link)))
|
81
|
-
(pcase
|
125
|
+
(pcase backend
|
82
126
|
(`html (if lang
|
83
127
|
(format "<a href=\"%s\" hreflang=\"%s\">%s</a>"
|
84
128
|
path lang desc)
|
85
129
|
(format "<a href=\"%s\">%s</a>" path desc)))
|
86
|
-
(
|
87
|
-
(_ (format "%s (%s)" desc path)))))
|
130
|
+
(_ nil))))
|
88
131
|
|
89
|
-
(defun fronde
|
90
|
-
"Visit
|
91
|
-
(browse-url (car (split-string link "
|
132
|
+
(defun fronde--org-i18n-follow (link)
|
133
|
+
"Visit the given i18n LINK."
|
134
|
+
(browse-url (car (split-string link "::"))))
|
92
135
|
|
93
136
|
(org-link-set-parameters "i18n"
|
94
|
-
:export #'fronde
|
95
|
-
:follow #'fronde
|
137
|
+
:export #'fronde--org-i18n-export
|
138
|
+
:follow #'fronde--org-i18n-follow)
|
96
139
|
|
97
140
|
|
98
141
|
;;; Set configuration options
|
99
142
|
|
100
|
-
(setq fronde
|
101
|
-
|
102
|
-
org-
|
143
|
+
(setq fronde-org-temp-dir (expand-file-name "var/tmp" fronde-current-work-dir)
|
144
|
+
fronde--keywords-slugs-alist (fronde--build-keywords-list)
|
145
|
+
org-publish-timestamp-directory (expand-file-name "timestamps/" fronde-org-temp-dir)
|
146
|
+
org-id-locations-file (expand-file-name "id-locations.el" fronde-org-temp-dir)
|
103
147
|
make-backup-files nil
|
104
|
-
enable-local-variables
|
105
|
-
|
148
|
+
enable-dir-local-variables nil
|
149
|
+
enable-local-variables t ;; enforce default
|
150
|
+
org-confirm-babel-evaluate t ;; enforce default
|
106
151
|
org-export-with-broken-links t
|
107
152
|
org-html-doctype "html5"
|
108
153
|
org-html-html5-fancy t
|
109
154
|
org-html-htmlize-output-type 'css
|
110
155
|
org-html-text-markup-alist '((bold . "<strong>%s</strong>")
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
(advice-add 'org-html-format-spec :around #'fronde
|
117
|
-
(advice-add 'org-gmi--format-spec :around #'fronde
|
156
|
+
(code . "<code>%s</code>")
|
157
|
+
(italic . "<em>%s</em>")
|
158
|
+
(strike-through . "<del>%s</del>")
|
159
|
+
(underline . "<span class=\"underline\">%s</span>")
|
160
|
+
(verbatim . "<code>%s</code>")))
|
161
|
+
(advice-add 'org-html-format-spec :around #'fronde--org-html-format-spec)
|
162
|
+
(advice-add 'org-gmi--format-spec :around #'fronde--org-gmi-format-spec)
|
118
163
|
|
119
164
|
(provide 'ox-fronde)
|
120
165
|
|