Class: Cmless

Inherits:
Object
  • Object
show all
Extended by:
Enumerable
Defined in:
lib/cmless.rb

Overview

CMS alternative: Content in markdown / Extract HTML and data for display

Defined Under Namespace

Classes: Error, Markdowner

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



12
13
14
# File 'lib/cmless.rb', line 12

def path
  @path
end

#titleObject (readonly)

Returns the value of attribute title.



13
14
15
# File 'lib/cmless.rb', line 13

def title
  @title
end

#title_htmlObject (readonly)

Returns the value of attribute title_html.



14
15
16
# File 'lib/cmless.rb', line 14

def title_html
  @title_html
end

#toc_htmlObject (readonly)

Returns the value of attribute toc_html.



15
16
17
# File 'lib/cmless.rb', line 15

def toc_html
  @toc_html
end

Class Method Details

.allObject



112
113
114
115
116
# File 'lib/cmless.rb', line 112

def all
  @all ||= objects_by_path.values.sort_by do |object|
    object.head_html.gsub('<p>', '').to_f rescue object.path
  end
end

.each(&block) ⇒ Object



106
107
108
109
110
# File 'lib/cmless.rb', line 106

def each(&block)
  all.each do |cmless|
    block.call(cmless)
  end
end

.extract_body_html(doc) ⇒ Object



178
179
180
181
182
183
# File 'lib/cmless.rb', line 178

def extract_body_html(doc)
  siblings = []
  body = doc.xpath('//body').first
  siblings.push(body.children.first.remove) while body.children.first
  siblings.map(&:to_s).join.strip
end

.extract_head_html(doc) ⇒ Object



169
170
171
172
173
174
175
176
# File 'lib/cmless.rb', line 169

def extract_head_html(doc)
  siblings = []
  body = doc.xpath('//body').first
  while body.children.first && !body.children.first.name.match(/h2/)
    siblings.push(body.children.first.remove)
  end
  siblings.map(&:to_s).join.strip
end

.extract_html(doc, title) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/cmless.rb', line 150

def extract_html(doc, title)
  following_siblings = []
  # UGLY:
  # - title coming in is based on method name,
  #   so it will only be [a-z0-9_].
  # - Nokogiri only has XPath 1.0, so no regex replacements,
  #   so we can't list every possible bad character.
  # - XPath itself does not have a syntax for escaping in string literals,
  #   so we concat.
  doc.xpath("//h2[translate(text(),concat('~!@#\{$%^&*()_+`-=\}-\";:<>,.?/|\[]',\"'\"),'')='#{title}']").first.tap do |header|
    return nil unless header
    while header.next_element && !header.next_element.name.match(/h2/)
      following_siblings.push(header.next_element.remove)
    end
    header.remove
  end
  following_siblings.map(&:to_s).join
end

.find_by_path(path) ⇒ Object



118
119
120
121
122
123
# File 'lib/cmless.rb', line 118

def find_by_path(path)
  objects_by_path[path] ||
    fail(Cmless::Error.new(
           "'#{path}' is not a valid path under '#{self::ROOT}'; " \
             "Expected one of #{objects_by_path.keys}"))
end

.objects_by_pathObject



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/cmless.rb', line 129

def objects_by_path
  @objects_by_path ||=
    begin
      unless File.directory?(self::ROOT)
        fail StandardError.new("#{self::ROOT} is not a directory")
      end
      @object_by_path_in_progress = {}
      Dir[Pathname(self::ROOT) + '**/*.md'].sort.each do |full_path|
        object = new(full_path)
        @object_by_path_in_progress[object.path] = object
      end
      @object_by_path_in_progress
    end
end

.objects_by_path_in_progressObject



125
126
127
# File 'lib/cmless.rb', line 125

def objects_by_path_in_progress
  @object_by_path_in_progress
end

.path_from_file_path(file_path) ⇒ Object

These are just used by the initialize. Perhaps there is a better place.



146
147
148
# File 'lib/cmless.rb', line 146

def path_from_file_path(file_path)
  file_path.to_s.gsub(self::ROOT + '/', '').gsub(/\.md$/, '')
end

Instance Method Details

#ancestorsObject



83
84
85
86
87
88
89
90
91
# File 'lib/cmless.rb', line 83

def ancestors
  @ancestors ||= begin
    split = path.split('/')
    (1..split.size - 1).to_a.map do |i|
      # to avoid infinite recursion, only look at the ones already loaded.
      self.class.objects_by_path_in_progress[split[0, i].join('/')]
    end
  end
end

#childrenObject



93
94
95
96
97
98
99
100
101
# File 'lib/cmless.rb', line 93

def children
  @children ||= begin
    self.class.objects_by_path.select do |other_path, _other_object|
      other_path.match(/^#{path}\/[^\/]+$/) # TODO: escape
    end.map do |_other_path, other_object|
      other_object
    end
  end
end

#parentObject

Instance methods:



79
80
81
# File 'lib/cmless.rb', line 79

def parent
  ancestors.last
end