mirror of https://github.com/freeCodeCamp/devdocs
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.1 KiB
143 lines
3.1 KiB
module Docs
|
|
class Doc
|
|
INDEX_FILENAME = 'index.json'
|
|
DB_FILENAME = 'db.json'
|
|
|
|
class << self
|
|
include Instrumentable
|
|
|
|
attr_accessor :name, :slug, :type, :release, :abstract, :links
|
|
|
|
def inherited(subclass)
|
|
subclass.type = type
|
|
end
|
|
|
|
def version(version = nil, &block)
|
|
return @version unless block_given?
|
|
|
|
klass = Class.new(self)
|
|
klass.name = name
|
|
klass.slug = slug
|
|
klass.version = version
|
|
klass.release = release
|
|
klass.links = links
|
|
klass.class_exec(&block)
|
|
@versions ||= []
|
|
@versions << klass
|
|
klass
|
|
end
|
|
|
|
def version=(value)
|
|
@version = value.to_s
|
|
end
|
|
|
|
def versions
|
|
@versions.presence || [self]
|
|
end
|
|
|
|
def version?
|
|
version.present?
|
|
end
|
|
|
|
def versioned?
|
|
@versions.presence
|
|
end
|
|
|
|
def name
|
|
@name || super.try(:demodulize)
|
|
end
|
|
|
|
def slug
|
|
slug = @slug || name.try(:downcase)
|
|
version? ? "#{slug}~#{version_slug}" : slug
|
|
end
|
|
|
|
def version_slug
|
|
slug = version.downcase
|
|
slug.gsub! '+', 'p'
|
|
slug.gsub! '#', 's'
|
|
slug.gsub! %r{[^a-z0-9\_\.]}, '_'
|
|
slug
|
|
end
|
|
|
|
def path
|
|
slug
|
|
end
|
|
|
|
def index_path
|
|
File.join path, INDEX_FILENAME
|
|
end
|
|
|
|
def db_path
|
|
File.join path, DB_FILENAME
|
|
end
|
|
|
|
def as_json
|
|
json = { name: name, slug: slug, type: type }
|
|
json[:links] = links if links.present?
|
|
json[:version] = version if version.present? || defined?(@version)
|
|
json[:release] = release if release.present?
|
|
json
|
|
end
|
|
|
|
def store_page(store, id)
|
|
store.open(path) do
|
|
if page = new.build_page(id) and store_page?(page)
|
|
store.write page[:store_path], page[:output]
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
|
|
def store_pages(store)
|
|
index = EntryIndex.new
|
|
pages = PageDb.new
|
|
|
|
store.replace(path) do
|
|
new.build_pages do |page|
|
|
next unless store_page?(page)
|
|
store.write page[:store_path], page[:output]
|
|
index.add page[:entries]
|
|
pages.add page[:path], page[:output]
|
|
end
|
|
|
|
if index.present?
|
|
store_index(store, INDEX_FILENAME, index)
|
|
store_index(store, DB_FILENAME, pages)
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def store_page?(page)
|
|
page[:entries].present?
|
|
end
|
|
|
|
def store_index(store, filename, index)
|
|
old_json = store.read(filename) || '{}'
|
|
new_json = index.to_json
|
|
instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
|
|
store.write(filename, new_json)
|
|
end
|
|
end
|
|
|
|
def initialize
|
|
raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated." if self.class.abstract
|
|
end
|
|
|
|
def build_page(id, &block)
|
|
raise NotImplementedError
|
|
end
|
|
|
|
def build_pages(&block)
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
end
|