cmless 0.0.1 → 0.0.2
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/lib/cmless.rb +53 -52
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 073521fc16da8478a83e71be3c439d09c2c47aa9
|
4
|
+
data.tar.gz: 259f6b6f2e6b52a56b523acf955ac471425e3cf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7a96411b03d0e08023988a70a72c6672f66e8a665e20caa395c93d2f289c9f7c9cc94606ce4dac99d355b64d744c9b2bf23332582ad31814c3b20adbc976034
|
7
|
+
data.tar.gz: 7a3dd7106279ea92a509c8f0fd9ec453e2045905d63ba8a362c2bd4c16e1815e1e025c9048b42f78e66d0ec2489b12ffaf1193ae4232d92565d262857318e7f8
|
data/lib/cmless.rb
CHANGED
@@ -6,140 +6,141 @@ require 'redcarpet'
|
|
6
6
|
require 'singleton'
|
7
7
|
require 'nokogiri'
|
8
8
|
|
9
|
+
# CMS alternative: Content in markdown / Extract HTML and data for display
|
9
10
|
class Cmless
|
10
|
-
|
11
11
|
attr_reader :path
|
12
12
|
attr_reader :title
|
13
|
-
|
13
|
+
|
14
14
|
private
|
15
|
-
|
16
|
-
# You should use find_by_path rather than creating your own
|
17
|
-
def initialize(file_path)
|
15
|
+
|
16
|
+
# You should use find_by_path rather than creating your own instances.
|
17
|
+
def initialize(file_path) # rubocop:disable Metrics/MethodLength
|
18
18
|
@path = self.class.path_from_file_path(file_path)
|
19
19
|
Nokogiri::HTML(Markdowner.instance.render(File.read(file_path))).tap do |doc|
|
20
20
|
@title = doc.xpath('//h1').first.remove.text
|
21
21
|
|
22
|
-
html_methods = self.class.instance_methods
|
23
|
-
|
24
|
-
|
22
|
+
html_methods = self.class.instance_methods
|
23
|
+
.select { |method| method.to_s.match(/\_html$/) }
|
24
|
+
|
25
25
|
if html_methods.include?(:head_html)
|
26
|
-
|
26
|
+
instance_variable_set('@head_html', Cmless.extract_head_html(doc))
|
27
27
|
html_methods.delete(:head_html)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
if html_methods.include?(:body_html)
|
31
|
-
|
31
|
+
instance_variable_set('@body_html', Cmless.extract_body_html(doc))
|
32
32
|
html_methods.delete(:body_html)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
html_methods.each do |method|
|
36
|
-
h2_name = method.to_s.gsub(/\_html$/, '').gsub('_',' ').capitalize
|
37
|
-
|
38
|
-
self.instance_variable_set(variable_name, Cmless.extract_html(doc, h2_name))
|
36
|
+
h2_name = method.to_s.gsub(/\_html$/, '').gsub('_', ' ').capitalize
|
37
|
+
instance_variable_set("@#{method}", Cmless.extract_html(doc, h2_name))
|
39
38
|
end
|
40
|
-
|
39
|
+
|
41
40
|
doc.text.strip.tap do |extra|
|
42
|
-
escaped = extra.gsub("\n",'\\n').gsub("\t",'\\t')
|
41
|
+
escaped = extra.gsub("\n", '\\n').gsub("\t", '\\t')
|
43
42
|
fail("#{file_path} has extra unused text: '#{escaped}'") unless extra == ''
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
public
|
49
|
-
|
48
|
+
|
50
49
|
# Instance methods:
|
51
|
-
|
50
|
+
|
52
51
|
def ancestors
|
53
52
|
@ancestors ||= begin
|
54
53
|
split = path.split('/')
|
55
|
-
(1..split.size-1).to_a.map do |i|
|
56
|
-
self.class.objects_by_path[split[0,i].join('/')]
|
54
|
+
(1..split.size - 1).to_a.map do |i|
|
55
|
+
self.class.objects_by_path[split[0, i].join('/')]
|
57
56
|
end
|
58
57
|
end
|
59
58
|
end
|
60
|
-
|
59
|
+
|
61
60
|
def children
|
62
61
|
@children ||= begin
|
63
|
-
self.class.objects_by_path.select do |other_path,
|
62
|
+
self.class.objects_by_path.select do |other_path, _other_object|
|
64
63
|
other_path.match(/^#{path}\/[^\/]+$/) # TODO: escape
|
65
|
-
end.map do |
|
64
|
+
end.map do |_other_path, other_object|
|
66
65
|
other_object
|
67
66
|
end
|
68
67
|
end
|
69
68
|
end
|
70
|
-
|
71
|
-
|
69
|
+
|
72
70
|
# Class methods:
|
73
|
-
|
71
|
+
|
72
|
+
def self.all
|
73
|
+
objects_by_path.values
|
74
|
+
end
|
75
|
+
|
74
76
|
def self.objects_by_path
|
75
77
|
@objects_by_path ||=
|
76
78
|
begin
|
77
|
-
unless File.directory?(self
|
78
|
-
|
79
|
+
unless File.directory?(self::ROOT)
|
80
|
+
fail StandardError.new("#{self::ROOT} is not a directory")
|
79
81
|
end
|
80
82
|
Hash[
|
81
|
-
Dir[Pathname(self
|
82
|
-
object =
|
83
|
+
Dir[Pathname(self::ROOT) + '**/*.md'].sort.map do |path|
|
84
|
+
object = new(path)
|
83
85
|
[object.path, object]
|
84
86
|
end
|
85
87
|
]
|
86
88
|
end
|
87
89
|
end
|
88
|
-
|
90
|
+
|
89
91
|
def self.find_by_path(path)
|
90
|
-
|
92
|
+
objects_by_path[path] || fail(IndexError.new("'#{path}' is not a valid path under '#{self::ROOT}'; Expected one of #{objects_by_path.keys}"))
|
91
93
|
end
|
92
94
|
|
93
95
|
def self.path_from_file_path(file_path)
|
94
|
-
file_path.to_s.gsub(self
|
96
|
+
file_path.to_s.gsub(self::ROOT + '/', '').gsub(/\.md$/, '')
|
95
97
|
end
|
96
|
-
|
98
|
+
|
97
99
|
def self.extract_html(doc, title)
|
98
100
|
following_siblings = []
|
99
101
|
doc.xpath("//h2[text()='#{title}']").first.tap do |header|
|
100
|
-
|
101
|
-
while header.next_element && !header.next_element.name.match(/h2/)
|
102
|
+
fail IndexError.new("Can't find header '#{title}'") unless header
|
103
|
+
while header.next_element && !header.next_element.name.match(/h2/)
|
102
104
|
following_siblings.push(header.next_element.remove)
|
103
105
|
end
|
104
106
|
header.remove
|
105
107
|
end
|
106
|
-
following_siblings.map
|
108
|
+
following_siblings.map(&:to_s).join
|
107
109
|
end
|
108
|
-
|
110
|
+
|
109
111
|
def self.extract_head_html(doc)
|
110
112
|
siblings = []
|
111
113
|
body = doc.xpath('//body').first
|
112
114
|
while body.children.first && !body.children.first.name.match(/h2/)
|
113
115
|
siblings.push(body.children.first.remove)
|
114
116
|
end
|
115
|
-
siblings.map
|
117
|
+
siblings.map(&:to_s).join.strip
|
116
118
|
end
|
117
|
-
|
119
|
+
|
118
120
|
def self.extract_body_html(doc)
|
119
121
|
siblings = []
|
120
122
|
body = doc.xpath('//body').first
|
121
123
|
while body.children.first
|
122
124
|
siblings.push(body.children.first.remove)
|
123
125
|
end
|
124
|
-
siblings.map
|
126
|
+
siblings.map(&:to_s).join.strip
|
125
127
|
end
|
126
|
-
|
127
|
-
|
128
|
+
|
128
129
|
# Utility class: (This could move.)
|
129
|
-
|
130
|
+
|
131
|
+
# Just a wrapper for Redcarpet
|
130
132
|
class Markdowner
|
131
133
|
include Singleton
|
132
|
-
|
133
|
-
def initialize
|
134
|
+
|
135
|
+
def initialize
|
134
136
|
@markdown = Redcarpet::Markdown.new(
|
135
|
-
|
136
|
-
|
137
|
+
Redcarpet::Render::XHTML.new(with_toc_data: true),
|
138
|
+
autolink: true)
|
137
139
|
end
|
138
|
-
|
140
|
+
|
139
141
|
def render(md_text)
|
140
142
|
return unless md_text
|
141
143
|
@markdown.render(md_text)
|
142
144
|
end
|
143
145
|
end
|
144
|
-
|
145
146
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuck McCallum
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
for display
|
13
|
+
description: |
|
14
|
+
CMS alternative: Content in markdown / Extract HTML and data for display
|
15
15
|
email: chuck_mccallum@wgbh.org
|
16
16
|
executables: []
|
17
17
|
extensions: []
|