Class: Skiptorium::Article
- Inherits:
-
Object
- Object
- Skiptorium::Article
- Defined in:
- lib/skiptorium/article.rb
Constant Summary collapse
- FRONT_MATTER_RX =
/---([\s\S]*?)---/.freeze
- FRONT_MATTER_LINE_RX =
/^(?<key>\w+)\s*:\s*(?<value>.*)/.freeze
Instance Attribute Summary collapse
-
#canonical_url ⇒ Object
readonly
Returns the value of attribute canonical_url.
-
#content ⇒ Object
readonly
Returns the value of attribute content.
-
#cover_image ⇒ Object
readonly
Returns the value of attribute cover_image.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#published_at ⇒ Object
readonly
Returns the value of attribute published_at.
-
#slug ⇒ Object
readonly
Returns the value of attribute slug.
-
#tags ⇒ Object
readonly
Returns the value of attribute tags.
-
#title ⇒ Object
readonly
Returns the value of attribute title.
Class Method Summary collapse
Instance Method Summary collapse
- #front_matter(key = nil) ⇒ Object
- #html? ⇒ Boolean
- #html_to_markdown(data) ⇒ Object
-
#initialize(attrs) ⇒ Article
constructor
A new instance of Article.
- #markdown? ⇒ Boolean
- #markdown_to_html(data) ⇒ Object
- #parse_front_matter(data) ⇒ Object
- #same?(other) ⇒ Boolean
- #stable_slug ⇒ Object
- #to_html ⇒ Object
- #to_markdown(fm = {}) ⇒ Object
Constructor Details
#initialize(attrs) ⇒ Article
Returns a new instance of Article.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/skiptorium/article.rb', line 12 def initialize(attrs) @id = attrs[:id] @title = attrs.fetch(:title).to_s.strip @tags = attrs[:tags] || [] @canonical_url = attrs[:canonical_url]&.strip @published_at = attrs[:published_at] || DateTime.now @cover_image = attrs[:cover_image] @slug = attrs[:slug]&.strip || stable_slug @markdown = attrs[:markdown] @html = attrs[:html] raw = attrs[:content].to_s.strip @content = if markdown? @front_matter = parse_front_matter(raw) || {}.with_indifferent_access raw.gsub(/---([\s\S]*?)---/, '').strip else @front_matter = {}.with_indifferent_access raw end end |
Instance Attribute Details
#canonical_url ⇒ Object (readonly)
Returns the value of attribute canonical_url.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def canonical_url @canonical_url end |
#content ⇒ Object (readonly)
Returns the value of attribute content.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def content @content end |
#cover_image ⇒ Object (readonly)
Returns the value of attribute cover_image.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def cover_image @cover_image end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def id @id end |
#published_at ⇒ Object (readonly)
Returns the value of attribute published_at.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def published_at @published_at end |
#slug ⇒ Object (readonly)
Returns the value of attribute slug.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def slug @slug end |
#tags ⇒ Object (readonly)
Returns the value of attribute tags.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def @tags end |
#title ⇒ Object (readonly)
Returns the value of attribute title.
7 8 9 |
# File 'lib/skiptorium/article.rb', line 7 def title @title end |
Class Method Details
.parse_date(str) ⇒ Object
108 109 110 111 112 |
# File 'lib/skiptorium/article.rb', line 108 def self.parse_date(str) DateTime.parse(str) if str rescue StandardError nil end |
Instance Method Details
#front_matter(key = nil) ⇒ Object
40 41 42 |
# File 'lib/skiptorium/article.rb', line 40 def front_matter(key = nil) key ? @front_matter&.fetch(key, nil) : @front_matter end |
#html? ⇒ Boolean
53 54 55 |
# File 'lib/skiptorium/article.rb', line 53 def html? @html end |
#html_to_markdown(data) ⇒ Object
94 95 96 |
# File 'lib/skiptorium/article.rb', line 94 def html_to_markdown(data) ReverseMarkdown.convert(data) end |
#markdown? ⇒ Boolean
49 50 51 |
# File 'lib/skiptorium/article.rb', line 49 def markdown? @markdown end |
#markdown_to_html(data) ⇒ Object
88 89 90 91 92 |
# File 'lib/skiptorium/article.rb', line 88 def markdown_to_html(data) renderer = Redcarpet::Render::HTML.new(prettify: true) md = Redcarpet::Markdown.new(renderer, fenced_code_blocks: true) md.render(data) end |
#parse_front_matter(data) ⇒ Object
98 99 100 101 102 103 104 105 106 |
# File 'lib/skiptorium/article.rb', line 98 def parse_front_matter(data) if (md_fm = data.match(FRONT_MATTER_RX)) front_matter = md_fm[1].strip.split("\n").map do |line| md = line.match(FRONT_MATTER_LINE_RX) "#{md[:key]}: '#{md[:value]}'" end.join("\n") YAML.safe_load(front_matter).with_indifferent_access end end |
#same?(other) ⇒ Boolean
34 35 36 37 38 |
# File 'lib/skiptorium/article.rb', line 34 def same?(other) (@slug && @slug == other.slug) || (@title && @title == other.title) || (@canonical_url && @canonical_url == other.canonical_url) end |
#stable_slug ⇒ Object
44 45 46 47 |
# File 'lib/skiptorium/article.rb', line 44 def stable_slug sl = Russian.transliterate(@title) sl.downcase.strip.gsub(/[\W\-_]+/, '_').gsub(/_$/, '').gsub(/^_/, '') end |
#to_html ⇒ Object
57 58 59 |
# File 'lib/skiptorium/article.rb', line 57 def to_html html? ? @content : markdown_to_html(@content) end |
#to_markdown(fm = {}) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/skiptorium/article.rb', line 61 def to_markdown(fm = {}) c = if markdown? @content else html_to_markdown(@content) end.strip header = front_matter.merge( { title: title, tags: [].flatten.compact, canonical_url: canonical_url, slug: stable_slug, cover_image: cover_image, image: cover_image, published_at: published_at&.strftime('%Y-%m-%d %H:%M:%S %z'), date: published_at&.strftime('%Y-%m-%d %H:%M:%S %z') }.compact.with_indifferent_access ).merge(fm.with_indifferent_access) [ header.to_hash.sort.to_h.to_yaml.strip, '---', c ].join("\n") end |