sitepress-core 2.0.0.beta9 → 2.0.0.beta10

Sign up to get free protection for your applications and to get access to all the features.
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