markdown_record 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +225 -0
  4. data/Rakefile +9 -0
  5. data/app/assets/config/markdown_cms_manifest.js +1 -0
  6. data/app/assets/stylesheets/markdown_cms/application.css +15 -0
  7. data/app/controllers/markdown_record/application_controller.rb +11 -0
  8. data/app/controllers/markdown_record/content_controller.rb +19 -0
  9. data/app/controllers/markdown_record/html_controller.rb +11 -0
  10. data/app/controllers/markdown_record/json_controller.rb +11 -0
  11. data/app/helpers/markdown_record/application_helper.rb +4 -0
  12. data/app/helpers/markdown_record/controller_helpers.rb +39 -0
  13. data/app/helpers/markdown_record/view_helpers.rb +84 -0
  14. data/app/models/markdown_record/demo/dsl_command.rb +10 -0
  15. data/app/models/markdown_record/demo/section.rb +9 -0
  16. data/app/models/markdown_record/tests/child_model.rb +15 -0
  17. data/app/models/markdown_record/tests/fake_active_record_model.rb +13 -0
  18. data/app/models/markdown_record/tests/model.rb +15 -0
  19. data/app/models/markdown_record/tests/other_child_model.rb +15 -0
  20. data/config/routes.rb +13 -0
  21. data/lib/generators/markdown_record_generator.rb +44 -0
  22. data/lib/markdown_record/association.rb +131 -0
  23. data/lib/markdown_record/associations.rb +106 -0
  24. data/lib/markdown_record/base.rb +25 -0
  25. data/lib/markdown_record/cli.rb +54 -0
  26. data/lib/markdown_record/configuration.rb +66 -0
  27. data/lib/markdown_record/content_associations.rb +46 -0
  28. data/lib/markdown_record/content_dsl/attribute.rb +22 -0
  29. data/lib/markdown_record/content_dsl/directory_fragment.rb +22 -0
  30. data/lib/markdown_record/content_dsl/disable.rb +22 -0
  31. data/lib/markdown_record/content_dsl/enable.rb +22 -0
  32. data/lib/markdown_record/content_dsl/end_attribute.rb +22 -0
  33. data/lib/markdown_record/content_dsl/end_model.rb +22 -0
  34. data/lib/markdown_record/content_dsl/fragment.rb +22 -0
  35. data/lib/markdown_record/content_dsl/model.rb +23 -0
  36. data/lib/markdown_record/content_dsl/render_format.rb +22 -0
  37. data/lib/markdown_record/content_dsl/render_strategy.rb +22 -0
  38. data/lib/markdown_record/content_dsl/use_layout.rb +22 -0
  39. data/lib/markdown_record/content_dsl.rb +37 -0
  40. data/lib/markdown_record/content_fragment.rb +123 -0
  41. data/lib/markdown_record/engine.rb +13 -0
  42. data/lib/markdown_record/errors/base.rb +6 -0
  43. data/lib/markdown_record/errors/duplicate_filename_error.rb +21 -0
  44. data/lib/markdown_record/errors/duplicate_id_error.rb +11 -0
  45. data/lib/markdown_record/errors/missing_parent_error.rb +11 -0
  46. data/lib/markdown_record/file_saver.rb +39 -0
  47. data/lib/markdown_record/html_renderer.rb +194 -0
  48. data/lib/markdown_record/indexer.rb +34 -0
  49. data/lib/markdown_record/json_renderer.rb +270 -0
  50. data/lib/markdown_record/model_inflator.rb +107 -0
  51. data/lib/markdown_record/path_utilities.rb +86 -0
  52. data/lib/markdown_record/rendering.rb +57 -0
  53. data/lib/markdown_record/routes_renderer.rb +0 -0
  54. data/lib/markdown_record/validator.rb +59 -0
  55. data/lib/markdown_record/version.rb +3 -0
  56. data/lib/markdown_record.rb +28 -0
  57. data/templates/Thorfile +3 -0
  58. data/templates/base/content/example_content.md +3 -0
  59. data/templates/base/layouts/_concatenated_layout.html.erb +8 -0
  60. data/templates/base/layouts/_custom_layout.html.erb +7 -0
  61. data/templates/base/layouts/_file_layout.html.erb +8 -0
  62. data/templates/base/layouts/_global_layout.html.erb +8 -0
  63. data/templates/demo/assets/images/ruby-logo.png +0 -0
  64. data/templates/demo/content/10_custom_models_and_associations.md.erb +78 -0
  65. data/templates/demo/content/11_controller_helpers.md.erb +20 -0
  66. data/templates/demo/content/12_configuration.md.erb +26 -0
  67. data/templates/demo/content/13_sandbox/1_foo.md +12 -0
  68. data/templates/demo/content/13_sandbox/2_sandbox_nested/1_bar.md +18 -0
  69. data/templates/demo/content/1_home.md.erb +40 -0
  70. data/templates/demo/content/2_installation.md.erb +129 -0
  71. data/templates/demo/content/3_rendering_basics.md.erb +71 -0
  72. data/templates/demo/content/4_content_dsl.md.erb +104 -0
  73. data/templates/demo/content/5_routes.md.erb +43 -0
  74. data/templates/demo/content/6_model_basics.md.erb +105 -0
  75. data/templates/demo/content/7_content_frags.md.erb +78 -0
  76. data/templates/demo/content/8_erb_syntax_and_view_helpers.md.erb +88 -0
  77. data/templates/demo/content/9_layouts.md.erb +15 -0
  78. data/templates/demo/layouts/_concatenated_layout.html.erb +12 -0
  79. data/templates/demo/layouts/_custom_layout.html.erb +14 -0
  80. data/templates/demo/layouts/_file_layout.html.erb +15 -0
  81. data/templates/demo/layouts/_global_layout.html.erb +108 -0
  82. data/templates/markdown_record_initializer.rb +3 -0
  83. data/templates/render_content.thor +57 -0
  84. metadata +270 -0
@@ -0,0 +1,131 @@
1
+ require "markdown_record/errors/duplicate_id_error"
2
+
3
+ module MarkdownRecord
4
+ class Association
5
+ attr_accessor :base_filters
6
+ attr_accessor :search_filters
7
+ attr_reader :fulfilled
8
+
9
+ def initialize(base_filters, search_filters = {})
10
+ @base_filters = base_filters
11
+ @include_fragments = false
12
+ @search_filters = search_filters
13
+ @data = []
14
+ @fulfilled = false
15
+ end
16
+
17
+ def execute
18
+ reset
19
+ final_filters = self.search_filters.merge(self.base_filters)
20
+ if @include_fragments
21
+ final_filters.merge!(:klass => ::MarkdownRecord::ContentFragment)
22
+ else
23
+ final_filters.merge!(:exclude_fragments => true)
24
+ end
25
+ results = MarkdownRecord::ModelInflator.new.where(final_filters)
26
+ @data.push(*results)
27
+ @fulfilled = true
28
+ end
29
+
30
+ def fragmentize
31
+ reset
32
+ @include_fragments = true
33
+ self
34
+ end
35
+
36
+ def to_fragments
37
+ execute unless fulfilled
38
+ return @data if @include_fragments
39
+
40
+ @data.map { |m| m.fragment }
41
+ end
42
+
43
+ def reset
44
+ @data = []
45
+ @fulfilled = false
46
+ end
47
+
48
+ def all
49
+ execute unless fulfilled
50
+ @data
51
+ end
52
+
53
+ def to_a
54
+ execute unless fulfilled
55
+ @data
56
+ end
57
+
58
+ def not(filters = {})
59
+ search_filters[:__not__] ||= {}
60
+ search_filters[:__not__].merge!(filters)
61
+ execute
62
+ self
63
+ end
64
+
65
+ def where(filters = {})
66
+ search_filters.merge!(filters)
67
+ execute
68
+ self
69
+ end
70
+
71
+ def each(...)
72
+ execute unless fulfilled
73
+ all unless fulfilled
74
+ @data.each(...)
75
+ end
76
+
77
+ def map(...)
78
+ execute unless fulfilled
79
+ execute
80
+ @data.map(...)
81
+ end
82
+
83
+ def count(...)
84
+ execute unless fulfilled
85
+ @data.count(...)
86
+ end
87
+
88
+ def any?(...)
89
+ execute unless fulfilled
90
+ @data.any?(...)
91
+ end
92
+
93
+ def empty?(...)
94
+ execute unless fulfilled
95
+ @data.empty?(...)
96
+ end
97
+
98
+ def first(...)
99
+ execute unless fulfilled
100
+ @data.first(...)
101
+ end
102
+
103
+ def last(...)
104
+ execute unless fulfilled
105
+ @data.first(...)
106
+ end
107
+
108
+ def second(...)
109
+ execute unless fulfilled
110
+ @data.second(...)
111
+ end
112
+
113
+ def third(...)
114
+ execute unless fulfilled
115
+ @data.third(...)
116
+ end
117
+
118
+ def fourth(...)
119
+ execute unless fulfilled
120
+ @data.fourth(...)
121
+ end
122
+
123
+ def __find__(id)
124
+ reset
125
+ search_filters.merge!({:id => id})
126
+ execute
127
+ raise ::MarkdownRecord::Errors::DuplicateIdError.new(@base_filters[:klass].name, id) if @data.count > 1
128
+ @data.first
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,106 @@
1
+ module MarkdownRecord
2
+ module Associations
3
+ extend ActiveSupport::Concern
4
+ include ::MarkdownRecord::PathUtilities
5
+
6
+ class_methods do
7
+ def has_many_content(association, **options)
8
+ klass = infer_klass(association, options)
9
+ raise ArgumentError.new("The association class name could not be inferred, and was not provided") if klass.nil?
10
+
11
+ foreign_key = "#{self.name.demodulize.underscore}_id".to_sym
12
+
13
+ define_method(association) do
14
+ klass.new_association({:klass => klass, foreign_key => self.id})
15
+ end
16
+ end
17
+
18
+ def has_one_content(association, **options)
19
+ klass = infer_klass(association, options)
20
+ raise ArgumentError.new("The association class name could not be inferred, and was not provided") if klass.nil?
21
+
22
+ foreign_key = "#{self.name.demodulize.underscore}_id".to_sym
23
+
24
+ define_method(association) do
25
+ results = klass.new_association({:klass => klass, foreign_key => self.id}).all
26
+ if results.count > 1
27
+ raise ArgumentError.new("Multiple MarkdownRecords belong to the same record in a has_one_content assocition: #{self.class.name} has a has_one_content #{association} and the following records ids were found #{ results.map(&:id) } ")
28
+ end
29
+
30
+ results.first
31
+ end
32
+ end
33
+
34
+ def belongs_to_content(association, **options)
35
+ klass = infer_klass(association, options)
36
+
37
+ raise ArgumentError.new("The association class name could not be inferred, and was not provided") if klass.nil?
38
+
39
+ foreign_key = "#{association}_id".to_sym
40
+ self.attribute foreign_key unless self.attributes[foreign_key].present?
41
+
42
+ define_method(association) do
43
+ klass.find(self[foreign_key])
44
+ end
45
+ end
46
+
47
+ def all
48
+ new_association({ :klass => self }).all
49
+ end
50
+
51
+ def where(filters = {})
52
+ new_association({ :klass => self }, filters)
53
+ end
54
+
55
+ def find(id)
56
+ new_association({ :klass => self }).__find__(id)
57
+ end
58
+
59
+ def infer_klass(association, options)
60
+ class_name = options[:class_name]
61
+ class_name ||= association.to_s.singularize.camelize
62
+
63
+ if self.name.include?("::") && !class_name.include?("::")
64
+ klass = "#{self.name.split('::')[0...-1].join("::")}::#{class_name}".safe_constantize
65
+ end
66
+
67
+ klass ||= class_name.camelize.safe_constantize
68
+ end
69
+ end
70
+
71
+ def siblings(filters = {})
72
+ self.class.new_association(filters.merge({:subdirectory => subdirectory}).merge!(not_self))
73
+ end
74
+
75
+ def class_siblings(filters = {})
76
+ self.class.new_association(filters.merge({:klass => self.class, :subdirectory => subdirectory, :__not__ => { :id => self.id }}))
77
+ end
78
+
79
+ def children(filters = {})
80
+ sub_start = "#{subdirectory}/".delete_prefix("/")
81
+ self.class.new_association(filters.merge({:subdirectory => Regexp.new("#{sub_start}[\\S|\\w]+")}).merge!(not_self))
82
+ end
83
+
84
+ def fragment
85
+ self.class.new_association.fragmentize.__find__(fragment_id)
86
+ end
87
+
88
+ private
89
+
90
+ def not_self
91
+ {
92
+ :__or__ => [
93
+ { :__not__ => {
94
+ :id => self.id
95
+ }
96
+ },
97
+ {
98
+ :__not__ => {
99
+ :type => self.type
100
+ }
101
+ }
102
+ ]
103
+ }
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,25 @@
1
+ require "active_attr"
2
+
3
+ module MarkdownRecord
4
+ class Base
5
+ include ::ActiveAttr::Model
6
+ include ::MarkdownRecord::Associations
7
+
8
+ attribute :id
9
+ attribute :type, :type => String
10
+ attribute :subdirectory, :type => String
11
+ attribute :filename, :type => String
12
+
13
+ def self.new_association(base_filters = {}, search_filters = {})
14
+ MarkdownRecord::Association.new(base_filters, search_filters)
15
+ end
16
+
17
+ def fragment_id
18
+ Pathname.new(subdirectory).join(filename).to_s
19
+ end
20
+
21
+ def self.json_klass
22
+ name.underscore
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,54 @@
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
@@ -0,0 +1,66 @@
1
+ module MarkdownRecord
2
+ class Configuration
3
+ include Singleton
4
+
5
+ attr_accessor :content_root
6
+ attr_accessor :rendered_content_root
7
+ attr_accessor :layout_directory
8
+ attr_accessor :concatenated_layout_path
9
+ attr_accessor :file_layout_path
10
+ attr_accessor :global_layout_path
11
+ attr_accessor :markdown_extensions
12
+ attr_accessor :html_render_options
13
+ attr_accessor :public_layout
14
+ attr_accessor :render_strategy
15
+ attr_accessor :html_routes
16
+ attr_accessor :json_routes
17
+ attr_accessor :content_routes
18
+ attr_accessor :mount_path
19
+ attr_accessor :render_content_fragment_json
20
+ attr_accessor :render_controller
21
+ attr_accessor :ignore_numeric_prefix
22
+
23
+ RENDER_STRATEGIES = [:full, :directory, :file]
24
+
25
+ def initialize
26
+ @content_root = Rails.root.join("markdown_record","content")
27
+ @rendered_content_root = Rails.root.join("markdown_record","rendered")
28
+ @layout_directory = Rails.root.join("markdown_record","layouts")
29
+ @html_render_options = {}
30
+ @markdown_extensions = { :fenced_code_blocks => true, :disable_indented_code_blocks => true, :no_intra_emphasis => true}
31
+ @concatenated_layout_path = "_concatenated_layout.html.erb"
32
+ @file_layout_path = "_file_layout.html.erb"
33
+ @global_layout_path = "_global_layout.html.erb"
34
+ @public_layout = "layouts/application"
35
+ @render_strategy = :full
36
+ @html_routes = [:show]
37
+ @json_routes = [:show]
38
+ @content_routes = [:show]
39
+ @mount_path = "mdr"
40
+ @render_content_fragment_json = true
41
+ @render_controller = nil
42
+ @ignore_numeric_prefix = true
43
+ end
44
+
45
+ def render_strategy_options(strategy = nil)
46
+ strat = strategy || @render_strategy
47
+
48
+ unless RENDER_STRATEGIES.include?(strat)
49
+ raise ::ArgumentError.new("Invalide render strategy.")
50
+ end
51
+
52
+ case strategy || @render_strategy
53
+ when :full
54
+ {:concat => true, :deep => true}
55
+ when :directory
56
+ {:concat => true, :deep => false}
57
+ when :file
58
+ {:concat => false, :deep => true}
59
+ end
60
+ end
61
+
62
+ def routing
63
+ { :html => html_routes, :json => json_routes, :content => content_routes}
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,46 @@
1
+ module MarkdownRecord
2
+ module ContentAssociations
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def has_many_content(association, **options)
7
+ klass = infer_klass(association, options)
8
+ raise ArgumentError.new("The association class name could not be inferred, and was not provided") if klass.nil?
9
+
10
+ foreign_key = "#{association.to_s.singularize}_ids"
11
+ raise ArgumentError.new("#{self} does not have the #{foreign_key} attribute required for this association.") unless self.attribute_names.include?(foreign_key)
12
+
13
+ define_method(association) do
14
+ klass.new_association({:klass => klass, :id => self[foreign_key.to_sym]})
15
+ end
16
+ end
17
+
18
+ def has_one_content(association, **options)
19
+ belongs_to_content(association, **options)
20
+ end
21
+
22
+ def belongs_to_content(association, **options)
23
+ klass = infer_klass(association, options)
24
+ raise ArgumentError.new("The association class name could not be inferred, and was not provided") if klass.nil?
25
+
26
+ foreign_key = "#{association.to_s.singularize}_id"
27
+ raise ArgumentError.new("#{self} does not have the #{foreign_key} attribute required for this association.") unless self.attribute_names.include?(foreign_key)
28
+
29
+ define_method(association) do
30
+ klass.find(self[foreign_key])
31
+ end
32
+ end
33
+
34
+ def infer_klass(association, options)
35
+ class_name = options[:class_name]
36
+ class_name ||= association.to_s.singularize.camelize
37
+
38
+ if self.name.include?("::") && !class_name.include?("::")
39
+ klass = "#{self.name.split('::')[0...-1].join("::")}::#{class_name}".safe_constantize
40
+ end
41
+
42
+ klass ||= class_name.camelize.safe_constantize
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,22 @@
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">)&lt;!--\s*attribute\s*:\s*(\w+)\s*(?::((?:html|md|int|float|string)?))?--&gt;(?!<\/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
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module DirectoryFragment
4
+ REGEX = /(?<!`|`\\n|`html\\n)<!--\s*directory_fragment\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*-->(?!`|\\n`)/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*directory_fragment\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*--&gt;(?!<\/code>)/
6
+
7
+ def directory_fragment_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ JSON.parse(match[1])
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
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module Disable
4
+ REGEX = /<!--\s*disable\s*-->/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*disable\s*--&gt;(?!<\/code>)/
6
+
7
+ def disable_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+
17
+ def self.remove_dsl(text)
18
+ text.gsub(ENCODED_REGEX, "")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module Enable
4
+ REGEX = /<!--\s*enable\s*-->/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*enable\s*--&gt;(?!<\/code>)/
6
+
7
+ def enable_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+
17
+ def self.remove_dsl(text)
18
+ text.gsub(ENCODED_REGEX, "")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module EndAttribute
4
+ REGEX = /(?<!`|`\\n|`html\\n)<!--\s*end_attribute\s*-->(?!`|\\n`)/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*end_attribute\s*--&gt;(?!<\/code>)/
6
+
7
+ def end_attribute_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+
17
+ def self.remove_dsl(text)
18
+ text.gsub(ENCODED_REGEX, "")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module EndModel
4
+ REGEX = /(?<!`|`\\n|`html\\n)<!--\s*end_model\s*-->(?!`|\\n`)/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*end_model\s*--&gt;(?!<\/code>)/
6
+
7
+ def end_model_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+
17
+ def self.remove_dsl(text)
18
+ text.gsub(ENCODED_REGEX, "")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module Fragment
4
+ REGEX = /(?<!`|`\\n|`html\\n)<!--\s*fragment\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*-->(?!`|\\n`)/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*fragment\s+({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*--&gt;(?!<\/code>)/
6
+
7
+ def fragment_dsl(text)
8
+ match = text.match(REGEX)
9
+
10
+ if match
11
+ JSON.parse(match[1])
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
@@ -0,0 +1,23 @@
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">)&lt;!--\s*model\s*({[\s"'\\\w:,.\[\]\{\}_\/]*})\s*--&gt;(?!<\/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
@@ -0,0 +1,22 @@
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">)&lt;!--\s*render_format\s*:\s*(.*)\s*--&gt;(?!<\/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
@@ -0,0 +1,22 @@
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">)&lt;!--\s*render_strategy\s*:\s*(.*)\s*--&gt;(?!<\/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
@@ -0,0 +1,22 @@
1
+ module MarkdownRecord
2
+ module ContentDsl
3
+ module UseLayout
4
+ REGEX = /(?<!`|`\\n|`html\\n)<!--\s*use_layout\s*:\s*(.*)\s*-->(?!`|\\n`)/
5
+ ENCODED_REGEX = /(?<!<code>|<code class="html">)&lt;!--\s*use_layout\s*:\s*(.*)\s*--&gt;(?!<\/code>)/
6
+
7
+ def use_layout_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