fronde 0.3.3 → 0.4.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/bin/fronde +15 -30
  3. data/lib/ext/nil_time.rb +25 -0
  4. data/lib/ext/r18n.rb +17 -0
  5. data/lib/ext/time.rb +49 -0
  6. data/lib/fronde/cli/commands.rb +92 -103
  7. data/lib/fronde/cli/data/Rakefile +8 -0
  8. data/lib/fronde/cli/data/config.yml +13 -0
  9. data/lib/fronde/cli/data/gitignore +7 -0
  10. data/lib/fronde/cli/data/zsh_completion +37 -0
  11. data/lib/fronde/cli/helpers.rb +55 -0
  12. data/lib/fronde/cli/opt_parse.rb +143 -0
  13. data/lib/fronde/cli/throbber.rb +99 -0
  14. data/lib/fronde/cli.rb +41 -42
  15. data/lib/fronde/config/data/org-config.el +24 -0
  16. data/lib/fronde/config/{ox-fronde.el → data/ox-fronde.el} +1 -1
  17. data/lib/fronde/config/helpers.rb +80 -0
  18. data/lib/fronde/config/lisp.rb +70 -0
  19. data/lib/fronde/config.rb +135 -99
  20. data/lib/fronde/emacs.rb +23 -20
  21. data/lib/fronde/index/atom_generator.rb +55 -66
  22. data/lib/fronde/index/data/all_tags.org +14 -0
  23. data/lib/fronde/index/data/template.org +22 -0
  24. data/lib/fronde/index/data/template.xml +37 -0
  25. data/lib/fronde/index/org_generator.rb +70 -88
  26. data/lib/fronde/index.rb +56 -82
  27. data/lib/fronde/org/file.rb +287 -0
  28. data/lib/fronde/org/file_extracter.rb +98 -0
  29. data/lib/fronde/org.rb +103 -0
  30. data/lib/fronde/preview.rb +43 -39
  31. data/lib/fronde/slug.rb +27 -0
  32. data/lib/fronde/source/gemini.rb +39 -0
  33. data/lib/fronde/source/html.rb +67 -0
  34. data/lib/fronde/source.rb +204 -0
  35. data/lib/fronde/templater.rb +94 -71
  36. data/lib/fronde/version.rb +1 -1
  37. data/lib/tasks/cli.rake +33 -0
  38. data/lib/tasks/org.rake +63 -43
  39. data/lib/tasks/site.rake +68 -30
  40. data/lib/tasks/sync.rake +41 -21
  41. data/lib/tasks/tags.rake +11 -7
  42. data/locales/en.yml +60 -14
  43. data/locales/fr.yml +68 -14
  44. metadata +57 -156
  45. data/lib/fronde/config/lisp_config.rb +0 -340
  46. data/lib/fronde/config/org-config.el +0 -19
  47. data/lib/fronde/org_file/class_methods.rb +0 -72
  48. data/lib/fronde/org_file/extracter.rb +0 -72
  49. data/lib/fronde/org_file/htmlizer.rb +0 -43
  50. data/lib/fronde/org_file.rb +0 -298
  51. data/lib/fronde/utils.rb +0 -229
data/lib/fronde/emacs.rb CHANGED
@@ -1,37 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fronde/config'
3
+ require_relative 'config'
4
4
 
5
5
  module Fronde
6
6
  # Wraps Gnu/Emacs calls
7
7
  class Emacs
8
- def initialize(file_path: nil, verbose: false)
9
- @file = file_path
8
+ def initialize(verbose: false)
10
9
  @verbose = verbose
10
+ @command = nil
11
11
  end
12
12
 
13
- def publish
14
- command = emacs_command(
15
- '-l ./var/lib/org-config.el', '--eval \'(org-publish "website")\''
16
- )
17
- if @verbose
18
- warn command
19
- return system(command, exception: true)
20
- end
21
- system command, out: '/dev/null', err: '/dev/null', exception: true
13
+ def publish(project = 'website')
14
+ build_command("(org-publish \"#{project}\")")
15
+ run_command
22
16
  end
23
17
 
24
18
  private
25
19
 
26
- def emacs_command(*arguments)
27
- default_emacs = Fronde::Config.get('emacs')
28
- emacs_cmd = [
29
- default_emacs || 'emacs -Q --batch -nw',
30
- '--eval \'(setq enable-dir-local-variables nil)\''
20
+ def run_command
21
+ cmd = @command.join(' ')
22
+ if @verbose
23
+ warn cmd
24
+ return system(cmd, exception: true)
25
+ end
26
+ system cmd, out: '/dev/null', err: '/dev/null', exception: true
27
+ end
28
+
29
+ def build_command(org_action)
30
+ default_emacs = Fronde::CONFIG.get('emacs')
31
+ @command = [default_emacs || 'emacs -Q --batch -nw']
32
+ @command << '--eval \'(setq inhibit-message t)\'' unless @verbose
33
+ @command += [
34
+ '--eval \'(setq enable-dir-local-variables nil)\'',
35
+ '-l ./var/lib/org-config.el',
36
+ "--eval '#{org_action}'"
31
37
  ]
32
- emacs_cmd << '--eval \'(setq inhibit-message t)\'' unless @verbose
33
- emacs_cmd.concat(arguments)
34
- emacs_cmd.join(' ')
35
38
  end
36
39
  end
37
40
  end
@@ -1,85 +1,74 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
4
- require 'fronde/config'
3
+ require_relative '../config'
5
4
 
6
5
  module Fronde
7
- # Embeds Atom feeds sepecific methods
8
- module IndexAtomGenerator
6
+ # Reopen Index class to embed Atom feeds sepecific methods
7
+ class Index
9
8
  def to_atom(index_name = 'index')
10
- content = [atom_header(index_name)]
11
- @index[index_name][0...10].each do |article|
12
- content << atom_entry(article)
13
- end
14
- format '%<content>s</feed>', content: content.join("\n")
9
+ entries = @index[index_name][0...10].map(&:to_h)
10
+ return atom_index(entries) if index_name == 'index'
11
+
12
+ atom_file(index_name, entries)
15
13
  end
16
14
 
17
15
  def write_atom(index_name)
18
- return unless save?
19
- slug = Fronde::OrgFile.slug index_name
20
- FileUtils.mkdir_p "#{@pubdir}/feeds"
21
- atomdest = "#{@pubdir}/feeds/#{slug}.xml"
22
- File.write(atomdest, to_atom(index_name))
16
+ slug = Slug.slug index_name
17
+ atomdest = "#{@project.publication_path}/feeds/#{slug}.xml"
18
+ File.write atomdest, to_atom(index_name)
19
+ end
20
+
21
+ def write_all_feeds(verbose: true)
22
+ FileUtils.mkdir_p "#{@project.publication_path}/feeds"
23
+ @index.each_key do |tag|
24
+ write_atom(tag)
25
+ warn R18n.t.fronde.index.atom_generated(tag: tag) if verbose
26
+ end
23
27
  end
24
28
 
25
29
  private
26
30
 
27
- # Render the Atom feed header.
31
+ # Render an Atom feed file.
28
32
  #
29
- # @param title [String] the title of the current atom feed
30
- # @return [String] the Atom header as a String
31
- def atom_header(title)
32
- domain = Fronde::Config.get('domain')
33
- upddate = @date.rfc3339
34
- if title == 'index'
35
- slug = 'index'
36
- tagurl = domain
37
- title = Fronde::Config.get('title', R18n.t.fronde.index.all_tags)
38
- else
39
- slug = Fronde::OrgFile.slug(title)
40
- tagurl = "#{domain}/tags/#{slug}.html"
41
- title = @tags_names[title]
42
- end
43
- title = CGI.escapeHTML(title)
44
- <<~ENDATOM
45
- <?xml version="1.0" encoding="utf-8"?>
46
- <feed xmlns="http://www.w3.org/2005/Atom"
47
- xmlns:dc="http://purl.org/dc/elements/1.1/"
48
- xmlns:wfw="http://wellformedweb.org/CommentAPI/"
49
- xml:lang="#{Fronde::Config.get('lang')}">
50
-
51
- <title>#{title}</title>
52
- <link href="#{domain}/feeds/#{slug}.xml" rel="self" type="application/atom+xml"/>
53
- <link href="#{tagurl}" rel="alternate" type="text/html" title="#{title}"/>
54
- <updated>#{upddate}</updated>
55
- <author><name>#{Fronde::Config.get('author', '')}</name></author>
56
- <id>urn:md5:#{Digest::MD5.hexdigest(domain)}</id>
57
- <generator uri="https://git.umaneti.net/fronde/about/">Fronde</generator>
58
- ENDATOM
33
+ # @param tag_name [String] the tag name of the current atom feed
34
+ # @param entries [Array] the article to list in this file
35
+ # @return [String] the Atom feed as a String
36
+ def atom_file(tag_name, entries)
37
+ domain = Fronde::CONFIG.get('domain')
38
+ slug = Slug.slug(tag_name)
39
+ tagurl = "#{domain}#{@project.public_absolute_path}tags/#{slug}.html"
40
+ Config::Helpers.render_liquid_template(
41
+ File.read(File.expand_path('./data/template.xml', __dir__)),
42
+ 'title' => @tags_names[tag_name],
43
+ 'lang' => Fronde::CONFIG.get('lang'),
44
+ 'domain' => domain,
45
+ 'slug' => slug,
46
+ 'tagurl' => tagurl,
47
+ 'upddate' => @date.xmlschema,
48
+ 'author' => Fronde::CONFIG.get('author'),
49
+ 'publication_format' => @project['mime_type'],
50
+ 'entries' => entries
51
+ )
59
52
  end
60
53
 
61
- # Render an Atom feed entry.
54
+ # Render the main/index Atom feed.
62
55
  #
63
- # @param article [Fronde::OrgFile] the related org document for this
64
- # entry
65
- # @return [String] the Atom entry as a String
66
- def atom_entry(article)
67
- keywords = article.keywords.map do |k|
68
- "<dc:subject>#{CGI.escapeHTML(k)}</dc:subject>"
69
- end.join
70
- keywords += "\n " if keywords != ''
71
- title = CGI.escapeHTML(article.title)
72
- <<~ENDENTRY
73
- <entry>
74
- <title>#{title}</title>
75
- <link href="#{article.url}" rel="alternate" type="text/html"
76
- title="#{title}"/>
77
- <id>urn:md5:#{Digest::MD5.hexdigest(article.timekey)}</id>
78
- <published>#{article.datestring(:rfc3339)}</published>
79
- <author><name>#{CGI.escapeHTML(article.author)}</name></author>
80
- #{keywords}<content type="html">#{CGI.escapeHTML(article.excerpt)}</content>
81
- </entry>
82
- ENDENTRY
56
+ # @param entries [Array] the article to list in this file
57
+ # @return [String] the Atom feed as a String
58
+ def atom_index(entries)
59
+ domain = Fronde::CONFIG.get('domain')
60
+ Config::Helpers.render_liquid_template(
61
+ File.read(File.expand_path('./data/template.xml', __dir__)),
62
+ 'title' => @project['title'],
63
+ 'lang' => Fronde::CONFIG.get('lang'),
64
+ 'domain' => domain,
65
+ 'slug' => 'index',
66
+ 'tagurl' => domain,
67
+ 'upddate' => @date.xmlschema,
68
+ 'author' => Fronde::CONFIG.get('author'),
69
+ 'publication_format' => @project['mime_type'],
70
+ 'entries' => entries
71
+ )
83
72
  end
84
73
  end
85
74
  end
@@ -0,0 +1,14 @@
1
+ #+title: {{ title }}
2
+ #+author: {{ author }}
3
+ #+language: {{ lang }}
4
+ {% for index in indexes %}
5
+ * {{ index.title }}
6
+ :PROPERTIES:
7
+ :HTML_CONTAINER_CLASS: index-tags
8
+ :UNNUMBERED: notoc
9
+ :END:
10
+
11
+ {% for tag in index.tags -%}
12
+ - [[{{ domain }}{{ project_path }}tags/{{ tag.slug }}.html][{{ tag.title }}]] ({{ tag.weight }})
13
+ {% endfor %}
14
+ {%- endfor -%}
@@ -0,0 +1,22 @@
1
+ #+title: {{ title }}
2
+ #+author: {{ author }}
3
+ #+language: {{ lang }}
4
+ {%- unless slug == '__HOME_PAGE__' %}
5
+ #+html_head_extra: <link rel="alternate" type="application/atom+xml" title="{{ title }}" href="{{ domain }}{{ project_path }}feeds/{{ slug }}.xml" />
6
+ {% endunless -%}
7
+ {%- assign last_year = 0 -%}
8
+ {% for article in entries %}
9
+ {% assign cur_year = article.timekey | slice: 0, 4 %}
10
+ {%- unless cur_year == last_year %}
11
+ * {% if cur_year == "0000" %}{{ unsorted }}{% else %}{{ cur_year }}{% endif %}
12
+ :PROPERTIES:
13
+ :HTML_CONTAINER_CLASS: index-year
14
+ :UNNUMBERED: notoc
15
+ :END:
16
+ {% assign last_year = cur_year %}
17
+ {% endunless -%}
18
+ - *[[{{ article.url }}][{{ article.title }}]]*
19
+ {%- if article.published != '' %} / {{ article.published }}{% endif -%}
20
+ {%- if article.excerpt != '' %} \\
21
+ {{ article.excerpt }}{% endif %}
22
+ {%- endfor %}
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom"
3
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
4
+ xml:lang="{{ lang }}">
5
+
6
+ <title>{{ title | escape }}</title>
7
+ <link href="{{ domain }}/feeds/{{ slug }}.xml" rel="self" type="application/atom+xml"/>
8
+ <link href="{{ tagurl }}" rel="alternate" type="text/html" title="{{ title }}"/>
9
+ <updated>{{ upddate }}</updated>
10
+ <author><name>{{ author }}</name></author>
11
+ <id>urn:md5:{{ domain | md5 }}</id>
12
+ <generator uri="https://git.umaneti.net/fronde/about/">Fronde</generator>
13
+
14
+ {%- for article in entries %}
15
+
16
+ <entry>
17
+ <title>{{ article.title | escape }}</title>
18
+ <link href="{{ article.url }}" rel="alternate"
19
+ type="{{ publication_format }}"
20
+ title="{{ article.title }}"/>
21
+ <id>urn:md5:{{ article.timekey | md5 }}</id>
22
+ <published>{{ article.published_xml }}</published>
23
+ <updated>{{ article.updated_xml }}</updated>
24
+ <author><name>{{ article.author | escape }}</name></author>
25
+ {%- for keyword in article.keywords %}
26
+ <dc:subject>{{ keyword | escape }}</dc:subject>
27
+ {%- endfor %}
28
+ {%- if publication_format == 'text/html' %}
29
+ <content type="html">
30
+ {%- else %}
31
+ <content>
32
+ {%- endif %}
33
+ {{- article.published_body | escape -}}
34
+ </content>
35
+ </entry>
36
+ {%- endfor %}
37
+ </feed>
@@ -1,114 +1,96 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using TimePatch
4
+
3
5
  module Fronde
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
6
+ # Reopen Index class to embed methods responsible for generating an
7
+ # org file for a given index.
8
+ class Index
9
+ def blog_home_page
10
+ org_index @project['title'], '__HOME_PAGE__', @entries.map(&:to_h)
11
+ end
12
+
13
+ def to_org(index_name = 'index')
9
14
  return all_tags_index if index_name == 'index'
10
- [org_header(index_name),
11
- org_articles(@index[index_name])].join("\n")
15
+
16
+ org_index(
17
+ @tags_names[index_name], index_name,
18
+ (@index[index_name] || []).map(&:to_h)
19
+ )
12
20
  end
13
21
  alias_method :to_s, :to_org
14
22
 
15
23
  def write_org(index_name)
16
- return unless save?
17
- slug = Fronde::OrgFile.slug index_name
18
- FileUtils.mkdir 'tags' unless Dir.exist? 'tags'
19
- content = to_org index_name
20
- orgdest = "tags/#{slug}.org"
21
- File.write(orgdest, content)
24
+ slug = Slug.slug index_name
25
+ orgdest = "#{@project['path']}/tags/#{slug}.org"
26
+ File.write orgdest, to_org(index_name)
22
27
  end
23
28
 
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])
29
+ def write_all_org(verbose: true)
30
+ FileUtils.mkdir_p "#{@project['path']}/tags"
31
+ @index.each_key do |tag|
32
+ write_org(tag)
33
+ warn R18n.t.fronde.index.index_generated(tag: tag) if verbose
30
34
  end
31
- content.join("\n")
35
+ write_blog_home_page(verbose)
32
36
  end
33
37
 
34
- def write_all_blog_home(verbose)
35
- Fronde::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
- File.write(orgdest, to_org(project['name'], is_project: true))
41
- end
42
- end
38
+ private
43
39
 
44
- def all_tags_index
45
- content = [
46
- org_header(R18n.t.fronde.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.fronde.index.send(t), 'index-tags')
51
- next if tags.empty?
52
- tags.each do |k|
53
- content << "- #{tag_published_url(k)} (#{@index[k].length})"
40
+ # Render an Org index file.
41
+ #
42
+ # @param title [String] the title of the current org index
43
+ # @param slug [String] the slug of the current org index
44
+ # @param entries [Array] the article to list in this file
45
+ # @return [String] the org file content as a String
46
+ def org_index(title, slug, entries)
47
+ entries.map! do |article|
48
+ published = article['published']
49
+ unless published == ''
50
+ article['published'] = R18n.t.fronde.index.published_on published
54
51
  end
52
+ article
55
53
  end
56
- content.join("\n")
57
- end
58
-
59
- def tag_published_url(tag_name)
60
- domain = Fronde::Config.get('domain')
61
- title = @tags_names[tag_name]
62
- tag_link = "#{domain}/tags/#{tag_name}.html"
63
- "[[#{tag_link}][#{title}]]"
54
+ Config::Helpers.render_liquid_template(
55
+ File.read(File.expand_path('./data/template.org', __dir__)),
56
+ 'title' => title,
57
+ 'slug' => slug,
58
+ 'project_path' => @project.public_absolute_path,
59
+ 'domain' => Fronde::CONFIG.get('domain'),
60
+ 'lang' => Fronde::CONFIG.get('lang'),
61
+ 'author' => Fronde::CONFIG.get('author'),
62
+ 'unsorted' => R18n.t.fronde.index.unsorted,
63
+ 'entries' => entries
64
+ )
64
65
  end
65
66
 
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 = Fronde::Config.get('title')
71
- end
72
- <<~HEADER.strip
73
- #+title: #{title}
74
- #+author: #{Fronde::Config.get('author')}
75
- #+language: #{Fronde::Config.get('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
67
+ def all_tags_index
68
+ indexes = sort_tags_by_name_and_weight.map do |title, tags|
69
+ all_tags = tags.map do |tag|
70
+ {
71
+ 'slug' => tag, 'title' => @tags_names[tag],
72
+ 'weight' => @index[tag].length
73
+ }
87
74
  end
88
- year_title + org_entry(article)
75
+ { 'title' => R18n.t.fronde.index.send(title), 'tags' => all_tags }
89
76
  end
77
+ Config::Helpers.render_liquid_template(
78
+ File.read(File.expand_path('./data/all_tags.org', __dir__)),
79
+ 'title' => R18n.t.fronde.index.all_tags,
80
+ 'lang' => Fronde::CONFIG.get('lang'),
81
+ 'author' => Fronde::CONFIG.get('author'),
82
+ 'domain' => Fronde::CONFIG.get('domain'),
83
+ 'project_path' => @project.public_absolute_path,
84
+ 'indexes' => indexes
85
+ )
90
86
  end
91
87
 
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.fronde.index.published_on art_date
97
- line += " / #{published}"
88
+ def write_blog_home_page(verbose)
89
+ orgdest = format('%<root>s/index.org', root: @project['path'])
90
+ if verbose
91
+ warn R18n.t.fronde.org.generate_blog_index(name: @project['name'])
98
92
  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.fronde.index.unsorted if year == '0000'
105
- <<~ENDPROP
106
- * #{year}
107
- :PROPERTIES:
108
- :HTML_CONTAINER_CLASS: #{html_class}
109
- :UNNUMBERED: notoc
110
- :END:
111
- ENDPROP
93
+ File.write(orgdest, blog_home_page)
112
94
  end
113
95
  end
114
96
  end
data/lib/fronde/index.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fileutils'
4
- require 'digest/md5'
5
- require 'fronde/config'
6
- require 'fronde/org_file'
7
- require 'fronde/index/atom_generator'
8
- require 'fronde/index/org_generator'
3
+ require_relative 'slug'
4
+ require_relative 'config'
5
+ require_relative 'org/file'
9
6
 
10
7
  module Fronde
11
8
  # Generates website indexes and atom feeds for all the org documents
@@ -13,118 +10,95 @@ module Fronde
13
10
  class Index
14
11
  attr_reader :date
15
12
 
16
- include Fronde::IndexAtomGenerator
17
- include Fronde::IndexOrgGenerator
18
-
19
- def initialize
20
- @pubdir = Fronde::Config.get('public_folder')
13
+ def initialize(project)
14
+ @project = project
21
15
  @index = { 'index' => [] }
22
- @projects = {}
16
+ @entries = []
23
17
  @tags_names = {}
24
- @date = DateTime.now
25
- feed
26
- sort!
18
+ @date = Time.now
19
+ generate_feeds if @project.blog?
20
+ sort_feeds!
27
21
  end
28
22
 
29
- def entries
30
- @index.keys.reject { |k| k == 'index' }
23
+ def all_tags
24
+ @index.keys.reject { |tag| tag == 'index' }
31
25
  end
32
26
 
33
27
  def empty?
34
28
  @index['index'].empty?
35
29
  end
36
30
 
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
31
  def sort_by(kind)
48
- if [:name, :weight].include?(kind)
32
+ accepted_values = %i[name weight]
33
+ if accepted_values.include?(kind)
49
34
  tags_sorted = sort_tags_by_name_and_weight["by_#{kind}".to_sym]
50
35
  # Reverse in order to have most important or A near next prompt
51
36
  # 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})"
37
+ return tags_sorted.map do |tag|
38
+ @tags_names[tag] + " (#{@index[tag].length})"
54
39
  end.reverse
55
40
  end
56
- raise ArgumentError, "#{kind} not in [:name, :weight]"
41
+ error_msg = R18n.t.fronde.error.index.wrong_sort_kind(
42
+ kind: kind, accepted_values: accepted_values.inspect
43
+ )
44
+ raise ArgumentError, error_msg
57
45
  end
58
46
 
59
- private
47
+ class << self
48
+ def all_html_blog_index(&block)
49
+ all_blogs = CONFIG.sources.filter_map do |project|
50
+ next unless project['type'] == 'html' && project.blog?
60
51
 
61
- def feed
62
- Fronde::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
- Fronde::OrgFile.new(org_file, project: project)
74
- )
52
+ Index.new(project)
75
53
  end
54
+ return all_blogs unless block
55
+
56
+ all_blogs.each(&block)
76
57
  end
77
58
  end
78
59
 
79
- def add_to_project_index(article)
80
- project = article.project
81
- @projects[project['name']] ||= []
82
- @projects[project['name']] << article
60
+ private
61
+
62
+ def generate_feeds
63
+ file_pattern = '**/*.org'
64
+ Dir.glob(file_pattern, base: @project['path']).map do |index_file|
65
+ # Obviously don't parse tags
66
+ next if index_file.start_with?('tags/')
67
+
68
+ org_file = File.join(@project['path'], index_file)
69
+ next if @project.exclude_file? org_file
70
+
71
+ add_to_indexes(Org::File.new(org_file))
72
+ end
83
73
  end
84
74
 
85
75
  def add_to_indexes(article)
86
76
  @index['index'] << article
87
- add_to_project_index article
88
- article.keywords.each do |k|
89
- slug = Fronde::OrgFile.slug k
90
- @tags_names[slug] = k # Overwrite is permitted
77
+ @entries << article
78
+ article.keywords.each do |tag|
79
+ slug = Slug.slug tag
80
+ @tags_names[slug] = tag # Overwrite is permitted
91
81
  @index[slug] ||= []
92
82
  @index[slug] << article
93
83
  end
94
84
  end
95
85
 
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 }
86
+ def sort_feeds!
87
+ @index.transform_values! do |articles|
88
+ articles.sort_by(&:timekey).reverse
102
89
  end
90
+ @entries = @entries.sort_by(&:timekey).reverse
103
91
  end
104
92
 
105
93
  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
- Fronde::Config.sources.each do |project|
125
- return true if project['is_blog'] && Dir.exist?(project['path'])
126
- end
127
- false
94
+ all_keys = all_tags
95
+ {
96
+ by_name: all_keys.sort,
97
+ by_weight: all_keys.sort_by { @index[_1].length }.reverse
98
+ }
128
99
  end
129
100
  end
130
101
  end
102
+
103
+ require_relative 'index/org_generator'
104
+ require_relative 'index/atom_generator'