sitepress-core 2.0.0.beta4 → 2.0.0.beta9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa11bbd1b48f37ec8ac67ca5c7e097988dd3c3c5b15d4e8c286bc182bfccd005
4
- data.tar.gz: e57cbd1a867e08e028c07d54a07a3b4212871202fe22f95680d70c7f62dab602
3
+ metadata.gz: 9a7a004d33fe5e05c2e1831ebcd902dc9c6bbcbf4650437b6e36984a1eb0e263
4
+ data.tar.gz: 9bd65a5f76ee6b166337887619e825c48c4580cb082448c63c8d78d1c549759b
5
5
  SHA512:
6
- metadata.gz: 48b3f8cca37f6c6b5d6ebf97d5d90edac5cb318c8f0f2481ef5b36157f80cca9b566a4066d746e7061fe4158c8134914102339d40deae3eaf6292718745c7b26
7
- data.tar.gz: 47b7cc455168355572800e2a95f7654838c7d86f17a3873317008d502f5c1e16afa19d896a80a84fb298db5e51c7ad760b17b713afcbde294e882001ad56564b
6
+ metadata.gz: 213d67af29c1e88c03f3ad72cb81001a2a938f418ca41717288f757581a409ec6daba877bdca903bb0a650c140d71e7252c113d2b4e0d9334b2e2726122ddb54
7
+ data.tar.gz: 68e40ac58a005c54262b050a3bc430eb3d2b81124705ce8aca39a87a3f0d07dd0fe9ab43283ead764c8afa9a00bf611fe6a903c2beb24d91b7eced7226b3ca7a
@@ -17,7 +17,4 @@ module Sitepress
17
17
  autoload :ResourcesPipeline, "sitepress/resources_pipeline"
18
18
  autoload :Site, "sitepress/site"
19
19
  autoload :SourceNodeMapper, "sitepress/source_node_mapper"
20
- module Middleware
21
- autoload :RequestCache, "sitepress/middleware/request_cache"
22
- end
23
20
  end
@@ -17,41 +17,13 @@ module Sitepress
17
17
 
18
18
  extend Forwardable
19
19
  def_delegators :frontmatter, :data, :body
20
+ def_delegators :path, :handler, :node_name, :format, :exists?
20
21
 
21
22
  def initialize(path: , mime_type: nil)
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 = Pathname.new path
26
- end
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
55
27
  end
56
28
 
57
29
  # Treat resources with the same request path as equal.
@@ -63,19 +35,22 @@ module Sitepress
63
35
  @mime_type ||= inferred_mime_type || DEFAULT_MIME_TYPE
64
36
  end
65
37
 
66
- def exists?
67
- File.exist? path
38
+ # Used by the Rails controller to short circuit additional processing if the
39
+ # asset is not renderable (e.g. is it erb or haml?)
40
+ def renderable?
41
+ !!handler
68
42
  end
69
43
 
70
44
  private
71
- def frontmatter
72
- Frontmatter.new File.read @path
73
- end
74
-
75
- # Returns the mime type of the file extension. If a type can't
76
- # be resolved then we'll just grab the first type.
77
- def inferred_mime_type
78
- MIME::Types.type_for(format_extension).first if format_extension
79
- end
45
+ def frontmatter
46
+ Frontmatter.new File.read path
47
+ end
48
+
49
+ # Returns the mime type of the file extension. If a type can't
50
+ # be resolved then we'll just grab the first type.
51
+ def inferred_mime_type
52
+ format_extension = path.format&.to_s
53
+ MIME::Types.type_for(format_extension).first if format_extension
54
+ end
80
55
  end
81
56
  end
@@ -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
@@ -80,7 +80,7 @@ module Sitepress
80
80
  end
81
81
 
82
82
  def inspect
83
- "<#{self.class}: name=#{name.inspect} formats=#{formats.map(&:request_path)} children=#{children.map(&:name).inspect}>"
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)
@@ -1,31 +1,127 @@
1
+ require "pathname"
2
+ require "mime-types"
3
+
1
4
  module Sitepress
2
5
  class Path
3
- DELIMITER = "/".freeze
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
- attr_reader :node_names, :ext
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 initialize(path, delimiter: DELIMITER)
8
- @path = path
9
- @delimiter = delimiter
10
- parse_path
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
- format = @ext.partition(".").last
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
- def strip_leading_slash(path)
21
- path.to_s.gsub(/^\//, "")
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
- 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)
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
@@ -6,7 +6,7 @@ module Sitepress
6
6
  # and may be altered by the resource proxy.
7
7
  class Resource
8
8
  extend Forwardable
9
- def_delegators :asset, :mime_type
9
+ def_delegators :asset, :mime_type, :handler
10
10
 
11
11
  attr_writer :body, :data
12
12
  attr_reader :node, :asset, :format
@@ -14,8 +14,6 @@ module Sitepress
14
14
  # Default scope for querying parent/child/sibling resources.
15
15
  DEFAULT_FILTER_SCOPE = :same
16
16
 
17
- RENDERABLE_MEDIA_TYPE = "text".freeze
18
-
19
17
  def initialize(asset:, node:, format: nil)
20
18
  @asset = asset
21
19
  @node = node
@@ -67,7 +65,7 @@ module Sitepress
67
65
  # parse. When this returns true in some cases, a reference to the file will be
68
66
  # passed and skip all the overhead of trying to parse and render.
69
67
  def renderable?
70
- asset.mime_type.media_type == RENDERABLE_MEDIA_TYPE
68
+ asset.renderable?
71
69
  end
72
70
 
73
71
  private
@@ -14,26 +14,18 @@ module Sitepress
14
14
  attr_reader :root_path
15
15
  attr_writer :resources_pipeline
16
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
21
-
22
17
  # TODO: Get rid of these so that folks have ot call site.resources.get ...
23
18
  extend Forwardable
24
19
  def_delegators :resources, :get, :glob
25
20
 
26
21
  def initialize(root_path: DEFAULT_ROOT_PATH)
27
22
  self.root_path = root_path
28
- # When Site#resources is called, the results should be cached in production
29
- # environments for performance reasons, but not in development environments.
30
- self.cache_resources = false
31
23
  end
32
24
 
33
25
  # A tree representation of the resourecs wthin the site. The root is a node that's
34
26
  # processed by the `resources_pipeline`.
35
27
  def root
36
- Node.new.tap do |node|
28
+ @root ||= Node.new.tap do |node|
37
29
  source_node_mapper.mount node
38
30
  resources_pipeline.process node
39
31
  end
@@ -41,13 +33,12 @@ module Sitepress
41
33
 
42
34
  # Returns a list of all the resources within #root.
43
35
  def resources
44
- with_resources_cache do
45
- ResourceCollection.new(node: root, root_path: pages_path)
46
- end
36
+ @resources ||= ResourceCollection.new(node: root, root_path: pages_path)
47
37
  end
48
38
 
49
- def clear_resources_cache
50
- @resources = nil
39
+ def reload!
40
+ @resources = @root = nil
41
+ self
51
42
  end
52
43
 
53
44
  # Root path to website project. Contains helpers, pages, and more.
@@ -108,10 +99,6 @@ module Sitepress
108
99
  end
109
100
 
110
101
  private
111
- def with_resources_cache
112
- clear_resources_cache unless cache_resources
113
- @resources ||= yield
114
- end
115
102
 
116
103
  def source_node_mapper
117
104
  @source_node_mapper ||= SourceNodeMapper.new(path: pages_path)
@@ -4,10 +4,11 @@ module Sitepress
4
4
  class SourceNodeMapper
5
5
  # Exclude swap files created by Textmate and vim from being added
6
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.
7
+ IGNORE_FILE_PATTERNS = [
8
+ "*~", # Created by many editors when things crash
9
+ "*.swp", # Created by vim
10
+ ".DS_Store", # Created by our friends at Apple
11
+ "*.orig" # Created when there's a git conflict
11
12
  ]
12
13
 
13
14
  # Partial rails prefix.
@@ -22,12 +23,13 @@ module Sitepress
22
23
 
23
24
  # Mounts the source files from the path to the given node.
24
25
  def mount(node)
25
- paths.each do |path, name, format|
26
+ paths.each do |path|
26
27
  if path.directory?
28
+ name = File.basename path
27
29
  SourceNodeMapper.new(path: path).mount node.add_child(name)
28
30
  else
29
31
  asset = Asset.new(path: path)
30
- node.add_child(name).formats.add(format: format, asset: asset)
32
+ node.add_child(asset.node_name).formats.add(format: asset.format, asset: asset)
31
33
  end
32
34
  end
33
35
  end
@@ -37,21 +39,22 @@ module Sitepress
37
39
  def paths
38
40
  Enumerator.new do |y|
39
41
  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 ]
42
+ next if ignore_file? path
43
+ y << path
45
44
  end
46
45
  end
47
46
  end
48
47
 
48
+ def ignore_file?(path)
49
+ is_partial_file?(path) or matches_ignore_file_pattern?(path)
50
+ end
51
+
49
52
  def is_partial_file?(path)
50
53
  path.basename.to_s.start_with? PARTIAL_PREFIX
51
54
  end
52
55
 
53
- def is_swap_file?(path)
54
- SWAP_FILE_EXTENSIONS.any? { |ext| path.to_s.end_with? ext }
56
+ def matches_ignore_file_pattern?(path)
57
+ IGNORE_FILE_PATTERNS.any? { |pattern| path.fnmatch? pattern }
55
58
  end
56
59
  end
57
60
  end
@@ -1,3 +1,3 @@
1
1
  module Sitepress
2
- VERSION = "2.0.0.beta4".freeze
2
+ VERSION = "2.0.0.beta9".freeze
3
3
  end
@@ -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.beta4
4
+ version: 2.0.0.beta9
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-02-24 00:00:00.000000000 Z
11
+ date: 2021-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,7 +79,6 @@ files:
79
79
  - lib/sitepress/extensions/proc_manipulator.rb
80
80
  - lib/sitepress/formats.rb
81
81
  - lib/sitepress/frontmatter.rb
82
- - lib/sitepress/middleware/request_cache.rb
83
82
  - lib/sitepress/node.rb
84
83
  - lib/sitepress/path.rb
85
84
  - lib/sitepress/resource.rb
@@ -90,7 +89,8 @@ files:
90
89
  - lib/sitepress/version.rb
91
90
  - sitepress-core.gemspec
92
91
  homepage: https://github.com/sitepress/sitepress
93
- licenses: []
92
+ licenses:
93
+ - MIT
94
94
  metadata: {}
95
95
  post_install_message:
96
96
  rdoc_options: []
@@ -107,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
107
  - !ruby/object:Gem::Version
108
108
  version: 1.3.1
109
109
  requirements: []
110
- rubygems_version: 3.2.3
110
+ rubygems_version: 3.1.4
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  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