neruda 0.2.4 → 0.2.6
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/lib/neruda/version.rb +1 -1
- metadata +24 -219
- data/LICENSE +0 -14
- data/bin/pablo +0 -193
- data/lib/neruda/config/lisp_config.rb +0 -260
- data/lib/neruda/config/org-config.el +0 -17
- data/lib/neruda/config/ox-neruda.el +0 -114
- data/lib/neruda/config.rb +0 -137
- data/lib/neruda/emacs.rb +0 -37
- data/lib/neruda/index/atom_generator.rb +0 -86
- data/lib/neruda/index/org_generator.rb +0 -114
- data/lib/neruda/index.rb +0 -130
- data/lib/neruda/org_file/class_methods.rb +0 -72
- data/lib/neruda/org_file/extracter.rb +0 -72
- data/lib/neruda/org_file/htmlizer.rb +0 -43
- data/lib/neruda/org_file.rb +0 -299
- data/lib/neruda/preview.rb +0 -55
- data/lib/neruda/templater.rb +0 -118
- data/lib/neruda/utils.rb +0 -214
- data/lib/tasks/org.rake +0 -91
- data/lib/tasks/site.rake +0 -55
- data/lib/tasks/sync.rake +0 -34
- data/lib/tasks/tags.rake +0 -19
- data/locales/en.yml +0 -38
- data/locales/fr.yml +0 -38
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Neruda
|
|
4
|
-
# Embeds methods responsible for generating an org file for a given
|
|
5
|
-
# index.
|
|
6
|
-
module IndexOrgGenerator
|
|
7
|
-
def to_org(index_name = 'index', is_project: false)
|
|
8
|
-
return project_home_page(index_name) if is_project
|
|
9
|
-
return all_tags_index if index_name == 'index'
|
|
10
|
-
[org_header(index_name),
|
|
11
|
-
org_articles(@index[index_name])].join("\n")
|
|
12
|
-
end
|
|
13
|
-
alias_method :to_s, :to_org
|
|
14
|
-
|
|
15
|
-
def write_org(index_name)
|
|
16
|
-
return unless save?
|
|
17
|
-
slug = Neruda::OrgFile.slug index_name
|
|
18
|
-
FileUtils.mkdir 'tags' unless Dir.exist? 'tags'
|
|
19
|
-
content = to_org index_name
|
|
20
|
-
orgdest = "tags/#{slug}.org"
|
|
21
|
-
IO.write(orgdest, content)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def project_home_page(project_name)
|
|
27
|
-
content = [org_header(project_name, is_tag: false)]
|
|
28
|
-
if @projects[project_name]&.any?
|
|
29
|
-
content += org_articles(@projects[project_name])
|
|
30
|
-
end
|
|
31
|
-
content.join("\n")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def write_all_blog_home(verbose)
|
|
35
|
-
Neruda::Config.sources.each do |project|
|
|
36
|
-
next unless project['is_blog']
|
|
37
|
-
next unless Dir.exist?(project['path'])
|
|
38
|
-
warn "Generated blog home for #{project['name']}" if verbose
|
|
39
|
-
orgdest = format('%<root>s/index.org', root: project['path'])
|
|
40
|
-
IO.write(orgdest, to_org(project['name'], is_project: true))
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def all_tags_index
|
|
45
|
-
content = [
|
|
46
|
-
org_header(R18n.t.neruda.index.all_tags, is_tag: false)
|
|
47
|
-
]
|
|
48
|
-
sort_tags_by_name_and_weight.each do |t, tags|
|
|
49
|
-
content << ''
|
|
50
|
-
content << org_title(R18n.t.neruda.index.send(t), 'index-tags')
|
|
51
|
-
next if tags.empty?
|
|
52
|
-
tags.each do |k|
|
|
53
|
-
content << "- #{tag_published_url(k)} (#{@index[k].length})"
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
content.join("\n")
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def tag_published_url(tag_name)
|
|
60
|
-
domain = Neruda::Config.settings['domain']
|
|
61
|
-
title = @tags_names[tag_name]
|
|
62
|
-
tag_link = "#{domain}/tags/#{tag_name}.html"
|
|
63
|
-
"[[#{tag_link}][#{title}]]"
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def org_header(title = nil, is_tag: true)
|
|
67
|
-
if is_tag
|
|
68
|
-
title = @tags_names[title]
|
|
69
|
-
elsif title.nil? || title == 'index'
|
|
70
|
-
title = Neruda::Config.settings['title']
|
|
71
|
-
end
|
|
72
|
-
<<~HEADER.strip
|
|
73
|
-
#+title: #{title}
|
|
74
|
-
#+author: #{Neruda::Config.settings['author']}
|
|
75
|
-
#+language: #{Neruda::Config.settings['lang']}
|
|
76
|
-
HEADER
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def org_articles(articles_list)
|
|
80
|
-
last_year = nil
|
|
81
|
-
articles_list.map do |article|
|
|
82
|
-
year_title = ''
|
|
83
|
-
year = article.timekey.slice(0, 4)
|
|
84
|
-
if year != last_year
|
|
85
|
-
year_title = format("\n%<title>s\n", title: org_title(year))
|
|
86
|
-
last_year = year
|
|
87
|
-
end
|
|
88
|
-
year_title + org_entry(article)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def org_entry(article)
|
|
93
|
-
line = "- *[[#{article.url}][#{article.title}]]*"
|
|
94
|
-
if article.date
|
|
95
|
-
art_date = article.datestring(:full, year: false)
|
|
96
|
-
published = R18n.t.neruda.index.published_on art_date
|
|
97
|
-
line += " / #{published}"
|
|
98
|
-
end
|
|
99
|
-
line += " \\\\\n #{article.excerpt}" if article.excerpt != ''
|
|
100
|
-
line
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def org_title(year, html_class = 'index-year')
|
|
104
|
-
year = R18n.t.neruda.index.unsorted if year == '0000'
|
|
105
|
-
<<~ENDPROP
|
|
106
|
-
* #{year}
|
|
107
|
-
:PROPERTIES:
|
|
108
|
-
:HTML_CONTAINER_CLASS: #{html_class}
|
|
109
|
-
:UNNUMBERED: notoc
|
|
110
|
-
:END:
|
|
111
|
-
ENDPROP
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
data/lib/neruda/index.rb
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
require 'digest/md5'
|
|
5
|
-
require 'neruda/config'
|
|
6
|
-
require 'neruda/org_file'
|
|
7
|
-
require 'neruda/index/atom_generator'
|
|
8
|
-
require 'neruda/index/org_generator'
|
|
9
|
-
|
|
10
|
-
module Neruda
|
|
11
|
-
# Generates website indexes and atom feeds for all the org documents
|
|
12
|
-
# keywords.
|
|
13
|
-
class Index
|
|
14
|
-
attr_reader :date
|
|
15
|
-
|
|
16
|
-
include Neruda::IndexAtomGenerator
|
|
17
|
-
include Neruda::IndexOrgGenerator
|
|
18
|
-
|
|
19
|
-
def initialize
|
|
20
|
-
@pubdir = Neruda::Config.settings['public_folder']
|
|
21
|
-
@index = { 'index' => [] }
|
|
22
|
-
@projects = {}
|
|
23
|
-
@tags_names = {}
|
|
24
|
-
@date = DateTime.now
|
|
25
|
-
feed
|
|
26
|
-
sort!
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def entries
|
|
30
|
-
@index.keys.reject { |k| k == 'index' }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def empty?
|
|
34
|
-
@index['index'].empty?
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def write_all(verbose: true)
|
|
38
|
-
@index.each_key do |k|
|
|
39
|
-
write_org(k)
|
|
40
|
-
warn "Generated index file for #{k}" if verbose
|
|
41
|
-
write_atom(k)
|
|
42
|
-
warn "Generated atom feed for #{k}" if verbose
|
|
43
|
-
end
|
|
44
|
-
write_all_blog_home(verbose)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def sort_by(kind)
|
|
48
|
-
if [:name, :weight].include?(kind)
|
|
49
|
-
tags_sorted = sort_tags_by_name_and_weight["by_#{kind}".to_sym]
|
|
50
|
-
# Reverse in order to have most important or A near next prompt
|
|
51
|
-
# and avoid to scroll to find the beginning of the list.
|
|
52
|
-
return tags_sorted.map do |k|
|
|
53
|
-
@tags_names[k] + " (#{@index[k].length})"
|
|
54
|
-
end.reverse
|
|
55
|
-
end
|
|
56
|
-
raise ArgumentError, "#{kind} not in [:name, :weight]"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
private
|
|
60
|
-
|
|
61
|
-
def feed
|
|
62
|
-
Neruda::Config.sources.each do |project|
|
|
63
|
-
next unless project['is_blog']
|
|
64
|
-
if project['recursive']
|
|
65
|
-
file_pattern = '**/*.org'
|
|
66
|
-
else
|
|
67
|
-
file_pattern = '*.org'
|
|
68
|
-
end
|
|
69
|
-
Dir.glob(file_pattern, base: project['path']).map do |s|
|
|
70
|
-
org_file = File.join(project['path'], s)
|
|
71
|
-
next if exclude_file?(org_file, project)
|
|
72
|
-
add_to_indexes(
|
|
73
|
-
Neruda::OrgFile.new(org_file, project: project)
|
|
74
|
-
)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def add_to_project_index(article)
|
|
80
|
-
project = article.project
|
|
81
|
-
@projects[project['name']] ||= []
|
|
82
|
-
@projects[project['name']] << article
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def add_to_indexes(article)
|
|
86
|
-
@index['index'] << article
|
|
87
|
-
add_to_project_index article
|
|
88
|
-
article.keywords.each do |k|
|
|
89
|
-
slug = Neruda::OrgFile.slug k
|
|
90
|
-
@tags_names[slug] = k # Overwrite is permitted
|
|
91
|
-
@index[slug] ||= []
|
|
92
|
-
@index[slug] << article
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def sort!
|
|
97
|
-
@index.each do |k, i|
|
|
98
|
-
@index[k] = i.sort { |a, b| b.timekey <=> a.timekey }
|
|
99
|
-
end
|
|
100
|
-
@projects.each do |k, i|
|
|
101
|
-
@projects[k] = i.sort { |a, b| b.timekey <=> a.timekey }
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def sort_tags_by_name_and_weight
|
|
106
|
-
tags_sorted = {}
|
|
107
|
-
all_keys = entries
|
|
108
|
-
tags_sorted[:by_name] = all_keys.sort
|
|
109
|
-
tags_sorted[:by_weight] = all_keys.sort do |a, b|
|
|
110
|
-
@index[b].length <=> @index[a].length
|
|
111
|
-
end
|
|
112
|
-
tags_sorted
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def exclude_file?(file_path, project)
|
|
116
|
-
# Obviously excluding index itself for blogs
|
|
117
|
-
return true if file_path == File.join(project['path'], 'index.org')
|
|
118
|
-
return false unless project['exclude']
|
|
119
|
-
file_path.match? project['exclude']
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def save?
|
|
123
|
-
return true unless empty?
|
|
124
|
-
Neruda::Config.sources.each do |project|
|
|
125
|
-
return true if project['is_blog'] && Dir.exist?(project['path'])
|
|
126
|
-
end
|
|
127
|
-
false
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Neruda
|
|
4
|
-
# This module holds class methods for the {Neruda::OrgFile} class.
|
|
5
|
-
module OrgFileClassMethods
|
|
6
|
-
def source_for_target(file_name)
|
|
7
|
-
# file_name may be frozen...
|
|
8
|
-
src = file_name.sub(/\.html\z/, '.org')
|
|
9
|
-
pubfolder = Neruda::Config.settings['public_folder']
|
|
10
|
-
src.sub!(/^#{pubfolder}\//, '')
|
|
11
|
-
# Look for match in each possible sources. The first found wins.
|
|
12
|
-
Neruda::Config.sources.each do |project|
|
|
13
|
-
if project['target'] == '.'
|
|
14
|
-
origin = File.join(project['path'], src)
|
|
15
|
-
else
|
|
16
|
-
origin = File.join(
|
|
17
|
-
project['path'], src.sub(/^#{project['target']}\//, '')
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
return origin if File.exist?(origin)
|
|
21
|
-
end
|
|
22
|
-
nil
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def target_for_source(file_name, project, with_public_folder: true)
|
|
26
|
-
return nil if file_name.nil?
|
|
27
|
-
# file_name may be frozen...
|
|
28
|
-
target = file_name.sub(/\.org\z/, '.html').sub(/^#{Dir.pwd}\//, '')
|
|
29
|
-
if project.nil?
|
|
30
|
-
subfolder = File.basename(File.dirname(target))
|
|
31
|
-
target = File.basename(target)
|
|
32
|
-
target = "#{subfolder}/#{target}" if subfolder != '.'
|
|
33
|
-
else
|
|
34
|
-
project_relative_path = project['path'].sub(/^#{Dir.pwd}\//, '')
|
|
35
|
-
target.sub!(/^#{project_relative_path}\//, '')
|
|
36
|
-
target = "#{project['target']}/#{target}" if project['target'] != '.'
|
|
37
|
-
end
|
|
38
|
-
return target unless with_public_folder
|
|
39
|
-
pubfolder = Neruda::Config.settings['public_folder']
|
|
40
|
-
"#{pubfolder}/#{target}"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def project_for_source(file_name)
|
|
44
|
-
# Look for match in each possible sources. The first found wins.
|
|
45
|
-
Neruda::Config.sources.each do |project|
|
|
46
|
-
project_relative_path = project['path'].sub(/^#{Dir.pwd}\//, '')
|
|
47
|
-
return project if file_name.match?(/^#{project_relative_path}\//)
|
|
48
|
-
end
|
|
49
|
-
nil
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def slug(title)
|
|
53
|
-
title.downcase.tr(' ', '-')
|
|
54
|
-
.encode('ascii', fallback: ->(k) { translit(k) })
|
|
55
|
-
.gsub(/[^\w-]/, '').delete_suffix('-')
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
private
|
|
59
|
-
|
|
60
|
-
def translit(char)
|
|
61
|
-
return 'a' if ['á', 'à', 'â', 'ä', 'ǎ', 'ã', 'å'].include?(char)
|
|
62
|
-
return 'e' if ['é', 'è', 'ê', 'ë', 'ě', 'ẽ'].include?(char)
|
|
63
|
-
return 'i' if ['í', 'ì', 'î', 'ï', 'ǐ', 'ĩ'].include?(char)
|
|
64
|
-
return 'o' if ['ó', 'ò', 'ô', 'ö', 'ǒ', 'õ'].include?(char)
|
|
65
|
-
return 'u' if ['ú', 'ù', 'û', 'ü', 'ǔ', 'ũ'].include?(char)
|
|
66
|
-
return 'y' if ['ý', 'ỳ', 'ŷ', 'ÿ', 'ỹ'].include?(char)
|
|
67
|
-
return 'c' if char == 'ç'
|
|
68
|
-
return 'n' if char == 'ñ'
|
|
69
|
-
'-'
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Neruda
|
|
4
|
-
# This module holds extracter methods for the {Neruda::OrgFile} class.
|
|
5
|
-
module OrgFileExtracter
|
|
6
|
-
private
|
|
7
|
-
|
|
8
|
-
# Main method, which will call the other to initialize an
|
|
9
|
-
# {Neruda::OrgFile} instance.
|
|
10
|
-
def extract_data
|
|
11
|
-
@content = IO.read @file
|
|
12
|
-
@title = extract_title
|
|
13
|
-
@subtitle = extract_subtitle
|
|
14
|
-
@date = extract_date
|
|
15
|
-
@author = extract_author
|
|
16
|
-
@keywords = extract_keywords
|
|
17
|
-
@lang = extract_lang
|
|
18
|
-
@excerpt = extract_excerpt
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def extract_date
|
|
22
|
-
timerx = '([0-9:]{5})(?::([0-9]{2}))?'
|
|
23
|
-
m = /^#\+date: *<([0-9-]{10}) [\w.]+(?: #{timerx})?> *$/i.match(@content)
|
|
24
|
-
return nil if m.nil?
|
|
25
|
-
@notime = m[2].nil?
|
|
26
|
-
if @notime
|
|
27
|
-
time = '00:00:00'
|
|
28
|
-
else
|
|
29
|
-
time = "#{m[2]}:#{m[3] || '00'}"
|
|
30
|
-
end
|
|
31
|
-
DateTime.strptime("#{m[1]} #{time}", '%Y-%m-%d %H:%M:%S')
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def extract_title
|
|
35
|
-
m = /^#\+title:(.+)$/i.match(@content)
|
|
36
|
-
if m.nil?
|
|
37
|
-
# Avoid to leak absolute path
|
|
38
|
-
project_relative_path = @file.sub(/^#{Dir.pwd}\//, '')
|
|
39
|
-
return project_relative_path
|
|
40
|
-
end
|
|
41
|
-
m[1].strip
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def extract_subtitle
|
|
45
|
-
m = /^#\+subtitle:(.+)$/i.match(@content)
|
|
46
|
-
return '' if m.nil?
|
|
47
|
-
m[1].strip
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def extract_author
|
|
51
|
-
m = /^#\+author:(.+)$/i.match(@content)
|
|
52
|
-
return Neruda::Config.settings['author'] if m.nil?
|
|
53
|
-
m[1].strip
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def extract_keywords
|
|
57
|
-
m = /^#\+keywords:(.+)$/i.match(@content)
|
|
58
|
-
return [] if m.nil?
|
|
59
|
-
m[1].split(',').map(&:strip)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def extract_lang
|
|
63
|
-
m = /^#\+language:(.+)$/i.match(@content)
|
|
64
|
-
return Neruda::Config.settings['lang'] if m.nil?
|
|
65
|
-
m[1].strip
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def extract_excerpt
|
|
69
|
-
@content.scan(/^#\+description:(.+)$/i).map { |l| l[0].strip }.join(' ')
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'neruda/config'
|
|
4
|
-
require 'neruda/emacs'
|
|
5
|
-
|
|
6
|
-
module Neruda
|
|
7
|
-
# This module holds HTML formatter methods for the {Neruda::OrgFile}
|
|
8
|
-
# class.
|
|
9
|
-
module OrgFileHtmlizer
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
# Format {Neruda::OrgFile#keywords} list in an HTML listing.
|
|
13
|
-
#
|
|
14
|
-
# @return [String] the HTML keywords list
|
|
15
|
-
def keywords_to_html
|
|
16
|
-
domain = Neruda::Config.settings['domain']
|
|
17
|
-
klist = @keywords.map do |k|
|
|
18
|
-
<<~KEYWORDLINK
|
|
19
|
-
<li class="keyword">
|
|
20
|
-
<a href="#{domain}/tags/#{Neruda::OrgFile.slug(k)}.html">#{k}</a>
|
|
21
|
-
</li>
|
|
22
|
-
KEYWORDLINK
|
|
23
|
-
end.join
|
|
24
|
-
"<ul class=\"keywords-list\">#{klist}</ul>"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Format {Neruda::OrgFile#date} as a HTML `time` tag.
|
|
28
|
-
#
|
|
29
|
-
# @return [String] the HTML `time` tag
|
|
30
|
-
def date_to_html(dateformat = :full)
|
|
31
|
-
return '<time></time>' if @date.nil?
|
|
32
|
-
"<time datetime=\"#{@date.rfc3339}\">#{datestring(dateformat)}</time>"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Format {Neruda::OrgFile#author} in a HTML `span` tag with a
|
|
36
|
-
# specific class.
|
|
37
|
-
#
|
|
38
|
-
# @return [String] the author HTML `span`
|
|
39
|
-
def author_to_html
|
|
40
|
-
"<span class=\"author\">#{@author}</span>"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|