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.



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

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.



59
60
61
# File 'lib/utopia/project/base.rb', line 59

def index
  @index
end

#rootObject (readonly)

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



55
56
57
# File 'lib/utopia/project/base.rb', line 55

def root
  @root
end

Class Method Details

.localObject

Load the current project and index its Ruby source files.



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

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.



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

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"


162
163
164
165
166
167
168
169
170
171
# File 'lib/utopia/project/base.rb', line 162

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

Load the supplemental document associated with a definition.



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/utopia/project/base.rb', line 108

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


144
145
146
147
148
149
150
# File 'lib/utopia/project/base.rb', line 144

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.



256
257
258
259
260
# File 'lib/utopia/project/base.rb', line 256

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


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

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"


180
181
182
183
184
185
186
# File 'lib/utopia/project/base.rb', line 180

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"


195
196
197
198
199
200
201
202
203
204
# File 'lib/utopia/project/base.rb', line 195

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

Format source text with links to referenced definitions.



127
128
129
130
131
132
133
134
135
# File 'lib/utopia/project/base.rb', line 127

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])


99
100
101
102
103
# File 'lib/utopia/project/base.rb', line 99

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


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

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

Get the project title from its README.



228
229
230
# File 'lib/utopia/project/base.rb', line 228

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

#readme_documentObject

Load the project README document.



220
221
222
223
224
# File 'lib/utopia/project/base.rb', line 220

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

#releasesObject

Enumerate the project releases.



242
243
244
245
246
# File 'lib/utopia/project/base.rb', line 242

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

#releases_documentObject

Load the project release notes document.



234
235
236
237
238
# File 'lib/utopia/project/base.rb', line 234

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.



77
78
79
# File 'lib/utopia/project/base.rb', line 77

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