Class: Utopia::Project::Base

Inherits:
Object
  • Object
show all
Extended by:
Thread::Local
Defined in:
lib/utopia/project/base.rb

Overview

Provides structured access to a project directory which contains source code and guides.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root = Dir.pwd) ⇒ Base

Initialize the project with the given root path.



41
42
43
44
45
46
47
48
49
# File 'lib/utopia/project/base.rb', line 41

def initialize(root = Dir.pwd)
  @root = root
  
  @source_path = Utopia::Path["/source"]
  
  @index = Decode::Index.new
  
  @links = Utopia::Content::Links.new(@root)
end

Instance Attribute Details

#indexObject

The source code index which is used for generating pages.



57
58
59
# File 'lib/utopia/project/base.rb', line 57

def index
  @index
end

#rootObject (readonly)

The file-system path to the root of the project.



53
54
55
# File 'lib/utopia/project/base.rb', line 53

def root
  @root
end

Class Method Details

.localObject



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/utopia/project/base.rb', line 27

def self.local
  instance = self.new
  
  source_files = Dir.glob(
    File.expand_path("{lib,app}/**/*.rb", instance.root)
  )
  
  instance.update(source_files)
  
  return instance
end

Instance Method Details

#best(definitions) ⇒ Object

Given an array of defintions, return the best definition for the purposes of generating documentation.



81
82
83
84
85
86
87
88
89
# File 'lib/utopia/project/base.rb', line 81

def best(definitions)
  definitions.each do |definition|
    if definition.documentation
      return definition
    end
  end
  
  return definitions.first
end

#document(text, definition = nil, language: definition&.language) ⇒ Object

Convert the given markdown text into HTML.

Updates source code references ({language identifier}) into links.

Examples:

Convert markdown to HTML

base = Utopia::Project::Base.new
doc = base.document("# Title")
doc.to_html # => "<h1>Title</h1>\n"


152
153
154
155
156
157
158
159
160
161
# File 'lib/utopia/project/base.rb', line 152

def document(text, definition = nil, language: definition&.language)
  case text
  when Enumerable
    text = text.to_a.join("\n")
  when nil
    return nil
  end
  
  Document.new(text, self, definition: definition, default_language: language)
end

#document_for(definition) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/utopia/project/base.rb', line 103

def document_for(definition)
  document_path = File.join("lib", definition.lexical_path.map{|_| _.to_s.downcase}) + ".md"
  
  if File.exist?(document_path)
    document = self.document(File.read(document_path), definition)
    
    if document.first_child.type == :header
      document.first_child.delete
    end
    
    return document
  end
end

#format(text, definition = nil, language: definition&.language, **options) ⇒ Object

Format the given text in the context of the given definition and language. See #document for details.

Examples:

Format text with code links

base = Utopia::Project::Base.new
base.format("See {Utopia::Project::Base#guides}.") # => XRB::MarkupString


134
135
136
137
138
139
140
# File 'lib/utopia/project/base.rb', line 134

def format(text, definition = nil, language: definition&.language, **options)
  if document = self.document(text, definition, language: language)
    return XRB::Markup.raw(
      document.to_html(**options)
    )
  end
end

#gemspecObject

Load and return the gemspec for this project.



238
239
240
241
242
# File 'lib/utopia/project/base.rb', line 238

def gemspec
  if gemspec_path = self.gemspec_path
    @gemspec ||= ::Gem::Specification.load(File.join(@root, gemspec_path))
  end
end

#guidesObject

Get the guides collection for this project.

Examples:

List guide titles

base = Utopia::Project::Base.new
base.guides.each do |guide|
  puts guide.title
end


204
205
206
# File 'lib/utopia/project/base.rb', line 204

def guides
  @guides ||= Guides.new(self, @links)
end

#id_for(definition, suffix = nil) ⇒ Object

Compute a unique string which can be used as id attribute in the HTML output.

Examples:

Compute id for a definition

base = Utopia::Project::Base.local
_, definition = base.lookup(i[Utopia Project Base])
base.id_for(definition) # => "Utopia::Project::Base"


170
171
172
173
174
175
176
# File 'lib/utopia/project/base.rb', line 170

def id_for(definition, suffix = nil)
  if suffix
    "#{definition.qualified_name}-#{suffix}"
  else
    definition.qualified_name
  end
end

Compute a link href to the given definition for use within the HTML output.

Examples:

Link to a definition

base = Utopia::Project::Base.local
_, definition = base.lookup(i[Utopia Project Base])
base.link_for(definition).to_s # => "/source/utopia/project/index#Utopia::Project::Base"


185
186
187
188
189
190
191
192
193
194
# File 'lib/utopia/project/base.rb', line 185

def link_for(definition)
  path = definition.lexical_path.map{|entry| entry.to_s}
  
  if definition.container?
    return XRB::Reference.new(@source_path + path + "index")
  else
    name = path.pop
    return XRB::Reference.new(@source_path + path + "index", fragment: id_for(definition))
  end
end

#linkify(text, definition, language: definition&.language) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/utopia/project/base.rb', line 117

def linkify(text, definition, language: definition&.language)
  rewriter = Linkify.new(self, language, text)
  
  code = language.code_for(text, @index, relative_to: definition)
  
  code.extract(rewriter)
  
  return rewriter.apply
end

#lookup(path) ⇒ Object

Given a lexical path, find the best definition for that path.

Examples:

Lookup a definition

base = Utopia::Project::Base.local
_, definition = base.lookup(i[Utopia Project Base])


97
98
99
100
101
# File 'lib/utopia/project/base.rb', line 97

def lookup(path)
  if node = @index.trie.lookup(path.map(&:to_sym))
    return node, best(node.values)
  end
end

#path_for(file_name) ⇒ Object

Return the absolute path for the given file name, if it exists in the project.

Examples:

Get README path

base = Utopia::Project::Base.new
base.path_for("readme.md") # => "/path/to/project/readme.md" or nil


66
67
68
69
70
71
# File 'lib/utopia/project/base.rb', line 66

def path_for(file_name)
  full_path = File.expand_path(file_name, @root)
  if File.exist?(full_path)
    return full_path
  end
end

#project_titleObject



214
215
216
# File 'lib/utopia/project/base.rb', line 214

def project_title
  readme_document&.title || "Project"
end

#readme_documentObject



208
209
210
211
212
# File 'lib/utopia/project/base.rb', line 208

def readme_document
  if path = self.path_for("readme.md") || self.path_for("README.md")
    Document.new(File.read(path), self)
  end
end

#releasesObject



224
225
226
227
228
# File 'lib/utopia/project/base.rb', line 224

def releases
  if releases_document = self.releases_document
    releases_document.releases
  end
end

#releases_documentObject



218
219
220
221
222
# File 'lib/utopia/project/base.rb', line 218

def releases_document
  if path = self.path_for("releases.md")
    ReleasesDocument.new(File.read(path), self)
  end
end

#update(paths) ⇒ Object

Update the index with the specified paths.



75
76
77
# File 'lib/utopia/project/base.rb', line 75

def update(paths)
  @index.update(paths)
end