markdown_record 0.1.3 → 0.1.4
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/README.md +63 -43
- data/app/helpers/markdown_record/application_helper.rb +23 -0
- data/app/helpers/markdown_record/controller_helpers.rb +1 -1
- data/app/helpers/markdown_record/view_helpers.rb +9 -3
- data/{lib → app/models}/markdown_record/base.rb +10 -0
- data/{lib → app/models}/markdown_record/content_fragment.rb +17 -2
- data/lib/generators/markdown_record_generator.rb +6 -0
- data/lib/markdown_record/configuration.rb +4 -0
- data/lib/markdown_record/file_sorting/base.rb +25 -0
- data/lib/markdown_record/file_sorting/date_sorter.rb +14 -0
- data/lib/markdown_record/file_sorting/sem_ver_sorter.rb +47 -0
- data/lib/markdown_record/{association.rb → models/association.rb} +20 -3
- data/lib/markdown_record/{associations.rb → models/associations.rb} +17 -9
- data/lib/markdown_record/{content_associations.rb → models/content_associations.rb} +4 -2
- data/lib/markdown_record/models/filtering.rb +13 -0
- data/lib/markdown_record/models/filters/array_filter.rb +11 -0
- data/lib/markdown_record/models/filters/base_filter.rb +35 -0
- data/lib/markdown_record/models/filters/hash_filter.rb +81 -0
- data/lib/markdown_record/models/filters/nil_filter.rb +11 -0
- data/lib/markdown_record/models/filters/range_filter.rb +11 -0
- data/lib/markdown_record/models/filters/regexp_filter.rb +11 -0
- data/lib/markdown_record/models/filters/symbol_filter.rb +14 -0
- data/lib/markdown_record/models/filters.rb +22 -0
- data/lib/markdown_record/models/model_inflator.rb +65 -0
- data/lib/markdown_record/path_utilities.rb +20 -11
- data/lib/markdown_record/rendering/content_dsl/attribute.rb +22 -0
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/directory_fragment.rb +3 -3
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/disable.rb +2 -2
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/enable.rb +2 -2
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/end_attribute.rb +3 -3
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/end_model.rb +3 -3
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/fragment.rb +3 -3
- data/lib/markdown_record/rendering/content_dsl/model.rb +22 -0
- data/lib/markdown_record/rendering/content_dsl/scope.rb +22 -0
- data/lib/markdown_record/{content_dsl → rendering/content_dsl}/use_layout.rb +3 -3
- data/lib/markdown_record/rendering/content_dsl.rb +45 -0
- data/lib/markdown_record/rendering/html_renderer.rb +22 -0
- data/lib/markdown_record/{indexer.rb → rendering/indexer.rb} +0 -10
- data/lib/markdown_record/rendering/json_renderer.rb +20 -0
- data/lib/markdown_record/rendering/nodes/html_base.rb +95 -0
- data/lib/markdown_record/rendering/nodes/html_directory.rb +51 -0
- data/lib/markdown_record/rendering/nodes/html_file.rb +48 -0
- data/lib/markdown_record/rendering/nodes/json_base.rb +55 -0
- data/lib/markdown_record/rendering/nodes/json_directory.rb +69 -0
- data/lib/markdown_record/rendering/nodes/json_file.rb +172 -0
- data/lib/markdown_record/{rendering.rb → rendering/rendering.rb} +1 -1
- data/lib/markdown_record/{validator.rb → rendering/validator.rb} +4 -4
- data/lib/markdown_record/version.rb +1 -1
- data/lib/markdown_record.rb +21 -14
- data/templates/demo/content/10_custom_models_and_associations.md.erb +27 -7
- data/templates/demo/content/11_controller_helpers.md.erb +2 -2
- data/templates/demo/content/12_configuration.md.erb +22 -3
- data/templates/demo/content/13_sandbox/1_foo.md +2 -1
- data/templates/demo/content/13_sandbox/2_sandbox_nested/1_bar.md +4 -1
- data/templates/demo/content/1_home.md.erb +30 -13
- data/templates/demo/content/2_installation.md.erb +61 -46
- data/templates/demo/content/3_rendering_basics.md.erb +3 -3
- data/templates/demo/content/4_content_dsl.md.erb +22 -11
- data/templates/demo/content/5_routes.md.erb +10 -7
- data/templates/demo/content/6_model_basics.md.erb +11 -11
- data/templates/demo/content/7_content_frags.md.erb +9 -6
- data/templates/demo/content/8_erb_syntax_and_view_helpers.md.erb +32 -11
- data/templates/demo/content/9_layouts.md.erb +3 -3
- data/templates/demo/layouts/_global_layout.html.erb +1 -0
- data/templates/demo/models/dsl_command.rb +6 -0
- data/templates/demo/models/section.rb +5 -0
- data/templates/render_content.thor +2 -1
- data/templates/tests/assets/images/ruby-logo.png +0 -0
- data/templates/tests/content/1_test_files_home.md.erb +31 -0
- data/templates/tests/content/2_content_dsl_tests/1_content_dsl.md.erb +162 -0
- data/templates/tests/content/2_content_dsl_tests/2_nested_directory/1_associations.md.erb +83 -0
- data/templates/tests/layouts/_concatenated_layout.html.erb +12 -0
- data/templates/tests/layouts/_custom_layout.html.erb +14 -0
- data/templates/tests/layouts/_file_layout.html.erb +15 -0
- data/templates/tests/layouts/_global_layout.html.erb +116 -0
- metadata +53 -34
- data/app/models/markdown_record/demo/dsl_command.rb +0 -10
- data/app/models/markdown_record/demo/section.rb +0 -9
- data/app/models/markdown_record/tests/child_model.rb +0 -15
- data/app/models/markdown_record/tests/fake_active_record_model.rb +0 -13
- data/app/models/markdown_record/tests/model.rb +0 -15
- data/app/models/markdown_record/tests/other_child_model.rb +0 -15
- data/lib/markdown_record/cli.rb +0 -54
- data/lib/markdown_record/content_dsl/attribute.rb +0 -22
- data/lib/markdown_record/content_dsl/model.rb +0 -23
- data/lib/markdown_record/content_dsl/render_format.rb +0 -22
- data/lib/markdown_record/content_dsl/render_strategy.rb +0 -22
- data/lib/markdown_record/content_dsl.rb +0 -37
- data/lib/markdown_record/html_renderer.rb +0 -194
- data/lib/markdown_record/json_renderer.rb +0 -270
- data/lib/markdown_record/model_inflator.rb +0 -107
- data/lib/markdown_record/routes_renderer.rb +0 -0
- /data/lib/markdown_record/{file_saver.rb → rendering/file_saver.rb} +0 -0
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module MarkdownRecord
|
|
2
|
-
module Tests
|
|
3
|
-
class OtherChildModel < ::MarkdownRecord::Base
|
|
4
|
-
attribute :string_field
|
|
5
|
-
attribute :int_field
|
|
6
|
-
attribute :float_field
|
|
7
|
-
attribute :bool_field
|
|
8
|
-
attribute :date_field
|
|
9
|
-
attribute :maybe_field
|
|
10
|
-
attribute :hash_field
|
|
11
|
-
|
|
12
|
-
belongs_to_content :model
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
data/lib/markdown_record/cli.rb
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
require 'thor'
|
|
2
|
-
|
|
3
|
-
module MarkdownRecord
|
|
4
|
-
|
|
5
|
-
class Cli < Thor
|
|
6
|
-
include ::Thor::Actions
|
|
7
|
-
|
|
8
|
-
source_root File.expand_path("../../spec/dummy", __dir__)
|
|
9
|
-
|
|
10
|
-
desc "install", "installs rendered comparison files for specs"
|
|
11
|
-
def install
|
|
12
|
-
# Install the gem in the dummy app
|
|
13
|
-
system "cd spec/dummy && rails g markdown_record"
|
|
14
|
-
|
|
15
|
-
# Run render_content thor task to generate content and save it
|
|
16
|
-
system "cd spec/dummy && thor render_content:all -s"
|
|
17
|
-
|
|
18
|
-
# Copy the generated content to the spec folder for the specs to use
|
|
19
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_1/content.html", "spec/rendered/chapter_1/content.html"
|
|
20
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_1/content.json", "spec/rendered/chapter_1/content.json"
|
|
21
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_1/content_fragments.json", "spec/rendered/chapter_1/content_fragments.json"
|
|
22
|
-
|
|
23
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_2/content.html", "spec/rendered/chapter_2/content.html"
|
|
24
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_2/content.json", "spec/rendered/chapter_2/content.json"
|
|
25
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_2/content_fragments.json", "spec/rendered/chapter_2/content_fragments.json"
|
|
26
|
-
|
|
27
|
-
copy_file "markdown_record/rendered/content.html", "spec/rendered/concatenated/content.html"
|
|
28
|
-
copy_file "markdown_record/rendered/content.json", "spec/rendered/concatenated/content.json"
|
|
29
|
-
copy_file "markdown_record/rendered/content_fragments.json", "spec/rendered/concatenated/content_fragments.json"
|
|
30
|
-
|
|
31
|
-
# Run render content again with a custom layout
|
|
32
|
-
system "cd spec/dummy && thor render_content:all -s -l \"_custom_layout.html.erb\" -r full"
|
|
33
|
-
|
|
34
|
-
# Copy the new files to the spec directory
|
|
35
|
-
copy_file "markdown_record/rendered/content.html", "spec/rendered/custom_layout/content.html"
|
|
36
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_1/content.html", "spec/rendered/custom_layout/chapter_1/content.html"
|
|
37
|
-
|
|
38
|
-
# Run render content again with a custom layout
|
|
39
|
-
system "cd spec/dummy && thor render_file:json -s -f part_1/chapter_1/content.md"
|
|
40
|
-
copy_file "markdown_record/rendered/content/part_1/chapter_1/content.json", "spec/rendered/chapter_1/no_frag_content.json"
|
|
41
|
-
|
|
42
|
-
# Remove generated content and installed files
|
|
43
|
-
FileUtils.remove_dir("spec/dummy/markdown_record/rendered", true)
|
|
44
|
-
FileUtils.remove_dir("spec/dummy/markdown_record/content", true)
|
|
45
|
-
FileUtils.remove_entry("spec/dummy/markdown_record/layouts/_concatenated_layout.html.erb", true)
|
|
46
|
-
FileUtils.remove_entry("spec/dummy/markdown_record/layouts/_file_layout.html.erb", true)
|
|
47
|
-
FileUtils.remove_entry("spec/dummy/lib/tasks/render_content.thor", true)
|
|
48
|
-
FileUtils.remove_entry("spec/dummy/lib/tasks/render_file.thor", true)
|
|
49
|
-
FileUtils.remove_entry("spec/dummy/config/initializers/markdown_record.rb", true)
|
|
50
|
-
FileUtils.remove_entry("spec/dummy/Thorfile", true)
|
|
51
|
-
gsub_file "spec/dummy/config/routes.rb", "\n mount MarkdownRecord::Engine, at: MarkdownRecord.config.mount_path, as: \"markdown_record\"", ""
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module MarkdownRecord
|
|
2
|
-
module ContentDsl
|
|
3
|
-
module Attribute
|
|
4
|
-
REGEX = /(?<!`|`\\n|`html\\n)<!--\s*attribute\s*:\s*(\w+)\s*(?::((?:html|md|int|float|string)?))?-->(?!`|\\n`)/
|
|
5
|
-
ENCODED_REGEX = /(?<!<code>|<code class="html">)<!--\s*attribute\s*:\s*(\w+)\s*(?::((?:html|md|int|float|string)?))?-->(?!<\/code>)/
|
|
6
|
-
|
|
7
|
-
def attribute_dsl(text)
|
|
8
|
-
match = text.match(REGEX)
|
|
9
|
-
|
|
10
|
-
if match
|
|
11
|
-
[match[1].strip, match[2]&.strip]
|
|
12
|
-
else
|
|
13
|
-
nil
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.remove_dsl(text)
|
|
18
|
-
text.gsub(ENCODED_REGEX, "")
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module MarkdownRecord
|
|
2
|
-
module ContentDsl
|
|
3
|
-
module Model
|
|
4
|
-
TEMP = /<!--\s*model\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*-->/
|
|
5
|
-
REGEX = /(?<!`|`\\n|`html\\n)<!--\s*model\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*-->(?!`|\\n`)/
|
|
6
|
-
ENCODED_REGEX = /(?<!<code>|<code class="html">)<!--\s*model\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*-->(?!<\/code>)/
|
|
7
|
-
|
|
8
|
-
def model_dsl(text)
|
|
9
|
-
match = text.match(REGEX)
|
|
10
|
-
|
|
11
|
-
if match
|
|
12
|
-
JSON.parse(match[1])
|
|
13
|
-
else
|
|
14
|
-
nil
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.remove_dsl(text)
|
|
19
|
-
text.gsub(ENCODED_REGEX, "")
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module MarkdownRecord
|
|
2
|
-
module ContentDsl
|
|
3
|
-
module RenderFormat
|
|
4
|
-
REGEX = /(?<!`|`\\n|`html\\n)<!--\s*render_format\s*:\s*(.*)\s*-->(?!`|\\n`)/
|
|
5
|
-
ENCODED_REGEX = /(?<!<code>|<code class="html">)<!--\s*render_format\s*:\s*(.*)\s*-->(?!<\/code>)/
|
|
6
|
-
|
|
7
|
-
def render_format_dsl(text)
|
|
8
|
-
match = text.match(REGEX)
|
|
9
|
-
|
|
10
|
-
if match
|
|
11
|
-
match[1].strip
|
|
12
|
-
else
|
|
13
|
-
nil
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.remove_dsl(text)
|
|
18
|
-
text.gsub(ENCODED_REGEX, "")
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module MarkdownRecord
|
|
2
|
-
module ContentDsl
|
|
3
|
-
module RenderStrategy
|
|
4
|
-
REGEX = /(?<!`|`\\n|`html\\n)<!--\s*render_strategy\s*:\s*(.*)\s*-->(?!`|\\n`)/
|
|
5
|
-
ENCODED_REGEX = /(?<!<code>|<code class="html">)<!--\s*render_strategy\s*:\s*(.*)\s*-->(?!<\/code>)/
|
|
6
|
-
|
|
7
|
-
def render_strategy_dsl(text)
|
|
8
|
-
match = text.match(REGEX)
|
|
9
|
-
|
|
10
|
-
if match
|
|
11
|
-
match[1].strip
|
|
12
|
-
else
|
|
13
|
-
nil
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.remove_dsl(text)
|
|
18
|
-
text.gsub(ENCODED_REGEX, "")
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
require "markdown_record/content_dsl/model"
|
|
2
|
-
require "markdown_record/content_dsl/attribute"
|
|
3
|
-
require "markdown_record/content_dsl/end_attribute"
|
|
4
|
-
require "markdown_record/content_dsl/end_model"
|
|
5
|
-
require "markdown_record/content_dsl/fragment"
|
|
6
|
-
require "markdown_record/content_dsl/directory_fragment"
|
|
7
|
-
require "markdown_record/content_dsl/use_layout"
|
|
8
|
-
require "markdown_record/content_dsl/disable"
|
|
9
|
-
require "markdown_record/content_dsl/enable"
|
|
10
|
-
|
|
11
|
-
module MarkdownRecord
|
|
12
|
-
module ContentDsl
|
|
13
|
-
include Model
|
|
14
|
-
include Attribute
|
|
15
|
-
include EndAttribute
|
|
16
|
-
include EndModel
|
|
17
|
-
include DirectoryFragment
|
|
18
|
-
include Fragment
|
|
19
|
-
include UseLayout
|
|
20
|
-
include Disable
|
|
21
|
-
include Enable
|
|
22
|
-
|
|
23
|
-
HTML_COMMENT_REGEX = /(<!--(?:(?:\s|.)(?!-->))*(?:.|\s)-->)/
|
|
24
|
-
|
|
25
|
-
def remove_dsl(text)
|
|
26
|
-
text = Model.remove_dsl(text)
|
|
27
|
-
text = Attribute.remove_dsl(text)
|
|
28
|
-
text = EndAttribute.remove_dsl(text)
|
|
29
|
-
text = EndModel.remove_dsl(text)
|
|
30
|
-
text = Fragment.remove_dsl(text)
|
|
31
|
-
text = UseLayout.remove_dsl(text)
|
|
32
|
-
text = Disable.remove_dsl(text)
|
|
33
|
-
text = Enable.remove_dsl(text)
|
|
34
|
-
text
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
require "redcarpet"
|
|
2
|
-
require "htmlbeautifier"
|
|
3
|
-
|
|
4
|
-
module MarkdownRecord
|
|
5
|
-
class HtmlRenderer < ::Redcarpet::Render::HTML
|
|
6
|
-
include ::MarkdownRecord::PathUtilities
|
|
7
|
-
include ::MarkdownRecord::ContentDsl
|
|
8
|
-
|
|
9
|
-
HTML_SUBSTITUTIONS = {
|
|
10
|
-
/<!---/ => "<!--",
|
|
11
|
-
/<!---/ => "<!--"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
def initialize(
|
|
15
|
-
file_saver: ::MarkdownRecord::FileSaver.new)
|
|
16
|
-
super(::MarkdownRecord.config.html_render_options)
|
|
17
|
-
@indexer = ::MarkdownRecord::Indexer.new
|
|
18
|
-
@markdown = ::Redcarpet::Markdown.new(self, ::MarkdownRecord.config.markdown_extensions)
|
|
19
|
-
@file_saver = file_saver
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def render_html_for_subdirectory(subdirectory: "", **options)
|
|
23
|
-
content = @indexer.index(subdirectory: subdirectory)
|
|
24
|
-
rendered_subdirectory = base_content_path.join(subdirectory)
|
|
25
|
-
|
|
26
|
-
html_content = render_html_recursively(content, rendered_subdirectory.to_s)
|
|
27
|
-
processed_html = process_html_recursively(html_content[rendered_subdirectory.to_s], rendered_subdirectory, options)
|
|
28
|
-
final_html = finalize_html_recursively(processed_html, rendered_subdirectory)
|
|
29
|
-
|
|
30
|
-
save_content_recursively(final_html, options, rendered_subdirectory)
|
|
31
|
-
{ :html_content => processed_html, :saved_files => @file_saver.saved_files }
|
|
32
|
-
nil
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def render_html_recursively(file_or_directory, file_or_directory_name)
|
|
38
|
-
case file_or_directory.class.name
|
|
39
|
-
when Hash.name # if it is a directory
|
|
40
|
-
directory_hash = { file_or_directory_name => {} } # hash representing the directory and its contents
|
|
41
|
-
|
|
42
|
-
file_or_directory.each do |child_file_or_directory_name, child_file_or_directory|
|
|
43
|
-
child_content_hash = render_html_recursively(child_file_or_directory, child_file_or_directory_name)
|
|
44
|
-
directory_hash[file_or_directory_name].merge!(child_content_hash)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
directory_hash
|
|
48
|
-
when String.name # if it is a file
|
|
49
|
-
{ file_or_directory_name => render_html(file_or_directory) }
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def render_html(html)
|
|
54
|
-
rendered_html = @markdown.render(html)
|
|
55
|
-
remove_dsl(rendered_html)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def process_html_recursively(file_or_directory, full_path, options)
|
|
59
|
-
case file_or_directory.class.name
|
|
60
|
-
when Hash.name
|
|
61
|
-
directory_hash = { full_path.to_s => {} } # hash representing the directory and its contents
|
|
62
|
-
|
|
63
|
-
file_or_directory.each do |child_file_or_directory_name, child_file_or_directory|
|
|
64
|
-
child_content_hash = process_html_recursively(child_file_or_directory, full_path.join(child_file_or_directory_name), options)
|
|
65
|
-
directory_hash[full_path.to_s].merge!(child_content_hash)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
if options[:concat]
|
|
69
|
-
concatenated_html = concatenate_html_recursively(directory_hash[full_path.to_s], []).join("\r\n")
|
|
70
|
-
directory_hash["#{full_path.to_s}.concat"] = process_html(concatenated_html, full_path.to_s, concatenated_layout)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
directory_hash.compact
|
|
74
|
-
when String.name # if it is a file
|
|
75
|
-
if options[:deep]
|
|
76
|
-
{ full_path.to_s => process_html(file_or_directory, full_path, custom_layout(file_or_directory) || file_layout) }
|
|
77
|
-
else
|
|
78
|
-
{ }
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def process_html(html, full_path, layout = nil)
|
|
84
|
-
processed_html = html.gsub(/<p>(\<%(\S|\s)*?%\>)<\/p>/){ CGI.unescapeHTML($1) }
|
|
85
|
-
processed_html = processed_html.gsub(/(\<%(\S|\s)*?%\>)/){ CGI.unescapeHTML($1) }
|
|
86
|
-
locals = erb_locals_from_path(full_path.to_s)
|
|
87
|
-
processed_html = render_erb(processed_html, locals) if full_path.to_s.ends_with?(".md.erb")
|
|
88
|
-
processed_html = render_erb(layout, locals.merge(html: processed_html)) if layout
|
|
89
|
-
processed_html
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def render_erb(html, locals)
|
|
93
|
-
render_controller = ::MarkdownRecord.config.render_controller || ::ApplicationController
|
|
94
|
-
rendered_html = render_controller.render(
|
|
95
|
-
inline: html,
|
|
96
|
-
locals: locals
|
|
97
|
-
).to_str
|
|
98
|
-
rendered_html
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def concatenate_html_recursively(content, html)
|
|
102
|
-
case content.class.name
|
|
103
|
-
when Hash.name
|
|
104
|
-
sorted_hash_values(content).each do |v|
|
|
105
|
-
concatenate_html_recursively(v, html)
|
|
106
|
-
end
|
|
107
|
-
when String.name
|
|
108
|
-
html << content
|
|
109
|
-
end
|
|
110
|
-
html
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def sorted_hash_values(hash)
|
|
114
|
-
values = []
|
|
115
|
-
keys = hash.keys.sort_by do |k|
|
|
116
|
-
basename = k.split("/").last
|
|
117
|
-
m = basename.match(/^(\d+)_/)
|
|
118
|
-
m.try(:[], 1).to_i || k
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
keys.each do |k|
|
|
122
|
-
values << hash[k] if !k.include?(".concat")
|
|
123
|
-
end
|
|
124
|
-
values
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def custom_layout(html)
|
|
128
|
-
layout = use_layout_dsl(html)
|
|
129
|
-
return unless layout
|
|
130
|
-
|
|
131
|
-
File.read(::MarkdownRecord.config.layout_directory.join(layout))
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def global_layout
|
|
135
|
-
global_layout_path = ::MarkdownRecord.config.global_layout_path
|
|
136
|
-
@global_layout ||= global_layout_path ? layout(global_layout_path) : nil
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def concatenated_layout
|
|
140
|
-
concatenated_layout_path = ::MarkdownRecord.config.concatenated_layout_path
|
|
141
|
-
@concatenated_layout ||= concatenated_layout_path ? layout(concatenated_layout_path) : nil
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def file_layout
|
|
145
|
-
file_layout_path = ::MarkdownRecord.config.file_layout_path
|
|
146
|
-
@file_layout ||= file_layout_path ? layout(file_layout_path) : nil
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def layout(path)
|
|
150
|
-
File.read(::MarkdownRecord.config.layout_directory.join(path))
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def finalize_html_recursively(content, rendered_subdirectory)
|
|
154
|
-
case content.class.name
|
|
155
|
-
when Hash.name
|
|
156
|
-
final_hash = {}
|
|
157
|
-
content.each do |key, value|
|
|
158
|
-
child_path = rendered_subdirectory.join(key)
|
|
159
|
-
final_hash[key] = finalize_html_recursively(value, child_path)
|
|
160
|
-
end
|
|
161
|
-
final_hash
|
|
162
|
-
when String.name
|
|
163
|
-
finalize_html(content, rendered_subdirectory)
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
def finalize_html(html, full_path)
|
|
168
|
-
locals = erb_locals_from_path(full_path)
|
|
169
|
-
final_html = html
|
|
170
|
-
final_html = render_erb(global_layout, locals.merge(html: final_html)) if global_layout
|
|
171
|
-
|
|
172
|
-
HTML_SUBSTITUTIONS.each do |find, replace|
|
|
173
|
-
final_html = final_html.gsub(find, replace)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
final_html = final_html.squeeze("\n")
|
|
177
|
-
final_html = HtmlBeautifier.beautify(final_html)
|
|
178
|
-
final_html
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def save_content_recursively(content, options, rendered_subdirectory)
|
|
182
|
-
case content.class.name
|
|
183
|
-
when Hash.name
|
|
184
|
-
content.each do |key, value|
|
|
185
|
-
child_path = rendered_subdirectory.join(key)
|
|
186
|
-
save_content_recursively(value, options, child_path)
|
|
187
|
-
end
|
|
188
|
-
when String.name
|
|
189
|
-
path = clean_path(rendered_subdirectory.to_s)
|
|
190
|
-
@file_saver.save_to_file(content, "#{path}.html", options)
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
end
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
require "redcarpet"
|
|
2
|
-
require "redcarpet/render_strip"
|
|
3
|
-
|
|
4
|
-
module MarkdownRecord
|
|
5
|
-
class JsonRenderer
|
|
6
|
-
include ::MarkdownRecord::PathUtilities
|
|
7
|
-
include ::MarkdownRecord::ContentDsl
|
|
8
|
-
|
|
9
|
-
def initialize(file_saver: ::MarkdownRecord::FileSaver.new)
|
|
10
|
-
@indexer = MarkdownRecord::Indexer.new
|
|
11
|
-
@json_models = {}
|
|
12
|
-
@described_models = []
|
|
13
|
-
@file_saver = file_saver
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def render_models_for_subdirectory(subdirectory: "", **options)
|
|
17
|
-
@directory_meta = {}
|
|
18
|
-
content = @indexer.index(subdirectory: subdirectory)
|
|
19
|
-
|
|
20
|
-
rendered_subdirectory = base_content_path.join(subdirectory)
|
|
21
|
-
json_hash, _ = render_models_recursively(content, rendered_subdirectory, options)
|
|
22
|
-
|
|
23
|
-
save_content_recursively(json_hash, options, Pathname.new(""))
|
|
24
|
-
json_hash
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def render_models_for_file(file_path:, **options)
|
|
28
|
-
file = @indexer.file(file_path)
|
|
29
|
-
|
|
30
|
-
# render json models
|
|
31
|
-
json = render_models(file, file_path, options)
|
|
32
|
-
|
|
33
|
-
# save json
|
|
34
|
-
@file_saver.save_to_file(json.to_json, "#{clean_path(file_path)}.json", options)
|
|
35
|
-
|
|
36
|
-
json
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
|
|
41
|
-
def render_models_recursively(file_or_directory, full_path, options)
|
|
42
|
-
case file_or_directory.class.name;
|
|
43
|
-
when Hash.name # if it is a directory
|
|
44
|
-
directory_hash, concat_hash = *render_nested_models(file_or_directory, full_path, options)
|
|
45
|
-
|
|
46
|
-
# concatenate child hashes if :concat = true
|
|
47
|
-
if options[:concat]
|
|
48
|
-
concatenate_nested_models(full_path, directory_hash, concat_hash, options)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
[directory_hash, concat_hash]
|
|
52
|
-
when String.name # if it is a file
|
|
53
|
-
content = render_models(file_or_directory, full_path, options)
|
|
54
|
-
|
|
55
|
-
if options[:deep] && options[:render_content_fragment_json]
|
|
56
|
-
add_content_fragment_for_file(content, full_path, false, @fragment_meta)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
content_hash = { full_path.basename.to_s => content }
|
|
60
|
-
result = [{}, {}]
|
|
61
|
-
result[0] = content_hash if options[:deep]
|
|
62
|
-
result[1] = content_hash if options[:concat]
|
|
63
|
-
result
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def render_nested_models(file_or_directory, full_path, options)
|
|
68
|
-
directory_hash = { full_path.basename.to_s => {} } # hash representing the directory and its contents
|
|
69
|
-
concat_hash = { full_path.basename.to_s => {} }
|
|
70
|
-
# iterate through directory contents
|
|
71
|
-
file_or_directory.each do |child_file_or_directory_name, child_file_or_directory|
|
|
72
|
-
|
|
73
|
-
# get full path for next recursion
|
|
74
|
-
child_full_path = full_path.join(child_file_or_directory_name)
|
|
75
|
-
# get response from next recursion
|
|
76
|
-
child_content_hash, child_concat_hash = render_models_recursively(
|
|
77
|
-
child_file_or_directory,
|
|
78
|
-
child_full_path,
|
|
79
|
-
options
|
|
80
|
-
)
|
|
81
|
-
# merge response hashes
|
|
82
|
-
concat_hash[full_path.basename.to_s].merge!(child_concat_hash)
|
|
83
|
-
directory_hash[full_path.basename.to_s].merge!(child_content_hash)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
[directory_hash, concat_hash]
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def concatenate_nested_models(full_path, directory_hash, concat_hash, options)
|
|
90
|
-
concatenated_json = {}
|
|
91
|
-
concatenate_json_recursively(concat_hash, concatenated_json)
|
|
92
|
-
|
|
93
|
-
# add content fragments if render_content_fragment_json = true
|
|
94
|
-
if options[:render_content_fragment_json]
|
|
95
|
-
filename, subdirectory = full_path_to_parts(full_path)
|
|
96
|
-
directory_meta = @directory_meta[clean_path("#{subdirectory}/#{filename}")] || {}
|
|
97
|
-
|
|
98
|
-
add_content_fragment_for_file(concat_hash[full_path.basename.to_s], full_path, true, directory_meta)
|
|
99
|
-
add_content_fragment_for_file(concatenated_json, full_path, true, directory_meta)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
directory_hash["#{full_path.basename.to_s}.concat"] = concatenated_json
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def render_models(content, full_path, options)
|
|
106
|
-
|
|
107
|
-
filename, subdirectory = full_path_to_parts(full_path)
|
|
108
|
-
|
|
109
|
-
@described_models = []
|
|
110
|
-
@json_models = {}
|
|
111
|
-
@fragment_meta = {}
|
|
112
|
-
enabled = true
|
|
113
|
-
|
|
114
|
-
content.split(HTML_COMMENT_REGEX).each do |text|
|
|
115
|
-
dsl_command = HTML_COMMENT_REGEX =~ text
|
|
116
|
-
|
|
117
|
-
if dsl_command
|
|
118
|
-
enabled = false if disable_dsl(text)
|
|
119
|
-
enabled = true if enable_dsl(text)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
if dsl_command && enabled
|
|
123
|
-
extract_model(text, filename, subdirectory)
|
|
124
|
-
extract_fragment_meta(text, subdirectory)
|
|
125
|
-
extract_attribute(text)
|
|
126
|
-
pop_attribute(text)
|
|
127
|
-
pop_model(text)
|
|
128
|
-
else
|
|
129
|
-
append_to_attribute(text)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
@described_models.each do |model|
|
|
134
|
-
finalize_attribute(model)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
@json_models.dup
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def add_content_fragment_for_file(json, full_path, concatenated, meta)
|
|
141
|
-
content_fragment = fragment_attributes_from_path(full_path).merge("meta" => meta, "concatenated" => concatenated)
|
|
142
|
-
|
|
143
|
-
json["markdown_record/content_fragment"] ||= []
|
|
144
|
-
json["markdown_record/content_fragment"] << content_fragment
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def concatenate_json_recursively(directory_hash, concatenated_json)
|
|
148
|
-
directory_hash.each do |key, value|
|
|
149
|
-
case value.class.name
|
|
150
|
-
when Hash.name
|
|
151
|
-
concatenate_json_recursively(value, concatenated_json)
|
|
152
|
-
when Array.name
|
|
153
|
-
concatenated_json[key] ||= []
|
|
154
|
-
concatenated_json[key] += value
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def save_content_recursively(content, options, rendered_subdirectory)
|
|
160
|
-
if content&.values&.first.is_a?(Array)
|
|
161
|
-
fragments = content.slice("markdown_record/content_fragment")
|
|
162
|
-
non_fragments = content.except("markdown_record/content_fragment")
|
|
163
|
-
path = clean_path(rendered_subdirectory.to_s)
|
|
164
|
-
@file_saver.save_to_file(non_fragments.to_json, "#{path}.json", options)
|
|
165
|
-
@file_saver.save_to_file(fragments.to_json, "#{path}.json", options, true)
|
|
166
|
-
else
|
|
167
|
-
content.each do |key, value|
|
|
168
|
-
child_path = rendered_subdirectory.join(key)
|
|
169
|
-
save_content_recursively(value, options, child_path)
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def extract_model(html, filename, subdirectory)
|
|
175
|
-
model = model_dsl(html)
|
|
176
|
-
|
|
177
|
-
if model
|
|
178
|
-
return unless model["type"].present?
|
|
179
|
-
|
|
180
|
-
model["subdirectory"] = clean_path(subdirectory)
|
|
181
|
-
model["filename"] = clean_path(filename)
|
|
182
|
-
|
|
183
|
-
# reset "type" to not have a prefix, in order to ensure
|
|
184
|
-
# consistent results between the internal only :klass filter
|
|
185
|
-
# which is used as an index in a hash (and has the prefix removed
|
|
186
|
-
# for consistency and deterministic behavior)
|
|
187
|
-
# and the externally filterable :type field.
|
|
188
|
-
model["type"] = model["type"].delete_prefix("::").strip
|
|
189
|
-
|
|
190
|
-
@json_models[model["type"]] ||= []
|
|
191
|
-
@json_models[model["type"]] << model
|
|
192
|
-
|
|
193
|
-
@described_models.push(model)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def extract_fragment_meta(html, subdirectory)
|
|
198
|
-
meta = fragment_dsl(html)
|
|
199
|
-
|
|
200
|
-
if meta
|
|
201
|
-
@fragment_meta = meta
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
directory_meta = directory_fragment_dsl(html)
|
|
205
|
-
|
|
206
|
-
if directory_meta
|
|
207
|
-
@directory_meta[subdirectory] = directory_meta
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def extract_attribute(text)
|
|
212
|
-
attribute, type = attribute_dsl(text)
|
|
213
|
-
type ||= "md"
|
|
214
|
-
|
|
215
|
-
if @described_models.last && attribute
|
|
216
|
-
model = @described_models.last
|
|
217
|
-
model[:described_attribute_type] = type
|
|
218
|
-
model[:described_attribute] = attribute
|
|
219
|
-
model[model[:described_attribute]] = []
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def append_to_attribute(text)
|
|
224
|
-
return if text.match(HTML_COMMENT_REGEX)
|
|
225
|
-
|
|
226
|
-
@described_models.each do |model|
|
|
227
|
-
next unless model[:described_attribute].present?
|
|
228
|
-
|
|
229
|
-
model[model[:described_attribute]] ||= []
|
|
230
|
-
model[model[:described_attribute]] << text
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def pop_attribute(text)
|
|
235
|
-
if @described_models.last && end_attribute_dsl(text)
|
|
236
|
-
finalize_attribute(@described_models.last)
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def pop_model(html)
|
|
241
|
-
if end_model_dsl(html)
|
|
242
|
-
@described_models.pop
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
def finalize_attribute(model)
|
|
247
|
-
return if model[:described_attribute].nil?
|
|
248
|
-
|
|
249
|
-
attribute_name = model.delete(:described_attribute)
|
|
250
|
-
attribute = model[attribute_name].join("\n")
|
|
251
|
-
type = model.delete(:described_attribute_type)
|
|
252
|
-
|
|
253
|
-
case type
|
|
254
|
-
when "html"
|
|
255
|
-
renderer = Redcarpet::Render::HTML.new
|
|
256
|
-
attribute = Redcarpet::Markdown.new(renderer).render(attribute)
|
|
257
|
-
when "md"
|
|
258
|
-
attribute = attribute.strip
|
|
259
|
-
when "int"
|
|
260
|
-
attribute = attribute.strip.gsub("\n", "").to_i
|
|
261
|
-
when "float"
|
|
262
|
-
attribute = attribute.strip.gsub("\n", "").to_f
|
|
263
|
-
when "string"
|
|
264
|
-
attribute = Redcarpet::Markdown.new(::Redcarpet::Render::StripDown).render(attribute).strip
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
model[attribute_name] = attribute
|
|
268
|
-
end
|
|
269
|
-
end
|
|
270
|
-
end
|