fronde 0.3.4 → 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.
- 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
|