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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5cf70bc7bfe4be124645f86a8182c31f2026a5c8c1736b79852e1ca17981b835
4
+ data.tar.gz: 7ff16d507f7fec68fcf09ecebfa7012cf5c8e700f4ebe74d73e163b83a02cea4
5
+ SHA512:
6
+ metadata.gz: 4f28579beda2d8605428020e04db510d9df937513560e5c1c8fb0768767e43573f785584316c7c5748516d9d4881ce0b32db1430a8f658906486af634daf110f
7
+ data.tar.gz: 5882b40b524c9a121aac21ef9adadc32868e1138c92adc47e8dfbbadc84e71e130526831f3e0a78148f9a04298cdecbae8ac068334542ea788e38d3a0fe16676
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2023 Bryant Morrill
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # MarkdownRecord
2
+
3
+ Welcome to MarkdownRecord. This project is still in BETA stage, and as such is subject to rapid change. There are many things that still need improving, so bear that in mind. That said, please feel free to test this project out and provide feedback in the form of GitHub issues! Thank you.
4
+
5
+ MarkdownRecord is a Rails engine that allows you to write markdown with embedded json like this:
6
+
7
+ ```md
8
+ <!--model
9
+ {
10
+ "type": "markdown_record/demo/section",
11
+ "id": 3,
12
+ "name": "Content DSL"
13
+ }
14
+ -->
15
+
16
+ # Content DSL
17
+
18
+ This section describes the Content DSL MarkdownRecord provides to allow you to define application data right alongside your written markdown content.
19
+
20
+ While writing documentation in your markdown source files, you can define json data using HTML comments which will then be made available to you within your application code...
21
+
22
+ ```
23
+
24
+ And then interact with your data in your application code like this:
25
+
26
+ ```ruby
27
+ MarkdownRecord::Demo::Section.find(3)
28
+ => #<MarkdownRecord::Demo::Section filename: "content_dsl", id: 3, name: "Content DSL", subdirectory: "content", type: "markdown_record/demo/section">
29
+ ```
30
+
31
+ And render your markdown content as HTML (with full ERB support) like this:
32
+
33
+ ```html
34
+ <h1>Content DSL</h1>
35
+
36
+ <p>This section describes the Content DSL MarkdownRecord provides to allow you to define application data right alongside your written markdown content.</p>
37
+
38
+ <p>While writing documentation in your markdown source files, you can define json data using HTML comments which will then be made available to you within your application code...</p>
39
+ ```
40
+
41
+ Or render your markdown content as JSON like this:
42
+
43
+ ```json
44
+ {"markdown_record/demo/section":[{"type":"markdown_record/demo/section","id":3,"name":"Content DSL","subdirectory":"content","filename":"content_dsl"}]}
45
+ ```
46
+
47
+ ## All without creating a single controller, writing a single migration, creating a single view, or defining a single route.
48
+
49
+ In other words, MarkdownRecord allows you to write your website's content and define static data at the same time, in the same markdown source file, and have it immediately available to render from your application. By embedding your static data right inside your markdown, or rather extracting your data from your content, you can cut out the hassle of writing database migrations and building forms just to store data that doesn't need to be updated by end users. This approach also helps to keep your application maintainable and consistent, as there will be less code (always a good thing) and only one source of truth for both your written copy and its associated data.
50
+
51
+ The MarkdownRecord engine is packed with super useful features, such as content fragments which let you interact with your source files from within your application code, a powerful (and soon to be extensible) markdown Content DSL that lets you extract data out of your written content and interact with it in an object oriented way, and view helpers to make navigating between your rendered HTML content easy.
52
+
53
+ ---
54
+
55
+ ## Why use MarkdownRecord?
56
+
57
+ MarkdownRecord is a solution for when you need to render written content in your web application, but also need object oriented and relational representations of your written content and the concepts it describes. This is a fairly narrow use case, but there are a few obvious situations where this could come in handy, such as:
58
+
59
+ - API documentation that is queryable, such that a client could query for available endpoints, required and optional parameters, etc.
60
+ - A website containing a blog or other static written copy where you want to attach meta data to it such as topic, keywords, etc.
61
+ - Hosting the rules for a table top game alongside a character or army building feature which needs to know what options are defined in the rules.
62
+ - Any situation where you have written copy and you want to represent the relationships between pieces of it or the concepts it describes in an your application code.
63
+
64
+ MarkdownRecord could be described as a *server side content management system*, as opposed to client side systems such as WordPress and other common blogging platforms, where the writing and editing are done in a browser. With MarkdownRecord you can write content locally without having to worry about converting it to HTML, storing it in a database or integrating a text editor into your web application. It gives you an alternative and way to deal with data with very few compromises.
65
+
66
+ ## Why not use MarkdownRecord?
67
+
68
+ MarkdownRecord should not be used if the code repository the host application lives in cannot be pushed to whenever content changes (unless there is some work around in place to fetch updated content and render it automatically). Without additional automation in place, you must run a command to have the engine pre-render your content locally, then push the results to wherever your application is hosted. As such, content that requires creating or editing from the client side is not something this engine should be used for.
69
+
70
+ ---
71
+ # Usage
72
+
73
+ ## Installation
74
+
75
+ This section explains how to install MarkdownRecord into a host application.
76
+
77
+ First, add this line to your application's Gemfile:
78
+
79
+ ```ruby
80
+ gem "markdown_record"
81
+ ```
82
+
83
+ And then execute:
84
+
85
+ ```bash
86
+ $ bundle install
87
+ ```
88
+
89
+ Then, from the root directory of your application run:
90
+
91
+ ```bash
92
+ $ rails g markdown_record --demo
93
+ ```
94
+
95
+ *Note: if you are already familiar with MarkdownRecord and don't want to install the demo content, you can omit the --demo argument.*
96
+
97
+ The above command will install the engine, resulting in the following output and changes to your application:
98
+
99
+ ```bash
100
+ create markdown_record/content
101
+ create markdown_record/layouts
102
+ create markdown_record/rendered
103
+ exist markdown_record/content
104
+ create markdown_record/content/controller_helpers.md.erb
105
+ create markdown_record/content/configuration.md.erb
106
+ create markdown_record/content/sandbox/foo.md
107
+ create markdown_record/content/home.md.erb
108
+ create markdown_record/content/installation.md.erb
109
+ create markdown_record/content/rendering_basics.md.erb
110
+ create markdown_record/content/content_dsl.md.erb
111
+ create markdown_record/content/routes.md.erb
112
+ create markdown_record/content/model_basics.md.erb
113
+ create markdown_record/content/content_frags.md.erb
114
+ create markdown_record/content/erb_syntax_and_view_helpers.md.erb
115
+ create markdown_record/content/custom_models_and_associations.md.erb
116
+ exist markdown_record/layouts
117
+ create markdown_record/layouts/_concatenated_layout.html.erb
118
+ create markdown_record/layouts/_custom_layout.html.erb
119
+ create markdown_record/layouts/_file_layout.html.erb
120
+ create markdown_record/layouts/_global_layout.html.erb
121
+ exist app/assets/images
122
+ create app/assets/images/ruby-logo.png
123
+ create config/initializers/markdown_record.rb
124
+ create Thorfile
125
+ create lib/tasks/render_content.thor
126
+ gsub config/routes.rb
127
+ ```
128
+
129
+ The files and folders inside `markdown_record/content` are for demo purposes only, and can be deleted once you are ready to create your own content.
130
+
131
+ By default, MarkdownRecord will look in the `markdown_record/content` directory for all your content, and all rendered content will be saved to the `markdown_record/rendered` directory.
132
+
133
+ The engine will be mounted in `config/routes.rb` under the `mdr` path by default.
134
+
135
+ An initializer will be created for you, where you will be able to configure the engine to use different directories and change other default settings. A later section of this guide will provide more details on configuration options.
136
+
137
+ A `Thorfile` and some thor tasks will also be added to your application. These tasks are used to render your content to HTML and JSON.
138
+
139
+ The final step in the installation process is to render the demo content that was installed in `markdown_record/content`. To do so, run this Thor task in your application's root directory:
140
+
141
+ ```bash
142
+ thor render_content:all -s
143
+ ```
144
+
145
+ You should see the following output:
146
+
147
+ ```bash
148
+ ---------------------------------------------------------------
149
+ rendering html and json content with options {:concat=>true, :deep=>true, :save=>true, :layout=>"_concatenated_layout.html.erb", :render_content_fragment_json=>true} ...
150
+ ---------------------------------------------------------------
151
+ rendered: /markdown_record/rendered/content_fragments.json
152
+ rendered: /markdown_record/rendered/content.json
153
+ rendered: /markdown_record/rendered/content/custom_models_and_associations_fragments.json
154
+ rendered: /markdown_record/rendered/content/custom_models_and_associations.json
155
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers_fragments.json
156
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.json
157
+ rendered: /markdown_record/rendered/content/content_frags_fragments.json
158
+ rendered: /markdown_record/rendered/content/content_frags.json
159
+ rendered: /markdown_record/rendered/content/model_basics_fragments.json
160
+ rendered: /markdown_record/rendered/content/model_basics.json
161
+ rendered: /markdown_record/rendered/content/routes_fragments.json
162
+ rendered: /markdown_record/rendered/content/routes.json
163
+ rendered: /markdown_record/rendered/content/content_dsl_fragments.json
164
+ rendered: /markdown_record/rendered/content/content_dsl.json
165
+ rendered: /markdown_record/rendered/content/rendering_basics_fragments.json
166
+ rendered: /markdown_record/rendered/content/rendering_basics.json
167
+ rendered: /markdown_record/rendered/content/installation_fragments.json
168
+ rendered: /markdown_record/rendered/content/installation.json
169
+ rendered: /markdown_record/rendered/content/home_fragments.json
170
+ rendered: /markdown_record/rendered/content/home.json
171
+ rendered: /markdown_record/rendered/content/sandbox_fragments.json
172
+ rendered: /markdown_record/rendered/content/sandbox.json
173
+ rendered: /markdown_record/rendered/content/sandbox/foo_fragments.json
174
+ rendered: /markdown_record/rendered/content/sandbox/foo.json
175
+ rendered: /markdown_record/rendered/content/configuration_fragments.json
176
+ rendered: /markdown_record/rendered/content/configuration.json
177
+ rendered: /markdown_record/rendered/content/controller_helpers_fragments.json
178
+ rendered: /markdown_record/rendered/content/controller_helpers.json
179
+ rendered: /markdown_record/rendered/content.html
180
+ rendered: /markdown_record/rendered/content/custom_models_and_associations.html
181
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.html
182
+ rendered: /markdown_record/rendered/content/content_frags.html
183
+ rendered: /markdown_record/rendered/content/model_basics.html
184
+ rendered: /markdown_record/rendered/content/routes.html
185
+ rendered: /markdown_record/rendered/content/content_dsl.html
186
+ rendered: /markdown_record/rendered/content/rendering_basics.html
187
+ rendered: /markdown_record/rendered/content/installation.html
188
+ rendered: /markdown_record/rendered/content/home.html
189
+ rendered: /markdown_record/rendered/content/sandbox.html
190
+ rendered: /markdown_record/rendered/content/sandbox/foo.html
191
+ rendered: /markdown_record/rendered/content/configuration.html
192
+ rendered: /markdown_record/rendered/content/controller_helpers.html
193
+ ---------------------------------------------------------------
194
+ 42 files rendered.
195
+ 42 files saved.
196
+ ```
197
+
198
+ Congratulations! You have installed MarkdownRecord. If you are not viewing this from the host application already, go ahead and start your Rails server and navigate to http://localhost:3000/mdr/content/home to continue following this guide.
199
+
200
+ ## Contributing
201
+
202
+ Contributions to this project are welcome. Please simply fork the project and open MRs into the main repo if you have something you would like to add or fix. Opening issues for any bugs or improvements you want to be considered is also appreciated.
203
+
204
+ While working within this code base, use `rake spec` to run tests. You can pass `SPEC=<path to spec file>` to run a specific spec file, and you make append `:<line number>` to run a specific example.
205
+
206
+ Things that need doing:
207
+
208
+ - Backfill pending tests
209
+ - Backfill missing tests
210
+ - Reorganize the `lib` folder to not be such a mess
211
+ - Write RDoc docs throughout
212
+
213
+ To test a local version of this gem in a local app, simply add the `path` parameter in your gemfile like so:
214
+
215
+ ```
216
+ gem "markdown_record", path: "../markdown_record"
217
+ ```
218
+
219
+ ## Roadmap
220
+
221
+ - Make the Content DSL extensible
222
+ - Add support for raw JSON files as source content
223
+
224
+ ## License
225
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require "rspec/core/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task default: :spec
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/markdown_record .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,11 @@
1
+ module MarkdownRecord
2
+ class ApplicationController < ActionController::Base
3
+ include ::MarkdownRecord::ControllerHelpers
4
+
5
+ before_action :render_not_found
6
+
7
+ def render_not_found
8
+ head :not_found unless content_fragment
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module MarkdownRecord
2
+ class ContentController < ApplicationController
3
+ def show
4
+ respond_to do |format|
5
+ format.html do |html|
6
+ render_html
7
+ end
8
+ format.json { render_json }
9
+ end
10
+ end
11
+
12
+ def download
13
+ respond_to do |format|
14
+ format.html { download_html }
15
+ format.json { download_json }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module MarkdownRecord
2
+ class HtmlController < ApplicationController
3
+ def show
4
+ render_html
5
+ end
6
+
7
+ def download
8
+ download_html
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module MarkdownRecord
2
+ class JsonController < ApplicationController
3
+ def show
4
+ render_json
5
+ end
6
+
7
+ def download
8
+ download_json
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module MarkdownRecord
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,39 @@
1
+ module MarkdownRecord
2
+ module ControllerHelpers
3
+ def render_html(fragment = content_fragment, layout = MarkdownRecord.config.public_layout)
4
+ if fragment.html_exists?
5
+ render file: fragment.html_path, layout: layout
6
+ else
7
+ head :not_found
8
+ end
9
+ end
10
+
11
+ def render_json(fragment = content_fragment)
12
+ if fragment.json_exists?
13
+ render file: fragment.json_path, layout: nil
14
+ else
15
+ head :not_found
16
+ end
17
+ end
18
+
19
+ def download_html(fragment = content_fragment, layout = MarkdownRecord.config.public_layout)
20
+ if fragment.html_exists?
21
+ send_file fragment.html_path, layout: layout
22
+ else
23
+ head :not_found
24
+ end
25
+ end
26
+
27
+ def download_json(fragment = content_fragment)
28
+ if fragment.json_exists?
29
+ send_file fragment.json_path, layout: nil
30
+ else
31
+ head :not_found
32
+ end
33
+ end
34
+
35
+ def content_fragment(content_path = params[:content_path])
36
+ ::MarkdownRecord::ContentFragment.find(content_path)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,84 @@
1
+ module MarkdownRecord
2
+ module ViewHelpers
3
+ def link_to_markdown_record(model, name = nil, html_options = nil, &block)
4
+ return nil if model.nil?
5
+
6
+ path = path_to_markdown_record(model, "")
7
+ name ||= model.name if model.respond_to?(:name)
8
+
9
+ block_given? ? link_to(path, html_options, nil, &block) : link_to(name, path, html_options, &block)
10
+ end
11
+
12
+ def link_to_markdown_record_html(model, name = nil, html_options = nil, &block)
13
+ return nil if model.nil?
14
+
15
+ path = path_to_markdown_record_html(model)
16
+ name ||= model.name if model.respond_to?(:name)
17
+
18
+ block_given? ? link_to(path, html_options, nil, &block) : link_to(name, path, html_options, &block)
19
+ end
20
+
21
+ def link_to_download_markdown_record_html(model, name = nil, html_options = nil, &block)
22
+ return nil if model.nil?
23
+
24
+ path = path_to_markdown_record_html(model, true)
25
+ name ||= model.name if model.respond_to?(:name)
26
+
27
+ block_given? ? link_to("/#{path}", html_options, nil, &block) : link_to(name, path, html_options, &block)
28
+ end
29
+
30
+ def path_to_markdown_record_html(model, download = false)
31
+ path_to_markdown_record(model, "html", download)
32
+ end
33
+
34
+ def url_for_markdown_record_html(model, download = false)
35
+ path = path_to_markdown_record_html(model, download)
36
+
37
+ "#{root_url}/#{path}"
38
+ end
39
+
40
+ def link_to_markdown_record_json(model, name = nil, html_options = nil, &block)
41
+ return nil if model.nil?
42
+
43
+ path = path_to_markdown_record_json(model)
44
+ name ||= model.name if model.respond_to?(:name)
45
+
46
+ block_given? ? link_to(path, html_options, nil, &block) : link_to(name, path, html_options, &block)
47
+ end
48
+
49
+ def link_to_download_markdown_record_json(model, name = nil, html_options = nil, &block)
50
+ return nil if model.nil?
51
+
52
+ path = path_to_markdown_record_json(model, true)
53
+ name ||= model.name if model.respond_to?(:name)
54
+
55
+ block_given? ? link_to("/#{path}", html_options, nil, &block) : link_to(name, path, html_options, &block)
56
+ end
57
+
58
+ def path_to_markdown_record_json(model, download = false)
59
+ path_to_markdown_record(model, "json", download)
60
+ end
61
+
62
+ def url_for_markdown_record_html(model, download = false)
63
+ path = path_to_markdown_record_json(model, download)
64
+
65
+ "#{root_url}/#{path}"
66
+ end
67
+
68
+ def path_to_markdown_record(model, ext, download = false)
69
+ raise ArgumentError.new("A MarkdownRecord model must be provided.") unless model&.is_a?(::MarkdownRecord::Base)
70
+
71
+ subdirectory = model.fragment_id
72
+
73
+ path = Pathname.new(MarkdownRecord.config.mount_path).join(ext)
74
+ path = path.join("download") if download
75
+ path = path.join(subdirectory).to_s
76
+
77
+ "/#{path}"
78
+ end
79
+
80
+ def render_html_example(example)
81
+ CGI.escapeHTML(example)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,10 @@
1
+ module MarkdownRecord
2
+ module Demo
3
+ class DslCommand < ::MarkdownRecord::Base
4
+ attribute :name
5
+ attribute :description
6
+
7
+ belongs_to_content :section
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module MarkdownRecord
2
+ module Demo
3
+ class Section < ::MarkdownRecord::Base
4
+ attribute :name
5
+
6
+ has_many_content :dsl_commands
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module MarkdownRecord
2
+ module Tests
3
+ class ChildModel < ::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
@@ -0,0 +1,13 @@
1
+ module MarkdownRecord
2
+ module Tests
3
+ class FakeActiveRecordModel
4
+ include ::ActiveAttr::Model
5
+ include ::MarkdownRecord::ContentAssociations
6
+ attribute :model_ids
7
+ attribute :child_model_id
8
+
9
+ has_many_content :models
10
+ belongs_to_content :child_model
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module MarkdownRecord
2
+ module Tests
3
+ class Model < ::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
+ has_many_content :child_models
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
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/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ ::MarkdownRecord::Engine.routes.draw do
2
+ routing_config = ::MarkdownRecord.config.routing
3
+
4
+ get "html/download/*content_path", to: "html#download" if routing_config[:html].include?(:download)
5
+ get "html/*content_path", to: "html#show" if routing_config[:html].include?(:show)
6
+
7
+ get "json/download/*content_path", to: "json#download" if routing_config[:json].include?(:download)
8
+ get "json/*content_path", to: "json#show" if routing_config[:json].include?(:show)
9
+
10
+ get "download/*content_path", to: "content#download" if routing_config[:content].include?(:download)
11
+ get "/*content_path", to: "content#show" if routing_config[:content].include?(:show)
12
+
13
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require "rails/generators"
3
+
4
+ class MarkdownRecordGenerator < Rails::Generators::Base
5
+ source_root File.expand_path("../../templates", __dir__)
6
+ class_option :demo, type: :boolean, aliases: :d
7
+
8
+ desc "This generator creates the default directories required for markdown_record and copies the default layout into the default location."
9
+ def create_directories
10
+ empty_directory "markdown_record/content"
11
+ empty_directory "markdown_record/layouts"
12
+ empty_directory "markdown_record/rendered"
13
+ end
14
+
15
+ def copy_demo_or_base
16
+ if options[:demo]
17
+ directory "demo/content", "markdown_record/content"
18
+ directory "demo/layouts", "markdown_record/layouts"
19
+ directory "demo/assets/images", "app/assets/images"
20
+ else
21
+ directory "base/content", "markdown_record/content"
22
+ directory "base/layouts", "markdown_record/layouts"
23
+ end
24
+ end
25
+
26
+ def copy_initializer
27
+ copy_file "markdown_record_initializer.rb", "config/initializers/markdown_record.rb"
28
+ end
29
+
30
+ def copy_thorfile
31
+ copy_file "Thorfile", "Thorfile"
32
+ end
33
+
34
+ def copy_thor_tasks
35
+ copy_file "render_content.thor", "lib/tasks/render_content.thor"
36
+ end
37
+
38
+ def mount_engine
39
+ gsub_file "config/routes.rb", "\n # Do not change this mount path here! Instead change it in the MarkdownRecord initializer.\n mount MarkdownRecord::Engine, at: MarkdownRecord.config.mount_path, as: \"markdown_record\"", ""
40
+ gsub_file "config/routes.rb", /Rails.application.routes.draw do/, "Rails.application.routes.draw do\n # Do not change this mount path here! Instead change it in the MarkdownRecord initializer.\n mount MarkdownRecord::Engine, at: MarkdownRecord.config.mount_path, as: \"markdown_record\""
41
+ end
42
+ end
43
+
44
+