fronde 0.3.4 → 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/bin/fronde +15 -30
- data/lib/ext/nil_time.rb +25 -0
- data/lib/ext/r18n.rb +37 -0
- data/lib/ext/time.rb +39 -0
- data/lib/ext/time_no_time.rb +23 -0
- data/lib/fronde/cli/commands.rb +97 -104
- data/lib/fronde/cli/data/Rakefile +8 -0
- data/lib/fronde/cli/data/config.yml +13 -0
- data/lib/fronde/cli/data/gitignore +6 -0
- data/lib/fronde/cli/data/zsh_completion +37 -0
- data/lib/fronde/cli/helpers.rb +55 -0
- data/lib/fronde/cli/opt_parse.rb +140 -0
- data/lib/fronde/cli/throbber.rb +110 -0
- data/lib/fronde/cli.rb +42 -42
- data/lib/fronde/config/data/org-config.el +25 -0
- data/lib/fronde/config/data/ox-fronde.el +158 -0
- 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 +62 -0
- data/lib/fronde/config/lisp.rb +80 -0
- data/lib/fronde/config.rb +148 -98
- data/lib/fronde/emacs.rb +23 -20
- data/lib/fronde/index/atom_generator.rb +55 -66
- data/lib/fronde/index/data/all_tags.org +19 -0
- data/lib/fronde/index/data/template.org +26 -0
- data/lib/fronde/index/data/template.xml +37 -0
- data/lib/fronde/index/org_generator.rb +72 -88
- data/lib/fronde/index.rb +57 -86
- data/lib/fronde/org/file.rb +299 -0
- data/lib/fronde/org/file_extracter.rb +101 -0
- data/lib/fronde/org.rb +105 -0
- data/lib/fronde/preview.rb +43 -39
- data/lib/fronde/slug.rb +54 -0
- data/lib/fronde/source/gemini.rb +34 -0
- data/lib/fronde/source/html.rb +67 -0
- data/lib/fronde/source.rb +209 -0
- 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 +101 -71
- data/lib/fronde/version.rb +1 -1
- data/lib/tasks/cli.rake +33 -0
- data/lib/tasks/org.rake +58 -43
- data/lib/tasks/site.rake +66 -31
- data/lib/tasks/sync.rake +37 -40
- data/lib/tasks/tags.rake +11 -7
- data/locales/en.yml +61 -14
- data/locales/fr.yml +69 -14
- metadata +77 -95
- data/lib/fronde/config/lisp_config.rb +0 -340
- data/lib/fronde/config/org-config.el +0 -19
- data/lib/fronde/config/ox-fronde.el +0 -121
- data/lib/fronde/org_file/class_methods.rb +0 -72
- data/lib/fronde/org_file/extracter.rb +0 -72
- data/lib/fronde/org_file/htmlizer.rb +0 -43
- data/lib/fronde/org_file.rb +0 -298
- data/lib/fronde/utils.rb +0 -229
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fronde
|
4
|
+
module CLI
|
5
|
+
# Helper code to help build the fronde option parser
|
6
|
+
module OptParse
|
7
|
+
# @return [Hash] the possible ~fronde~ options and their
|
8
|
+
# configuration
|
9
|
+
FRONDE_OPTIONS = {
|
10
|
+
'-a' => { long: 'author' },
|
11
|
+
'-f' => { long: 'force', boolean: true },
|
12
|
+
'-h' => { long: 'help', boolean: true, method: :on_tail,
|
13
|
+
help: R18n.t.fronde.bin.options.help },
|
14
|
+
'-l' => { long: 'lang', keyword: 'LOCALE' },
|
15
|
+
'-o' => { long: 'output', keyword: 'FORMAT', choices: %w[gemini html] },
|
16
|
+
'-t' => { long: 'title' },
|
17
|
+
'-v' => { long: 'verbose', boolean: true, method: :on_tail },
|
18
|
+
'-V' => { long: 'version', boolean: true, method: :on_tail,
|
19
|
+
help: R18n.t.fronde.bin.options.version }
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
# TODO: jekyll new [path] / jekyll build / jekyll clean / jekyll serve
|
23
|
+
# TODO: hugo new site [path] / hugo / hugo new content / hugo server
|
24
|
+
# TODO: zola init [path] / zola build --root path_to_project / zola serve
|
25
|
+
|
26
|
+
# @return [Hash] the possible ~fronde~ subcommands and their
|
27
|
+
# configuration
|
28
|
+
FRONDE_COMMANDS = {
|
29
|
+
'new' => { opts: ['-a', '-l', '-o', '-t', '-v'], label: 'new <path>' },
|
30
|
+
'init' => { alias: 'new' },
|
31
|
+
'update' => {},
|
32
|
+
'config' => { alias: 'update' },
|
33
|
+
'preview' => {},
|
34
|
+
'open' => { opts: ['-a', '-l', '-t', '-v'], label: 'open <path>' },
|
35
|
+
'edit' => { alias: 'open' },
|
36
|
+
'build' => { opts: ['-f'] },
|
37
|
+
'publish' => {},
|
38
|
+
'help' => {},
|
39
|
+
'basic' => { opts: ['-h', '-V'], label: '<command>' }
|
40
|
+
}.freeze
|
41
|
+
|
42
|
+
class << self
|
43
|
+
# Returns the short and long options specification for a given
|
44
|
+
# short option.
|
45
|
+
#
|
46
|
+
# This method use the {Fronde::CLI::OptParse::FRONDE_OPTIONS}
|
47
|
+
# Hash to retrieve corresponding values.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# spec = Fronde::CLI::OptParse.decorate_option('-a')
|
51
|
+
# => ['-a AUTHOR', '--author AUTHOR']
|
52
|
+
#
|
53
|
+
# @param short [String] the short option to decorate
|
54
|
+
# @return [Array] the short and long specification for an option
|
55
|
+
def decorate_option(short)
|
56
|
+
opt = FRONDE_OPTIONS[short]
|
57
|
+
long = "--#{opt[:long]}"
|
58
|
+
if opt[:boolean]
|
59
|
+
config = [short, long]
|
60
|
+
else
|
61
|
+
key = opt[:keyword] || opt[:long].upcase
|
62
|
+
config = [short, format('%<long>s %<key>s', long: long, key: key)]
|
63
|
+
end
|
64
|
+
config.push opt[:choices], opt[:help]
|
65
|
+
config.compact
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the ~fronde~ help summary for a given command.
|
69
|
+
#
|
70
|
+
# @param command [String] the command for which a summary
|
71
|
+
# should be given
|
72
|
+
# @return [String]
|
73
|
+
def summarize_command(command)
|
74
|
+
(FRONDE_COMMANDS[command][:opts] || []).map do |k|
|
75
|
+
short, long = decorate_option(k)
|
76
|
+
opt = FRONDE_OPTIONS[k]
|
77
|
+
label = [short, long].join(', ')
|
78
|
+
line = [format(' %<opt>s', opt: label).ljust(30), opt[:help]]
|
79
|
+
choices = opt[:choices]
|
80
|
+
line << "(#{choices.join(', ')})" if choices
|
81
|
+
line.compact.join(' ')
|
82
|
+
end.join("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
def help_command_body(command)
|
86
|
+
command_opts_doc = summarize_command(command)
|
87
|
+
return '' if command_opts_doc == ''
|
88
|
+
|
89
|
+
body = [R18n.t.fronde.bin.options.cmd_title, command_opts_doc]
|
90
|
+
if command == 'basic'
|
91
|
+
body += ['', R18n.t.fronde.bin.commands.cmd_title, list_commands]
|
92
|
+
end
|
93
|
+
body.join("\n")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns a formatted list of available commands for ~fronde~.
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
def list_commands
|
100
|
+
FRONDE_COMMANDS.filter_map do |cmd, opt|
|
101
|
+
next if cmd == 'basic'
|
102
|
+
|
103
|
+
line = [' ', cmd.ljust(10)]
|
104
|
+
if opt.has_key? :alias
|
105
|
+
line << R18n.t.fronde.bin.commands.alias(opt[:alias])
|
106
|
+
else
|
107
|
+
line << R18n.t.fronde.bin.commands[cmd]
|
108
|
+
end
|
109
|
+
line.join(' ')
|
110
|
+
end.join("\n")
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns the real command name for a given command, which may be
|
114
|
+
# an alias.
|
115
|
+
#
|
116
|
+
# @param command [String] the command to resolve
|
117
|
+
# @return [String]
|
118
|
+
def resolve_possible_alias(command)
|
119
|
+
return 'basic' unless FRONDE_COMMANDS.include?(command)
|
120
|
+
|
121
|
+
cmd_opt = FRONDE_COMMANDS[command]
|
122
|
+
return cmd_opt[:alias] if cmd_opt.has_key?(:alias)
|
123
|
+
|
124
|
+
command
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns the given command options.
|
128
|
+
#
|
129
|
+
# This method will first try to resolve command alias, if any.
|
130
|
+
#
|
131
|
+
# @param command [String] the command, which options should be returned
|
132
|
+
# @return [Hash] the command options
|
133
|
+
def command_options(command)
|
134
|
+
cmd = resolve_possible_alias command
|
135
|
+
FRONDE_COMMANDS[cmd].merge(name: cmd)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rainbow'
|
4
|
+
|
5
|
+
module Fronde
|
6
|
+
module CLI
|
7
|
+
# Decorations for the command line
|
8
|
+
class Throbber
|
9
|
+
# @return [Hash] the possible throbber themes
|
10
|
+
THROBBER_FRAMES = {
|
11
|
+
'basic' => '-\|/',
|
12
|
+
'basicdots' => '⋯⋱⋮⋰',
|
13
|
+
'moon' => '🌑🌒🌓🌔🌕🌖🌗🌘',
|
14
|
+
'clock' => '🕛🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚',
|
15
|
+
'bricks' => '⣷⣯⣟⡿⢿⣻⣽⣾',
|
16
|
+
'points' => '·⁘⁛⁘',
|
17
|
+
'quadrant' => '▙▛▜▟',
|
18
|
+
'default' => ['⠁ ⠂ ⠄ ⡀ ⠄ ⠂ ⠁', '⠂ ⠁ ⠂ ⠄ ⡀ ⠄ ⠂', '⠄ ⠂ ⠁ ⠂ ⠄ ⡀ ⠄',
|
19
|
+
'⡀ ⠄ ⠂ ⠁ ⠂ ⠄ ⡀', '⠄ ⡀ ⠄ ⠂ ⠁ ⠂ ⠄', '⠂ ⠄ ⡀ ⠄ ⠂ ⠁ ⠂']
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
def initialize(thread, message)
|
23
|
+
@frames = select_frames
|
24
|
+
@term_width = terminal_width
|
25
|
+
@thread = thread
|
26
|
+
@thread.abort_on_exception = false
|
27
|
+
@thread.report_on_exception = false
|
28
|
+
@message = message
|
29
|
+
end
|
30
|
+
|
31
|
+
def run
|
32
|
+
thread_loop
|
33
|
+
rescue RuntimeError => e
|
34
|
+
show_error
|
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:
|
41
|
+
else
|
42
|
+
show_message Rainbow(R18n.t.fronde.bin.done).green, "\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# Animates strings in the user console to alert him that something
|
47
|
+
# is running in the background.
|
48
|
+
#
|
49
|
+
# The animation is chosen among a bunch of themes, with the
|
50
|
+
# configuration option ~throbber~ (retrieved via
|
51
|
+
# {Fronde::Config::Store#get}).
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# long_stuff = Thread.new { very_long_operation }
|
55
|
+
# Fronde::CLI::Throbber.run(long_stuff, 'Computing hard stuff:')
|
56
|
+
#
|
57
|
+
# @param thread [Thread] the long-running operation to decorate
|
58
|
+
# @param message [String] the message to display before the throbber
|
59
|
+
# @return [void]
|
60
|
+
def run(thread, message)
|
61
|
+
throbber = new(thread, message)
|
62
|
+
throbber.run
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
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
|
+
|
79
|
+
def terminal_width
|
80
|
+
# Not a tty. Docker?
|
81
|
+
return 0 unless system('test -t 0')
|
82
|
+
|
83
|
+
`stty size`.strip.split[1].to_i - 1
|
84
|
+
end
|
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
|
+
|
91
|
+
def show_error
|
92
|
+
warn(
|
93
|
+
format(
|
94
|
+
"%<message>s %<label>s\n%<explanation>s",
|
95
|
+
message: @message,
|
96
|
+
label: Rainbow(R18n.t.fronde.error.bin.label).bold.red,
|
97
|
+
explanation: Rainbow(R18n.t.fronde.error.bin.explanation).bold
|
98
|
+
)
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def select_frames
|
103
|
+
model = Fronde::CONFIG.get 'throbber', 'default'
|
104
|
+
model = 'default' unless THROBBER_FRAMES.has_key?(model)
|
105
|
+
|
106
|
+
THROBBER_FRAMES[model]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/fronde/cli.rb
CHANGED
@@ -1,60 +1,60 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rake'
|
4
|
-
|
4
|
+
require_relative 'cli/commands'
|
5
5
|
|
6
6
|
module Fronde
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
module CLI
|
8
|
+
# Fronde CLI app
|
9
|
+
class App
|
10
|
+
def initialize(opts = {})
|
11
|
+
@options = { verbose: false }.merge(opts)
|
12
|
+
@command = @rake = nil
|
13
|
+
@argv = []
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
+
include Commands
|
16
17
|
|
17
|
-
|
18
|
+
def run(argv)
|
19
|
+
@argv = argv
|
20
|
+
@command = OptParse.resolve_possible_alias(@argv.shift || 'basic')
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
init_gitignore unless File.exist?('.gitignore')
|
22
|
-
end
|
22
|
+
if help_param_given?
|
23
|
+
return 2 if @options[:recover_from_error]
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
Rake.verbose(false) unless @options[:verbose]
|
27
|
-
@rake.raw_load_rakefile
|
28
|
-
end
|
25
|
+
return true
|
26
|
+
end
|
29
27
|
|
30
|
-
|
31
|
-
rakefile = <<~RAKE
|
32
|
-
# frozen_string_literal: true
|
28
|
+
init_rake if %w[build preview publish].include?(@command)
|
33
29
|
|
34
|
-
|
35
|
-
|
30
|
+
method = :"fronde_#{@command}"
|
31
|
+
return 2 if method_unknown?(method)
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
R18n.set(Fronde::Config.get('lang', 'en'))
|
40
|
-
R18n::Filters.on(:named_variables)
|
33
|
+
send method
|
34
|
+
end
|
41
35
|
|
42
|
-
|
36
|
+
private
|
43
37
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
def init_rake
|
39
|
+
@rake = Rake.application
|
40
|
+
Rake.verbose(false) unless @options[:verbose]
|
41
|
+
@rake.load_rakefile
|
42
|
+
end
|
43
|
+
|
44
|
+
def help_param_given?
|
45
|
+
return false unless @options[:help]
|
46
|
+
|
47
|
+
fronde_help
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_unknown?(method)
|
52
|
+
return false if respond_to?(method)
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
lib
|
54
|
-
public_html
|
55
|
-
var
|
56
|
-
GITIGNORE
|
57
|
-
File.write '.gitignore', gitignore
|
54
|
+
warn R18n.t.fronde.error.bin.no_command
|
55
|
+
fronde_help
|
56
|
+
true
|
57
|
+
end
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
;; Add org-mode to load path
|
2
|
+
(add-to-list 'load-path (expand-file-name "org-{{ org_version }}/lisp" "{{ work_dir }}/lib"))
|
3
|
+
;; Load last version of htmlize.el
|
4
|
+
(load-file (expand-file-name "htmlize.el" "{{ work_dir }}/lib"))
|
5
|
+
|
6
|
+
;; Current project options
|
7
|
+
(setq fronde-version "{{ version }}"
|
8
|
+
fronde-current-work-dir "{{ work_dir }}"
|
9
|
+
fronde-domain "{{ domain }}"
|
10
|
+
user-mail-address "{{ author.email }}"
|
11
|
+
user-full-name "{{ author.name }}"
|
12
|
+
org-html-metadata-timestamp-format "{{ long_date_fmt }}"
|
13
|
+
org-gmi-timestamp-format "{{ long_date_fmt }}"
|
14
|
+
org-publish-project-alist
|
15
|
+
`({% for project in all_projects -%}
|
16
|
+
("{{ project.name }}"
|
17
|
+
{%- for attribute in project.attributes %}
|
18
|
+
:{{ attribute[0] }} {{ attribute[1] | cast_lisp_value: attribute[0] }}
|
19
|
+
{%- endfor %})
|
20
|
+
{% endfor -%}
|
21
|
+
("website" :components ("{{ all_projects | map: 'name' | join: '" "' | remove: '" "tags' }}"))))
|
22
|
+
|
23
|
+
;; Load fronde lib
|
24
|
+
(load-file (expand-file-name "ox-gmi.el" "{{ work_dir }}/lib"))
|
25
|
+
(load-file (expand-file-name "ox-fronde.el" "{{ fronde_data_dir }}"))
|
@@ -0,0 +1,158 @@
|
|
1
|
+
;;; ox-fronde.el --- Fronde Gem specific helpers for Org Export Engine -*- lexical-binding: t; -*-
|
2
|
+
|
3
|
+
;; Copyright (C) 2011-2019 Free Software Foundation, Inc.
|
4
|
+
|
5
|
+
;; Author: Étienne Deparis <etienne at depar dot is>
|
6
|
+
;; Keywords: org, export
|
7
|
+
|
8
|
+
;; This file is not part of GNU Emacs.
|
9
|
+
|
10
|
+
;; GNU Emacs is free software: you can redistribute it and/or modify
|
11
|
+
;; it under the terms of the GNU General Public License as published by
|
12
|
+
;; the Free Software Foundation, either version 3 of the License, or
|
13
|
+
;; (at your option) any later version.
|
14
|
+
|
15
|
+
;; GNU Emacs is distributed in the hope that it will be useful,
|
16
|
+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
;; GNU General Public License for more details.
|
19
|
+
|
20
|
+
;; You should have received a copy of the GNU General Public License
|
21
|
+
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
22
|
+
|
23
|
+
;;; Commentary:
|
24
|
+
|
25
|
+
;; This library implements specific helpers function, needed by the Ruby
|
26
|
+
;; Gem Fronde, which offers an easy way to publish a static website
|
27
|
+
;; using Org files as sources.
|
28
|
+
|
29
|
+
;;; Code:
|
30
|
+
|
31
|
+
(require 'org)
|
32
|
+
(require 'ox-html)
|
33
|
+
(require 'ox-gmi)
|
34
|
+
|
35
|
+
;;; Function Declarations
|
36
|
+
|
37
|
+
(defvar fronde-version ""
|
38
|
+
"Version of the current fronde installation.")
|
39
|
+
|
40
|
+
(defvar fronde-current-work-dir nil
|
41
|
+
"Location of the current fronde website base directory.")
|
42
|
+
|
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.
|
78
|
+
INFO is a plist used as a communication channel."
|
79
|
+
(let ((output (funcall upstream info)))
|
80
|
+
(push `(?A . ,(format "<span class=\"author\">%s</span>"
|
81
|
+
(org-export-data (plist-get info :author) info)))
|
82
|
+
output)
|
83
|
+
(push `(?k . ,(org-export-data (plist-get info :keywords) info)) output)
|
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))))))
|
91
|
+
output)
|
92
|
+
(push `(?l . ,(org-export-data (plist-get info :language) info)) 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)
|
95
|
+
(push `(?x . ,(org-export-data (plist-get info :description) info)) output)
|
96
|
+
(push `(?X . ,(format "<p>%s</p>"
|
97
|
+
(org-export-data (plist-get info :description) info)))
|
98
|
+
output)))
|
99
|
+
|
100
|
+
(defun fronde--org-gmi-format-spec (upstream info)
|
101
|
+
"Advise UPSTREAM to return format specification for gemini postamble.
|
102
|
+
INFO is a plist used as a communication channel."
|
103
|
+
(let ((output (funcall upstream info)))
|
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)))
|
112
|
+
|
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 "::"))
|
116
|
+
(path (car splitted-link))
|
117
|
+
(desc (or description path))
|
118
|
+
(lang (cadr splitted-link)))
|
119
|
+
(pcase backend
|
120
|
+
(`html (if lang
|
121
|
+
(format "<a href=\"%s\" hreflang=\"%s\">%s</a>"
|
122
|
+
path lang desc)
|
123
|
+
(format "<a href=\"%s\">%s</a>" path desc)))
|
124
|
+
(_ nil))))
|
125
|
+
|
126
|
+
(defun fronde--org-i18n-follow (link)
|
127
|
+
"Visit the given i18n LINK."
|
128
|
+
(browse-url (car (split-string link "::"))))
|
129
|
+
|
130
|
+
(org-link-set-parameters "i18n"
|
131
|
+
:export #'fronde--org-i18n-export
|
132
|
+
:follow #'fronde--org-i18n-follow)
|
133
|
+
|
134
|
+
|
135
|
+
;;; Set configuration options
|
136
|
+
|
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)
|
140
|
+
make-backup-files nil
|
141
|
+
enable-local-variables :all
|
142
|
+
org-confirm-babel-evaluate nil
|
143
|
+
org-export-with-broken-links t
|
144
|
+
org-html-doctype "html5"
|
145
|
+
org-html-html5-fancy t
|
146
|
+
org-html-htmlize-output-type 'css
|
147
|
+
org-html-text-markup-alist '((bold . "<strong>%s</strong>")
|
148
|
+
(code . "<code>%s</code>")
|
149
|
+
(italic . "<em>%s</em>")
|
150
|
+
(strike-through . "<del>%s</del>")
|
151
|
+
(underline . "<span class=\"underline\">%s</span>")
|
152
|
+
(verbatim . "<code>%s</code>")))
|
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)
|
155
|
+
|
156
|
+
(provide 'ox-fronde)
|
157
|
+
|
158
|
+
;;; ox-fronde.el ends here
|