Class: Obsidian::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/obsidian/parser/page.rb

Overview

A page in the vault corresponding to either a markdown document, or a directory containing other documents.

If a directory contains an index.md, that is used as the content of the directory page; otherwise content will be nil.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(title:, slug:, last_modified: nil, content: nil, parent: nil) ⇒ Page

Returns a new instance of Page.



14
15
16
17
18
19
20
21
22
# File 'lib/obsidian/parser/page.rb', line 14

def initialize(title:, slug:, last_modified: nil, content: nil, parent: nil)
  # TODO: check frontmatter for titles as well
  @title = title
  @slug = slug
  @last_modified = last_modified
  @content = content
  @parent = parent
  @children = {}
end

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content.



144
145
146
# File 'lib/obsidian/parser/page.rb', line 144

def content
  @content
end

#last_modifiedObject (readonly)

Returns the value of attribute last_modified.



143
144
145
# File 'lib/obsidian/parser/page.rb', line 143

def last_modified
  @last_modified
end

#parentObject (readonly)

Returns the value of attribute parent.



145
146
147
# File 'lib/obsidian/parser/page.rb', line 145

def parent
  @parent
end

#slugObject (readonly)

Returns the value of attribute slug.



142
143
144
# File 'lib/obsidian/parser/page.rb', line 142

def slug
  @slug
end

#titleObject (readonly)

Returns the value of attribute title.



141
142
143
# File 'lib/obsidian/parser/page.rb', line 141

def title
  @title
end

Class Method Details

.create_rootObject



10
11
12
# File 'lib/obsidian/parser/page.rb', line 10

def self.create_root
  Page.new(title: "", slug: "")
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



41
42
43
44
45
# File 'lib/obsidian/parser/page.rb', line 41

def ==(other)
  self.class == other.class &&
    !slug.nil? &&
    slug == other&.slug
end

#add_page(slug, last_modified: nil, content: nil) ⇒ Object

Add a note to the tree based on its slug. Call this method on the root page. When calling this method, you must ensure that anscestor pages are added before their descendents.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/obsidian/parser/page.rb', line 57

def add_page(slug, last_modified: nil, content: nil)
  path_components = slug.split("/")

  if path_components.empty?
    update_content(content: content, last_modified: last_modified)
    return
  end

  title = path_components.pop

  parent = path_components.reduce(self) do |index, anscestor_title|
    anscestor_slug = Obsidian.build_slug(anscestor_title, index.slug)
    index.get_or_create_child(slug: anscestor_slug, title: anscestor_title)
  end

  parent.get_or_create_child(
    title: title,
    slug: slug,
    last_modified: last_modified,
    content: content
  ).tap do |page|
    page.update_content(content: content, last_modified: last_modified)
  end
end

#childrenObject



99
100
101
# File 'lib/obsidian/parser/page.rb', line 99

def children
  @children.values.sort_by { |c| [c.is_index? ? 0 : 1, c.title] }
end

#find_in_tree(query_slug) ⇒ Object

Return the page that matches a slug. If there is an exact match, we should always return that Otherwise, if we can skip over some anscestors and get a match, then return the first, shortest match. If a query slug contains ‘/index` we ignore it and treat it the same as `/`



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/obsidian/parser/page.rb', line 117

def find_in_tree(query_slug)
  # Exact match
  return self if slug == query_slug

  # Partial match
  query_parts = query_slug.split("/").reject { |part| part == "index" }
  length = query_parts.size
  slug_parts = slug.split("/")

  if slug_parts.length >= length
    if slug_parts.slice(-length, length) == query_parts
      return self
    end
  end

  # Recurse
  children.each do |child|
    result = child.find_in_tree(query_slug)
    return result unless result.nil?
  end

  nil
end

#get_or_create_child(title:, slug:, last_modified: nil, content: nil) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/obsidian/parser/page.rb', line 82

def get_or_create_child(title:, slug:, last_modified: nil, content: nil)
  # TODO: validate slug matches the current page slug

  @children[title] ||= Page.new(
    slug: slug,
    title: title,
    last_modified: last_modified,
    content: content,
    parent: self
  )
end

#hashObject



49
50
51
# File 'lib/obsidian/parser/page.rb', line 49

def hash
  slug.hash
end

#inspectObject



28
29
30
# File 'lib/obsidian/parser/page.rb', line 28

def inspect
  "Page(title: #{title.inspect}, slug: #{slug.inspect})"
end

#is_index?Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/obsidian/parser/page.rb', line 24

def is_index?
  !children.empty?
end

#update_content(content:, last_modified:) ⇒ Object



94
95
96
97
# File 'lib/obsidian/parser/page.rb', line 94

def update_content(content:, last_modified:)
  @content ||= content
  @last_modified ||= last_modified
end

#uriObject

Apply percent encoding to the slug



33
34
35
36
37
38
39
# File 'lib/obsidian/parser/page.rb', line 33

def uri
  if slug == ""
    "/"
  else
    "/" + slug.split("/").map { |part| ERB::Util.url_encode(part) }.join("/")
  end
end

#walk_tree(&block) ⇒ Object



103
104
105
106
107
108
109
# File 'lib/obsidian/parser/page.rb', line 103

def walk_tree(&block)
  block.call(self)

  children.each do |page|
    page.walk_tree(&block)
  end
end