sitepress-core 2.0.0.beta9 → 2.0.0.beta10

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: 9a7a004d33fe5e05c2e1831ebcd902dc9c6bbcbf4650437b6e36984a1eb0e263
4
- data.tar.gz: 9bd65a5f76ee6b166337887619e825c48c4580cb082448c63c8d78d1c549759b
3
+ metadata.gz: 86f9eb2e3903461a6661161ec2f581804b634e2405f90897b6f63bf9adb3e01e
4
+ data.tar.gz: 77cdcc509daf4f20fbf83545ea1e906b61d523c6f0c7ab7614277b4e049096f8
5
5
  SHA512:
6
- metadata.gz: 213d67af29c1e88c03f3ad72cb81001a2a938f418ca41717288f757581a409ec6daba877bdca903bb0a650c140d71e7252c113d2b4e0d9334b2e2726122ddb54
7
- data.tar.gz: 68e40ac58a005c54262b050a3bc430eb3d2b81124705ce8aca39a87a3f0d07dd0fe9ab43283ead764c8afa9a00bf611fe6a903c2beb24d91b7eced7226b3ca7a
6
+ metadata.gz: 15a2854e3ea0562eee7db1a64d880fbddee2d6cfd0b1b772f91e4e13ba3b35cce52f9590627494b49f3b97bde0ae5f855c2506c3af2e66abf61430803bca429a
7
+ data.tar.gz: e3d263d7d5ebcdad165ad39e56eadbbe333fc3855fabc38150de1cef71cb3fddd2d12cc1e93da7ffff488641a75b72ec66269fb7f8f71ab25b742a729fe85e44
@@ -8,13 +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
21
  end
@@ -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
- # frontmatter or be renderable via a template. Multiple resources
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,14 +16,15 @@ module Sitepress
16
16
  attr_reader :path
17
17
 
18
18
  extend Forwardable
19
- def_delegators :frontmatter, :data, :body
19
+ def_delegators :parser, :data, :body
20
20
  def_delegators :path, :handler, :node_name, :format, :exists?
21
21
 
22
- def initialize(path: , mime_type: nil)
22
+ def initialize(path:, mime_type: nil, parser: Parsers::Frontmatter)
23
23
  # The MIME::Types gem returns an array when types are looked up.
24
24
  # This grabs the first one, which is likely the intent on these lookups.
25
25
  @mime_type = Array(mime_type).first
26
26
  @path = Path.new path
27
+ @parser_klass = parser
27
28
  end
28
29
 
29
30
  # Treat resources with the same request path as equal.
@@ -41,9 +42,15 @@ module Sitepress
41
42
  !!handler
42
43
  end
43
44
 
45
+ # Set the parser equal to a thing.
46
+ def parser=(parser_klass)
47
+ @parser = nil
48
+ @parser_klass = parser_klass
49
+ end
50
+
44
51
  private
45
- def frontmatter
46
- Frontmatter.new File.read path
52
+ def parser
53
+ @parser ||= @parser_klass.new File.read path
47
54
  end
48
55
 
49
56
  # Returns the mime type of the file extension. If a type can't
@@ -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
@@ -21,7 +21,7 @@ module Sitepress
21
21
  end
22
22
 
23
23
  def remove(extension)
24
- @formats.delete(symbolize(extension))
24
+ @formats.delete symbolize(extension)
25
25
  end
26
26
 
27
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
@@ -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,15 @@
1
+ require "yaml"
2
+
3
+ module Sitepress
4
+ module Parsers
5
+ # Parses nothing. The body is returned and the data is blank.
6
+ class Base
7
+ attr_reader :body, :data
8
+
9
+ def initialize(source)
10
+ @body = source
11
+ @data = {}
12
+ end
13
+ end
14
+ end
15
+ 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
@@ -5,19 +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, :handler
10
-
11
8
  attr_writer :body, :data
12
- attr_reader :node, :asset, :format
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
- def initialize(asset:, node:, format: nil)
16
+ def initialize(asset:, node:, format: nil, mime_type: nil, handler: nil)
18
17
  @asset = asset
19
18
  @node = node
20
- @format = format
19
+ @format = format || asset.format
20
+ @mime_type = mime_type || asset.mime_type
21
+ @handler = handler || asset.handler
21
22
  end
22
23
 
23
24
  def request_path
@@ -11,8 +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
19
+ attr_accessor :node_mapper
16
20
 
17
21
  # TODO: Get rid of these so that folks have ot call site.resources.get ...
18
22
  extend Forwardable
@@ -20,13 +24,14 @@ module Sitepress
20
24
 
21
25
  def initialize(root_path: DEFAULT_ROOT_PATH)
22
26
  self.root_path = root_path
27
+ self.node_mapper = DEFAULT_NODE_MAPPER
23
28
  end
24
29
 
25
30
  # A tree representation of the resourecs wthin the site. The root is a node that's
26
31
  # processed by the `resources_pipeline`.
27
32
  def root
28
33
  @root ||= Node.new.tap do |node|
29
- source_node_mapper.mount node
34
+ node_mapper.new(path: pages_path, node: node).map
30
35
  resources_pipeline.process node
31
36
  end
32
37
  end
@@ -97,11 +102,5 @@ module Sitepress
97
102
  def resources_pipeline
98
103
  @resources_pipeline ||= ResourcesPipeline.new
99
104
  end
100
-
101
- private
102
-
103
- def source_node_mapper
104
- @source_node_mapper ||= SourceNodeMapper.new(path: pages_path)
105
- end
106
105
  end
107
106
  end
@@ -1,3 +1,3 @@
1
1
  module Sitepress
2
- VERSION = "2.0.0.beta9".freeze
2
+ VERSION = "2.0.0.beta10".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: 2.0.0.beta9
4
+ version: 2.0.0.beta10
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-06-01 00:00:00.000000000 Z
11
+ date: 2021-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,17 +75,22 @@ 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
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
83
89
  - lib/sitepress/path.rb
84
90
  - lib/sitepress/resource.rb
85
91
  - lib/sitepress/resource_collection.rb
86
92
  - lib/sitepress/resources_pipeline.rb
87
93
  - lib/sitepress/site.rb
88
- - lib/sitepress/source_node_mapper.rb
89
94
  - lib/sitepress/version.rb
90
95
  - sitepress-core.gemspec
91
96
  homepage: https://github.com/sitepress/sitepress
@@ -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.1.4
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,60 +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
- 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
12
- ]
13
-
14
- # Partial rails prefix.
15
- PARTIAL_PREFIX = "_".freeze
16
-
17
- attr_reader :assets, :path
18
- alias :root :path
19
-
20
- def initialize(path:)
21
- @path = path
22
- end
23
-
24
- # Mounts the source files from the path to the given node.
25
- def mount(node)
26
- paths.each do |path|
27
- if path.directory?
28
- name = File.basename path
29
- SourceNodeMapper.new(path: path).mount node.add_child(name)
30
- else
31
- asset = Asset.new(path: path)
32
- node.add_child(asset.node_name).formats.add(format: asset.format, asset: asset)
33
- end
34
- end
35
- end
36
-
37
- private
38
- # Returns a list of files, paths, and node names to iterate through to build out nodes
39
- def paths
40
- Enumerator.new do |y|
41
- root.each_child do |path|
42
- next if ignore_file? path
43
- y << path
44
- end
45
- end
46
- end
47
-
48
- def ignore_file?(path)
49
- is_partial_file?(path) or matches_ignore_file_pattern?(path)
50
- end
51
-
52
- def is_partial_file?(path)
53
- path.basename.to_s.start_with? PARTIAL_PREFIX
54
- end
55
-
56
- def matches_ignore_file_pattern?(path)
57
- IGNORE_FILE_PATTERNS.any? { |pattern| path.fnmatch? pattern }
58
- end
59
- end
60
- end