fronde 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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