Class: Brief::Document
Defined Under Namespace
Modules: Attachments, FrontMatter, Rendering, Templating
Classes: ContentExtractor, Section, Structure
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#has_attachments?, #render_attachments
Methods included from Templating
#generate_content
#data=, #frontmatter_line_count
Methods included from Rendering
#script_contents, #script_preamble, #to_html, #unwrapped_html
Constructor Details
#initialize(path, options = {}) ⇒ Document
Returns a new instance of Document.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# File 'lib/brief/document.rb', line 13
def initialize(path, options = {})
if path.respond_to?(:key?) && options.empty?
@frontmatter = path.to_mash
else
@path = Pathname(path)
end
@options = options.to_mash
if @path && self.path.exist?
@raw_content = self.path.read
load_frontmatter
elsif options[:contents]
@raw_content = options[:contents]
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object
291
292
293
294
295
296
297
|
# File 'lib/brief/document.rb', line 291
def method_missing(meth, *args, &block)
if data.respond_to?(meth)
data.send(meth, *args, &block)
else
super
end
end
|
Instance Attribute Details
#content ⇒ Object
Returns the value of attribute content.
11
12
13
|
# File 'lib/brief/document.rb', line 11
def content
@content
end
|
#frontmatter ⇒ Object
Returns the value of attribute frontmatter.
11
12
13
|
# File 'lib/brief/document.rb', line 11
def frontmatter
@frontmatter
end
|
#options ⇒ Object
Returns the value of attribute options.
11
12
13
|
# File 'lib/brief/document.rb', line 11
def options
@options
end
|
#path ⇒ Object
Returns the value of attribute path.
11
12
13
|
# File 'lib/brief/document.rb', line 11
def path
@path
end
|
#raw_content ⇒ Object
Returns the value of attribute raw_content.
11
12
13
|
# File 'lib/brief/document.rb', line 11
def raw_content
@raw_content
end
|
Class Method Details
.from_contents(content, frontmatter, &block) ⇒ Object
8
9
|
# File 'lib/brief/document.rb', line 8
def self.from_contents(content, frontmatter, &block)
end
|
Instance Method Details
#at(*args, &block) ⇒ Object
Returns a Nokogiri::HTML::Element
186
187
188
|
# File 'lib/brief/document.rb', line 186
def at(*args, &block)
parser.send(:at, *args, &block)
end
|
#attachments ⇒ Object
115
116
117
|
# File 'lib/brief/document.rb', line 115
def attachments
Array(data.attachments)
end
|
#briefcase ⇒ Object
129
130
131
|
# File 'lib/brief/document.rb', line 129
def briefcase
(@briefcase_root && Brief.cases[@briefcase_root]) || Brief.case
end
|
#combined_data_and_content ⇒ Object
102
103
104
105
|
# File 'lib/brief/document.rb', line 102
def combined_data_and_content
return content if data.nil? || data.empty?
frontmatter.to_hash.to_yaml + "---\n\n#{ content }"
end
|
#content_hash ⇒ Object
46
47
48
|
# File 'lib/brief/document.rb', line 46
def content_hash
Digest::MD5.hexdigest(@content.to_s)
end
|
#content_stale? ⇒ Boolean
54
55
56
|
# File 'lib/brief/document.rb', line 54
def content_stale?
content_hash != file_hash
end
|
#css(*args, &block) ⇒ Object
Shortcut for querying the rendered HTML by css selectors.
This will allow for model data attributes to be pulled from the document contents.
Returns a Nokogiri::HTML::Element
181
182
183
|
# File 'lib/brief/document.rb', line 181
def css(*args, &block)
parser.send(:css, *args, &block)
end
|
#data ⇒ Object
107
108
109
|
# File 'lib/brief/document.rb', line 107
def data
frontmatter
end
|
#document ⇒ Object
30
31
32
|
# File 'lib/brief/document.rb', line 30
def document
self
end
|
#document_type ⇒ Object
245
246
247
|
# File 'lib/brief/document.rb', line 245
def document_type
options.fetch(:type) { document_type! }
end
|
#document_type! ⇒ Object
249
250
251
252
253
|
# File 'lib/brief/document.rb', line 249
def document_type!
existing = data && data.type
return existing if existing
parent_folder_name.try(:singularize)
end
|
#exist? ⇒ Boolean
226
227
228
|
# File 'lib/brief/document.rb', line 226
def exist?
path && path.exist?
end
|
#extension ⇒ Object
212
213
214
|
# File 'lib/brief/document.rb', line 212
def extension
path.extname
end
|
190
191
192
193
194
195
196
197
198
199
200
201
202
|
# File 'lib/brief/document.rb', line 190
def (*args)
options = args.
args = options.delete(:args) if options.is_a?(Hash) && options.key?(:args)
case
when options.empty? && args.length == 1 && args.first.is_a?(String)
results = css(args.first)
results = results.first if results.length > 1 && args.first.match(/:first-of-type/)
results.try(:text).to_s
else
binding.pry
end
end
|
#file_hash ⇒ Object
50
51
52
|
# File 'lib/brief/document.rb', line 50
def file_hash
Digest::MD5.hexdigest(path.read.to_s)
end
|
#fragment ⇒ Object
283
284
285
|
# File 'lib/brief/document.rb', line 283
def fragment
@fragment ||= Nokogiri::HTML.fragment(to_raw_html)
end
|
#has_sections? ⇒ Boolean
133
134
135
|
# File 'lib/brief/document.rb', line 133
def has_sections?
model_class.section_mappings.length > 0
end
|
#in_briefcase(briefcase) ⇒ Object
119
120
121
122
123
124
125
126
127
|
# File 'lib/brief/document.rb', line 119
def in_briefcase(briefcase)
@briefcase_root = briefcase.root
unless Brief::Util.ensure_child_path(briefcase.docs_path, path)
raise 'Invalid document path'
end
self
end
|
#include_attachments? ⇒ Boolean
111
112
113
|
# File 'lib/brief/document.rb', line 111
def include_attachments?
attachments.length > 0
end
|
#inspect ⇒ Object
38
39
40
|
# File 'lib/brief/document.rb', line 38
def inspect
"#{ model_class }.at_path(#{relative_path})"
end
|
#model_attributes ⇒ Object
216
217
218
219
220
|
# File 'lib/brief/document.rb', line 216
def model_attributes
(data || {}).to_hash
.merge(path: path, document: self)
.reverse_merge(type: document_type)
end
|
#model_class ⇒ Object
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
# File 'lib/brief/document.rb', line 230
def model_class
case
when @model_class
@model_class
when briefcase
briefcase.model_class_for(self)
when data && data.type
Brief::Model.for_type(data.type)
when parent_folder_name.length > 0
Brief::Model.for_folder_name(parent_folder_name)
else
raise 'Could not determine the model class to use for this document. Specify the type, or put it in a folder that maps to the correct type.'
end
end
|
#model_instance_registered? ⇒ Boolean
Each model class tracks the instances of the models created and ensures that there is a 1-1 relationship between a document path and the model.
262
263
264
265
266
|
# File 'lib/brief/document.rb', line 262
def model_instance_registered?
model_class && model_class.models.any? do |model|
model.path == path
end
end
|
#parent_folder_name ⇒ Object
255
256
257
|
# File 'lib/brief/document.rb', line 255
def parent_folder_name
path.parent.basename.to_s.downcase
end
|
#parser ⇒ Object
276
277
278
279
280
281
|
# File 'lib/brief/document.rb', line 276
def parser
@parser ||= begin
structure.prescan
structure.create_wrappers
end
end
|
#raw=(val) ⇒ Object
58
59
60
61
62
63
|
# File 'lib/brief/document.rb', line 58
def raw= val
@raw_set = true
@raw_content = val
@raw_content
end
|
#refresh! ⇒ Object
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/brief/document.rb', line 80
def refresh!
@content = nil
@raw_content = path.read
@frontmatter = nil
@raw_frontmatter = nil
@refreshing = true
@content_hash = nil
load_frontmatter
true
end
|
#relative_path ⇒ Object
42
43
44
|
# File 'lib/brief/document.rb', line 42
def relative_path
briefcase.present? ? path.relative_path_from(briefcase.docs_path) : path
end
|
#relative_path_identifier ⇒ Object
204
205
206
207
208
209
210
|
# File 'lib/brief/document.rb', line 204
def relative_path_identifier
if Brief.case
path.relative_path_from(Brief.case.root)
else
path.to_s
end
end
|
#respond_to?(method) ⇒ Boolean
268
269
270
|
# File 'lib/brief/document.rb', line 268
def respond_to?(method)
super || (data && data.respond_to?(method)) || (data && data.key?(method))
end
|
#save ⇒ Object
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/brief/document.rb', line 69
def save
if set_raw?
file_contents = raw_content
else
file_contents = combined_data_and_content
end
path.open('w') {|fh| fh.write(file_contents) }
refresh!
end
|
#save! ⇒ Object
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/brief/document.rb', line 91
def save!
if set_raw?
file_contents = raw_content
else
file_contents = combined_data_and_content
end
path.open('w+') {|fh| fh.write(file_contents) }
refresh!
end
|
#section_headings ⇒ Object
137
138
139
|
# File 'lib/brief/document.rb', line 137
def section_headings
sections.keys
end
|
#sections ⇒ Object
150
151
152
153
154
155
156
157
158
159
160
161
|
# File 'lib/brief/document.rb', line 150
def sections
mappings = model_class.section_mappings
@sections = {}.to_mash
mappings.each do |name, mapping|
fragment = css("section[data-heading='#{name}']").first
@sections[name.parameterize.downcase.underscore] = Brief::Document::Section.new(name, fragment, mapping)
end
@sections
end
|
#sections_data ⇒ Object
141
142
143
144
145
146
147
148
|
# File 'lib/brief/document.rb', line 141
def sections_data
section_headings.reduce({}) do |memo, heading|
section = sections.send(heading)
items = section.items rescue nil
memo[heading] = items if items
memo
end
end
|
#set_raw? ⇒ Boolean
65
66
67
|
# File 'lib/brief/document.rb', line 65
def set_raw?
!!@raw_set
end
|
#structure ⇒ Object
272
273
274
|
# File 'lib/brief/document.rb', line 272
def structure
@structure_analyzer ||= Brief::Document::Structure.new(fragment, raw_content.lines.to_a)
end
|
#to_model ⇒ Object
222
223
224
|
# File 'lib/brief/document.rb', line 222
def to_model
model_class.try(:new, model_attributes)
end
|
#to_s ⇒ Object
34
35
36
|
# File 'lib/brief/document.rb', line 34
def to_s
"#{ model_class }.at_path(#{relative_path})"
end
|
#type ⇒ Object
287
288
289
|
# File 'lib/brief/document.rb', line 287
def type
document_type
end
|