sitepress-core 3.1.4 → 3.2.1

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: fbbed93cfbaf395da33ffb939720222ee959dc3f1a7319e09a17fe27b1455fc9
4
- data.tar.gz: d38a5eba66742b7c58380058b9ff7889800a5842e39a8ba4f5045b815245eb6e
3
+ metadata.gz: 0f5128994ea5970446da051ce17c700fd2a0ad99c1bd2716bc8628b244ca7e21
4
+ data.tar.gz: ce9393f3fa9218eda6fbc41523e2be852f91f069cb41a2fd50e8964e945a1555
5
5
  SHA512:
6
- metadata.gz: a6dff42c8c8ee2041700db14cbf569030022b8a9e2b6202504173137ceedaf6c686aaf9da5171cf80e860064dd302323327ab0a30b7ca27a1f75dd6f2f0ac874
7
- data.tar.gz: c91b64049fe1b1b93908c2e356d2d10d0632dd926421c48f1f8aa80e71558624659c7a3cfdd001f54ac5f727ff1ed4db6e39a692cd2b560fd5fce025361da3d9
6
+ metadata.gz: edc9fb30418337a90b81d0de0dd7a08c306222d3ac45598393a21586ba3cd6a9527f3d52820ae6844886adbea6b5a16b441a22cc2bb62e5a2d870617616436d1
7
+ data.tar.gz: 27b342cae371ec2a524c2a999c3f99abbf34ead1168d6650150fea5bfe450ea55f3d8b4bdd35f6d295f6560a8edf1a08e7bf38b9449fd18c1a4c05ebd097cb40
@@ -1,5 +1,6 @@
1
1
  require "mime/types"
2
2
  require "forwardable"
3
+ require "fileutils"
3
4
 
4
5
  module Sitepress
5
6
  # Represents a file on a web server that may be parsed to extract
@@ -19,7 +20,7 @@ module Sitepress
19
20
  attr_reader :path
20
21
 
21
22
  extend Forwardable
22
- def_delegators :parser, :data, :body
23
+ def_delegators :renderer, :render
23
24
  def_delegators :path, :handler, :node_name, :format, :exists?
24
25
 
25
26
  def initialize(path:, mime_type: nil, parser: DEFAULT_PARSER)
@@ -30,6 +31,14 @@ module Sitepress
30
31
  @parser_klass = parser
31
32
  end
32
33
 
34
+ def data
35
+ @data ||= exists? ? parse_error { parser.data } : {}
36
+ end
37
+
38
+ def body
39
+ @body ||= exists? ? parse_error { parser.body } : nil
40
+ end
41
+
33
42
  # Treat resources with the same request path as equal.
34
43
  def ==(asset)
35
44
  path == asset.path
@@ -39,8 +48,9 @@ module Sitepress
39
48
  @mime_type ||= inferred_mime_type || DEFAULT_MIME_TYPE
40
49
  end
41
50
 
42
- # Used by the Rails controller to short circuit additional processing if the
43
- # asset is not renderable (e.g. is it erb or haml?)
51
+ # Certain files, like binary file types, aren't something that we should try to
52
+ # parse. When this returns true in some cases, a reference to the file will be
53
+ # passed and skip all the overhead of trying to parse and render.
44
54
  def renderable?
45
55
  !!handler
46
56
  end
@@ -51,7 +61,33 @@ module Sitepress
51
61
  @parser_klass = parser_klass
52
62
  end
53
63
 
64
+ def updated_at
65
+ File.mtime path
66
+ end
67
+
68
+ def created_at
69
+ File.ctime path
70
+ end
71
+
72
+ def destroy
73
+ FIleUtils.rm path
74
+ end
75
+
76
+ def save
77
+ File.write path, render
78
+ end
79
+
80
+ def renderer
81
+ @parser_klass::Renderer.new(data: data, body: body)
82
+ end
83
+
54
84
  private
85
+ def parse_error(&parse)
86
+ parse.call
87
+ rescue StandardError => e
88
+ raise ParseError.new("Error parsing asset at #{path.to_s}: #{e}")
89
+ end
90
+
55
91
  def parser
56
92
  @parser ||= @parser_klass.new File.read path
57
93
  end
@@ -0,0 +1,47 @@
1
+ module Sitepress
2
+ class Data
3
+ def initialize(data)
4
+ @data = data
5
+ end
6
+
7
+ def fetch(key, *args, &block)
8
+ wrap_value { @data.fetch(key.to_s, *args, &block) }
9
+ end
10
+
11
+ def [](key)
12
+ wrap_value { @data[key.to_s] }
13
+ end
14
+
15
+ def method_missing(name, *args, **kwargs, &block)
16
+ if respond_to? name
17
+ self.send name, *args, **kwargs, &block
18
+ else
19
+ key, modifier, _ = name.to_s.partition("!")
20
+ wrap_value do
21
+ case modifier
22
+ when ""
23
+ @data[key]
24
+ when "!"
25
+ @data.fetch(key)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def dig(*args, **kwargs, &block)
32
+ wrap_value { @data.dig(*args, **kwargs, &block) }
33
+ end
34
+
35
+ private
36
+ def wrap_value(&block)
37
+ case value = block.call
38
+ when Hash
39
+ self.class.new value
40
+ when Array
41
+ value.map { |v| wrap_value { v } }
42
+ else
43
+ value
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,12 +1,46 @@
1
1
  require "yaml"
2
+ require "date"
2
3
 
3
4
  module Sitepress
4
5
  module Parsers
5
6
  # Parses metadata from the header of the page.
6
-
7
- # TODO: Redo this to use File readline and pos to
8
- # perform faster
9
7
  class Frontmatter < Base
8
+ class Renderer
9
+ attr_reader :body, :data
10
+
11
+ def initialize(body:, data:)
12
+ @body = body
13
+ @data = data
14
+ end
15
+
16
+ def dump_yaml(data)
17
+ if YAML.respond_to? :safe_dump
18
+ YAML.safe_dump data, permitted_classes: Frontmatter.permitted_classes
19
+ else
20
+ # Live dangerously, lol
21
+ YAML.dump data
22
+ end
23
+ end
24
+
25
+ def render
26
+ [
27
+ dump_yaml(data),
28
+ Frontmatter::DELIMITER,
29
+ $/,
30
+ $/,
31
+ body
32
+ ].join
33
+ end
34
+ end
35
+
36
+ # Default classes that we'll allow YAML to parse. Ideally this doesn't
37
+ # get too huge and we let users control it by setting
38
+ # `Sitepress::Parsers::Frontmatter.permitted_classes = [Whatever, SuperDanger]`
39
+ PERMITTED_CLASSES = [
40
+ Date,
41
+ Time
42
+ ]
43
+
10
44
  DELIMITER = "---".freeze
11
45
  NEWLINE = /\r\n?|\n/.freeze
12
46
  PATTERN = /\A(#{DELIMITER}#{NEWLINE}(.+?)#{NEWLINE}#{DELIMITER}#{NEWLINE}*)?(.+)\Z/m
@@ -16,7 +50,24 @@ module Sitepress
16
50
  end
17
51
 
18
52
  def data
19
- @data ? YAML.load(@data) : {}
53
+ @data ? load_yaml(@data) : {}
54
+ end
55
+
56
+ def load_yaml(data)
57
+ if YAML.respond_to? :safe_load
58
+ YAML.safe_load data, permitted_classes: self.class.permitted_classes
59
+ else
60
+ # Live dangerously, lol
61
+ YAML.load data
62
+ end
63
+ end
64
+
65
+ class << self
66
+ attr_writer :permitted_classes
67
+
68
+ def permitted_classes
69
+ @permitted_classes ||= PERMITTED_CLASSES
70
+ end
20
71
  end
21
72
  end
22
73
  end
@@ -49,7 +49,7 @@ module Sitepress
49
49
  end
50
50
 
51
51
  def exists?
52
- File.exists? path
52
+ File.exist? path
53
53
  end
54
54
 
55
55
  def expand_path
@@ -5,6 +5,9 @@ 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, :renderable?
10
+
8
11
  attr_writer :body, :data
9
12
  attr_reader :node, :asset
10
13
 
@@ -62,12 +65,6 @@ module Sitepress
62
65
  @lineage ||= node.parents.reject(&:root?).reverse.map(&:name)
63
66
  end
64
67
 
65
- # Certain files, like binary file types, aren't something that we should try to
66
- # parse. When this returns true in some cases, a reference to the file will be
67
- # passed and skip all the overhead of trying to parse and render.
68
- def renderable?
69
- asset.renderable?
70
- end
71
68
 
72
69
  private
73
70
  # Filters parent/child/sibling resources by a type. The default behavior is to only return
@@ -15,8 +15,8 @@ module Sitepress
15
15
  DEFAULT_NODE_MAPPER = AssetNodeMapper
16
16
 
17
17
  attr_reader :root_path
18
- attr_writer :resources_pipeline
19
18
  attr_accessor :node_mapper
19
+ attr_writer :resources_pipeline
20
20
 
21
21
  # TODO: Get rid of these so that folks have ot call site.resources.get ...
22
22
  extend Forwardable
@@ -53,19 +53,38 @@ module Sitepress
53
53
 
54
54
  # Location of website pages.
55
55
  def pages_path
56
- root_path.join("pages")
56
+ @pages_path ||= root_path.join("pages")
57
57
  end
58
58
 
59
+ def pages_path=(path)
60
+ @pages_path = Pathname.new(path)
61
+ end
62
+
63
+ # Location of helper files.
59
64
  def helpers_path
60
- root_path.join("helpers")
65
+ @helpers_path ||= root_path.join("helpers")
66
+ end
67
+
68
+ def helpers_path=(path)
69
+ @helpers_path = Pathname.new(path)
61
70
  end
62
71
 
72
+ # Location of rails assets
63
73
  def assets_path
64
- root_path.join("assets")
74
+ @assets_path ||= root_path.join("assets")
75
+ end
76
+
77
+ def assets_path=(path)
78
+ @assets_path = Pathname.new(path)
65
79
  end
66
80
 
81
+ # Location of pages models.
67
82
  def models_path
68
- root_path.join("models")
83
+ @models_path ||= root_path.join("models")
84
+ end
85
+
86
+ def models_path=(path)
87
+ @models_path = Pathname.new(path)
69
88
  end
70
89
 
71
90
  # Quick and dirty way to manipulate resources in the site without
@@ -1,3 +1,3 @@
1
1
  module Sitepress
2
- VERSION = "3.1.4".freeze
2
+ VERSION = "3.2.1".freeze
3
3
  end
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: 3.1.4
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brad Gessler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-04 00:00:00.000000000 Z
11
+ date: 2023-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,6 +77,7 @@ files:
77
77
  - lib/sitepress/asset.rb
78
78
  - lib/sitepress/asset_node_mapper.rb
79
79
  - lib/sitepress/asset_paths.rb
80
+ - lib/sitepress/data.rb
80
81
  - lib/sitepress/extensions/layouts.rb
81
82
  - lib/sitepress/extensions/proc_manipulator.rb
82
83
  - lib/sitepress/formats.rb
@@ -114,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
115
  - !ruby/object:Gem::Version
115
116
  version: '0'
116
117
  requirements: []
117
- rubygems_version: 3.3.20
118
+ rubygems_version: 3.4.1
118
119
  signing_key:
119
120
  specification_version: 4
120
121
  summary: An embeddable file-backed content management system.