sitepress-core 2.0.0.beta7 → 2.0.0.beta11
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 -5
- data/lib/sitepress/asset.rb +25 -43
- data/lib/sitepress/asset_node_mapper.rb +45 -0
- data/lib/sitepress/asset_paths.rb +49 -0
- data/lib/sitepress/formats.rb +3 -1
- data/lib/sitepress/frontmatter.rb +1 -1
- data/lib/sitepress/node.rb +1 -1
- data/lib/sitepress/parsers.rb +12 -0
- data/lib/sitepress/parsers/base.rb +15 -0
- data/lib/sitepress/parsers/frontmatter.rb +23 -0
- data/lib/sitepress/parsers/notion.rb +31 -0
- data/lib/sitepress/path.rb +112 -16
- data/lib/sitepress/resource.rb +8 -9
- data/lib/sitepress/site.rb +11 -25
- data/lib/sitepress/version.rb +1 -1
- data/sitepress-core.gemspec +1 -0
- metadata +11 -6
- data/lib/sitepress/middleware/request_cache.rb +0 -26
- data/lib/sitepress/source_node_mapper.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc50a42114bd539241b9912de736e7e7a0bd100b8dab7888d0066ce7a8d90d23
|
4
|
+
data.tar.gz: 57f845092973c3c5914cbf1a694d405dde8c0b4848c4814886d3a03622160571
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 303e85302ad15b352a66a0f3a7c03cecf16194465b353236009f4cd0373c8a98d87a18a753b5dc9df884c593e44f8d00b8495fb2abff681eed525d3e806ac2ee
|
7
|
+
data.tar.gz: 60510800525f2de93ceb161950217d5c261ae92fbbb7ecf46c254cbbfdae2204e44522f0ab7105d362f28d82c837c07a7d7ec18c73cefc525efa7ed68287b625
|
data/lib/sitepress-core.rb
CHANGED
@@ -8,16 +8,14 @@ module Sitepress
|
|
8
8
|
ExistingRequestPathError = Class.new(InvalidRequestPathError)
|
9
9
|
|
10
10
|
autoload :Asset, "sitepress/asset"
|
11
|
+
autoload :AssetNodeMapper, "sitepress/asset_node_mapper"
|
12
|
+
autoload :AssetPaths, "sitepress/asset_paths"
|
11
13
|
autoload :Formats, "sitepress/formats"
|
12
|
-
autoload :Frontmatter, "sitepress/frontmatter"
|
13
14
|
autoload :Node, "sitepress/node"
|
14
15
|
autoload :Path, "sitepress/path"
|
16
|
+
autoload :Parsers, "sitepress/parsers"
|
15
17
|
autoload :Resource, "sitepress/resource"
|
16
18
|
autoload :ResourceCollection, "sitepress/resource_collection"
|
17
19
|
autoload :ResourcesPipeline, "sitepress/resources_pipeline"
|
18
20
|
autoload :Site, "sitepress/site"
|
19
|
-
autoload :SourceNodeMapper, "sitepress/source_node_mapper"
|
20
|
-
module Middleware
|
21
|
-
autoload :RequestCache, "sitepress/middleware/request_cache"
|
22
|
-
end
|
23
21
|
end
|
data/lib/sitepress/asset.rb
CHANGED
@@ -4,7 +4,7 @@ require "pathname"
|
|
4
4
|
|
5
5
|
module Sitepress
|
6
6
|
# Represents a file on a web server that may be parsed to extract
|
7
|
-
#
|
7
|
+
# metadata or be renderable via a template. Multiple resources
|
8
8
|
# may point to the same asset. Properties of an asset should be mutable.
|
9
9
|
# The Resource object is immutable and may be modified by the Resources proxy.
|
10
10
|
class Asset
|
@@ -16,42 +16,15 @@ module Sitepress
|
|
16
16
|
attr_reader :path
|
17
17
|
|
18
18
|
extend Forwardable
|
19
|
-
def_delegators :
|
19
|
+
def_delegators :parser, :data, :body
|
20
|
+
def_delegators :path, :handler, :node_name, :format, :exists?
|
20
21
|
|
21
|
-
def initialize(path: ,
|
22
|
+
def initialize(path:, mime_type: nil, parser: Parsers::Frontmatter)
|
22
23
|
# The MIME::Types gem returns an array when types are looked up.
|
23
24
|
# This grabs the first one, which is likely the intent on these lookups.
|
24
25
|
@mime_type = Array(mime_type).first
|
25
|
-
@path =
|
26
|
-
|
27
|
-
|
28
|
-
# List of all file extensions.
|
29
|
-
def extensions
|
30
|
-
path.basename.to_s.split(".").drop(1)
|
31
|
-
end
|
32
|
-
|
33
|
-
def basename
|
34
|
-
path.basename.to_s.split(".").first
|
35
|
-
end
|
36
|
-
alias :node_name :basename
|
37
|
-
|
38
|
-
def format_basename
|
39
|
-
[basename, format_extension].join(".")
|
40
|
-
end
|
41
|
-
|
42
|
-
# Returns the format extension.
|
43
|
-
def format_extension
|
44
|
-
extensions.first
|
45
|
-
end
|
46
|
-
|
47
|
-
# The base name with the format extension.
|
48
|
-
def format_name
|
49
|
-
[basename, format_extension].join(".")
|
50
|
-
end
|
51
|
-
|
52
|
-
# Returns a list of the rendering extensions.
|
53
|
-
def template_extensions
|
54
|
-
extensions.drop(1)
|
26
|
+
@path = Path.new path
|
27
|
+
@parser_klass = parser
|
55
28
|
end
|
56
29
|
|
57
30
|
# Treat resources with the same request path as equal.
|
@@ -63,19 +36,28 @@ module Sitepress
|
|
63
36
|
@mime_type ||= inferred_mime_type || DEFAULT_MIME_TYPE
|
64
37
|
end
|
65
38
|
|
66
|
-
|
67
|
-
|
39
|
+
# Used by the Rails controller to short circuit additional processing if the
|
40
|
+
# asset is not renderable (e.g. is it erb or haml?)
|
41
|
+
def renderable?
|
42
|
+
!!handler
|
68
43
|
end
|
69
44
|
|
70
|
-
|
71
|
-
def
|
72
|
-
|
45
|
+
# Set the parser equal to a thing.
|
46
|
+
def parser=(parser_klass)
|
47
|
+
@parser = nil
|
48
|
+
@parser_klass = parser_klass
|
73
49
|
end
|
74
50
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
51
|
+
private
|
52
|
+
def parser
|
53
|
+
@parser ||= @parser_klass.new File.read path
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the mime type of the file extension. If a type can't
|
57
|
+
# be resolved then we'll just grab the first type.
|
58
|
+
def inferred_mime_type
|
59
|
+
format_extension = path.format&.to_s
|
60
|
+
MIME::Types.type_for(format_extension).first if format_extension
|
61
|
+
end
|
80
62
|
end
|
81
63
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Sitepress
|
2
|
+
# Maps a tree of Directory and Asset objects in a a tree of nodes that
|
3
|
+
# format the navigational structure of a website. You can override this
|
4
|
+
# this in a site to deal with different file systems. For example, Notion
|
5
|
+
# has a completely different file structure for its content than Rails, so
|
6
|
+
# we could extend this class to properly map those differences into a tree
|
7
|
+
# of nodes.
|
8
|
+
class AssetNodeMapper
|
9
|
+
attr_reader :node, :asset_paths
|
10
|
+
|
11
|
+
def initialize(path:, node:)
|
12
|
+
@asset_paths = AssetPaths.new(path: path)
|
13
|
+
@node = node
|
14
|
+
end
|
15
|
+
|
16
|
+
# Mounts the source files from the path to the given node.
|
17
|
+
def map
|
18
|
+
asset_paths.each do |path|
|
19
|
+
if path.directory?
|
20
|
+
process_directory path
|
21
|
+
else
|
22
|
+
process_asset path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def process_directory(path)
|
30
|
+
node_name = File.basename path
|
31
|
+
node_mapper path: path, node: node.add_child(node_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_asset(path)
|
35
|
+
asset = Asset.new(path: path)
|
36
|
+
node.add_child(asset.node_name).formats.add(format: asset.format, asset: asset)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def node_mapper(*args, **kwargs)
|
42
|
+
self.class.new(*args, **kwargs).map
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module Sitepress
|
4
|
+
# Iterates through a folder, ignores partials and files that are well known to
|
5
|
+
# not be part of the website files, like `.DS_Store`, etc.
|
6
|
+
class AssetPaths
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# Exclude swap files created by Textmate and vim from being added
|
10
|
+
# to the sitemap.
|
11
|
+
IGNORE_FILE_PATTERNS = [
|
12
|
+
"*~", # Created by many editors when things crash
|
13
|
+
"*.swp", # Created by vim
|
14
|
+
".DS_Store", # Created by our friends at Apple
|
15
|
+
"*.orig" # Created when there's a git conflict
|
16
|
+
]
|
17
|
+
|
18
|
+
# Template files that start with `_user.html.erb` are partials that we want
|
19
|
+
# to ignore for the site's navigation tree.
|
20
|
+
PARTIAL_PREFIX = "_".freeze
|
21
|
+
|
22
|
+
attr_reader :path
|
23
|
+
|
24
|
+
def initialize(path:)
|
25
|
+
@path = Pathname.new(path)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a list of files, paths, and node names to iterate through to build out nodes
|
29
|
+
def each
|
30
|
+
path.each_child do |path|
|
31
|
+
yield path unless ignore_file? path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def ignore_file?(path)
|
38
|
+
is_partial_file?(path) or matches_ignore_file_pattern?(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_partial_file?(path)
|
42
|
+
path.basename.to_s.start_with? PARTIAL_PREFIX
|
43
|
+
end
|
44
|
+
|
45
|
+
def matches_ignore_file_pattern?(path)
|
46
|
+
IGNORE_FILE_PATTERNS.any? { |pattern| path.basename.fnmatch? pattern }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/sitepress/formats.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
1
3
|
module Sitepress
|
2
4
|
# Manages collections of resources that share the same Node. Given the files `/a.html` and `/a.gif`,
|
3
5
|
# both of these assets would be stored in the `Node#name = "a"` under `Node#formats` with
|
@@ -19,7 +21,7 @@ module Sitepress
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def remove(extension)
|
22
|
-
@formats.delete
|
24
|
+
@formats.delete symbolize(extension)
|
23
25
|
end
|
24
26
|
|
25
27
|
def get(extension)
|
@@ -5,7 +5,7 @@ module Sitepress
|
|
5
5
|
|
6
6
|
# TODO: Redo this to use File readline and pos to
|
7
7
|
# perform faster
|
8
|
-
class Frontmatter
|
8
|
+
class Parsers::Frontmatter
|
9
9
|
DELIMITER = "---".freeze
|
10
10
|
NEWLINE = /\r\n?|\n/.freeze
|
11
11
|
PATTERN = /\A(#{DELIMITER}#{NEWLINE}(.+?)#{NEWLINE}#{DELIMITER}#{NEWLINE}*)?(.+)\Z/m
|
data/lib/sitepress/node.rb
CHANGED
@@ -80,7 +80,7 @@ module Sitepress
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def inspect
|
83
|
-
"<#{self.class}: name=#{name.inspect} formats=#{formats.
|
83
|
+
"<#{self.class}: name=#{name.inspect}, formats=#{formats.extensions.inspect}, children=#{children.map(&:name).inspect}, resource_request_paths=#{formats.map(&:request_path)}>"
|
84
84
|
end
|
85
85
|
|
86
86
|
def dig(*args)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Sitepress
|
4
|
+
# Parsers parse the data and the body out of an asset. The resulting
|
5
|
+
# data is referenced by `Resource#data`, which is `current_page.data`
|
6
|
+
# from page templates.
|
7
|
+
module Parsers
|
8
|
+
autoload :Base, "sitepress/parsers/base"
|
9
|
+
autoload :Frontmatter, "sitepress/parsers/frontmatter"
|
10
|
+
autoload :Notion, "sitepress/parsers/notion"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Sitepress
|
4
|
+
module Parsers
|
5
|
+
# Parses metadata from the header of the page.
|
6
|
+
|
7
|
+
# TODO: Redo this to use File readline and pos to
|
8
|
+
# perform faster
|
9
|
+
class Frontmatter < Base
|
10
|
+
DELIMITER = "---".freeze
|
11
|
+
NEWLINE = /\r\n?|\n/.freeze
|
12
|
+
PATTERN = /\A(#{DELIMITER}#{NEWLINE}(.+?)#{NEWLINE}#{DELIMITER}#{NEWLINE}*)?(.+)\Z/m
|
13
|
+
|
14
|
+
def initialize(content)
|
15
|
+
_, @data, @body = content.match(PATTERN).captures
|
16
|
+
end
|
17
|
+
|
18
|
+
def data
|
19
|
+
@data ? YAML.load(@data) : {}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Sitepress
|
4
|
+
module Parsers
|
5
|
+
# Parses metadata from the header of the page.
|
6
|
+
class Notion < Base
|
7
|
+
DELIMITER = /\n\n/.freeze
|
8
|
+
TITLE_KEY = "Title".freeze
|
9
|
+
KEY_DELIMITER = ":".freeze
|
10
|
+
|
11
|
+
def initialize(content)
|
12
|
+
scanner = StringScanner.new(content)
|
13
|
+
# Parse title
|
14
|
+
scanner.scan(/# (.+)#{DELIMITER}/)
|
15
|
+
@title = scanner.captures.first
|
16
|
+
# Parse metadata
|
17
|
+
@raw_data = []
|
18
|
+
while scanner.scan(/(.+?)#{KEY_DELIMITER} (.+)\n/)
|
19
|
+
@raw_data.append scanner.captures
|
20
|
+
end
|
21
|
+
scanner.scan(/\n/)
|
22
|
+
# Parse body
|
23
|
+
@body = scanner.rest
|
24
|
+
end
|
25
|
+
|
26
|
+
def data
|
27
|
+
Hash[@raw_data.prepend([TITLE_KEY, @title])]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/sitepress/path.rb
CHANGED
@@ -1,31 +1,127 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "mime-types"
|
3
|
+
|
1
4
|
module Sitepress
|
2
5
|
class Path
|
3
|
-
|
6
|
+
# Default handler extensions. Handlers are anything that render or
|
7
|
+
# manipulate the contents of the file into a different output, like
|
8
|
+
# ERB or HAML.
|
9
|
+
HANDLER_EXTENSIONS = %i[haml erb md markdown]
|
10
|
+
|
11
|
+
# The root node name is a blank string.
|
12
|
+
ROOT_NODE_NAME = "".freeze
|
13
|
+
|
14
|
+
# The name of the root path
|
15
|
+
ROOT_PATH = "/".freeze
|
16
|
+
|
17
|
+
attr_reader :handler, :format, :path, :node_name, :dirname, :basename
|
18
|
+
|
19
|
+
# When Rails boots, it sets the handler extensions so that paths
|
20
|
+
# can be properly parsed.
|
21
|
+
class << self
|
22
|
+
attr_writer :handler_extensions
|
23
|
+
|
24
|
+
def handler_extensions
|
25
|
+
@handler_extensions ||= HANDLER_EXTENSIONS
|
26
|
+
end
|
27
|
+
end
|
4
28
|
|
5
|
-
|
29
|
+
def initialize(path, path_seperator: File::SEPARATOR, handler_extensions: self.class.handler_extensions)
|
30
|
+
@path = path.to_s
|
31
|
+
@path_seperator = Regexp.new(path_seperator)
|
32
|
+
@handler_extensions = handler_extensions
|
33
|
+
parse
|
34
|
+
end
|
35
|
+
|
36
|
+
def node_names
|
37
|
+
@node_names ||= node_name_ancestors.push(node_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Necessary for operations like `File.read path` where `path` is an instance
|
41
|
+
# of this object.
|
42
|
+
def to_str
|
43
|
+
@path
|
44
|
+
end
|
45
|
+
alias :to_s :to_str
|
46
|
+
|
47
|
+
def ==(path)
|
48
|
+
to_s == path.to_s
|
49
|
+
end
|
6
50
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
51
|
+
def exists?
|
52
|
+
File.exists? path
|
53
|
+
end
|
54
|
+
|
55
|
+
def expand_path
|
56
|
+
File.expand_path path
|
11
57
|
end
|
12
58
|
|
13
59
|
def format
|
14
|
-
|
15
|
-
return nil if format.nil? or format.empty?
|
16
|
-
format.to_sym
|
60
|
+
(handler_is_format? ? handler : @format)&.to_sym
|
17
61
|
end
|
18
62
|
|
19
63
|
private
|
20
|
-
|
21
|
-
|
64
|
+
# TODO: I don't want to look this up everytime I try to figure out the
|
65
|
+
# extension. I'll have to create an extension registry .
|
66
|
+
|
67
|
+
# Rails has handlers, like `:html` and `:raw` that are both
|
68
|
+
# handlers and formats. If we don't account for this, then the object
|
69
|
+
# would return a `nil` for a file named `blah.html`.
|
70
|
+
def handler_is_format?
|
71
|
+
return false if @handler.nil?
|
72
|
+
@format.nil? and MIME::Types.type_for(@handler.to_s).any?
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse
|
76
|
+
@dirname, @basename = File.split(path)
|
77
|
+
parse_basename
|
78
|
+
end
|
79
|
+
|
80
|
+
# Given a filename, this will work out the extensions, formats, and node_name.
|
81
|
+
def parse_basename
|
82
|
+
base = basename
|
83
|
+
filename, extname = split_filename(base)
|
84
|
+
|
85
|
+
# This is a root path, so we have to treat it a little differently
|
86
|
+
# so that the node mapper and node names work properly.
|
87
|
+
if filename == ROOT_PATH and extname.nil?
|
88
|
+
@node_name = ROOT_NODE_NAME
|
89
|
+
elsif extname
|
90
|
+
extname = extname.to_sym
|
91
|
+
|
92
|
+
# We have an extension! Let's figure out if its a handler or not.
|
93
|
+
if @handler_extensions.include? extname
|
94
|
+
# Yup, its a handler. Set those variables accordingly.
|
95
|
+
@handler = extname
|
96
|
+
base = filename
|
97
|
+
end
|
98
|
+
|
99
|
+
# Now let's get the format (e.g. :html, :xml, :json) for the path and
|
100
|
+
# the key, which is just the basename without the format extension.
|
101
|
+
@node_name, format = split_filename(base)
|
102
|
+
@format = format
|
103
|
+
else
|
104
|
+
@node_name = filename
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# If given a path `/a/b/c`, thsi would return `["a", "b", "c"].
|
109
|
+
def node_name_ancestors
|
110
|
+
strip_leading_prefix(File.dirname(path)).split(@path_seperator)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Make it easier to split the last extension off a filename.
|
114
|
+
# For example, if you run `split_filename("c.taco.html")`
|
115
|
+
# it would return `["c.taco", "html"]`. If you ran it against
|
116
|
+
# something like `split_filename("c")`, it would return `["c"]`
|
117
|
+
def split_filename(string)
|
118
|
+
base, _, extension = string.rpartition(".")
|
119
|
+
base.empty? ? [extension] : [base, extension]
|
22
120
|
end
|
23
121
|
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
@file = File.basename(file, @ext)
|
28
|
-
@node_names = path.split(@delimiter).push(@file)
|
122
|
+
# Strips leading `/` or leading `.` if the path is relative.
|
123
|
+
def strip_leading_prefix(dirname)
|
124
|
+
dirname.to_s.gsub(/^#{@path_seperator}|\./, "")
|
29
125
|
end
|
30
126
|
end
|
31
127
|
end
|
data/lib/sitepress/resource.rb
CHANGED
@@ -5,21 +5,20 @@ module Sitepress
|
|
5
5
|
# resources that point to the same asset. Resources are immutable
|
6
6
|
# and may be altered by the resource proxy.
|
7
7
|
class Resource
|
8
|
-
extend Forwardable
|
9
|
-
def_delegators :asset, :mime_type
|
10
|
-
|
11
8
|
attr_writer :body, :data
|
12
|
-
attr_reader :node, :asset
|
9
|
+
attr_reader :node, :asset
|
10
|
+
|
11
|
+
attr_accessor :format, :mime_type, :handler
|
13
12
|
|
14
13
|
# Default scope for querying parent/child/sibling resources.
|
15
14
|
DEFAULT_FILTER_SCOPE = :same
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(asset:, node:, format: nil)
|
16
|
+
def initialize(asset:, node:, format: nil, mime_type: nil, handler: nil)
|
20
17
|
@asset = asset
|
21
18
|
@node = node
|
22
|
-
@format = format
|
19
|
+
@format = format || asset.format
|
20
|
+
@mime_type = mime_type || asset.mime_type
|
21
|
+
@handler = handler || asset.handler
|
23
22
|
end
|
24
23
|
|
25
24
|
def request_path
|
@@ -67,7 +66,7 @@ module Sitepress
|
|
67
66
|
# parse. When this returns true in some cases, a reference to the file will be
|
68
67
|
# passed and skip all the overhead of trying to parse and render.
|
69
68
|
def renderable?
|
70
|
-
asset.
|
69
|
+
asset.renderable?
|
71
70
|
end
|
72
71
|
|
73
72
|
private
|
data/lib/sitepress/site.rb
CHANGED
@@ -11,13 +11,12 @@ module Sitepress
|
|
11
11
|
# Default root_path for site.
|
12
12
|
DEFAULT_ROOT_PATH = Pathname.new(".").freeze
|
13
13
|
|
14
|
+
# Maps Rail-ish template files & structures into the site's node tree.
|
15
|
+
DEFAULT_NODE_MAPPER = AssetNodeMapper
|
16
|
+
|
14
17
|
attr_reader :root_path
|
15
18
|
attr_writer :resources_pipeline
|
16
|
-
|
17
|
-
# Cache resources for production runs of Sitepress. Development
|
18
|
-
# modes don't cache to optimize for files reloading.
|
19
|
-
attr_accessor :cache_resources
|
20
|
-
alias :cache_resources? :cache_resources
|
19
|
+
attr_accessor :node_mapper
|
21
20
|
|
22
21
|
# TODO: Get rid of these so that folks have ot call site.resources.get ...
|
23
22
|
extend Forwardable
|
@@ -25,29 +24,26 @@ module Sitepress
|
|
25
24
|
|
26
25
|
def initialize(root_path: DEFAULT_ROOT_PATH)
|
27
26
|
self.root_path = root_path
|
28
|
-
|
29
|
-
# environments for performance reasons, but not in development environments.
|
30
|
-
self.cache_resources = false
|
27
|
+
self.node_mapper = DEFAULT_NODE_MAPPER
|
31
28
|
end
|
32
29
|
|
33
30
|
# A tree representation of the resourecs wthin the site. The root is a node that's
|
34
31
|
# processed by the `resources_pipeline`.
|
35
32
|
def root
|
36
|
-
Node.new.tap do |node|
|
37
|
-
|
33
|
+
@root ||= Node.new.tap do |node|
|
34
|
+
node_mapper.new(path: pages_path, node: node).map
|
38
35
|
resources_pipeline.process node
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
39
|
# Returns a list of all the resources within #root.
|
43
40
|
def resources
|
44
|
-
|
45
|
-
ResourceCollection.new(node: root, root_path: pages_path)
|
46
|
-
end
|
41
|
+
@resources ||= ResourceCollection.new(node: root, root_path: pages_path)
|
47
42
|
end
|
48
43
|
|
49
|
-
def
|
50
|
-
@resources = nil
|
44
|
+
def reload!
|
45
|
+
@resources = @root = nil
|
46
|
+
self
|
51
47
|
end
|
52
48
|
|
53
49
|
# Root path to website project. Contains helpers, pages, and more.
|
@@ -106,15 +102,5 @@ module Sitepress
|
|
106
102
|
def resources_pipeline
|
107
103
|
@resources_pipeline ||= ResourcesPipeline.new
|
108
104
|
end
|
109
|
-
|
110
|
-
private
|
111
|
-
def with_resources_cache
|
112
|
-
clear_resources_cache unless cache_resources
|
113
|
-
@resources ||= yield
|
114
|
-
end
|
115
|
-
|
116
|
-
def source_node_mapper
|
117
|
-
@source_node_mapper ||= SourceNodeMapper.new(path: pages_path)
|
118
|
-
end
|
119
105
|
end
|
120
106
|
end
|
data/lib/sitepress/version.rb
CHANGED
data/sitepress-core.gemspec
CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Sitepress::VERSION
|
9
9
|
spec.authors = ["Brad Gessler"]
|
10
10
|
spec.email = ["bradgessler@gmail.com"]
|
11
|
+
spec.licenses = ["MIT"]
|
11
12
|
|
12
13
|
spec.summary = %q{An embeddable file-backed content management system.}
|
13
14
|
spec.homepage = "https://github.com/sitepress/sitepress"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sitepress-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Gessler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,22 +75,27 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- lib/sitepress-core.rb
|
77
77
|
- lib/sitepress/asset.rb
|
78
|
+
- lib/sitepress/asset_node_mapper.rb
|
79
|
+
- lib/sitepress/asset_paths.rb
|
78
80
|
- lib/sitepress/extensions/layouts.rb
|
79
81
|
- lib/sitepress/extensions/proc_manipulator.rb
|
80
82
|
- lib/sitepress/formats.rb
|
81
83
|
- lib/sitepress/frontmatter.rb
|
82
|
-
- lib/sitepress/middleware/request_cache.rb
|
83
84
|
- lib/sitepress/node.rb
|
85
|
+
- lib/sitepress/parsers.rb
|
86
|
+
- lib/sitepress/parsers/base.rb
|
87
|
+
- lib/sitepress/parsers/frontmatter.rb
|
88
|
+
- lib/sitepress/parsers/notion.rb
|
84
89
|
- lib/sitepress/path.rb
|
85
90
|
- lib/sitepress/resource.rb
|
86
91
|
- lib/sitepress/resource_collection.rb
|
87
92
|
- lib/sitepress/resources_pipeline.rb
|
88
93
|
- lib/sitepress/site.rb
|
89
|
-
- lib/sitepress/source_node_mapper.rb
|
90
94
|
- lib/sitepress/version.rb
|
91
95
|
- sitepress-core.gemspec
|
92
96
|
homepage: https://github.com/sitepress/sitepress
|
93
|
-
licenses:
|
97
|
+
licenses:
|
98
|
+
- MIT
|
94
99
|
metadata: {}
|
95
100
|
post_install_message:
|
96
101
|
rdoc_options: []
|
@@ -107,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
112
|
- !ruby/object:Gem::Version
|
108
113
|
version: 1.3.1
|
109
114
|
requirements: []
|
110
|
-
rubygems_version: 3.
|
115
|
+
rubygems_version: 3.2.3
|
111
116
|
signing_key:
|
112
117
|
specification_version: 4
|
113
118
|
summary: An embeddable file-backed content management system.
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Sitepress
|
2
|
-
module Middleware
|
3
|
-
# Reloads the Sitepress cache between requests if cache resources is enabled.
|
4
|
-
# This ensures that the Sitepress resources are loaded only once per request
|
5
|
-
# for development environments so that the site isn're reloaded per call. Used
|
6
|
-
# from the Rails app and from the stand-alone Sitepress server.
|
7
|
-
class RequestCache
|
8
|
-
def initialize(app, site:)
|
9
|
-
@app, @site = app, site
|
10
|
-
end
|
11
|
-
|
12
|
-
# Cache resources for the duration of the request, even if
|
13
|
-
# caching is disabled.
|
14
|
-
def call(env)
|
15
|
-
cache_resources = @site.cache_resources
|
16
|
-
begin
|
17
|
-
@site.cache_resources = true
|
18
|
-
@app.call env
|
19
|
-
ensure
|
20
|
-
@site.cache_resources = cache_resources
|
21
|
-
@site.clear_resources_cache unless @site.cache_resources
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,57 +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 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
|