embeddable_content 0.1.19

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.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +62 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +15 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +49 -0
  8. data/Rakefile +22 -0
  9. data/app/assets/config/embeddable_content_manifest.js +0 -0
  10. data/app/assets/images/embeddable_content/.keep +0 -0
  11. data/app/assets/javascripts/desmos/support.js +12 -0
  12. data/app/assets/javascripts/geogebra/support.js +14 -0
  13. data/app/assets/stylesheets/embeddable_content/.keep +0 -0
  14. data/app/controllers/.keep +0 -0
  15. data/app/controllers/concerns/cms/embeddable_content_controller.rb +14 -0
  16. data/app/controllers/concerns/embeddable_content_controller.rb +85 -0
  17. data/app/helpers/.keep +0 -0
  18. data/app/mailers/.keep +0 -0
  19. data/app/models/.keep +0 -0
  20. data/app/models/concerns/provides_embeddable_content.rb +59 -0
  21. data/app/models/embeddable_model_config.rb +55 -0
  22. data/app/models/embedder_config.rb +45 -0
  23. data/app/models/embedding.rb +25 -0
  24. data/app/services/embeddable_content/desmos_files/doc_processor.rb +5 -0
  25. data/app/services/embeddable_content/desmos_files/node_processor.rb +7 -0
  26. data/app/services/embeddable_content/doc_processor.rb +63 -0
  27. data/app/services/embeddable_content/embedded_tag_info.rb +50 -0
  28. data/app/services/embeddable_content/embedded_tags.rb +30 -0
  29. data/app/services/embeddable_content/embedder.rb +89 -0
  30. data/app/services/embeddable_content/embedder_base.rb +68 -0
  31. data/app/services/embeddable_content/fragment_embedder.rb +30 -0
  32. data/app/services/embeddable_content/geogebra_files/doc_processor.rb +5 -0
  33. data/app/services/embeddable_content/geogebra_files/node_processor.rb +11 -0
  34. data/app/services/embeddable_content/html_tags/doc_processor.rb +11 -0
  35. data/app/services/embeddable_content/html_tags/node_processor.rb +26 -0
  36. data/app/services/embeddable_content/images/attributions_processor.rb +60 -0
  37. data/app/services/embeddable_content/images/doc_processor.rb +54 -0
  38. data/app/services/embeddable_content/images/image_downloader.rb +60 -0
  39. data/app/services/embeddable_content/images/img_tag_attributes.rb +125 -0
  40. data/app/services/embeddable_content/images/modal_dialog.rb +74 -0
  41. data/app/services/embeddable_content/images/node_processor.rb +91 -0
  42. data/app/services/embeddable_content/images/shared.rb +11 -0
  43. data/app/services/embeddable_content/node_processor.rb +75 -0
  44. data/app/services/embeddable_content/presentation_tags/doc_processor.rb +5 -0
  45. data/app/services/embeddable_content/presentation_tags/node_processor.rb +35 -0
  46. data/app/services/embeddable_content/record_node_processor.rb +90 -0
  47. data/app/services/embeddable_content/replacement_template_manager.rb +21 -0
  48. data/app/services/embeddable_content/sad_embedded_tags.rb +29 -0
  49. data/app/services/embeddable_content/scrubber.rb +32 -0
  50. data/app/services/embeddable_content/template_based.rb +19 -0
  51. data/app/services/embeddable_content/template_manager.rb +100 -0
  52. data/app/services/embeddable_content/tex/base_renderer.rb +33 -0
  53. data/app/services/embeddable_content/tex/canvas_renderer.rb +15 -0
  54. data/app/services/embeddable_content/tex/doc_processor.rb +55 -0
  55. data/app/services/embeddable_content/tex/mathjax_renderer.rb +11 -0
  56. data/app/services/embeddable_content/tex/mml_renderer.rb +11 -0
  57. data/app/services/embeddable_content/tex/schoology_string_renderer.rb +15 -0
  58. data/app/services/embeddable_content/tex/svg_renderer.rb +11 -0
  59. data/app/services/embeddable_content/token_replacement_map.rb +32 -0
  60. data/app/services/embeddable_content/tree_based_node_processor.rb +23 -0
  61. data/app/services/embeddable_content/video_links/doc_processor.rb +5 -0
  62. data/app/services/embeddable_content/video_links/node_processor.rb +46 -0
  63. data/app/services/embeddable_content/video_links/vimeo_player_settings.rb +19 -0
  64. data/app/services/embeddable_content/visual_element_node_processor.rb +13 -0
  65. data/app/services/embeddable_content/widget_files/doc_processor.rb +5 -0
  66. data/app/services/embeddable_content/widget_files/node_processor.rb +7 -0
  67. data/app/views/.keep +0 -0
  68. data/app/views/embeddable_content/replacements/desmos_files/_applet.html.slim +8 -0
  69. data/app/views/embeddable_content/replacements/desmos_files/_description.html.slim +6 -0
  70. data/app/views/embeddable_content/replacements/desmos_files/cc.html.slim +1 -0
  71. data/app/views/embeddable_content/replacements/desmos_files/cms.html.slim +1 -0
  72. data/app/views/embeddable_content/replacements/desmos_files/editable.html.slim +1 -0
  73. data/app/views/embeddable_content/replacements/desmos_files/exported.html.slim +1 -0
  74. data/app/views/embeddable_content/replacements/desmos_files/kiddom.html.slim +1 -0
  75. data/app/views/embeddable_content/replacements/desmos_files/print.html.slim +1 -0
  76. data/app/views/embeddable_content/replacements/desmos_files/qti.html.slim +1 -0
  77. data/app/views/embeddable_content/replacements/desmos_files/schoology.html.slim +1 -0
  78. data/app/views/embeddable_content/replacements/desmos_files/web.html.slim +1 -0
  79. data/app/views/embeddable_content/replacements/geogebra_files/_applet.html.slim +11 -0
  80. data/app/views/embeddable_content/replacements/geogebra_files/_description.html.slim +9 -0
  81. data/app/views/embeddable_content/replacements/geogebra_files/cc.html.slim +1 -0
  82. data/app/views/embeddable_content/replacements/geogebra_files/cms.html.slim +1 -0
  83. data/app/views/embeddable_content/replacements/geogebra_files/editable.html.slim +1 -0
  84. data/app/views/embeddable_content/replacements/geogebra_files/exported.html.slim +1 -0
  85. data/app/views/embeddable_content/replacements/geogebra_files/kiddom.html.slim +1 -0
  86. data/app/views/embeddable_content/replacements/geogebra_files/print.html.slim +1 -0
  87. data/app/views/embeddable_content/replacements/geogebra_files/qti.html.slim +1 -0
  88. data/app/views/embeddable_content/replacements/geogebra_files/schoology.html.slim +1 -0
  89. data/app/views/embeddable_content/replacements/geogebra_files/web.html.slim +1 -0
  90. data/app/views/embeddable_content/replacements/html_tags/editable.html.slim +16 -0
  91. data/app/views/embeddable_content/replacements/images/_button_close.html.slim +9 -0
  92. data/app/views/embeddable_content/replacements/images/_button_open.html.slim +9 -0
  93. data/app/views/embeddable_content/replacements/images/_image_embed.html.slim +14 -0
  94. data/app/views/embeddable_content/replacements/images/_modal_content.html.slim +30 -0
  95. data/app/views/embeddable_content/replacements/images/_modal_dialog.html.slim +17 -0
  96. data/app/views/embeddable_content/replacements/images/cc.html.slim +12 -0
  97. data/app/views/embeddable_content/replacements/images/cms.html.slim +1 -0
  98. data/app/views/embeddable_content/replacements/images/editable.html.slim +1 -0
  99. data/app/views/embeddable_content/replacements/images/exported.html.slim +1 -0
  100. data/app/views/embeddable_content/replacements/images/kiddom.html.slim +12 -0
  101. data/app/views/embeddable_content/replacements/images/print.html.slim +1 -0
  102. data/app/views/embeddable_content/replacements/images/qti.html.slim +6 -0
  103. data/app/views/embeddable_content/replacements/images/schoology.html.slim +12 -0
  104. data/app/views/embeddable_content/replacements/images/web.html.slim +1 -0
  105. data/app/views/embeddable_content/replacements/presentation_tags/_default.html.slim +6 -0
  106. data/app/views/embeddable_content/replacements/presentation_tags/print.html.slim +1 -0
  107. data/app/views/embeddable_content/replacements/status/warning.html.slim +12 -0
  108. data/app/views/embeddable_content/replacements/video_links/_caption.html.slim +13 -0
  109. data/app/views/embeddable_content/replacements/video_links/_description.html.slim +12 -0
  110. data/app/views/embeddable_content/replacements/video_links/_video_embed.html.slim +13 -0
  111. data/app/views/embeddable_content/replacements/video_links/_video_player.html.slim +6 -0
  112. data/app/views/embeddable_content/replacements/video_links/_vimeo_player.html.slim +6 -0
  113. data/app/views/embeddable_content/replacements/video_links/cc.html.slim +1 -0
  114. data/app/views/embeddable_content/replacements/video_links/cms.html.slim +1 -0
  115. data/app/views/embeddable_content/replacements/video_links/editable.html.slim +1 -0
  116. data/app/views/embeddable_content/replacements/video_links/exported.html.slim +1 -0
  117. data/app/views/embeddable_content/replacements/video_links/kiddom.html.slim +1 -0
  118. data/app/views/embeddable_content/replacements/video_links/print.html.slim +1 -0
  119. data/app/views/embeddable_content/replacements/video_links/qti.html.slim +1 -0
  120. data/app/views/embeddable_content/replacements/video_links/schoology.html.slim +1 -0
  121. data/app/views/embeddable_content/replacements/video_links/web.html.slim +1 -0
  122. data/app/views/embeddable_content/replacements/widget_files/_widget_omitted.html.slim +8 -0
  123. data/app/views/embeddable_content/replacements/widget_files/_widget_script.html.slim +13 -0
  124. data/app/views/embeddable_content/replacements/widget_files/cc.html.slim +1 -0
  125. data/app/views/embeddable_content/replacements/widget_files/cms.html.slim +1 -0
  126. data/app/views/embeddable_content/replacements/widget_files/editable.html.slim +1 -0
  127. data/app/views/embeddable_content/replacements/widget_files/exported.html.slim +1 -0
  128. data/app/views/embeddable_content/replacements/widget_files/kiddom.html.slim +1 -0
  129. data/app/views/embeddable_content/replacements/widget_files/print.html.slim +1 -0
  130. data/app/views/embeddable_content/replacements/widget_files/qti.html.slim +1 -0
  131. data/app/views/embeddable_content/replacements/widget_files/schoology.html.slim +1 -0
  132. data/app/views/embeddable_content/replacements/widget_files/web.html.slim +1 -0
  133. data/bin/rails +25 -0
  134. data/config/initializers/embeddable_content.rb +3 -0
  135. data/config/routes.rb +2 -0
  136. data/embeddable_content.gemspec +48 -0
  137. data/lib/embeddable_content/engine.rb +8 -0
  138. data/lib/embeddable_content/version.rb +3 -0
  139. data/lib/embeddable_content.rb +3 -0
  140. data/lib/tasks/embeddable_content_tasks.rake +4 -0
  141. metadata +309 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d248938f6cfb46c41b491e75619538d518388329abe8970add6cb42188ee2247
4
+ data.tar.gz: 34843aabc66b6e11dcd4addb69e70c52b71bf8db70039ef111bc5f53a16bb8c5
5
+ SHA512:
6
+ metadata.gz: 3de97e6f33fad46331b1a9662db068b8ef81913675d224bf0e128b1a2ff1581414ffbbbaf07ad9c68af624c2c75e6c4a99544a6950c25e4ff602ec5c3cc90db0
7
+ data.tar.gz: 4dfcd81715bfa44e337f5ce8eb8a602f180ed3f3eb62d7569a2b236b87ea5ae030fc084c059d3cdce3f5f9310a2bab2283421d6b873459a8e6895077854d0da7
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/db/*.sqlite3-journal
6
+ spec/dummy/log/*.log
7
+ spec/dummy/tmp/
8
+ spec/dummy/.sass-cache
9
+ tmp/
10
+
11
+ Gemfile.lock
12
+
13
+ .generators
14
+ .idea/
15
+ .rakeTasks
data/.rubocop.yml ADDED
@@ -0,0 +1,62 @@
1
+ require:
2
+ - rubocop-rails
3
+
4
+ Style/Documentation:
5
+ Enabled: false
6
+ Layout/ArgumentAlignment:
7
+ Enabled: false
8
+ Layout/HashAlignment:
9
+ Enabled: false
10
+ Layout/ParameterAlignment:
11
+ Enabled: false
12
+ Layout/LeadingCommentSpace:
13
+ Enabled: false
14
+ Style/NumericLiterals:
15
+ Enabled: false
16
+ Style/FrozenStringLiteralComment:
17
+ Enabled: false
18
+ Rails/InverseOf:
19
+ Enabled: false
20
+ Metrics/MethodLength:
21
+ Exclude:
22
+ - config/routes//**/*.rb
23
+ Metrics/BlockLength:
24
+ ExcludedMethods:
25
+ [
26
+ "describe",
27
+ "described_class",
28
+ "context",
29
+ "scenario",
30
+ "feature",
31
+ "let",
32
+ "shared_examples",
33
+ "shared_examples_for",
34
+ "shared_context",
35
+ "before",
36
+ ]
37
+ Exclude:
38
+ - "*.gemspec"
39
+ - db/schema.rb
40
+ - db/migrate/*.rb
41
+ - config/initializers/**/*.rb
42
+ - config/routes.rb
43
+ - config/routes/**/*.rb
44
+ - spec/factories/*.rb
45
+ - spec/policies/**/*.rb
46
+ - spec/system/**/*.rb
47
+ Security/YAMLLoad:
48
+ Exclude:
49
+ - spec/support/shared_examples/embeddable_content.rb
50
+ AllCops:
51
+ Exclude:
52
+ - db/schema.rb
53
+ - bin/*
54
+ - Rakefile
55
+ - config/environments/production.rb
56
+ - config/initializers/backtrace_silencers.rb
57
+ - config/initializers/devise.rb
58
+ - config/initializers/simple_form.rb
59
+ - config/initializers/wrap_parameters.rb
60
+ - config/puma.rb
61
+ - db/migrate/*.rb
62
+ - db/seeds.rb
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.6
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ # Declare your gem's dependencies in embeddable_content.gemspec.
5
+ # Bundler will treat runtime dependencies like base dependencies, and
6
+ # development dependencies will be added by default to the :development group.
7
+ gemspec
8
+
9
+ # Declare any dependencies that are still in development here instead of in
10
+ # your gemspec. These might include edge Rails or gems from your path or
11
+ # Git. Remember to move these dependencies to your gemspec before releasing
12
+ # your gem to rubygems.org.
13
+
14
+ # To use a debugger
15
+ # gem 'byebug', group: [:development, :test]
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Eric Connally
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,49 @@
1
+ # EmbeddableContent
2
+
3
+ Embedder functionality has been extracted to this gem to reduce client-app dependencies.
4
+
5
+ ## Installation
6
+
7
+ For IM gems, add this to your application's Gemfile:
8
+
9
+ ``` ruby
10
+ git_source(:im) do |repo_name|
11
+ "https://github.com/illustrativemathematics/#{repo_name}.git"
12
+ end
13
+ ```
14
+
15
+ Then add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'embeddable_content', im: 'embeddable_content'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install embeddable_content
28
+
29
+ ## Usage
30
+
31
+ Ask Eric.
32
+
33
+ ## Development
34
+
35
+ N.b. (EDC): This bit was auto-generated so it's unclear how relevant it is.
36
+
37
+ After checking out the repo, run `bin/setup` to install dependencies.
38
+ Then, run `rake spec` to run the tests.
39
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`.
42
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
43
+ which will create a git tag for the version, push git commits and tags,
44
+ and push the `.gem` file to [rubygems.org](https://rubygems.org).
45
+
46
+ ## Contributing
47
+
48
+ Bug reports and pull requests are welcome on GitHub at
49
+ https://github.com/illustrativemathematics/embeddable_content.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'EmbeddableContent'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
File without changes
File without changes
@@ -0,0 +1,12 @@
1
+ document.addEventListener("DOMContentLoaded", function() {
2
+ document
3
+ .querySelectorAll('.embedded-content-desmos-file')
4
+ .forEach(loadDesmosCalculator);
5
+ });
6
+
7
+ function loadDesmosCalculator(elmt) {
8
+ var state = elmt.dataset['state'],
9
+ calculatorElmt = elmt.getElementsByClassName('desmos-calculator')[0],
10
+ calculator = Desmos.GraphingCalculator(calculatorElmt);
11
+ calculator.setState(state);
12
+ };
@@ -0,0 +1,14 @@
1
+ document.addEventListener("DOMContentLoaded", function() {
2
+ document
3
+ .querySelectorAll('.embedded-content-geogebra-file')
4
+ .forEach(loadGeogebraApplet);
5
+ });
6
+
7
+ function loadGeogebraApplet(elmt) {
8
+ var container = elmt.getElementsByClassName('ggb-applet-container')[0],
9
+ dataNode = elmt.getElementsByClassName('ggb-base-64-data')[0],
10
+ parameters = JSON.parse(dataNode.dataset['parameters']),
11
+ applet = new GGBApplet(parameters, '5.0');
12
+ applet.setHTML5Codebase('/GeoGebra/HTML5/5.0/web3d/');
13
+ applet.inject(container.id);
14
+ };
File without changes
File without changes
@@ -0,0 +1,14 @@
1
+ module Cms
2
+ module EmbeddableContentController
3
+ extend ActiveSupport::Concern
4
+ include ::EmbeddableContentController
5
+
6
+ included do
7
+ embed_content_for :show
8
+ end
9
+
10
+ def embedder_target
11
+ :cms
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,85 @@
1
+ module EmbeddableContentController
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def embed_content_for(* actions)
6
+ whitelisted_embedder_actions.replace actions
7
+ end
8
+
9
+ def do_not_embed_content_for(* actions)
10
+ blacklisted_embedder_actions.replace actions
11
+ end
12
+ end
13
+
14
+ included do
15
+ class_attribute :whitelisted_embedder_actions, default: []
16
+ class_attribute :blacklisted_embedder_actions, default: []
17
+
18
+ after_action :embed_content
19
+ end
20
+
21
+ private
22
+
23
+ def handle_unknown_format_error
24
+ embed_content
25
+ end
26
+
27
+ def embed_content
28
+ render_embedded_content if embedder_required_for_action?
29
+ end
30
+
31
+ def render_embedded_content
32
+ render_html
33
+ end
34
+
35
+ def render_html
36
+ response.body = embedded_html
37
+ end
38
+
39
+ def embedder_required_for_action?
40
+ embedder_required_by_default? || embedder_action_whitelisted?
41
+ end
42
+
43
+ def embedder_required_by_default?
44
+ !embedder_action_blacklisted? && whitelisted_embedder_actions.empty?
45
+ end
46
+
47
+ def embedder_action_whitelisted?
48
+ whitelisted_embedder_actions.map(&:to_s).include? action_name
49
+ end
50
+
51
+ def embedder_action_blacklisted?
52
+ blacklisted_embedder_actions.map(&:to_s).include? action_name
53
+ end
54
+
55
+ def embedded_html
56
+ @embedded_html ||= embedder.embed_content! raw_html
57
+ end
58
+
59
+ def raw_html
60
+ @raw_html ||= response.body.presence || render_raw_html
61
+ end
62
+
63
+ def requested_format
64
+ request.format.to_sym
65
+ end
66
+
67
+ def render_raw_html
68
+ raise 'Define this method for blank response body (e.g., docx)'
69
+ end
70
+
71
+ def embedder
72
+ @embedder ||= create_embedder
73
+ end
74
+
75
+ def create_embedder
76
+ raise_missing_target if embedder_target.blank?
77
+
78
+ EmbeddableContent::Embedder.new embedder_target
79
+ end
80
+
81
+ def raise_missing_target
82
+ raise "No embedder target defined for action '#{action_name}'" \
83
+ " and format '#{requested_format}'"
84
+ end
85
+ end
data/app/helpers/.keep ADDED
File without changes
data/app/mailers/.keep ADDED
File without changes
data/app/models/.keep ADDED
File without changes
@@ -0,0 +1,59 @@
1
+ module ProvidesEmbeddableContent
2
+ extend ActiveSupport::Concern
3
+ include ActionView::Helpers::TagHelper
4
+
5
+ class_methods do
6
+ def embeddable_model_config
7
+ @embeddable_model_config ||= EmbeddableModelConfig.for_model self
8
+ end
9
+
10
+ delegate(*EmbeddableModelConfig.attributes, to: :embeddable_model_config)
11
+ end
12
+
13
+ included do
14
+ validates :title, presence: true
15
+ delegate(*EmbeddableModelConfig.attributes, to: self)
16
+ end
17
+
18
+ def embeddable_tag_extension
19
+ try(:file).try(:filename).try(:extension) || embeddable_tag_ext
20
+ end
21
+
22
+ def embeddable_tag(opts = {})
23
+ convert_safe_buffer_to_string tag(embeddable_tag_name, embeddable_tag_attrs(opts))
24
+ end
25
+
26
+ def template_based?
27
+ defined?(super) ? super : false
28
+ end
29
+
30
+ private
31
+
32
+ def convert_safe_buffer_to_string(safe_buffer)
33
+ safe_buffer.to_str
34
+ end
35
+
36
+ def embeddable_tag_attrs(opts)
37
+ { src: "/#{model_name.route_key}/#{id}.#{embeddable_tag_extension}",
38
+ data: data_attributes(opts) }.compact
39
+ end
40
+
41
+ def data_attributes(opts)
42
+ return unless tree_based?
43
+
44
+ tree_based_data_attributes opts
45
+ end
46
+
47
+ def tree_based_data_attributes(opts)
48
+ tree_node = opts[:tree_node]
49
+ tree_node_id = tree_node&.id ||
50
+ EmbeddableContent::TREE_EMBEDDER_ID_PLACEHOLDER
51
+ tree_ref_id = tree_node&.ref_id ||
52
+ EmbeddableContent::TREE_EMBEDDER_ID_PLACEHOLDER
53
+ tree_code = Tree.where(id: tree_ref_id)&.pluck(:code)&.first
54
+ { tree_ref_id: tree_ref_id,
55
+ tree_node_id: tree_node_id,
56
+ tree_code: tree_code,
57
+ tag_title: title }.compact
58
+ end
59
+ end
@@ -0,0 +1,55 @@
1
+ class EmbeddableModelConfig < ApplicationRecord
2
+ IGNORED_ATTRIBUTES = %w[id created_at updated_at].freeze
3
+ BOOLEAN_ATTRIBUTES =
4
+ %w[tree_based?
5
+ always_display_tag_indicator?
6
+ embeddable_applet?
7
+ embeddable_image?
8
+ requires_rendering?].freeze
9
+
10
+ def self.ckeditor_config
11
+ pluck :embeddable_tag_selector, :ckeditor_allowed_content
12
+ end
13
+
14
+ def self.ckeditor_allowed_content_rules
15
+ ckeditor_config.map do |selector, content|
16
+ [selector, content]
17
+ end.to_h
18
+ end
19
+
20
+ def self.attributes
21
+ @attributes ||= (attribute_names -
22
+ IGNORED_ATTRIBUTES +
23
+ BOOLEAN_ATTRIBUTES).map(&:to_sym)
24
+ end
25
+
26
+ def self.all_embeddable_models
27
+ all.map(&:embeddable_model)
28
+ end
29
+
30
+ def self.embeddable_image_models
31
+ where(embeddable_image: true).map(&:embeddable_model)
32
+ end
33
+
34
+ def self.embeddable_applet_models
35
+ where(embeddable_applet: true).map(&:embeddable_model)
36
+ end
37
+
38
+ def self.embeddable_tree_based_models
39
+ where(tree_based: true).map(&:embeddable_model)
40
+ end
41
+
42
+ def self.for_model(embeddable_model)
43
+ find_by! embeddable_model_name: embeddable_model.model_name.name
44
+ end
45
+
46
+ def embeddable_model
47
+ embeddable_model_name.constantize
48
+ end
49
+
50
+ def styled_indicator_selector(tree_node: nil)
51
+ return embeddable_tag_name unless tree_based? && tree_node.present?
52
+
53
+ "#{embeddable_tag_name}[data-tree-ref-id=\"#{tree_node.ref_id}\"]".html_safe
54
+ end
55
+ end
@@ -0,0 +1,45 @@
1
+ class EmbedderConfig < ApplicationRecord
2
+ TARGET_CATEGORY_ENUM_CONSULT_BEFORE_CHANGING =
3
+ { cms: 0,
4
+ print: 1,
5
+ web: 2,
6
+ editable: 3,
7
+ exported: 4,
8
+ qti: 5,
9
+ cc: 6,
10
+ schoology: 7,
11
+ kiddom: 8 }.freeze
12
+ SCOPE_CATEGORY_ENUM_CONSULT_BEFORE_CHANGING =
13
+ { document: 0,
14
+ fragment: 1 }.freeze
15
+ TEX_OUTPUT_FORMAT_CONSULT_BEFORE_CHANGING =
16
+ { mathjax: 0,
17
+ svg: 1,
18
+ mml: 2,
19
+ canvas: 3,
20
+ schoology_string: 4}.freeze
21
+ OUTPUT_FORMAT_CONSULT_BEFORE_CHANGING =
22
+ { html: 0,
23
+ xml: 1 }.freeze
24
+ DEFAULT_OUTPUT_FORMAT = OUTPUT_FORMAT_CONSULT_BEFORE_CHANGING[:html]
25
+
26
+ ALL_TARGETS = TARGET_CATEGORY_ENUM_CONSULT_BEFORE_CHANGING.keys.freeze
27
+
28
+ enum target: TARGET_CATEGORY_ENUM_CONSULT_BEFORE_CHANGING
29
+ enum scope: SCOPE_CATEGORY_ENUM_CONSULT_BEFORE_CHANGING
30
+ enum tex_output_format: TEX_OUTPUT_FORMAT_CONSULT_BEFORE_CHANGING
31
+ enum output_format: OUTPUT_FORMAT_CONSULT_BEFORE_CHANGING
32
+
33
+ def self.for_target(target)
34
+ find_by target: target
35
+ end
36
+
37
+ def all_other_targets
38
+ @all_other_targets ||= ALL_TARGETS - [target.to_sym]
39
+ end
40
+
41
+ # EDC: this could be added to field on table
42
+ def aria_attrs?
43
+ !qti?
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ class Embedding < ApplicationRecord
2
+ INDIFFERENT_RUN_ORDER = 0
3
+ MATH_TYPESETTING_RUN_ORDER = 1000
4
+ DEFAULT_RUN_ORDER = INDIFFERENT_RUN_ORDER
5
+
6
+ RUN_ORDER_ENUM_CONSULT_BEFORE_CHANGING = {
7
+ indifferent: INDIFFERENT_RUN_ORDER,
8
+ math_typesetting: MATH_TYPESETTING_RUN_ORDER
9
+ }.freeze
10
+
11
+ enum run_order: RUN_ORDER_ENUM_CONSULT_BEFORE_CHANGING
12
+
13
+ def self.in_run_order
14
+ order :run_order
15
+ end
16
+
17
+ def doc_processor_for(embedder)
18
+ "EmbeddableContent::#{processor_module}::DocProcessor"
19
+ .constantize.new embedder
20
+ end
21
+
22
+ def process_target?(target)
23
+ processor_targets.include? target.to_s
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module EmbeddableContent
2
+ module DesmosFiles
3
+ class DocProcessor < EmbeddableContent::DocProcessor; end
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module EmbeddableContent
2
+ module DesmosFiles
3
+ class NodeProcessor < EmbeddableContent::RecordNodeProcessor
4
+ include TemplateBased
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,63 @@
1
+ module EmbeddableContent
2
+ class DocProcessor < EmbedderBase
3
+ PROCESS_NODES_BY_DEFAULT = true
4
+
5
+ attr_reader :embedder
6
+
7
+ delegate :document, :html, :rebuild_document, to: :embedder
8
+ delegate :selector, :process_target?, to: :embedding
9
+
10
+ def initialize(embedder)
11
+ @embedder = embedder
12
+ super embedder.config
13
+ end
14
+
15
+ def process!
16
+ return unless process_target?(target)
17
+
18
+ pre_process
19
+ process_matching_nodes if process_nodes?
20
+ post_process
21
+ refresh_html
22
+ end
23
+
24
+ def embedding
25
+ @embedding ||= Embedding.find_by processor_module: embedding_module
26
+ end
27
+
28
+ private
29
+
30
+ def refresh_html
31
+ html.replace document.to_s
32
+ end
33
+
34
+ def pre_process; end
35
+
36
+ def process_matching_nodes
37
+ matching_nodes.each.with_index(1) { |node, idx| process_node(node, idx) }
38
+ end
39
+
40
+ def post_process; end
41
+
42
+ def process_nodes?
43
+ PROCESS_NODES_BY_DEFAULT
44
+ end
45
+
46
+ def process_node(node, node_index)
47
+ node_processor_factory.new(self, node, node_index).process!
48
+ end
49
+
50
+ def node_selector
51
+ @node_selector ||= embedding_module.underscore.dasherize.singularize
52
+ end
53
+
54
+ def matching_nodes
55
+ @matching_nodes ||= document.css node_selector
56
+ end
57
+
58
+ def node_processor_factory
59
+ @node_processor_factory ||=
60
+ "#{module_name}::NodeProcessor".constantize
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,50 @@
1
+ module EmbeddableContent
2
+ class EmbeddedTagInfo
3
+ attr_reader :record, :embedded_model, :attr, :dom_node
4
+
5
+ def initialize(record, embedded_model, attr, dom_node)
6
+ @record = record
7
+ @embedded_model = embedded_model
8
+ @attr = attr
9
+ @dom_node = dom_node
10
+ end
11
+
12
+ def available?
13
+ match.present?
14
+ end
15
+
16
+ def embedded_record_id
17
+ match.try :first
18
+ end
19
+
20
+ def embedded_record_ext
21
+ match.try :last
22
+ end
23
+
24
+ def embedded_record
25
+ @embedded_record ||= embedded_model.find embedded_record_id
26
+ end
27
+
28
+ private
29
+
30
+ def src
31
+ @src ||= dom_node.attributes['src'].to_html
32
+ end
33
+
34
+ def embed_src_path
35
+ embedded_model.model_name.route_key
36
+ end
37
+
38
+ def match
39
+ @match ||= src.match(%r{\/#{embed_src_path}\/(\d+)\.(\w+)}).try :captures
40
+ end
41
+
42
+ def document
43
+ @document ||= Nokogiri::HTML.fragment searchable_text
44
+ end
45
+
46
+ def searchable_text
47
+ record[attr].is_a?(Array) ? record[attr].join(' ') : record[attr]
48
+ end
49
+ end
50
+ end