sitepress-core 0.1.29 → 2.0.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sitepress-core.rb +3 -2
- data/lib/sitepress/asset.rb +2 -12
- data/lib/sitepress/formats.rb +19 -11
- data/lib/sitepress/node.rb +111 -0
- data/lib/sitepress/path.rb +31 -0
- data/lib/sitepress/resource.rb +37 -12
- data/lib/sitepress/resources_pipeline.rb +1 -1
- data/lib/sitepress/site.rb +15 -25
- data/lib/sitepress/source_node_mapper.rb +57 -0
- data/lib/sitepress/version.rb +1 -1
- data/sitepress-core.gemspec +2 -2
- metadata +16 -16
- data/lib/sitepress/directory_collection.rb +0 -24
- data/lib/sitepress/resources_node.rb +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 704ead2c0f9de6bb248d0ec498ec43e0a8be1b907e037fe6a31c0c12cc04805a
|
4
|
+
data.tar.gz: d720eddebcaf3066c2eae4e8c0efba237cf9156a751c4dbfef88608b333f72c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c543445434532c284bef304d3a6dcc1eb54c714248818e37ae8415aa4c58a6bfbef5c836ed7b1fb0b47efa181d4745e04d7484b68b08af72c955b7c23b6ec74
|
7
|
+
data.tar.gz: 966740865aa555ea9ce5bbd2e4bd6a455cc0e071e6fbbe798db830c2086e2284faa5b6edc1cd1e98ea44a2121e1b6dc20dc19defdde9c62621749563b54c0e14
|
data/lib/sitepress-core.rb
CHANGED
@@ -8,14 +8,15 @@ module Sitepress
|
|
8
8
|
ExistingRequestPathError = Class.new(InvalidRequestPathError)
|
9
9
|
|
10
10
|
autoload :Asset, "sitepress/asset"
|
11
|
-
autoload :DirectoryCollection, "sitepress/directory_collection"
|
12
11
|
autoload :Formats, "sitepress/formats"
|
13
12
|
autoload :Frontmatter, "sitepress/frontmatter"
|
13
|
+
autoload :Node, "sitepress/node"
|
14
|
+
autoload :Path, "sitepress/path"
|
14
15
|
autoload :Resource, "sitepress/resource"
|
15
16
|
autoload :ResourceCollection, "sitepress/resource_collection"
|
16
17
|
autoload :ResourcesPipeline, "sitepress/resources_pipeline"
|
17
|
-
autoload :ResourcesNode, "sitepress/resources_node"
|
18
18
|
autoload :Site, "sitepress/site"
|
19
|
+
autoload :SourceNodeMapper, "sitepress/source_node_mapper"
|
19
20
|
module Middleware
|
20
21
|
autoload :RequestCache, "sitepress/middleware/request_cache"
|
21
22
|
end
|
data/lib/sitepress/asset.rb
CHANGED
@@ -30,10 +30,10 @@ module Sitepress
|
|
30
30
|
path.basename.to_s.split(".").drop(1)
|
31
31
|
end
|
32
32
|
|
33
|
-
# TODO: This is really a "key" or "leafname".
|
34
33
|
def basename
|
35
34
|
path.basename.to_s.split(".").first
|
36
35
|
end
|
36
|
+
alias :node_name :basename
|
37
37
|
|
38
38
|
def format_basename
|
39
39
|
[basename, format_extension].join(".")
|
@@ -64,17 +64,7 @@ module Sitepress
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def exists?
|
67
|
-
File.
|
68
|
-
end
|
69
|
-
|
70
|
-
# Spits out a reasonable default request path. This may be changed
|
71
|
-
# via Resource#request_path.
|
72
|
-
def to_request_path
|
73
|
-
if ext = format_extension
|
74
|
-
path.dirname.join(basename).sub_ext(".#{ext}").to_s
|
75
|
-
else
|
76
|
-
path.to_s
|
77
|
-
end
|
67
|
+
File.exist? path
|
78
68
|
end
|
79
69
|
|
80
70
|
private
|
data/lib/sitepress/formats.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Sitepress
|
2
|
-
# Manages collections of resources that share the same
|
3
|
-
# both of these assets would be stored in the `
|
2
|
+
# Manages collections of resources that share the same Node. Given the files `/a.html` and `/a.gif`,
|
3
|
+
# both of these assets would be stored in the `Node#name = "a"` under `Node#formats` with
|
4
4
|
# the extensions `.gif`, and `.html`.
|
5
5
|
class Formats
|
6
6
|
include Enumerable
|
7
7
|
|
8
8
|
extend Forwardable
|
9
9
|
def_delegators :@formats, :size, :clear
|
10
|
+
def_delegators :@node, :default_format
|
10
11
|
|
11
12
|
def initialize(node: )
|
12
13
|
@node = node
|
@@ -17,12 +18,12 @@ module Sitepress
|
|
17
18
|
@formats.values.each(&block)
|
18
19
|
end
|
19
20
|
|
20
|
-
def remove(
|
21
|
-
@formats.delete(
|
21
|
+
def remove(extension)
|
22
|
+
@formats.delete(symbolize(extension))
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
-
@formats[
|
25
|
+
def get(extension)
|
26
|
+
@formats[symbolize(extension || default_format)]
|
26
27
|
end
|
27
28
|
|
28
29
|
def extensions
|
@@ -33,17 +34,24 @@ module Sitepress
|
|
33
34
|
find { |f| f.mime_type == mime_type }
|
34
35
|
end
|
35
36
|
|
36
|
-
def add(asset
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def add(asset:, format: nil)
|
38
|
+
format = symbolize(format || default_format)
|
39
|
+
|
40
|
+
resource = Resource.new(asset: asset, node: @node, format: format)
|
41
|
+
if @formats.has_key? format
|
42
|
+
raise Sitepress::ExistingRequestPathError, "Resource at #{resource.request_path} already set with format #{format.inspect}"
|
40
43
|
else
|
41
|
-
@formats[
|
44
|
+
@formats[format] = resource
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
def inspect
|
46
49
|
"<#{self.class}: resources=#{map(&:request_path)}>"
|
47
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def symbolize(format)
|
54
|
+
format&.to_sym
|
55
|
+
end
|
48
56
|
end
|
49
57
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Sitepress
|
2
|
+
# Resource nodes give resources their parent/sibling/child relationships. The relationship are determined
|
3
|
+
# by the `request_path` given to an asset when its added to a node. Given the `request_path` `/foo/bar/biz/buz.html`,
|
4
|
+
# a tree of resource nodes would be built named `foo`, `bar`, `biz`, `buz`. `foo` would be the "root" node and `buz`
|
5
|
+
# a leaf node. The actual `buz.html` asset is then stored on the leaf node as a resource. This tree structure
|
6
|
+
# makes it possible to reason through path relationships from code to build out elements in a website like tree navigation.
|
7
|
+
class Node
|
8
|
+
attr_reader :parent, :name, :default_format, :default_name
|
9
|
+
|
10
|
+
# Default extension
|
11
|
+
DEFAULT_EXTENSION = :html
|
12
|
+
|
13
|
+
DEFAULT_NAME = "index".freeze
|
14
|
+
|
15
|
+
def initialize(parent: nil, name: nil, default_format: DEFAULT_EXTENSION, default_name: DEFAULT_NAME)
|
16
|
+
@parent = parent
|
17
|
+
@name = name.freeze
|
18
|
+
@default_format = default_format
|
19
|
+
@default_name = default_name
|
20
|
+
yield self if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
def formats
|
24
|
+
@formats ||= Formats.new(node: self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the immediate children nodes.
|
28
|
+
def children
|
29
|
+
child_nodes.values
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns sibling nodes and self.
|
33
|
+
def siblings
|
34
|
+
parent ? parent.children : []
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns all parents up to the root node.
|
38
|
+
def parents
|
39
|
+
parents = []
|
40
|
+
node = parent
|
41
|
+
while node do
|
42
|
+
parents << node
|
43
|
+
node = node.parent
|
44
|
+
end
|
45
|
+
parents
|
46
|
+
end
|
47
|
+
|
48
|
+
def root?
|
49
|
+
parent.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
def leaf?
|
53
|
+
child_nodes.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def flatten(resources: [])
|
57
|
+
formats.each{ |resource| resources << resource }
|
58
|
+
children.each do |child|
|
59
|
+
child.flatten.each{ |resource| resources << resource }
|
60
|
+
end
|
61
|
+
resources
|
62
|
+
end
|
63
|
+
|
64
|
+
def remove
|
65
|
+
formats.clear
|
66
|
+
parent.remove_child(name) if leaf?
|
67
|
+
end
|
68
|
+
|
69
|
+
def get(path)
|
70
|
+
path = Path.new(path)
|
71
|
+
node = dig(*path.node_names)
|
72
|
+
node.formats.get(path.format) if node
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_child(name)
|
76
|
+
return self if name == default_name
|
77
|
+
child_nodes[name].tap do |node|
|
78
|
+
yield node if block_given?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def inspect
|
83
|
+
"<#{self.class}: name=#{name.inspect} formats=#{formats.map(&:request_path)} children=#{children.map(&:name).inspect}>"
|
84
|
+
end
|
85
|
+
|
86
|
+
def dig(*args)
|
87
|
+
head, *tail = args
|
88
|
+
if (head.nil? or head.empty? or head == default_name) and tail.empty?
|
89
|
+
self
|
90
|
+
elsif child_nodes.has_key?(head)
|
91
|
+
child_nodes[head].dig(*tail)
|
92
|
+
else
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
def remove_child(name)
|
99
|
+
child_nodes.delete(name)
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def build_child(name)
|
104
|
+
Node.new(parent: self, name: name, default_format: default_format, default_name: default_name)
|
105
|
+
end
|
106
|
+
|
107
|
+
def child_nodes
|
108
|
+
@child_nodes ||= Hash.new { |hash, key| hash[key] = build_child(key) }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sitepress
|
2
|
+
class Path
|
3
|
+
DELIMITER = "/".freeze
|
4
|
+
|
5
|
+
attr_reader :node_names, :ext
|
6
|
+
|
7
|
+
def initialize(path, delimiter: DELIMITER)
|
8
|
+
@path = path
|
9
|
+
@delimiter = delimiter
|
10
|
+
parse_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def format
|
14
|
+
format = @ext.partition(".").last
|
15
|
+
return nil if format.nil? or format.empty?
|
16
|
+
format.to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def strip_leading_slash(path)
|
21
|
+
path.to_s.gsub(/^\//, "")
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_path
|
25
|
+
path, _, file = strip_leading_slash(@path).rpartition(@delimiter)
|
26
|
+
@ext = File.extname(file)
|
27
|
+
@file = File.basename(file, @ext)
|
28
|
+
@node_names = path.split(@delimiter).push(@file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/sitepress/resource.rb
CHANGED
@@ -9,23 +9,21 @@ module Sitepress
|
|
9
9
|
def_delegators :asset, :mime_type
|
10
10
|
|
11
11
|
attr_writer :body, :data
|
12
|
-
attr_reader :node, :asset, :
|
12
|
+
attr_reader :node, :asset, :format
|
13
13
|
|
14
14
|
# Default scope for querying parent/child/sibling resources.
|
15
15
|
DEFAULT_FILTER_SCOPE = :same
|
16
16
|
|
17
|
-
|
17
|
+
RENDERABLE_MEDIA_TYPE = "text".freeze
|
18
|
+
|
19
|
+
def initialize(asset:, node:, format: nil)
|
18
20
|
@asset = asset
|
19
21
|
@node = node
|
20
|
-
@
|
22
|
+
@format = format
|
21
23
|
end
|
22
24
|
|
23
25
|
def request_path
|
24
|
-
|
25
|
-
# TODO: This `compact` makes me nervous. How can we handle this better?
|
26
|
-
lineage = node.parents.reverse.map(&:name).compact
|
27
|
-
file_name = [node.name, @ext].join
|
28
|
-
File.join("/", *lineage, file_name)
|
26
|
+
File.join("/", *lineage, request_filename)
|
29
27
|
end
|
30
28
|
|
31
29
|
def data
|
@@ -37,7 +35,7 @@ module Sitepress
|
|
37
35
|
end
|
38
36
|
|
39
37
|
def inspect
|
40
|
-
"<#{self.class}:#{object_id} request_path=#{request_path.inspect} asset_path=#{
|
38
|
+
"<#{self.class}:#{object_id} request_path=#{request_path.inspect} asset_path=#{asset.path.to_s.inspect}>"
|
41
39
|
end
|
42
40
|
|
43
41
|
def parent(**args)
|
@@ -60,6 +58,18 @@ module Sitepress
|
|
60
58
|
resource.request_path == request_path
|
61
59
|
end
|
62
60
|
|
61
|
+
# Used internally to construct paths from the current node up to the root node.
|
62
|
+
def lineage
|
63
|
+
@lineage ||= node.parents.reject(&:root?).reverse.map(&:name)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Certain files, like binary file types, aren't something that we should try to
|
67
|
+
# parse. When this returns true in some cases, a reference to the file will be
|
68
|
+
# passed and skip all the overhead of trying to parse and render.
|
69
|
+
def renderable?
|
70
|
+
asset.mime_type.media_type == RENDERABLE_MEDIA_TYPE
|
71
|
+
end
|
72
|
+
|
63
73
|
private
|
64
74
|
# Filters parent/child/sibling resources by a type. The default behavior is to only return
|
65
75
|
# resources of the same type. For example given the pages `/a.html`, `/a.gif`, `/a/b.html`,
|
@@ -79,14 +89,29 @@ module Sitepress
|
|
79
89
|
when :all
|
80
90
|
nodes.map{ |node| node.formats }
|
81
91
|
when :same
|
82
|
-
nodes.map{ |n| n.formats.
|
83
|
-
when String
|
84
|
-
nodes.map{ |n| n.formats.
|
92
|
+
nodes.map{ |n| n.formats.get(format) }.flatten
|
93
|
+
when String, Symbol, NilClass
|
94
|
+
nodes.map{ |n| n.formats.get(type) }.flatten
|
85
95
|
when MIME::Type
|
86
96
|
nodes.map{ |n| n.formats.mime_type(type) }.flatten
|
87
97
|
else
|
88
98
|
raise ArgumentError, "Invalid type argument #{type}. Must be either :same, :all, an extension string, or a Mime::Type"
|
89
99
|
end
|
90
100
|
end
|
101
|
+
|
102
|
+
# Deals with situations, particularly in the root node and other "index" nodes, for the `request_path`
|
103
|
+
def request_filename
|
104
|
+
if node.root? and node.default_format == format
|
105
|
+
""
|
106
|
+
elsif node.root? and format
|
107
|
+
"#{node.default_name}.#{format}"
|
108
|
+
elsif node.root?
|
109
|
+
node.default_name
|
110
|
+
elsif format.nil? or node.default_format == format
|
111
|
+
node.name
|
112
|
+
else
|
113
|
+
"#{node.name}.#{format}"
|
114
|
+
end
|
115
|
+
end
|
91
116
|
end
|
92
117
|
end
|
data/lib/sitepress/site.rb
CHANGED
@@ -11,7 +11,8 @@ module Sitepress
|
|
11
11
|
# Default root_path for site.
|
12
12
|
DEFAULT_ROOT_PATH = Pathname.new(".").freeze
|
13
13
|
|
14
|
-
attr_reader :root_path
|
14
|
+
attr_reader :root_path
|
15
|
+
attr_writer :resources_pipeline
|
15
16
|
|
16
17
|
# Cache resources for production runs of Sitepress. Development
|
17
18
|
# modes don't cache to optimize for files reloading.
|
@@ -32,8 +33,8 @@ module Sitepress
|
|
32
33
|
# A tree representation of the resourecs wthin the site. The root is a node that's
|
33
34
|
# processed by the `resources_pipeline`.
|
34
35
|
def root
|
35
|
-
|
36
|
-
|
36
|
+
Node.new.tap do |node|
|
37
|
+
source_node_mapper.mount node
|
37
38
|
resources_pipeline.process node
|
38
39
|
end
|
39
40
|
end
|
@@ -41,12 +42,12 @@ module Sitepress
|
|
41
42
|
# Returns a list of all the resources within #root.
|
42
43
|
def resources
|
43
44
|
with_resources_cache do
|
44
|
-
ResourceCollection.new(node: root, root_path:
|
45
|
+
ResourceCollection.new(node: root, root_path: pages_path)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
49
|
def clear_resources_cache
|
49
|
-
@
|
50
|
+
@resources = nil
|
50
51
|
end
|
51
52
|
|
52
53
|
# Root path to website project. Contains helpers, pages, and more.
|
@@ -63,6 +64,10 @@ module Sitepress
|
|
63
64
|
root_path.join("helpers")
|
64
65
|
end
|
65
66
|
|
67
|
+
def assets_path
|
68
|
+
root_path.join("assets")
|
69
|
+
end
|
70
|
+
|
66
71
|
# Quick and dirty way to manipulate resources in the site without
|
67
72
|
# creating classes that implement the #process_resources method.
|
68
73
|
#
|
@@ -97,34 +102,19 @@ module Sitepress
|
|
97
102
|
end
|
98
103
|
|
99
104
|
# An array of procs that manipulate the tree and resources from the
|
100
|
-
#
|
105
|
+
# Node returned by #root.
|
101
106
|
def resources_pipeline
|
102
|
-
@
|
107
|
+
@resources_pipeline ||= ResourcesPipeline.new
|
103
108
|
end
|
104
109
|
|
105
110
|
private
|
106
111
|
def with_resources_cache
|
107
112
|
clear_resources_cache unless cache_resources
|
108
|
-
@
|
113
|
+
@resources ||= yield
|
109
114
|
end
|
110
115
|
|
111
|
-
|
112
|
-
|
113
|
-
# Exclude swap files created by Textmate and vim from being added
|
114
|
-
# to the sitemap.
|
115
|
-
SWAP_FILE_EXTENSIONS = [
|
116
|
-
"~",
|
117
|
-
".swp"
|
118
|
-
]
|
119
|
-
|
120
|
-
# Lazy stream of files that will be rendered by resources.
|
121
|
-
def pages_assets(glob = DEFAULT_GLOB)
|
122
|
-
# TODO: Move this into the DirectoryHandler class so that its not
|
123
|
-
# a concern of site.rb
|
124
|
-
paths = Dir.glob(pages_path.join(glob)).reject do |path|
|
125
|
-
File.directory? path or SWAP_FILE_EXTENSIONS.any? { |ext| path.end_with? ext }
|
126
|
-
end
|
127
|
-
paths.lazy.map { |path| Asset.new(path: path) }
|
116
|
+
def source_node_mapper
|
117
|
+
@source_node_mapper ||= SourceNodeMapper.new(path: pages_path)
|
128
118
|
end
|
129
119
|
end
|
130
120
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Sitepress
|
2
|
+
# Maps a directory of assets into a set of routes that correspond with
|
3
|
+
# the `path` root.
|
4
|
+
class SourceNodeMapper
|
5
|
+
# Exclude swap files created by Textmate and vim from being added
|
6
|
+
# to the sitemap.
|
7
|
+
SWAP_FILE_EXTENSIONS = [
|
8
|
+
"~",
|
9
|
+
".swp",
|
10
|
+
".DS_Store" # TODO: Not a swap file, but something that should be ignored.
|
11
|
+
]
|
12
|
+
|
13
|
+
# Partial rails prefix.
|
14
|
+
PARTIAL_PREFIX = "_".freeze
|
15
|
+
|
16
|
+
attr_reader :assets, :path
|
17
|
+
alias :root :path
|
18
|
+
|
19
|
+
def initialize(path:)
|
20
|
+
@path = path
|
21
|
+
end
|
22
|
+
|
23
|
+
# Mounts the source files from the path to the given node.
|
24
|
+
def mount(node)
|
25
|
+
paths.each do |path, name, format|
|
26
|
+
if path.directory?
|
27
|
+
SourceNodeMapper.new(path: path).mount node.add_child(name)
|
28
|
+
else
|
29
|
+
asset = Asset.new(path: path)
|
30
|
+
node.add_child(name).formats.add(format: format, asset: asset)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
# Returns a list of files, paths, and node names to iterate through to build out nodes
|
37
|
+
def paths
|
38
|
+
Enumerator.new do |y|
|
39
|
+
root.each_child do |path|
|
40
|
+
next if is_swap_file? path
|
41
|
+
next if is_partial_file? path
|
42
|
+
|
43
|
+
node_name, node_format, template_handler = path.basename.to_s.split(".")
|
44
|
+
y << [ path, node_name, node_format&.to_sym ]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def is_partial_file?(path)
|
50
|
+
path.basename.to_s.start_with? PARTIAL_PREFIX
|
51
|
+
end
|
52
|
+
|
53
|
+
def is_swap_file?(path)
|
54
|
+
SWAP_FILE_EXTENSIONS.any? { |ext| path.to_s.end_with? ext }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/sitepress/version.rb
CHANGED
data/sitepress-core.gemspec
CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_development_dependency "bundler", "
|
21
|
-
spec.add_development_dependency "rake", "~>
|
20
|
+
spec.add_development_dependency "bundler", ">= 1.11"
|
21
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
22
22
|
spec.add_development_dependency "rspec", "~> 3.0"
|
23
23
|
|
24
24
|
spec.add_runtime_dependency "mime-types", ">= 2.99"
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sitepress-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0.beta3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Gessler
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.11'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.99'
|
69
|
-
description:
|
69
|
+
description:
|
70
70
|
email:
|
71
71
|
- bradgessler@gmail.com
|
72
72
|
executables: []
|
@@ -75,23 +75,24 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- lib/sitepress-core.rb
|
77
77
|
- lib/sitepress/asset.rb
|
78
|
-
- lib/sitepress/directory_collection.rb
|
79
78
|
- lib/sitepress/extensions/layouts.rb
|
80
79
|
- lib/sitepress/extensions/proc_manipulator.rb
|
81
80
|
- lib/sitepress/formats.rb
|
82
81
|
- lib/sitepress/frontmatter.rb
|
83
82
|
- lib/sitepress/middleware/request_cache.rb
|
83
|
+
- lib/sitepress/node.rb
|
84
|
+
- lib/sitepress/path.rb
|
84
85
|
- lib/sitepress/resource.rb
|
85
86
|
- lib/sitepress/resource_collection.rb
|
86
|
-
- lib/sitepress/resources_node.rb
|
87
87
|
- lib/sitepress/resources_pipeline.rb
|
88
88
|
- lib/sitepress/site.rb
|
89
|
+
- lib/sitepress/source_node_mapper.rb
|
89
90
|
- lib/sitepress/version.rb
|
90
91
|
- sitepress-core.gemspec
|
91
92
|
homepage: https://github.com/sitepress/sitepress
|
92
93
|
licenses: []
|
93
94
|
metadata: {}
|
94
|
-
post_install_message:
|
95
|
+
post_install_message:
|
95
96
|
rdoc_options: []
|
96
97
|
require_paths:
|
97
98
|
- lib
|
@@ -102,13 +103,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
103
|
version: '0'
|
103
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
105
|
requirements:
|
105
|
-
- - "
|
106
|
+
- - ">"
|
106
107
|
- !ruby/object:Gem::Version
|
107
|
-
version:
|
108
|
+
version: 1.3.1
|
108
109
|
requirements: []
|
109
|
-
|
110
|
-
|
111
|
-
signing_key:
|
110
|
+
rubygems_version: 3.2.3
|
111
|
+
signing_key:
|
112
112
|
specification_version: 4
|
113
113
|
summary: An embeddable file-backed content management system.
|
114
114
|
test_files: []
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Sitepress
|
2
|
-
# Maps a directory of assets into a set of routes that correspond with
|
3
|
-
# the `path` root.
|
4
|
-
class DirectoryCollection
|
5
|
-
attr_reader :assets, :path
|
6
|
-
|
7
|
-
def initialize(path: , assets:)
|
8
|
-
@path = path
|
9
|
-
@assets = assets
|
10
|
-
end
|
11
|
-
|
12
|
-
def mount(node)
|
13
|
-
assets.each { |a| node.add path: asset_path_to_request_path(a), asset: a }
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
# Given a @file_path of `/hi`, this method changes `/hi/there/friend.html.erb`
|
18
|
-
# to an absolute `/there/friend` format by removing the file extensions
|
19
|
-
def asset_path_to_request_path(asset)
|
20
|
-
# Relative path of resource to the file_path of this project.
|
21
|
-
asset.path.dirname.join(asset.format_basename).relative_path_from(path).to_s
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
module Sitepress
|
2
|
-
# Resource nodes give resources their parent/sibling/child relationships. The relationship are determined
|
3
|
-
# by the `request_path` given to an asset when its added to a node. Given the `request_path` `/foo/bar/biz/buz.html`,
|
4
|
-
# a tree of resource nodes would be built named `foo`, `bar`, `biz`, `buz`. `foo` would be the "root" node and `buz`
|
5
|
-
# a leaf node. The actual `buz.html` asset is then stored on the leaf node as a resource. This tree structure
|
6
|
-
# makes it possible to reason through path relationships from code to build out elements in a website like tree navigation.
|
7
|
-
class ResourcesNode
|
8
|
-
attr_reader :parent, :name
|
9
|
-
|
10
|
-
DELIMITER = "/".freeze
|
11
|
-
|
12
|
-
def initialize(parent: nil, delimiter: ResourcesNode::DELIMITER, name: nil)
|
13
|
-
@parent = parent
|
14
|
-
@name = name.freeze
|
15
|
-
@delimiter = delimiter.freeze
|
16
|
-
end
|
17
|
-
|
18
|
-
def formats
|
19
|
-
@formats ||= Formats.new(node: self)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Returns the immediate children nodes.
|
23
|
-
def children
|
24
|
-
child_nodes.values
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns sibling nodes.
|
28
|
-
def siblings
|
29
|
-
parent ? parent.children.reject{ |c| c == self } : []
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns all parents up to the root node.
|
33
|
-
def parents
|
34
|
-
parents = []
|
35
|
-
node = parent
|
36
|
-
while node do
|
37
|
-
parents << node
|
38
|
-
node = node.parent
|
39
|
-
end
|
40
|
-
parents
|
41
|
-
end
|
42
|
-
|
43
|
-
def root?
|
44
|
-
parent.nil?
|
45
|
-
end
|
46
|
-
|
47
|
-
def leaf?
|
48
|
-
child_nodes.empty?
|
49
|
-
end
|
50
|
-
|
51
|
-
def flatten(resources: [])
|
52
|
-
formats.each{ |resource| resources << resource }
|
53
|
-
children.each do |child|
|
54
|
-
child.flatten.each{ |resource| resources << resource }
|
55
|
-
end
|
56
|
-
resources
|
57
|
-
end
|
58
|
-
|
59
|
-
def remove
|
60
|
-
if leaf?
|
61
|
-
# TODO: Check the parents to see if they also need to be removed if
|
62
|
-
# this call orphans the tree up to a resource.
|
63
|
-
parent.remove_child(name)
|
64
|
-
else
|
65
|
-
formats.clear
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def add(path: , asset: )
|
70
|
-
head, *path = tokenize(path)
|
71
|
-
if path.empty?
|
72
|
-
# When there's no more paths, we're left with the format (e.g. ".html")
|
73
|
-
formats.add(asset: asset, ext: head)
|
74
|
-
else
|
75
|
-
child_nodes[head].add(path: path, asset: asset)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
alias :[]= :add
|
79
|
-
|
80
|
-
def get(path)
|
81
|
-
*path, ext = tokenize(path)
|
82
|
-
if node = dig(*path)
|
83
|
-
node.formats.ext(ext)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def get_node(path)
|
88
|
-
*path, _ = tokenize(path)
|
89
|
-
dig(*path)
|
90
|
-
end
|
91
|
-
alias :[] :get_node
|
92
|
-
|
93
|
-
def inspect
|
94
|
-
"<#{self.class}: formats=#{formats.map(&:request_path)} children=#{children.map(&:name).inspect}>"
|
95
|
-
end
|
96
|
-
|
97
|
-
# TODO: I don't really like how the path is broken up with the "ext" at the end.
|
98
|
-
# It feels inconsistent. Either make an object/struct that encaspulates this or
|
99
|
-
# just pass `index.html` through to the end.
|
100
|
-
def dig(*args)
|
101
|
-
head, *tail = args
|
102
|
-
if head.nil? and tail.empty?
|
103
|
-
self
|
104
|
-
elsif child_nodes.has_key?(head)
|
105
|
-
child_nodes[head].dig(*tail)
|
106
|
-
else
|
107
|
-
nil
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
protected
|
112
|
-
def remove_child(path)
|
113
|
-
*_, segment, _ = tokenize(path)
|
114
|
-
child_nodes.delete(segment)
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
def add_child_node(name)
|
119
|
-
ResourcesNode.new(parent: self, delimiter: @delimiter, name: name)
|
120
|
-
end
|
121
|
-
|
122
|
-
def child_nodes
|
123
|
-
@child_nodes ||= Hash.new { |hash, key| hash[key] = add_child_node(key) }
|
124
|
-
end
|
125
|
-
|
126
|
-
# Returns all of the names for the path along with the format, if set.
|
127
|
-
def tokenize(path)
|
128
|
-
return path if path.respond_to? :to_a
|
129
|
-
path, _, file = path.gsub(/^\//, "").rpartition(@delimiter)
|
130
|
-
ext = File.extname(file)
|
131
|
-
file = File.basename(file, ext)
|
132
|
-
path.split(@delimiter).push(file).push(ext)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|