fronde 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ext/r18n.rb +20 -0
  3. data/lib/ext/time.rb +6 -16
  4. data/lib/ext/time_no_time.rb +23 -0
  5. data/lib/fronde/cli/commands.rb +16 -12
  6. data/lib/fronde/cli/data/gitignore +0 -1
  7. data/lib/fronde/cli/opt_parse.rb +4 -7
  8. data/lib/fronde/cli/throbber.rb +24 -13
  9. data/lib/fronde/cli.rb +3 -2
  10. data/lib/fronde/config/data/org-config.el +3 -2
  11. data/lib/fronde/config/data/ox-fronde.el +72 -35
  12. data/lib/fronde/config/data/themes/umaneti/css/htmlize.css +364 -0
  13. data/lib/fronde/config/data/themes/umaneti/css/style.css +250 -0
  14. data/lib/fronde/config/data/themes/umaneti/img/bottom.png +0 -0
  15. data/lib/fronde/config/data/themes/umaneti/img/content.png +0 -0
  16. data/lib/fronde/config/data/themes/umaneti/img/tic.png +0 -0
  17. data/lib/fronde/config/data/themes/umaneti/img/top.png +0 -0
  18. data/lib/fronde/config/helpers.rb +0 -18
  19. data/lib/fronde/config/lisp.rb +13 -3
  20. data/lib/fronde/config.rb +40 -26
  21. data/lib/fronde/emacs.rb +1 -1
  22. data/lib/fronde/index/data/all_tags.org +6 -1
  23. data/lib/fronde/index/data/template.org +8 -4
  24. data/lib/fronde/index/org_generator.rb +2 -0
  25. data/lib/fronde/index.rb +12 -15
  26. data/lib/fronde/org/file.rb +39 -27
  27. data/lib/fronde/org/file_extracter.rb +15 -12
  28. data/lib/fronde/org.rb +11 -9
  29. data/lib/fronde/slug.rb +39 -12
  30. data/lib/fronde/source/gemini.rb +0 -5
  31. data/lib/fronde/source/html.rb +5 -5
  32. data/lib/fronde/source.rb +13 -8
  33. data/lib/fronde/sync/neocities.rb +220 -0
  34. data/lib/fronde/sync/rsync.rb +46 -0
  35. data/lib/fronde/sync.rb +32 -0
  36. data/lib/fronde/templater.rb +18 -11
  37. data/lib/fronde/version.rb +1 -1
  38. data/lib/tasks/org.rake +12 -17
  39. data/lib/tasks/site.rake +10 -13
  40. data/lib/tasks/sync.rake +13 -36
  41. data/lib/tasks/tags.rake +2 -2
  42. data/locales/en.yml +1 -0
  43. data/locales/fr.yml +1 -0
  44. metadata +49 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31ed851cf895abccd33ec85ab91459e4310c9716631d096efd89d18fd16bf190
4
- data.tar.gz: 901e11daea515cff4336f05a13a67604a5d73ca9fc020efb8250b34fbdb72450
3
+ metadata.gz: 8691e788789cb725772213237a67731dc67ae77eeecc8d1d409e6779d94a22c8
4
+ data.tar.gz: d2f67191b421f902e1b41d7845fc07026843e227cfd3f70cdeff0f4d87e36b8e
5
5
  SHA512:
6
- metadata.gz: 1190105b49652d3bf177602a9ca37906f9a4659416f821734b17b5a49269825726019a6b69ad47b312937d75b362e658b93026003ffc42cd92859b601c9c8e96
7
- data.tar.gz: 4e34d65345c82cc39237521c2e79365bbe4c23572fa4c4fa7d65e2d5aa7119d095a2956ec569e03c6cb459e7f1f37fe933aac3d2b0fdcefafb69f1cea8ef695b
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] wether or not the string must contain the
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
- locale = R18n.get.locale
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
@@ -27,13 +27,13 @@ module Fronde
27
27
  init_rake
28
28
  @rake.options.build_all = true
29
29
  @rake['org:upgrade'].invoke
30
- 0
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
- 0
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
- 0
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
- (system(*cmd) && 0) || 1
61
+ system(*cmd)
62
62
  end
63
63
 
64
64
  def fronde_publish
65
65
  @rake['sync:push'].invoke
66
- 0
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
- warn format("%<label>s\n\n", label: R18n.t.fronde.bin.usage(label))
74
+ output = [format_label(R18n.t.fronde.bin.usage(label))]
75
75
  cmd = cmd_opt[:name] || @command
76
- if R18n.t.fronde.bin.commands[cmd].translated?
77
- warn format("%<label>s\n\n", label: R18n.t.fronde.bin.commands[cmd])
78
- end
79
- body = OptParse.help_command_body(cmd)
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
@@ -1,4 +1,3 @@
1
- .dir-locals.el
2
1
  .ruby-version
3
2
  Rakefile
4
3
  lib/
@@ -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 << opt[:choices] if opt[:choices]
65
- config << opt[:help] if opt[:help]
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
 
@@ -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
- term_width = terminal_width
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
- done = Rainbow(R18n.t.fronde.bin.done).green
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
- return 0
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}".to_sym
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/version "{{ version }}"
8
- fronde/current-work-dir "{{ work_dir }}"
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/version ""
38
- "Version of the current fronde installation")
37
+ (defvar fronde-version ""
38
+ "Version of the current fronde installation.")
39
39
 
40
- (defvar fronde/current-work-dir nil
40
+ (defvar fronde-current-work-dir nil
41
41
  "Location of the current fronde website base directory.")
42
42
 
43
- (defvar fronde/org-temp-dir nil
44
- "Location of the local Org temporary directory (where to place
45
- org timestamps and id locations).")
46
-
47
- (defun fronde/org-html-format-spec (upstream info)
48
- "Return format specification for preamble and postamble.
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\">%s</ul>"
56
- (mapconcat
57
- (lambda (k) (format "<li class=\"keyword\">%s</li>" k))
58
- (split-string (or (plist-get info :keywords) "") ",+ *")
59
- "\n")))
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/version)) output)
63
- (push `(?N . ,(format "<a href=\"https://etienne.depar.is/fronde/\">Fronde</a> %s" fronde/version)) output)
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/org-gmi-format-spec (upstream info)
70
- "Return format specification for gemini postamble.
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 `(?n . ,(format "Fronde %s" fronde/version)) output)))
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/org-i18n-export (link description format)
76
- "Export a i18n link"
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 format
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
- (`latex (format "\\href{%s}{%s}" path desc))
87
- (_ (format "%s (%s)" desc path)))))
124
+ (_ nil))))
88
125
 
89
- (defun fronde/org-i18n-follow (link)
90
- "Visit a i18n link"
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/org-i18n-export
95
- :follow #'fronde/org-i18n-follow)
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/org-temp-dir (expand-file-name "var/tmp" fronde/current-work-dir)
101
- org-publish-timestamp-directory (expand-file-name "timestamps/" fronde/org-temp-dir)
102
- org-id-locations-file (expand-file-name "id-locations.el" fronde/org-temp-dir)
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/org-html-format-spec)
117
- (advice-add 'org-gmi--format-spec :around #'fronde/org-gmi-format-spec)
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