This commit is contained in:
Alex Kotov 2024-09-12 04:34:48 +04:00
parent 03c4eca9b0
commit 78ff370a4e
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
8 changed files with 197 additions and 0 deletions

View file

@ -2,4 +2,5 @@
source 'https://rubygems.org'
gem 'addressable', '~> 2.8'
gem 'i18n', '~> 1.14'

View file

@ -34,3 +34,15 @@ Chapter 2 paragraph text
Gemtext epilogue
## Related articles
=> ./foo-bar 1) 2024-09-12 Foo Bar
## Links
=> https://example.com 2) Example Domain

View file

@ -81,3 +81,23 @@ Chapter 2 paragraph text
<div>
HTTP epilogue
</div>
<h2>Related articles</h2>
<ol>
<li id="self-foo-bar" value="1" class="fragment-highlight">
<span class="text-muted">
<time datetime="2024-09-12">
September 12, 2024
</time>
</span>
<a href="./foo-bar">Foo Bar</a>
</li>
</ol>
<h2>Links</h2>
<ol>
<li id="link-example-com" value="2" class="fragment-highlight">
<a href="https://example.com">Example Domain</a>
(<a href="https://web.archive.org/arch/example.com">web.archive.org</a>)
</li>
</ol>

View file

@ -58,3 +58,30 @@ article.epilogue do |custom|
custom.for :html, 'HTTP epilogue'
custom.for :gemtext, 'Gemtext epilogue'
end
article.footnotes_category 'Related articles' do |category|
category.footnote(
category: :self,
slug: 'foo-bar',
index: 1,
url: './foo-bar',
text: 'Foo Bar',
date: '2024-09-12',
)
end
article.footnotes_category 'Links' do |category|
category.footnote(
category: :link,
slug: 'example-com',
index: 2,
url: 'https://example.com',
text: 'Example Domain',
alt_urls: [
{
name: 'web.archive.org',
url: 'https://web.archive.org/arch/example.com',
},
],
)
end

View file

@ -1,12 +1,15 @@
# frozen_string_literal: true
require 'cgi'
require 'date'
require 'forwardable'
require 'open3'
require 'pathname'
require 'uri'
require 'yaml'
require 'addressable'
require_relative 'repubmark/config'
require_relative 'repubmark/highlight'
require_relative 'repubmark/titled_ref'
@ -19,6 +22,7 @@ require_relative 'repubmark/elems/article'
# Always inside Article
require_relative 'repubmark/elems/annotation'
require_relative 'repubmark/elems/custom_logue'
require_relative 'repubmark/elems/footnotes_category'
# Always inside Article, Chapter
require_relative 'repubmark/elems/chapter'
# Always inside Annotation, Blockquote, Chapter
@ -57,6 +61,9 @@ require_relative 'repubmark/elems/text'
require_relative 'repubmark/elems/link'
require_relative 'repubmark/elems/power'
# Always inside FootnotesCategory
require_relative 'repubmark/elems/footnote'
module Repubmark
FORMATS = %i[gemtext html summary_plain word_count].freeze

View file

@ -8,6 +8,7 @@ module Repubmark
def initialize(config) # rubocop:disable Lint/MissingSuper
@parent = nil
self.config = config
@footnotes_categories = []
end
#################
@ -32,6 +33,7 @@ module Repubmark
@annotation&.to_html,
@chapter&.to_html,
@epilogue&.to_html,
*@footnotes_categories.map(&:to_html),
].compact.join.freeze
end
@ -41,6 +43,7 @@ module Repubmark
@annotation&.to_gemtext,
@chapter&.to_gemtext,
@epilogue&.to_gemtext,
*@footnotes_categories.map(&:to_gemtext),
].compact.join("\n\n\n").freeze
end
@ -94,6 +97,13 @@ module Repubmark
nil
end
def footnotes_category(name)
footnotes_category = FootnotesCategory.new self, name
@footnotes_categories << footnotes_category
yield footnotes_category
nil
end
private
def config=(config)

View file

@ -0,0 +1,74 @@
# frozen_string_literal: true
module Repubmark
module Elems
class Footnote < Base
EM_DASH = '—'
parents :FootnotesCategory
attr_reader :category, :slug, :index, :url,
:text, :descr, :date, :alt_urls
def initialize(parent, **kwargs)
super parent
kwargs.each { |k, v| send :"#{k}=", v }
end
#################
# Basic methods #
#################
def to_html
result = ''
result +=
%(<li id="#{category}-#{slug}" value="#{index}" class="fragment-highlight">\n)
if date
result += %(<span class="text-muted">\n)
result += %(<time datetime="#{date}">\n)
result += "#{I18n.localize(Date.parse(date), format: :long)}\n"
result += "</time>\n"
result += "</span>\n"
end
if url
scheme = Addressable::URI.parse(url).scheme&.downcase
if scheme
unless %w[http https].include? scheme
result += %(<span class="badge text-bg-secondary">\n)
result += %(#{scheme}://\n)
result += "</span>\n"
end
end
result += %(<a href="#{url}">#{text}</a>\n)
else
result += %(#{text}\n)
end
result += " &mdash; #{descr}\n" if descr
if alt_urls&.any?
result += %[(#{
alt_urls.map do |alt_url|
%(<a href=\"#{alt_url[:url]}\">#{alt_url[:name]}</a>)
end.join ', '
})\n]
end
result += '</li>'
result.freeze
end
def to_gemtext
result = ''
result += url ? "=> #{url}" : '*'
result += " #{index})"
result += " #{Date.parse(date)}" if date
result += " #{text}"
result += " #{EM_DASH} #{descr}" if descr
result.freeze
end
private
attr_writer :category, :slug, :index, :url,
:text, :descr, :date, :alt_urls
end
end
end

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
module Repubmark
module Elems
class FootnotesCategory < Base
parents :Article
def initialize(parent, title)
super parent
@title = title
@footnotes = []
end
#################
# Basic methods #
#################
def to_html
<<~HTML
<h2>#@title</h2>
<ol>
#{@footnotes.map(&:to_html).map(&:strip).join("\n")}
</ol>
HTML
end
def to_gemtext
<<~GEMTEXT
## #@title
#{@footnotes.map(&:to_gemtext).map(&:strip).join("\n")}
GEMTEXT
end
###################
# Builder methods #
###################
def footnote(**kwargs)
@footnotes << Footnote.new(self, **kwargs)
nil
end
end
end
end