fronde 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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 +62 -42
  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 +53 -110
  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'