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.
- checksums.yaml +4 -4
 - data/bin/fronde +15 -30
 - data/lib/ext/nil_time.rb +25 -0
 - data/lib/ext/r18n.rb +17 -0
 - data/lib/ext/time.rb +49 -0
 - data/lib/fronde/cli/commands.rb +92 -103
 - data/lib/fronde/cli/data/Rakefile +8 -0
 - data/lib/fronde/cli/data/config.yml +13 -0
 - data/lib/fronde/cli/data/gitignore +7 -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 +143 -0
 - data/lib/fronde/cli/throbber.rb +99 -0
 - data/lib/fronde/cli.rb +41 -42
 - data/lib/fronde/config/data/org-config.el +24 -0
 - data/lib/fronde/config/{ox-fronde.el → data/ox-fronde.el} +1 -1
 - data/lib/fronde/config/helpers.rb +80 -0
 - data/lib/fronde/config/lisp.rb +70 -0
 - data/lib/fronde/config.rb +135 -99
 - data/lib/fronde/emacs.rb +23 -20
 - data/lib/fronde/index/atom_generator.rb +55 -66
 - data/lib/fronde/index/data/all_tags.org +14 -0
 - data/lib/fronde/index/data/template.org +22 -0
 - data/lib/fronde/index/data/template.xml +37 -0
 - data/lib/fronde/index/org_generator.rb +70 -88
 - data/lib/fronde/index.rb +56 -82
 - data/lib/fronde/org/file.rb +287 -0
 - data/lib/fronde/org/file_extracter.rb +98 -0
 - data/lib/fronde/org.rb +103 -0
 - data/lib/fronde/preview.rb +43 -39
 - data/lib/fronde/slug.rb +27 -0
 - data/lib/fronde/source/gemini.rb +39 -0
 - data/lib/fronde/source/html.rb +67 -0
 - data/lib/fronde/source.rb +204 -0
 - data/lib/fronde/templater.rb +94 -71
 - data/lib/fronde/version.rb +1 -1
 - data/lib/tasks/cli.rake +33 -0
 - data/lib/tasks/org.rake +63 -43
 - data/lib/tasks/site.rake +68 -30
 - data/lib/tasks/sync.rake +41 -21
 - data/lib/tasks/tags.rake +11 -7
 - data/locales/en.yml +60 -14
 - data/locales/fr.yml +68 -14
 - metadata +57 -156
 - data/lib/fronde/config/lisp_config.rb +0 -340
 - data/lib/fronde/config/org-config.el +0 -19
 - 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
 
| 
         @@ -1,72 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module Fronde
         
     | 
| 
       4 
     | 
    
         
            -
              # This module holds class methods for the {Fronde::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 = Fronde::Config.get('public_folder')
         
     | 
| 
       10 
     | 
    
         
            -
                  src.sub!(/^#{pubfolder}\//, '')
         
     | 
| 
       11 
     | 
    
         
            -
                  # Look for match in each possible sources. The first found wins.
         
     | 
| 
       12 
     | 
    
         
            -
                  Fronde::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 = Fronde::Config.get('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 
     | 
    
         
            -
                  Fronde::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 Fronde
         
     | 
| 
       4 
     | 
    
         
            -
              # This module holds extracter methods for the {Fronde::OrgFile} class.
         
     | 
| 
       5 
     | 
    
         
            -
              module OrgFileExtracter
         
     | 
| 
       6 
     | 
    
         
            -
                private
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                # Main method, which will call the other to initialize an
         
     | 
| 
       9 
     | 
    
         
            -
                #   {Fronde::OrgFile} instance.
         
     | 
| 
       10 
     | 
    
         
            -
                def extract_data
         
     | 
| 
       11 
     | 
    
         
            -
                  @content = File.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 Fronde::Config.get('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 Fronde::Config.get('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 'fronde/config'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'fronde/emacs'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            module Fronde
         
     | 
| 
       7 
     | 
    
         
            -
              # This module holds HTML formatter methods for the {Fronde::OrgFile}
         
     | 
| 
       8 
     | 
    
         
            -
              # class.
         
     | 
| 
       9 
     | 
    
         
            -
              module OrgFileHtmlizer
         
     | 
| 
       10 
     | 
    
         
            -
                private
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                # Format {Fronde::OrgFile#keywords} list in an HTML listing.
         
     | 
| 
       13 
     | 
    
         
            -
                #
         
     | 
| 
       14 
     | 
    
         
            -
                # @return [String] the HTML keywords list
         
     | 
| 
       15 
     | 
    
         
            -
                def keywords_to_html
         
     | 
| 
       16 
     | 
    
         
            -
                  domain = Fronde::Config.get('domain')
         
     | 
| 
       17 
     | 
    
         
            -
                  klist = @keywords.map do |k|
         
     | 
| 
       18 
     | 
    
         
            -
                    <<~KEYWORDLINK
         
     | 
| 
       19 
     | 
    
         
            -
                      <li class="keyword">
         
     | 
| 
       20 
     | 
    
         
            -
                        <a href="#{domain}/tags/#{Fronde::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 {Fronde::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 {Fronde::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
         
     | 
    
        data/lib/fronde/org_file.rb
    DELETED
    
    | 
         @@ -1,298 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'time'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'fileutils'
         
     | 
| 
       5 
     | 
    
         
            -
            # fronde/config is required by htmlizer
         
     | 
| 
       6 
     | 
    
         
            -
            require 'fronde/org_file/htmlizer'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'fronde/org_file/extracter'
         
     | 
| 
       8 
     | 
    
         
            -
            require 'fronde/org_file/class_methods'
         
     | 
| 
       9 
     | 
    
         
            -
            require 'fronde/index'
         
     | 
| 
       10 
     | 
    
         
            -
            require 'fronde/version'
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            module Fronde
         
     | 
| 
       13 
     | 
    
         
            -
              # Handles org files.
         
     | 
| 
       14 
     | 
    
         
            -
              #
         
     | 
| 
       15 
     | 
    
         
            -
              # This class is responsible for reading or writing existing or new org
         
     | 
| 
       16 
     | 
    
         
            -
              # files, and formating their content to be used on the generated
         
     | 
| 
       17 
     | 
    
         
            -
              # website.
         
     | 
| 
       18 
     | 
    
         
            -
              class OrgFile # rubocop:disable Metrics/ClassLength
         
     | 
| 
       19 
     | 
    
         
            -
                # @return [String] the title of the current org document, taken from
         
     | 
| 
       20 
     | 
    
         
            -
                #   the ~#+title:~ header.
         
     | 
| 
       21 
     | 
    
         
            -
                attr_reader :title
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                # @return [String] the subtitle of the current org document, taken
         
     | 
| 
       24 
     | 
    
         
            -
                #   from the ~#+subtitle:~ header.
         
     | 
| 
       25 
     | 
    
         
            -
                attr_reader :subtitle
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                # @return [DateTime] the date and time of the current org document,
         
     | 
| 
       28 
     | 
    
         
            -
                #   taken from the ~#+date:~ header.
         
     | 
| 
       29 
     | 
    
         
            -
                attr_reader :date
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                # @return [Boolean] wether a time has been extracted from the
         
     | 
| 
       32 
     | 
    
         
            -
                #   current org document ~#+date:~ header.
         
     | 
| 
       33 
     | 
    
         
            -
                attr_reader :notime
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                # The author of the current org document, taken from the ~#+author:~
         
     | 
| 
       36 
     | 
    
         
            -
                #   header.
         
     | 
| 
       37 
     | 
    
         
            -
                #
         
     | 
| 
       38 
     | 
    
         
            -
                # If the current document doesn't have any authorship information,
         
     | 
| 
       39 
     | 
    
         
            -
                # the one from the ~config.yml~ file will be used instead
         
     | 
| 
       40 
     | 
    
         
            -
                #
         
     | 
| 
       41 
     | 
    
         
            -
                # @return [String] the author name
         
     | 
| 
       42 
     | 
    
         
            -
                attr_reader :author
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                # @return [Array] the keywords list of the current org document,
         
     | 
| 
       45 
     | 
    
         
            -
                #   taken from the ~#+keywords:~ header.
         
     | 
| 
       46 
     | 
    
         
            -
                attr_reader :keywords
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                # @return [String] the description of this org document, taken from
         
     | 
| 
       49 
     | 
    
         
            -
                #   the ~#+description:~ header.
         
     | 
| 
       50 
     | 
    
         
            -
                attr_reader :excerpt
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                # The locale of the current org document, taken from the
         
     | 
| 
       53 
     | 
    
         
            -
                #   ~#+language:~ header.
         
     | 
| 
       54 
     | 
    
         
            -
                #
         
     | 
| 
       55 
     | 
    
         
            -
                # If the current document doesn't have any language information, the
         
     | 
| 
       56 
     | 
    
         
            -
                # one from the ~config.yml~ file will be used instead, or "en" by
         
     | 
| 
       57 
     | 
    
         
            -
                # default.
         
     | 
| 
       58 
     | 
    
         
            -
                #
         
     | 
| 
       59 
     | 
    
         
            -
                # @return [String] the document lang
         
     | 
| 
       60 
     | 
    
         
            -
                attr_reader :lang
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                # @return [String] the relative path to the source of this document.
         
     | 
| 
       63 
     | 
    
         
            -
                attr_reader :file
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                # @return [String] the relative path to the generated html file of
         
     | 
| 
       66 
     | 
    
         
            -
                #   this document.
         
     | 
| 
       67 
     | 
    
         
            -
                attr_reader :html_file
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                # @return [String] the url of this document, build from the ~domain~
         
     | 
| 
       70 
     | 
    
         
            -
                #   settings and the above {#html_file @html_file} attribute.
         
     | 
| 
       71 
     | 
    
         
            -
                attr_reader :url
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                # @return [String] the project owning this document.
         
     | 
| 
       74 
     | 
    
         
            -
                attr_reader :project
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                extend Fronde::OrgFileClassMethods
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
                include Fronde::OrgFileExtracter
         
     | 
| 
       79 
     | 
    
         
            -
                include Fronde::OrgFileHtmlizer
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                # Prepares the file named by ~file_name~ for read and write
         
     | 
| 
       82 
     | 
    
         
            -
                #   operations.
         
     | 
| 
       83 
     | 
    
         
            -
                #
         
     | 
| 
       84 
     | 
    
         
            -
                # If the file ~file_name~ does not exist, the new instance may be
         
     | 
| 
       85 
     | 
    
         
            -
                # populated by data given in the ~opts~ parameter.
         
     | 
| 
       86 
     | 
    
         
            -
                #
         
     | 
| 
       87 
     | 
    
         
            -
                # @example
         
     | 
| 
       88 
     | 
    
         
            -
                #     File.exist? './test.org'
         
     | 
| 
       89 
     | 
    
         
            -
                #     => true
         
     | 
| 
       90 
     | 
    
         
            -
                #     o = Fronde::OrgFile.new('./test.org')
         
     | 
| 
       91 
     | 
    
         
            -
                #     => #<Fronde::OrgFile @file='./test.org'...>
         
     | 
| 
       92 
     | 
    
         
            -
                #     o.title
         
     | 
| 
       93 
     | 
    
         
            -
                #     => "This is an existing test file"
         
     | 
| 
       94 
     | 
    
         
            -
                #     File.exist? '/tmp/does_not_exist.org'
         
     | 
| 
       95 
     | 
    
         
            -
                #     => false
         
     | 
| 
       96 
     | 
    
         
            -
                #     o = Fronde::OrgFile.new('/tmp/does_not_exist.org')
         
     | 
| 
       97 
     | 
    
         
            -
                #     => #<Fronde::OrgFile @file='/tmp/does_not_exist.org'...>
         
     | 
| 
       98 
     | 
    
         
            -
                #     o.title
         
     | 
| 
       99 
     | 
    
         
            -
                #     => ""
         
     | 
| 
       100 
     | 
    
         
            -
                #     File.exist? '/tmp/other.org'
         
     | 
| 
       101 
     | 
    
         
            -
                #     => false
         
     | 
| 
       102 
     | 
    
         
            -
                #     o = Fronde::OrgFile.new('/tmp/other.org', title: 'New file')
         
     | 
| 
       103 
     | 
    
         
            -
                #     => #<Fronde::OrgFile @file='/tmp/other.org'...>
         
     | 
| 
       104 
     | 
    
         
            -
                #     o.title
         
     | 
| 
       105 
     | 
    
         
            -
                #     => "New file"
         
     | 
| 
       106 
     | 
    
         
            -
                #
         
     | 
| 
       107 
     | 
    
         
            -
                # @param file_name [String] path to the corresponding Org file
         
     | 
| 
       108 
     | 
    
         
            -
                # @param opts [Hash] optional data to initialize new Org file
         
     | 
| 
       109 
     | 
    
         
            -
                # @option opts [String] title ('') the title of the new Org file
         
     | 
| 
       110 
     | 
    
         
            -
                # @option opts [String] author (system user or '') the author of the
         
     | 
| 
       111 
     | 
    
         
            -
                #   document
         
     | 
| 
       112 
     | 
    
         
            -
                # @option opts [String] project the project owning this file
         
     | 
| 
       113 
     | 
    
         
            -
                #   must be stored
         
     | 
| 
       114 
     | 
    
         
            -
                # @return [Fronde::OrgFile] the new instance of Fronde::OrgFile
         
     | 
| 
       115 
     | 
    
         
            -
                def initialize(file_name, opts = {})
         
     | 
| 
       116 
     | 
    
         
            -
                  file_name = nil if file_name == ''
         
     | 
| 
       117 
     | 
    
         
            -
                  @file = file_name
         
     | 
| 
       118 
     | 
    
         
            -
                  @html_file = nil
         
     | 
| 
       119 
     | 
    
         
            -
                  @url = nil
         
     | 
| 
       120 
     | 
    
         
            -
                  @project = opts.delete :project
         
     | 
| 
       121 
     | 
    
         
            -
                  @options = opts
         
     | 
| 
       122 
     | 
    
         
            -
                  build_html_file_and_url
         
     | 
| 
       123 
     | 
    
         
            -
                  if @file && File.exist?(@file)
         
     | 
| 
       124 
     | 
    
         
            -
                    extract_data
         
     | 
| 
       125 
     | 
    
         
            -
                  else
         
     | 
| 
       126 
     | 
    
         
            -
                    init_empty_file
         
     | 
| 
       127 
     | 
    
         
            -
                  end
         
     | 
| 
       128 
     | 
    
         
            -
                end
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                # Returns a String representation of the document date, which aims
         
     | 
| 
       131 
     | 
    
         
            -
                #   to be used to sort several OrgFiles.
         
     | 
| 
       132 
     | 
    
         
            -
                #
         
     | 
| 
       133 
     | 
    
         
            -
                # The format used for the key is ~%Y%m%d%H%M%S~. If the current
         
     | 
| 
       134 
     | 
    
         
            -
                # OrgFile instance does not have a date, this mehod return
         
     | 
| 
       135 
     | 
    
         
            -
                # ~00000000000000~. If the current OrgFile instance does not have
         
     | 
| 
       136 
     | 
    
         
            -
                # time information, the date is padded with zeros.
         
     | 
| 
       137 
     | 
    
         
            -
                #
         
     | 
| 
       138 
     | 
    
         
            -
                # @example with the org header ~#+date: <2019-07-03 Wed 20:52:49>~
         
     | 
| 
       139 
     | 
    
         
            -
                #     org_file.date
         
     | 
| 
       140 
     | 
    
         
            -
                #     => #<DateTime: 2019-07-03T20:52:49+02:00...>
         
     | 
| 
       141 
     | 
    
         
            -
                #     org_file.timekey
         
     | 
| 
       142 
     | 
    
         
            -
                #     => "20190703205349"
         
     | 
| 
       143 
     | 
    
         
            -
                #
         
     | 
| 
       144 
     | 
    
         
            -
                # @example with the org header ~#+date: <2019-07-03 Wed>~
         
     | 
| 
       145 
     | 
    
         
            -
                #     org_file.date
         
     | 
| 
       146 
     | 
    
         
            -
                #     => #<DateTime: 2019-07-03T00:00:00+02:00...>
         
     | 
| 
       147 
     | 
    
         
            -
                #     org_file.timekey
         
     | 
| 
       148 
     | 
    
         
            -
                #     => "20190703000000"
         
     | 
| 
       149 
     | 
    
         
            -
                #
         
     | 
| 
       150 
     | 
    
         
            -
                # @example with no date header in the org file
         
     | 
| 
       151 
     | 
    
         
            -
                #     org_file.date
         
     | 
| 
       152 
     | 
    
         
            -
                #     => nil
         
     | 
| 
       153 
     | 
    
         
            -
                #     org_file.timekey
         
     | 
| 
       154 
     | 
    
         
            -
                #     => "00000000000000"
         
     | 
| 
       155 
     | 
    
         
            -
                #
         
     | 
| 
       156 
     | 
    
         
            -
                # @return [String] the document key
         
     | 
| 
       157 
     | 
    
         
            -
                def timekey
         
     | 
| 
       158 
     | 
    
         
            -
                  return '00000000000000' if @date.nil?
         
     | 
| 
       159 
     | 
    
         
            -
                  @date.strftime('%Y%m%d%H%M%S')
         
     | 
| 
       160 
     | 
    
         
            -
                end
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                # Returns the current OrgFile instance DateTime as a String.
         
     | 
| 
       163 
     | 
    
         
            -
                #
         
     | 
| 
       164 
     | 
    
         
            -
                # This method accepts three values for the ~dateformat~ parameter:
         
     | 
| 
       165 
     | 
    
         
            -
                #
         
     | 
| 
       166 
     | 
    
         
            -
                # - ~:full~ (or ~:long~) :: outputs a complete date and time
         
     | 
| 
       167 
     | 
    
         
            -
                #   representation, localized through R18n;
         
     | 
| 
       168 
     | 
    
         
            -
                # - ~:short~ :: outputs a short date representation (without time),
         
     | 
| 
       169 
     | 
    
         
            -
                #   localized with R18n;
         
     | 
| 
       170 
     | 
    
         
            -
                # - ~:rfc3339~ :: outputs the RFC 3339 date and time representation,
         
     | 
| 
       171 
     | 
    
         
            -
                #   used in atom feed.
         
     | 
| 
       172 
     | 
    
         
            -
                #
         
     | 
| 
       173 
     | 
    
         
            -
                # @param dateformat [Symbol] the format to use to convert DateTime
         
     | 
| 
       174 
     | 
    
         
            -
                #   into String
         
     | 
| 
       175 
     | 
    
         
            -
                # @param year [Boolean] wether or not the ~:full~ format must
         
     | 
| 
       176 
     | 
    
         
            -
                #   contain the year
         
     | 
| 
       177 
     | 
    
         
            -
                # @return [String] the document DateTime string representation
         
     | 
| 
       178 
     | 
    
         
            -
                def datestring(dateformat = :full, year: true)
         
     | 
| 
       179 
     | 
    
         
            -
                  return '' if @date.nil?
         
     | 
| 
       180 
     | 
    
         
            -
                  return R18n.l @date.to_date if dateformat == :short
         
     | 
| 
       181 
     | 
    
         
            -
                  return @date.rfc3339 if dateformat == :rfc3339
         
     | 
| 
       182 
     | 
    
         
            -
                  locale = R18n.get.locale
         
     | 
| 
       183 
     | 
    
         
            -
                  long_fmt = R18n.t.fronde.index.full_date_format(
         
     | 
| 
       184 
     | 
    
         
            -
                    date: locale.format_date_full(@date, year: year)
         
     | 
| 
       185 
     | 
    
         
            -
                  )
         
     | 
| 
       186 
     | 
    
         
            -
                  unless @notime
         
     | 
| 
       187 
     | 
    
         
            -
                    long_fmt = R18n.t.fronde.index.full_date_with_time_format(
         
     | 
| 
       188 
     | 
    
         
            -
                      date: long_fmt, time: locale.time_format.delete('_').strip
         
     | 
| 
       189 
     | 
    
         
            -
                    )
         
     | 
| 
       190 
     | 
    
         
            -
                  end
         
     | 
| 
       191 
     | 
    
         
            -
                  locale.strftime(@date, long_fmt)
         
     | 
| 
       192 
     | 
    
         
            -
                end
         
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
                # Formats given ~string~ with values of the current OrgFile.
         
     | 
| 
       195 
     | 
    
         
            -
                #
         
     | 
| 
       196 
     | 
    
         
            -
                # This method expects to find percent-tags in the given ~string~ and
         
     | 
| 
       197 
     | 
    
         
            -
                # replace them by their corresponding value.
         
     | 
| 
       198 
     | 
    
         
            -
                #
         
     | 
| 
       199 
     | 
    
         
            -
                # It reuses the same tags than the ~org-html-format-spec~ method.
         
     | 
| 
       200 
     | 
    
         
            -
                #
         
     | 
| 
       201 
     | 
    
         
            -
                # *** Format:
         
     | 
| 
       202 
     | 
    
         
            -
                #
         
     | 
| 
       203 
     | 
    
         
            -
                # - %a :: the raw author name
         
     | 
| 
       204 
     | 
    
         
            -
                # - %A :: the HTML rendering of the author name, equivalent to
         
     | 
| 
       205 
     | 
    
         
            -
                #         ~<span class="author">%a</span>~
         
     | 
| 
       206 
     | 
    
         
            -
                # - %d :: the ~:short~ date HTML representation, equivalent
         
     | 
| 
       207 
     | 
    
         
            -
                #         to ~<time datetime="%I">%i</time>~
         
     | 
| 
       208 
     | 
    
         
            -
                # - %D :: the ~:full~ date and time HTML representation
         
     | 
| 
       209 
     | 
    
         
            -
                # - %i :: the raw ~:short~ date and time
         
     | 
| 
       210 
     | 
    
         
            -
                # - %I :: the raw ~:rfc3339~ date and time
         
     | 
| 
       211 
     | 
    
         
            -
                # - %k :: the keywords separated by a comma
         
     | 
| 
       212 
     | 
    
         
            -
                # - %K :: the HTML list rendering of the keywords
         
     | 
| 
       213 
     | 
    
         
            -
                # - %l :: the lang of the document
         
     | 
| 
       214 
     | 
    
         
            -
                # - %L :: the license information, taken from the
         
     | 
| 
       215 
     | 
    
         
            -
                #         {Fronde::Config#settings}
         
     | 
| 
       216 
     | 
    
         
            -
                # - %n :: the Fronde name and version
         
     | 
| 
       217 
     | 
    
         
            -
                # - %N :: the Fronde name and version with a link to the project
         
     | 
| 
       218 
     | 
    
         
            -
                #         home on the name
         
     | 
| 
       219 
     | 
    
         
            -
                # - %s :: the subtitle of the document
         
     | 
| 
       220 
     | 
    
         
            -
                # - %t :: the title of the document
         
     | 
| 
       221 
     | 
    
         
            -
                # - %u :: the web path to the related published HTML document
         
     | 
| 
       222 
     | 
    
         
            -
                # - %x :: the raw description (eXcerpt)
         
     | 
| 
       223 
     | 
    
         
            -
                # - %X :: the description, enclosed in an HTML ~p~ tag, equivalent
         
     | 
| 
       224 
     | 
    
         
            -
                #         to ~<p>%x</p>~
         
     | 
| 
       225 
     | 
    
         
            -
                #
         
     | 
| 
       226 
     | 
    
         
            -
                # @example
         
     | 
| 
       227 
     | 
    
         
            -
                #     org_file.format("Article written by %a the %d")
         
     | 
| 
       228 
     | 
    
         
            -
                #     => "Article written by Alice Smith the Wednesday 3rd July"
         
     | 
| 
       229 
     | 
    
         
            -
                #
         
     | 
| 
       230 
     | 
    
         
            -
                # @return [String] the given ~string~ after replacement occurs
         
     | 
| 
       231 
     | 
    
         
            -
                # rubocop:disable Metrics/MethodLength
         
     | 
| 
       232 
     | 
    
         
            -
                # rubocop:disable Layout/LineLength
         
     | 
| 
       233 
     | 
    
         
            -
                def format(string)
         
     | 
| 
       234 
     | 
    
         
            -
                  string.gsub('%a', @author)
         
     | 
| 
       235 
     | 
    
         
            -
                        .gsub('%A', author_to_html)
         
     | 
| 
       236 
     | 
    
         
            -
                        .gsub('%d', date_to_html(:short))
         
     | 
| 
       237 
     | 
    
         
            -
                        .gsub('%D', date_to_html)
         
     | 
| 
       238 
     | 
    
         
            -
                        .gsub('%i', datestring(:short))
         
     | 
| 
       239 
     | 
    
         
            -
                        .gsub('%I', datestring(:rfc3339))
         
     | 
| 
       240 
     | 
    
         
            -
                        .gsub('%k', @keywords.join(', '))
         
     | 
| 
       241 
     | 
    
         
            -
                        .gsub('%K', keywords_to_html)
         
     | 
| 
       242 
     | 
    
         
            -
                        .gsub('%l', @lang)
         
     | 
| 
       243 
     | 
    
         
            -
                        .gsub('%L', Fronde::Config.get('license', '').gsub(/\s+/, ' ').strip)
         
     | 
| 
       244 
     | 
    
         
            -
                        .gsub('%n', "Fronde #{Fronde::VERSION}")
         
     | 
| 
       245 
     | 
    
         
            -
                        .gsub('%N', "<a href=\"https://git.umaneti.net/fronde/about/\">Fronde</a> #{Fronde::VERSION}")
         
     | 
| 
       246 
     | 
    
         
            -
                        .gsub('%s', @subtitle)
         
     | 
| 
       247 
     | 
    
         
            -
                        .gsub('%t', @title)
         
     | 
| 
       248 
     | 
    
         
            -
                        .gsub('%u', @html_file || '')
         
     | 
| 
       249 
     | 
    
         
            -
                        .gsub('%x', @excerpt)
         
     | 
| 
       250 
     | 
    
         
            -
                        .gsub('%X', "<p>#{@excerpt}</p>")
         
     | 
| 
       251 
     | 
    
         
            -
                end
         
     | 
| 
       252 
     | 
    
         
            -
                # rubocop:enable Layout/LineLength
         
     | 
| 
       253 
     | 
    
         
            -
                # rubocop:enable Metrics/MethodLength
         
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
       255 
     | 
    
         
            -
                # Writes the current OrgFile content to the underlying file.
         
     | 
| 
       256 
     | 
    
         
            -
                #
         
     | 
| 
       257 
     | 
    
         
            -
                # The intermediate parent folders are created if necessary.
         
     | 
| 
       258 
     | 
    
         
            -
                #
         
     | 
| 
       259 
     | 
    
         
            -
                # @return [Integer] the length written (as returned by the
         
     | 
| 
       260 
     | 
    
         
            -
                #   underlying ~File.write~ method call)
         
     | 
| 
       261 
     | 
    
         
            -
                def write
         
     | 
| 
       262 
     | 
    
         
            -
                  raise TypeError, 'no conversion from nil file name to path.' if @file.nil?
         
     | 
| 
       263 
     | 
    
         
            -
                  file_dir = File.dirname @file
         
     | 
| 
       264 
     | 
    
         
            -
                  FileUtils.mkdir_p file_dir unless Dir.exist? file_dir
         
     | 
| 
       265 
     | 
    
         
            -
                  File.write @file, @content
         
     | 
| 
       266 
     | 
    
         
            -
                end
         
     | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
       268 
     | 
    
         
            -
                private
         
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
                def build_html_file_and_url
         
     | 
| 
       271 
     | 
    
         
            -
                  return if @file.nil?
         
     | 
| 
       272 
     | 
    
         
            -
                  @html_file = Fronde::OrgFile.target_for_source(
         
     | 
| 
       273 
     | 
    
         
            -
                    @file, @project, with_public_folder: false
         
     | 
| 
       274 
     | 
    
         
            -
                  )
         
     | 
| 
       275 
     | 
    
         
            -
                  @url = "#{Fronde::Config.get('domain')}/#{@html_file}"
         
     | 
| 
       276 
     | 
    
         
            -
                end
         
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
     | 
    
         
            -
                def init_empty_file
         
     | 
| 
       279 
     | 
    
         
            -
                  @title = @options[:title] || ''
         
     | 
| 
       280 
     | 
    
         
            -
                  @subtitle = ''
         
     | 
| 
       281 
     | 
    
         
            -
                  @date = DateTime.now
         
     | 
| 
       282 
     | 
    
         
            -
                  @notime = false
         
     | 
| 
       283 
     | 
    
         
            -
                  @author = @options[:author] || Fronde::Config.get('author')
         
     | 
| 
       284 
     | 
    
         
            -
                  @keywords = []
         
     | 
| 
       285 
     | 
    
         
            -
                  @lang = @options[:lang] || Fronde::Config.get('lang')
         
     | 
| 
       286 
     | 
    
         
            -
                  @excerpt = ''
         
     | 
| 
       287 
     | 
    
         
            -
                  body = @options[:content] || ''
         
     | 
| 
       288 
     | 
    
         
            -
                  @content = @options[:raw_content] || <<~ORG
         
     | 
| 
       289 
     | 
    
         
            -
                    #+title: #{@title}
         
     | 
| 
       290 
     | 
    
         
            -
                    #+date: <#{@date.strftime('%Y-%m-%d %a. %H:%M:%S')}>
         
     | 
| 
       291 
     | 
    
         
            -
                    #+author: #{@author}
         
     | 
| 
       292 
     | 
    
         
            -
                    #+language: #{@lang}
         
     | 
| 
       293 
     | 
    
         
            -
             
     | 
| 
       294 
     | 
    
         
            -
                    #{body}
         
     | 
| 
       295 
     | 
    
         
            -
                  ORG
         
     | 
| 
       296 
     | 
    
         
            -
                end
         
     | 
| 
       297 
     | 
    
         
            -
              end
         
     | 
| 
       298 
     | 
    
         
            -
            end
         
     |