contentfs 0.1.1 → 0.5.0
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/CHANGELOG.md +33 -3
- data/LICENSE +1 -1
- data/lib/contentfs/content.rb +15 -5
- data/lib/contentfs/database.rb +70 -16
- data/lib/contentfs/renderers/markdown.rb +2 -27
- data/lib/contentfs/renderers/markdown/code.rb +15 -5
- data/lib/contentfs/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82208eb59ae04f8483de860c59b496e0bfe47488c6693ee80b2517bb69c37619
|
4
|
+
data.tar.gz: '0685aaaf67a70ee5f713015ffc1312b8554598e7153d8427d957b8785007b312'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89f9d947f2bff284a260b10da2207d0305f85ee8df746078dd8aa57c23c70314580b04472235818e9fb9acd24e745d0f0995e03a47a3e1dd12282eb2be3765fd
|
7
|
+
data.tar.gz: 890b635054dbe37744334035bf495205bf97a4aebe4acdea70ac0e4c9572d5103ff5b98994cfae633f5d62ae5c52351293aea311707edcdc1b3b568af9e74026
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,42 @@
|
|
1
|
-
## v0.
|
1
|
+
## [v0.5.0](https://github.com/metabahn/contentfs/releases/tag/v0.5.0)
|
2
|
+
|
3
|
+
*released on 2021-04-01*
|
4
|
+
|
5
|
+
* `chg` [#10](https://github.com/metabahn/contentfs/pull/10) Replace redcarpet with cmark ([bryanp](https://github.com/bryanp))
|
6
|
+
|
7
|
+
## [v0.4.0](https://github.com/metabahn/contentfs/releases/tag/v0.4.0)
|
8
|
+
|
9
|
+
*released on 2021-04-01*
|
10
|
+
|
11
|
+
* `add` [#9](https://github.com/metabahn/contentfs/pull/9) Includes ([bryanp](https://github.com/bryanp))
|
12
|
+
|
13
|
+
## [v0.3.0](https://github.com/metabahn/contentfs/releases/tag/v0.3.0)
|
14
|
+
|
15
|
+
*released on 2020-11-18*
|
16
|
+
|
17
|
+
* `chg` [#8](https://github.com/metabahn/contentfs/pull/8) Load database content from _content to avoid collisions ([bryanp](https://github.com/bryanp))
|
18
|
+
|
19
|
+
## v0.2.1
|
2
20
|
|
3
21
|
*unreleased*
|
4
22
|
|
23
|
+
* `fix` [#7](https://github.com/metabahn/contentfs/pull/7) Order content and databases by prefix or slug ([bryanp](https://github.com/bryanp))
|
24
|
+
|
25
|
+
## [v0.2.0](https://github.com/metabahn/contentfs/releases/tag/v0.2.0)
|
26
|
+
|
27
|
+
*released on 2020-11-14*
|
28
|
+
|
29
|
+
* `add` [#6](https://github.com/metabahn/contentfs/pull/6) Expose database metadata ([bryanp](https://github.com/bryanp))
|
30
|
+
|
31
|
+
## [v0.1.1](https://github.com/metabahn/contentfs/releases/tag/v0.1.1)
|
32
|
+
|
33
|
+
*released on 2020-11-13*
|
34
|
+
|
5
35
|
* `fix` [#5](https://github.com/metabahn/contentfs/pull/5) Remove front-matter from content ([bryanp](https://github.com/bryanp))
|
6
36
|
|
7
|
-
## v0.1.0
|
37
|
+
## [v0.1.0](https://github.com/metabahn/contentfs/releases/tag/v0.1.0)
|
8
38
|
|
9
|
-
*
|
39
|
+
*released on 2020-11-12*
|
10
40
|
|
11
41
|
* `add` [#4](https://github.com/metabahn/contentfs/pull/4) Expose namespaces for databases and content ([bryanp](https://github.com/bryanp))
|
12
42
|
* `add` [#3](https://github.com/metabahn/contentfs/pull/3) Introduce `Database#nested` for iterating over databases ([bryanp](https://github.com/bryanp))
|
data/LICENSE
CHANGED
data/lib/contentfs/content.rb
CHANGED
@@ -12,24 +12,26 @@ module ContentFS
|
|
12
12
|
#
|
13
13
|
class Content
|
14
14
|
class << self
|
15
|
-
def load(path, metadata: {}, namespace: [])
|
16
|
-
new(path: path, metadata: metadata, namespace: namespace)
|
15
|
+
def load(path, database:, metadata: {}, namespace: [])
|
16
|
+
new(path: path, database: database, metadata: metadata, namespace: namespace)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
FRONT_MATTER_REGEXP = /\A---\s*\n(.*?\n?)^---\s*$\n?/m
|
21
|
+
INCLUDE_REGEXP = /<!-- @include\s*([a-zA-Z0-9\-_\/.]*) -->/
|
21
22
|
|
22
23
|
attr_reader :format, :prefix, :slug, :metadata, :namespace
|
23
24
|
|
24
|
-
def initialize(path:, metadata: {}, namespace: [])
|
25
|
+
def initialize(path:, database:, metadata: {}, namespace: [])
|
25
26
|
path = Pathname.new(path)
|
26
27
|
extname = path.extname
|
27
28
|
name = path.basename(extname)
|
28
29
|
prefix, remainder = Prefix.build(name)
|
29
30
|
@prefix = prefix
|
30
|
-
@format = extname.to_s[1
|
31
|
+
@format = extname.to_s[1..]&.to_sym
|
31
32
|
@slug = Slug.build(remainder)
|
32
33
|
@namespace = namespace.dup << @slug
|
34
|
+
@database = database
|
33
35
|
|
34
36
|
content = path.read
|
35
37
|
@metadata = metadata.merge(parse_metadata(content))
|
@@ -41,8 +43,16 @@ module ContentFS
|
|
41
43
|
end
|
42
44
|
|
43
45
|
def render
|
46
|
+
working_content = @content.dup
|
47
|
+
|
48
|
+
@content.scan(INCLUDE_REGEXP) do |match|
|
49
|
+
if (include = @database.find_include(match[0]))
|
50
|
+
working_content.gsub!($~.to_s, include.render)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
44
54
|
if @format && (renderer = Renderers.resolve(@format))
|
45
|
-
renderer.render(
|
55
|
+
renderer.render(working_content)
|
46
56
|
else
|
47
57
|
to_s
|
48
58
|
end
|
data/lib/contentfs/database.rb
CHANGED
@@ -11,23 +11,22 @@ module ContentFS
|
|
11
11
|
#
|
12
12
|
class Database
|
13
13
|
class << self
|
14
|
-
def load(path, namespace: [], root: true)
|
15
|
-
new(path: path, namespace: namespace, root: root)
|
14
|
+
def load(path, parent: nil, namespace: [], root: true)
|
15
|
+
new(path: path, parent: parent, namespace: namespace, root: root)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
METADATA_FILE = "_metadata.yml"
|
20
20
|
|
21
|
-
attr_reader :prefix, :slug, :namespace
|
21
|
+
attr_reader :prefix, :slug, :namespace, :metadata
|
22
22
|
|
23
|
-
def initialize(path:, namespace: [], root: false)
|
23
|
+
def initialize(path:, parent: nil, namespace: [], root: false)
|
24
24
|
path = Pathname.new(path)
|
25
25
|
name = path.basename(path.extname)
|
26
26
|
prefix, remainder = Prefix.build(name)
|
27
27
|
@prefix = prefix
|
28
|
-
@children = {}
|
29
|
-
@nested = {}
|
30
28
|
@namespace = namespace.dup
|
29
|
+
@parent = parent
|
31
30
|
|
32
31
|
unless root
|
33
32
|
@slug = Slug.build(remainder)
|
@@ -36,28 +35,54 @@ module ContentFS
|
|
36
35
|
|
37
36
|
metadata_path = path.join(METADATA_FILE)
|
38
37
|
|
39
|
-
metadata = if metadata_path.exist?
|
38
|
+
@metadata = if metadata_path.exist?
|
40
39
|
YAML.safe_load(metadata_path.read).to_h
|
41
40
|
else
|
42
41
|
{}
|
43
42
|
end
|
44
43
|
|
44
|
+
content_path = path.join.glob("_content.*")[0]
|
45
|
+
|
46
|
+
@content = if content_path&.exist?
|
47
|
+
Content.load(content_path, database: self, metadata: @metadata, namespace: @namespace)
|
48
|
+
end
|
49
|
+
|
50
|
+
children, nested, includes = {}, {}, {}
|
45
51
|
Pathname.new(path).glob("*") do |path|
|
46
|
-
|
52
|
+
underscored = path.basename.to_s.start_with?("_")
|
53
|
+
next if underscored && path.directory?
|
47
54
|
|
48
55
|
if path.directory?
|
49
|
-
database = Database.load(path, namespace: @namespace, root: false)
|
50
|
-
|
56
|
+
database = Database.load(path, parent: self, namespace: @namespace, root: false)
|
57
|
+
nested[database.slug] = database
|
58
|
+
elsif underscored
|
59
|
+
content = Content.load(path, database: self, metadata: @metadata, namespace: @namespace)
|
60
|
+
|
61
|
+
includes[content.slug.to_s[1..].to_sym] = content
|
51
62
|
else
|
52
|
-
content = Content.load(path, metadata: metadata, namespace: @namespace)
|
63
|
+
content = Content.load(path, database: self, metadata: @metadata, namespace: @namespace)
|
53
64
|
|
54
|
-
|
55
|
-
@content = content
|
56
|
-
else
|
57
|
-
@children[content.slug] = content
|
58
|
-
end
|
65
|
+
children[content.slug] = content
|
59
66
|
end
|
60
67
|
end
|
68
|
+
|
69
|
+
@children = Hash[
|
70
|
+
children.sort_by { |key, content|
|
71
|
+
(content.prefix || content.slug).to_s
|
72
|
+
}
|
73
|
+
]
|
74
|
+
|
75
|
+
@nested = Hash[
|
76
|
+
nested.sort_by { |key, database|
|
77
|
+
(database.prefix || database.slug).to_s
|
78
|
+
}
|
79
|
+
]
|
80
|
+
|
81
|
+
@includes = Hash[
|
82
|
+
includes.sort_by { |key, content|
|
83
|
+
(content.prefix || content.slug).to_s
|
84
|
+
}
|
85
|
+
]
|
61
86
|
end
|
62
87
|
|
63
88
|
def content
|
@@ -100,6 +125,35 @@ module ContentFS
|
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
128
|
+
def find_include(path)
|
129
|
+
@includes[path.to_sym] || find_child_include(path) || find_parent_include(path) || find_include_from_toplevel(path)
|
130
|
+
end
|
131
|
+
|
132
|
+
def toplevel
|
133
|
+
@parent ? @parent.toplevel : self
|
134
|
+
end
|
135
|
+
|
136
|
+
private def find_child_include(path)
|
137
|
+
return unless path.include?("/")
|
138
|
+
|
139
|
+
path_parts = path.split("/", 2)
|
140
|
+
@nested[path_parts[0].to_sym]&.find_include(path_parts[1])
|
141
|
+
end
|
142
|
+
|
143
|
+
private def find_parent_include(path)
|
144
|
+
return if @parent.nil?
|
145
|
+
return unless path.start_with?("../")
|
146
|
+
|
147
|
+
path_parts = path.split("../", 2)
|
148
|
+
@parent.find_include(path_parts[1])
|
149
|
+
end
|
150
|
+
|
151
|
+
private def find_include_from_toplevel(path)
|
152
|
+
return if @parent.nil?
|
153
|
+
|
154
|
+
toplevel.find_include(path)
|
155
|
+
end
|
156
|
+
|
103
157
|
def to_s
|
104
158
|
@content&.to_s.to_s
|
105
159
|
end
|
@@ -1,39 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "commonmarker"
|
4
4
|
|
5
5
|
module ContentFS
|
6
6
|
module Renderers
|
7
7
|
# @api private
|
8
8
|
class Markdown
|
9
9
|
class << self
|
10
|
-
OPTIONS = {
|
11
|
-
autolink: true,
|
12
|
-
footnotes: true,
|
13
|
-
fenced_code_blocks: true,
|
14
|
-
tables: true
|
15
|
-
}.freeze
|
16
|
-
|
17
10
|
def render(content)
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def options
|
22
|
-
OPTIONS
|
23
|
-
end
|
24
|
-
|
25
|
-
private def renderer
|
26
|
-
@_renderer ||= Redcarpet::Markdown.new(Renderer, options)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class Renderer < Redcarpet::Render::HTML
|
31
|
-
def block_quote(quote)
|
32
|
-
if (match = quote.match(/<p>\[(.*)\]/))
|
33
|
-
%(<blockquote class="#{match[1]}">#{quote.gsub("[#{match[1]}]", "")}</blockquote>)
|
34
|
-
else
|
35
|
-
super
|
36
|
-
end
|
11
|
+
CommonMarker.render_html(content, [:DEFAULT, :UNSAFE])
|
37
12
|
end
|
38
13
|
end
|
39
14
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rouge"
|
4
|
-
require "rouge/plugins/redcarpet"
|
5
4
|
|
6
5
|
require_relative "../markdown"
|
7
6
|
|
@@ -12,16 +11,27 @@ module ContentFS
|
|
12
11
|
class Code
|
13
12
|
class << self
|
14
13
|
def render(content)
|
15
|
-
renderer.render(content)
|
14
|
+
renderer.render(CommonMarker.render_doc(content))
|
16
15
|
end
|
17
16
|
|
18
17
|
private def renderer
|
19
|
-
|
18
|
+
SyntaxRenderer.new(options: [:DEFAULT, :UNSAFE])
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
|
-
class
|
24
|
-
|
22
|
+
class SyntaxRenderer < CommonMarker::HtmlRenderer
|
23
|
+
def code_block(node)
|
24
|
+
block do
|
25
|
+
language = node.fence_info.split(/\s+/)[0]
|
26
|
+
out("<div class=\"highlight\"><pre class=\"highlight #{language}\"><code>")
|
27
|
+
out(syntax_highlight(node.string_content, language))
|
28
|
+
out('</code></pre></div>')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private def syntax_highlight(source, language)
|
33
|
+
Rouge::Formatters::HTML.new.format(Rouge::Lexer.find(language).lex(source))
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
data/lib/contentfs/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contentfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Powell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A structured content file system.
|
14
14
|
email: bryan@metabahn.com
|
@@ -47,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
requirements: []
|
50
|
-
rubygems_version: 3.
|
50
|
+
rubygems_version: 3.2.4
|
51
51
|
signing_key:
|
52
52
|
specification_version: 4
|
53
53
|
summary: A structured content file system.
|