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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8691e788789cb725772213237a67731dc67ae77eeecc8d1d409e6779d94a22c8
|
4
|
+
data.tar.gz: d2f67191b421f902e1b41d7845fc07026843e227cfd3f70cdeff0f4d87e36b8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8d3fa0a8bbfbcdecbf7a65ffc93b420876ddb27acf574a5a1a066b988ce2e039ff780b0a71bd6056f3a75b52072f4c37489135a6ead712e0a728f8385453de2
|
7
|
+
data.tar.gz: d2bd28e4fa15b156a83c61b79426f74e3e48534cfe483f92a03dd3d9a4a0675252843bb991bbb114f45421865b52e6b7f6f7dd500261cc0d8236063838f7baf4
|
data/lib/ext/r18n.rb
CHANGED
@@ -13,5 +13,25 @@ module R18nPatch
|
|
13
13
|
date: date_fmt, time: time_fmt
|
14
14
|
)
|
15
15
|
end
|
16
|
+
|
17
|
+
# Returns the given Time instance as a localized long string.
|
18
|
+
#
|
19
|
+
# @param time [Time] the Time instance to format
|
20
|
+
# @param with_year [Boolean] whether or not the string must contain
|
21
|
+
# the year
|
22
|
+
# @param with_time [Boolean] whether or not the string must contain
|
23
|
+
# the time
|
24
|
+
# @return [String] the localized Time string representation
|
25
|
+
def long_date_string(time, with_year: true, with_time: true)
|
26
|
+
long_fmt = fronde.index.full_date_format(
|
27
|
+
date: @locale.format_date_full(time, year: with_year)
|
28
|
+
)
|
29
|
+
if with_time
|
30
|
+
long_fmt = fronde.index.full_date_with_time_format(
|
31
|
+
date: long_fmt, time: @locale.time_format.delete('_').strip
|
32
|
+
)
|
33
|
+
end
|
34
|
+
@locale.strftime(time, long_fmt)
|
35
|
+
end
|
16
36
|
end
|
17
37
|
end
|
data/lib/ext/time.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'r18n'
|
4
|
+
using R18nPatch
|
5
|
+
|
3
6
|
# Monkey patch to add some helpers
|
4
7
|
module TimePatch
|
5
8
|
refine Time do
|
@@ -17,26 +20,13 @@ module TimePatch
|
|
17
20
|
"<time datetime=\"#{xmlschema}\">#{l18n_short_date_string}</time>"
|
18
21
|
end
|
19
22
|
|
20
|
-
def no_time=(value)
|
21
|
-
@no_time = value
|
22
|
-
end
|
23
|
-
|
24
23
|
# Returns the current Time instance as a localized long string.
|
25
24
|
#
|
26
|
-
# @param with_year [Boolean]
|
27
|
-
# year
|
25
|
+
# @param with_year [Boolean] whether or not the string must contain
|
26
|
+
# the year
|
28
27
|
# @return [String] the localized Time string representation
|
29
28
|
def l18n_long_date_string(with_year: true)
|
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)
|
29
|
+
R18n.t.long_date_string(self, with_year: with_year)
|
40
30
|
end
|
41
31
|
|
42
32
|
# Format the current Time as a HTML `time` tag showing a long date.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'r18n'
|
4
|
+
using R18nPatch
|
5
|
+
|
6
|
+
using TimePatch
|
7
|
+
|
8
|
+
# A time emulator to keep the fact that the time information was
|
9
|
+
# missing, even if it behaves as a Time object for the given date.
|
10
|
+
class TimeNoTime < Time
|
11
|
+
# Returns the current Time instance as a localized long string.
|
12
|
+
#
|
13
|
+
# @param with_year [Boolean] wether or not the string must contain the
|
14
|
+
# year
|
15
|
+
# @return [String] the localized Time string representation
|
16
|
+
def l18n_long_date_string(with_year: true)
|
17
|
+
R18n.t.long_date_string(self, with_year: with_year, with_time: false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parse_no_time(string)
|
21
|
+
strptime("#{string} 00:00:00", '%Y-%m-%d %H:%M:%S')
|
22
|
+
end
|
23
|
+
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,18 +71,22 @@ 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(R18n.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(R18n.t.fronde.bin.commands[cmd])
|
77
|
+
output << OptParse.help_command_body(cmd)
|
78
|
+
warn output.join
|
79
|
+
true
|
82
80
|
end
|
83
81
|
|
84
82
|
private
|
85
83
|
|
84
|
+
def format_label(label)
|
85
|
+
return '' if label == '' || label.is_a?(R18n::Untranslated)
|
86
|
+
|
87
|
+
format("%<label>s\n\n", label: label)
|
88
|
+
end
|
89
|
+
|
86
90
|
def file_name_from_title
|
87
91
|
title = @options[:title] || R18n.t.fronde.bin.options.default_title
|
88
92
|
# No title, nor a reliable file_path? Better abort
|
data/lib/fronde/cli/opt_parse.rb
CHANGED
@@ -61,9 +61,8 @@ module Fronde
|
|
61
61
|
key = opt[:keyword] || opt[:long].upcase
|
62
62
|
config = [short, format('%<long>s %<key>s', long: long, key: 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
|
|
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(R18n.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(R18n.t.fronde.bin.done).green, "\n"
|
48
43
|
end
|
49
44
|
|
50
45
|
class << self
|
@@ -70,6 +65,17 @@ module Fronde
|
|
70
65
|
|
71
66
|
private
|
72
67
|
|
68
|
+
def thread_loop
|
69
|
+
frames_len = @frames.length
|
70
|
+
current = 0
|
71
|
+
while @thread.alive?
|
72
|
+
sleep 0.1
|
73
|
+
show_message @frames[current % frames_len]
|
74
|
+
current += 1
|
75
|
+
end
|
76
|
+
@thread.join # Ensure any inner exception is re-raised
|
77
|
+
end
|
78
|
+
|
73
79
|
def terminal_width
|
74
80
|
# Not a tty. Docker?
|
75
81
|
return 0 unless system('test -t 0')
|
@@ -77,6 +83,11 @@ module Fronde
|
|
77
83
|
`stty size`.strip.split[1].to_i - 1
|
78
84
|
end
|
79
85
|
|
86
|
+
def show_message(suffix, end_of_line = "\r")
|
87
|
+
message = "#{@message} #{suffix}".ljust(@term_width)
|
88
|
+
print "#{message}#{end_of_line}"
|
89
|
+
end
|
90
|
+
|
80
91
|
def show_error
|
81
92
|
warn(
|
82
93
|
format(
|
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
|
@@ -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,72 +34,109 @@
|
|
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
|
+
(defun fronde--format-rich-keywords (info function)
|
51
|
+
"Extract keywords from INFO and apply FUNCTION on them.
|
52
|
+
FUNCTION is expected to format each keyword for a rich display for the
|
53
|
+
current export backend. FUNCTION must receive 3 arguments: the current
|
54
|
+
KEYWORD, its related SLUG and the current project BASE-URI."
|
55
|
+
(let ((base-uri (plist-get info :fronde-base-uri))
|
56
|
+
(current-path (symbol-file 'fronde--format-rich-keywords))
|
57
|
+
sluglib)
|
58
|
+
(when current-path
|
59
|
+
(setq sluglib
|
60
|
+
(expand-file-name
|
61
|
+
(format "%s../../slug" (file-name-directory current-path)))))
|
62
|
+
(mapcar
|
63
|
+
(lambda (k)
|
64
|
+
(let ((slug (if sluglib
|
65
|
+
(string-trim-right
|
66
|
+
(shell-command-to-string
|
67
|
+
(format "ruby -r %s -e \"puts Fronde::Slug.slug '%s'\""
|
68
|
+
(shell-quote-argument sluglib)
|
69
|
+
(shell-quote-argument k))))
|
70
|
+
k)))
|
71
|
+
(funcall function k slug base-uri)))
|
72
|
+
(split-string
|
73
|
+
(org-export-data (plist-get info :keywords) info)
|
74
|
+
",+ *"))))
|
75
|
+
|
76
|
+
(defun fronde--org-html-format-spec (upstream info)
|
77
|
+
"Advise UPSTREAM to return format specification for preamble and postamble.
|
49
78
|
INFO is a plist used as a communication channel."
|
50
79
|
(let ((output (funcall upstream info)))
|
51
80
|
(push `(?A . ,(format "<span class=\"author\">%s</span>"
|
52
81
|
(org-export-data (plist-get info :author) info)))
|
53
82
|
output)
|
54
83
|
(push `(?k . ,(org-export-data (plist-get info :keywords) info)) output)
|
55
|
-
(push `(?K . ,(format "<ul class=\"keywords-list\"
|
56
|
-
(
|
57
|
-
|
58
|
-
|
59
|
-
|
84
|
+
(push `(?K . ,(format "<ul class=\"keywords-list\">\n%s</ul>"
|
85
|
+
(apply #'concat
|
86
|
+
(fronde--format-rich-keywords
|
87
|
+
info
|
88
|
+
(lambda (k slug base-uri)
|
89
|
+
(format "<li class=\"keyword\"><a href=\"%stags/%s.html\">%s</a></li>\n"
|
90
|
+
base-uri slug k))))))
|
60
91
|
output)
|
61
92
|
(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
|
93
|
+
(push `(?n . ,(format "Fronde %s" fronde-version)) output)
|
94
|
+
(push `(?N . ,(format "<a href=\"https://etienne.depar.is/fronde/\">Fronde</a> %s" fronde-version)) output)
|
64
95
|
(push `(?x . ,(org-export-data (plist-get info :description) info)) output)
|
65
96
|
(push `(?X . ,(format "<p>%s</p>"
|
66
97
|
(org-export-data (plist-get info :description) info)))
|
67
98
|
output)))
|
68
99
|
|
69
|
-
(defun fronde
|
70
|
-
"
|
100
|
+
(defun fronde--org-gmi-format-spec (upstream info)
|
101
|
+
"Advise UPSTREAM to return format specification for gemini postamble.
|
71
102
|
INFO is a plist used as a communication channel."
|
72
103
|
(let ((output (funcall upstream info)))
|
73
|
-
(push `(?
|
104
|
+
(push `(?K . ,(org-gmi--build-links-list
|
105
|
+
(fronde--format-rich-keywords
|
106
|
+
info
|
107
|
+
(lambda (k slug base-uri)
|
108
|
+
(list (format "%stags/%s.gmi" base-uri slug)
|
109
|
+
(format "🏷️ %s" k))))))
|
110
|
+
output)
|
111
|
+
(push `(?n . ,(format "Fronde %s" fronde-version)) output)))
|
74
112
|
|
75
|
-
(defun fronde
|
76
|
-
"Export
|
77
|
-
(let* ((splitted-link (split-string link "
|
113
|
+
(defun fronde--org-i18n-export (link description backend)
|
114
|
+
"Export the given i18n LINK with its DESCRIPTION for the current BACKEND."
|
115
|
+
(let* ((splitted-link (split-string link "::"))
|
78
116
|
(path (car splitted-link))
|
79
117
|
(desc (or description path))
|
80
118
|
(lang (cadr splitted-link)))
|
81
|
-
(pcase
|
119
|
+
(pcase backend
|
82
120
|
(`html (if lang
|
83
121
|
(format "<a href=\"%s\" hreflang=\"%s\">%s</a>"
|
84
122
|
path lang desc)
|
85
123
|
(format "<a href=\"%s\">%s</a>" path desc)))
|
86
|
-
(
|
87
|
-
(_ (format "%s (%s)" desc path)))))
|
124
|
+
(_ nil))))
|
88
125
|
|
89
|
-
(defun fronde
|
90
|
-
"Visit
|
91
|
-
(browse-url (car (split-string link "
|
126
|
+
(defun fronde--org-i18n-follow (link)
|
127
|
+
"Visit the given i18n LINK."
|
128
|
+
(browse-url (car (split-string link "::"))))
|
92
129
|
|
93
130
|
(org-link-set-parameters "i18n"
|
94
|
-
:export #'fronde
|
95
|
-
:follow #'fronde
|
131
|
+
:export #'fronde--org-i18n-export
|
132
|
+
:follow #'fronde--org-i18n-follow)
|
96
133
|
|
97
134
|
|
98
135
|
;;; Set configuration options
|
99
136
|
|
100
|
-
(setq fronde
|
101
|
-
org-publish-timestamp-directory (expand-file-name "timestamps/" fronde
|
102
|
-
org-id-locations-file (expand-file-name "id-locations.el" fronde
|
137
|
+
(setq fronde-org-temp-dir (expand-file-name "var/tmp" fronde-current-work-dir)
|
138
|
+
org-publish-timestamp-directory (expand-file-name "timestamps/" fronde-org-temp-dir)
|
139
|
+
org-id-locations-file (expand-file-name "id-locations.el" fronde-org-temp-dir)
|
103
140
|
make-backup-files nil
|
104
141
|
enable-local-variables :all
|
105
142
|
org-confirm-babel-evaluate nil
|
@@ -113,8 +150,8 @@ INFO is a plist used as a communication channel."
|
|
113
150
|
(strike-through . "<del>%s</del>")
|
114
151
|
(underline . "<span class=\"underline\">%s</span>")
|
115
152
|
(verbatim . "<code>%s</code>")))
|
116
|
-
(advice-add 'org-html-format-spec :around #'fronde
|
117
|
-
(advice-add 'org-gmi--format-spec :around #'fronde
|
153
|
+
(advice-add 'org-html-format-spec :around #'fronde--org-html-format-spec)
|
154
|
+
(advice-add 'org-gmi--format-spec :around #'fronde--org-gmi-format-spec)
|
118
155
|
|
119
156
|
(provide 'ox-fronde)
|
120
157
|
|