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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +62 -0
- data/.ruby-version +1 -0
- data/Gemfile +15 -0
- data/MIT-LICENSE +20 -0
- data/README.md +49 -0
- data/Rakefile +22 -0
- data/app/assets/config/embeddable_content_manifest.js +0 -0
- data/app/assets/images/embeddable_content/.keep +0 -0
- data/app/assets/javascripts/desmos/support.js +12 -0
- data/app/assets/javascripts/geogebra/support.js +14 -0
- data/app/assets/stylesheets/embeddable_content/.keep +0 -0
- data/app/controllers/.keep +0 -0
- data/app/controllers/concerns/cms/embeddable_content_controller.rb +14 -0
- data/app/controllers/concerns/embeddable_content_controller.rb +85 -0
- data/app/helpers/.keep +0 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/models/concerns/provides_embeddable_content.rb +59 -0
- data/app/models/embeddable_model_config.rb +55 -0
- data/app/models/embedder_config.rb +45 -0
- data/app/models/embedding.rb +25 -0
- data/app/services/embeddable_content/desmos_files/doc_processor.rb +5 -0
- data/app/services/embeddable_content/desmos_files/node_processor.rb +7 -0
- data/app/services/embeddable_content/doc_processor.rb +63 -0
- data/app/services/embeddable_content/embedded_tag_info.rb +50 -0
- data/app/services/embeddable_content/embedded_tags.rb +30 -0
- data/app/services/embeddable_content/embedder.rb +89 -0
- data/app/services/embeddable_content/embedder_base.rb +68 -0
- data/app/services/embeddable_content/fragment_embedder.rb +30 -0
- data/app/services/embeddable_content/geogebra_files/doc_processor.rb +5 -0
- data/app/services/embeddable_content/geogebra_files/node_processor.rb +11 -0
- data/app/services/embeddable_content/html_tags/doc_processor.rb +11 -0
- data/app/services/embeddable_content/html_tags/node_processor.rb +26 -0
- data/app/services/embeddable_content/images/attributions_processor.rb +60 -0
- data/app/services/embeddable_content/images/doc_processor.rb +54 -0
- data/app/services/embeddable_content/images/image_downloader.rb +60 -0
- data/app/services/embeddable_content/images/img_tag_attributes.rb +125 -0
- data/app/services/embeddable_content/images/modal_dialog.rb +74 -0
- data/app/services/embeddable_content/images/node_processor.rb +91 -0
- data/app/services/embeddable_content/images/shared.rb +11 -0
- data/app/services/embeddable_content/node_processor.rb +75 -0
- data/app/services/embeddable_content/presentation_tags/doc_processor.rb +5 -0
- data/app/services/embeddable_content/presentation_tags/node_processor.rb +35 -0
- data/app/services/embeddable_content/record_node_processor.rb +90 -0
- data/app/services/embeddable_content/replacement_template_manager.rb +21 -0
- data/app/services/embeddable_content/sad_embedded_tags.rb +29 -0
- data/app/services/embeddable_content/scrubber.rb +32 -0
- data/app/services/embeddable_content/template_based.rb +19 -0
- data/app/services/embeddable_content/template_manager.rb +100 -0
- data/app/services/embeddable_content/tex/base_renderer.rb +33 -0
- data/app/services/embeddable_content/tex/canvas_renderer.rb +15 -0
- data/app/services/embeddable_content/tex/doc_processor.rb +55 -0
- data/app/services/embeddable_content/tex/mathjax_renderer.rb +11 -0
- data/app/services/embeddable_content/tex/mml_renderer.rb +11 -0
- data/app/services/embeddable_content/tex/schoology_string_renderer.rb +15 -0
- data/app/services/embeddable_content/tex/svg_renderer.rb +11 -0
- data/app/services/embeddable_content/token_replacement_map.rb +32 -0
- data/app/services/embeddable_content/tree_based_node_processor.rb +23 -0
- data/app/services/embeddable_content/video_links/doc_processor.rb +5 -0
- data/app/services/embeddable_content/video_links/node_processor.rb +46 -0
- data/app/services/embeddable_content/video_links/vimeo_player_settings.rb +19 -0
- data/app/services/embeddable_content/visual_element_node_processor.rb +13 -0
- data/app/services/embeddable_content/widget_files/doc_processor.rb +5 -0
- data/app/services/embeddable_content/widget_files/node_processor.rb +7 -0
- data/app/views/.keep +0 -0
- data/app/views/embeddable_content/replacements/desmos_files/_applet.html.slim +8 -0
- data/app/views/embeddable_content/replacements/desmos_files/_description.html.slim +6 -0
- data/app/views/embeddable_content/replacements/desmos_files/cc.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/cms.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/editable.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/exported.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/kiddom.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/qti.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/schoology.html.slim +1 -0
- data/app/views/embeddable_content/replacements/desmos_files/web.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/_applet.html.slim +11 -0
- data/app/views/embeddable_content/replacements/geogebra_files/_description.html.slim +9 -0
- data/app/views/embeddable_content/replacements/geogebra_files/cc.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/cms.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/editable.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/exported.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/kiddom.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/qti.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/schoology.html.slim +1 -0
- data/app/views/embeddable_content/replacements/geogebra_files/web.html.slim +1 -0
- data/app/views/embeddable_content/replacements/html_tags/editable.html.slim +16 -0
- data/app/views/embeddable_content/replacements/images/_button_close.html.slim +9 -0
- data/app/views/embeddable_content/replacements/images/_button_open.html.slim +9 -0
- data/app/views/embeddable_content/replacements/images/_image_embed.html.slim +14 -0
- data/app/views/embeddable_content/replacements/images/_modal_content.html.slim +30 -0
- data/app/views/embeddable_content/replacements/images/_modal_dialog.html.slim +17 -0
- data/app/views/embeddable_content/replacements/images/cc.html.slim +12 -0
- data/app/views/embeddable_content/replacements/images/cms.html.slim +1 -0
- data/app/views/embeddable_content/replacements/images/editable.html.slim +1 -0
- data/app/views/embeddable_content/replacements/images/exported.html.slim +1 -0
- data/app/views/embeddable_content/replacements/images/kiddom.html.slim +12 -0
- data/app/views/embeddable_content/replacements/images/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/images/qti.html.slim +6 -0
- data/app/views/embeddable_content/replacements/images/schoology.html.slim +12 -0
- data/app/views/embeddable_content/replacements/images/web.html.slim +1 -0
- data/app/views/embeddable_content/replacements/presentation_tags/_default.html.slim +6 -0
- data/app/views/embeddable_content/replacements/presentation_tags/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/status/warning.html.slim +12 -0
- data/app/views/embeddable_content/replacements/video_links/_caption.html.slim +13 -0
- data/app/views/embeddable_content/replacements/video_links/_description.html.slim +12 -0
- data/app/views/embeddable_content/replacements/video_links/_video_embed.html.slim +13 -0
- data/app/views/embeddable_content/replacements/video_links/_video_player.html.slim +6 -0
- data/app/views/embeddable_content/replacements/video_links/_vimeo_player.html.slim +6 -0
- data/app/views/embeddable_content/replacements/video_links/cc.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/cms.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/editable.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/exported.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/kiddom.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/qti.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/schoology.html.slim +1 -0
- data/app/views/embeddable_content/replacements/video_links/web.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/_widget_omitted.html.slim +8 -0
- data/app/views/embeddable_content/replacements/widget_files/_widget_script.html.slim +13 -0
- data/app/views/embeddable_content/replacements/widget_files/cc.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/cms.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/editable.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/exported.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/kiddom.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/print.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/qti.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/schoology.html.slim +1 -0
- data/app/views/embeddable_content/replacements/widget_files/web.html.slim +1 -0
- data/bin/rails +25 -0
- data/config/initializers/embeddable_content.rb +3 -0
- data/config/routes.rb +2 -0
- data/embeddable_content.gemspec +48 -0
- data/lib/embeddable_content/engine.rb +8 -0
- data/lib/embeddable_content/version.rb +3 -0
- data/lib/embeddable_content.rb +3 -0
- data/lib/tasks/embeddable_content_tasks.rake +4 -0
- metadata +309 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
module Images
|
|
3
|
+
class NodeProcessor < EmbeddableContent::VisualElementNodeProcessor
|
|
4
|
+
delegate :target, :image_catalog, to: :embedder
|
|
5
|
+
delegate :attribution, :long_description, :label, :alt_text,
|
|
6
|
+
to: :record
|
|
7
|
+
|
|
8
|
+
def modal_dialog
|
|
9
|
+
@modal_dialog = ModalDialog.new self
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def img_tag_attrs
|
|
13
|
+
@img_tag_attrs ||= ImgTagAttributes.new(self).to_h
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
TARGETS_THAT_DISPLAY_A_MODAL_DIALOG = %i[web].freeze
|
|
17
|
+
def display_modal_dialog?
|
|
18
|
+
TARGETS_THAT_DISPLAY_A_MODAL_DIALOG.include? target.to_sym
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
TARGETS_THAT_USE_DIV_TAGS = %i[editable].freeze
|
|
22
|
+
TARGETS_THAT_USE_FIGURE_TAGS = %i[cms print web exported qti cc schoology]
|
|
23
|
+
.freeze
|
|
24
|
+
def figure_tag
|
|
25
|
+
case target
|
|
26
|
+
when *TARGETS_THAT_USE_DIV_TAGS then :div
|
|
27
|
+
when *TARGETS_THAT_USE_FIGURE_TAGS then :figure
|
|
28
|
+
else raise "Undefined tag for target: #{target}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def node_can_be_removed?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def node_selector_class
|
|
37
|
+
[super, 'embedded-content-image'].join ' '
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def catalog_image
|
|
43
|
+
image_catalog << record
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def replace_node
|
|
47
|
+
record.render_svg if svg_should_be_rendered?
|
|
48
|
+
catalog_image if image_should_be_catalogued?
|
|
49
|
+
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def svg_should_be_rendered?
|
|
54
|
+
config.render_images? &&
|
|
55
|
+
record_model.requires_rendering? &&
|
|
56
|
+
attachment_status_matters? &&
|
|
57
|
+
attachment_unavailable?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def attachment_unavailable?
|
|
61
|
+
!attached_file.attached? ||
|
|
62
|
+
!attachment_url_response_status_ok?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def attachment_url_response_status_ok?
|
|
66
|
+
attachment_url_response.instance_of? Net::HTTPOK
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def attachment_url_response
|
|
70
|
+
@attachment_url_response ||= Net::HTTP.get_response s3_ttl_service_uri
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def s3_ttl_service_uri
|
|
74
|
+
@s3_ttl_service_uri ||= URI.parse s3_ttl_service_url
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def attachment_status_matters?
|
|
78
|
+
Rails.env.production? &&
|
|
79
|
+
ENV['VERIFY_ATTACHMENT_STATUS'].eql?('true')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def image_should_be_catalogued?
|
|
83
|
+
record.present? && attribution.present?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def route_keys
|
|
87
|
+
%i[tikz_files image_files]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class NodeProcessor < EmbedderBase
|
|
3
|
+
NODE_CAN_BE_REMOVED_BY_DEFAULT = true
|
|
4
|
+
SELECTOR_CLASS_BLANK_BY_DEFAULT = nil
|
|
5
|
+
RECORD_BLANK_BY_DEFAULT = nil
|
|
6
|
+
ALL_TARGETS_PROCESSED_BY_DEFAULT = EmbedderConfig::ALL_TARGETS
|
|
7
|
+
DEFAULT_TEMPLATE_MANAGER_CLASS = TemplateManager
|
|
8
|
+
ADDED_CLASSES_BLANK_BY_DEFAULT = [].freeze
|
|
9
|
+
|
|
10
|
+
attr_reader :node, :node_index, :doc_processor, :error
|
|
11
|
+
|
|
12
|
+
delegate :embedder, to: :doc_processor
|
|
13
|
+
delegate :warning_node, to: :template_manager
|
|
14
|
+
|
|
15
|
+
def initialize(doc_processor, node, node_index)
|
|
16
|
+
@doc_processor = doc_processor
|
|
17
|
+
@node = node
|
|
18
|
+
@node_index = node_index
|
|
19
|
+
super embedder.config, embedder.options
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def process!
|
|
23
|
+
process_node || remove_node
|
|
24
|
+
rescue StandardError => e
|
|
25
|
+
@error = e
|
|
26
|
+
node.replace warning_node
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def node_selector_class
|
|
30
|
+
SELECTOR_CLASS_BLANK_BY_DEFAULT
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def node_added_classes
|
|
34
|
+
ADDED_CLASSES_BLANK_BY_DEFAULT
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def record
|
|
38
|
+
RECORD_BLANK_BY_DEFAULT
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def process_node
|
|
44
|
+
replace_node if node_should_be_replaced?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def node_should_be_replaced?
|
|
48
|
+
targets_that_require_processing.include? target
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def targets_that_require_processing
|
|
52
|
+
ALL_TARGETS_PROCESSED_BY_DEFAULT
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def replace_node
|
|
56
|
+
raise 'implement in a subclass'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def remove_node
|
|
60
|
+
node.remove if node_can_be_removed?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def node_can_be_removed?
|
|
64
|
+
NODE_CAN_BE_REMOVED_BY_DEFAULT
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def template_manager
|
|
68
|
+
@template_manager ||= template_manager_class.new self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def template_manager_class
|
|
72
|
+
DEFAULT_TEMPLATE_MANAGER_CLASS
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
module PresentationTags
|
|
3
|
+
class NodeProcessor < EmbeddableContent::TreeBasedNodeProcessor
|
|
4
|
+
include TemplateBased
|
|
5
|
+
|
|
6
|
+
alias presentation_tag record
|
|
7
|
+
|
|
8
|
+
def node_added_classes
|
|
9
|
+
['presentation-tag-classes-added',
|
|
10
|
+
presentation_tag.added_class].join ' '
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
delegate :template_based?, to: :presentation_tag
|
|
16
|
+
|
|
17
|
+
def replace_node
|
|
18
|
+
template_based? ? super : modify_parent
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def modify_parent
|
|
22
|
+
parent_node.add_class node_added_classes
|
|
23
|
+
remove_node
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parent_node
|
|
27
|
+
@parent_node ||= node.parent
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def targets_that_require_processing
|
|
31
|
+
%i[print]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class RecordNodeProcessor < NodeProcessor
|
|
3
|
+
delegate :title, to: :record
|
|
4
|
+
|
|
5
|
+
def record_id
|
|
6
|
+
@record_id ||= tag_match_data[:id] if tag_references_record?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def record_model
|
|
10
|
+
@record_model ||= tag_match_data[:model].classify.constantize if
|
|
11
|
+
tag_references_record?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def record_css_id_for(type)
|
|
15
|
+
"#{type}-#{record_model}-#{record_id}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def record
|
|
19
|
+
@record ||= target_scope.find record_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def s3_url(with_extension: false)
|
|
23
|
+
with_extension ? s3_url_with_extension : bare_s3_url
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cms_url
|
|
27
|
+
src_url
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def s3_ttl_service_url
|
|
31
|
+
if Rails.env.test?
|
|
32
|
+
Pathname
|
|
33
|
+
.new(ActiveStorage::Blob.service.send(:path_for, blob.key))
|
|
34
|
+
.relative_path_from Rails.root
|
|
35
|
+
else
|
|
36
|
+
blob.service_url(content_type: content_type)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def attached_file
|
|
41
|
+
record.file
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def node_selector_class
|
|
45
|
+
"embedded-content-#{record_model.model_name.param_key.dasherize}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
delegate :s3_bucket, to: :embedder
|
|
51
|
+
delegate :blob, to: :attached_file
|
|
52
|
+
delegate :content_type, to: :blob
|
|
53
|
+
|
|
54
|
+
def bare_s3_url
|
|
55
|
+
"https://s3.amazonaws.com/#{s3_bucket}/#{blob_key}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def s3_url_with_extension
|
|
59
|
+
"#{bare_s3_url}.#{blob.filename.extension}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def blob_key
|
|
63
|
+
blob.key
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def src_url
|
|
67
|
+
@src_url ||= node.attr 'src'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def tag_match_data
|
|
71
|
+
@tag_match_data ||= regex_src_url.match src_url
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def regex_src_url
|
|
75
|
+
%r{\/(?<model>#{route_keys.join('|')})\/(?<id>\d+)\.(?<ext>\w+)}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def target_scope
|
|
79
|
+
record_model
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def tag_references_record?
|
|
83
|
+
tag_match_data.present?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def node_should_be_replaced?
|
|
87
|
+
super && tag_match_data.present?
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class ReplacementTemplateManager < TemplateManager
|
|
3
|
+
def replacement_node
|
|
4
|
+
render_target || warning_node
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def node_templates_subdir
|
|
10
|
+
@node_templates_subdir ||= node_type.underscore
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def node_templates_path
|
|
14
|
+
@node_templates_path ||= templates_dir.join node_templates_subdir
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def target_path
|
|
18
|
+
@target_path ||= node_templates_path.join target.to_s
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class SadEmbeddedTags
|
|
3
|
+
attr_accessor :ed_node, :sad_related_records, :embedded_models
|
|
4
|
+
|
|
5
|
+
def initialize(ed_node, embedded_models)
|
|
6
|
+
@ed_node = ed_node
|
|
7
|
+
@sad_related_records = SadRelatedRecords.new ed_node
|
|
8
|
+
@embedded_models = embedded_models
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def each
|
|
12
|
+
@ed_node.tags.each do |tag|
|
|
13
|
+
tag.html_attrs.each do |attr|
|
|
14
|
+
EmbeddedTags.new(tag, attr, embedded_models).each do |info|
|
|
15
|
+
yield nil, nil, info
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
sad_related_records.each do |node, node_address, related_record|
|
|
21
|
+
related_record.html_attrs.each do |attr|
|
|
22
|
+
EmbeddedTags.new(related_record, attr, embedded_models).each do |info|
|
|
23
|
+
yield node, node_address, info
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class Scrubber < EmbedderBase
|
|
3
|
+
def scrub(document)
|
|
4
|
+
document.search(scrubbed_nodes_selector).remove
|
|
5
|
+
document
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def scrubbed_nodes_selector
|
|
11
|
+
all_selectors.join ','
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def all_selectors
|
|
15
|
+
selectors_for_other_targets <<
|
|
16
|
+
'.removed-for-all-embedder-targets' <<
|
|
17
|
+
selector_for_current_target
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def selector_for_current_target
|
|
21
|
+
".removed-for-#{target}-embedder-target"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def selectors_for_other_targets
|
|
25
|
+
all_other_targets.map { |tgt| selector_for_other_target tgt }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def selector_for_other_target(tgt)
|
|
29
|
+
".removed-for-all-but-#{tgt}-embedder-target"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
module TemplateBased
|
|
3
|
+
delegate :replacement_node, to: :template_manager
|
|
4
|
+
|
|
5
|
+
def node_type
|
|
6
|
+
@node_type ||= embedding_module.underscore
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def replace_node
|
|
12
|
+
node.replace replacement_node
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def template_manager_class
|
|
16
|
+
ReplacementTemplateManager
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
class TemplateManager < EmbedderBase
|
|
3
|
+
DEFAULT_NUM_BACKTRACE_LINES = 10
|
|
4
|
+
NUM_BACKTRACE_LINES =
|
|
5
|
+
ENV.fetch('NUM_BACKTRACE_LINES', DEFAULT_NUM_BACKTRACE_LINES).try :to_i
|
|
6
|
+
|
|
7
|
+
attr_reader :node_processor
|
|
8
|
+
|
|
9
|
+
delegate :record, :node, :node_type, :error, :node_selector_class,
|
|
10
|
+
:node_added_classes, :node_index,
|
|
11
|
+
to: :node_processor
|
|
12
|
+
|
|
13
|
+
def initialize(node_processor)
|
|
14
|
+
@node_processor = node_processor
|
|
15
|
+
super node_processor.config, node_processor.options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def warning_node
|
|
19
|
+
render_path warning_node_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def selected_backtrace_lines
|
|
23
|
+
return if error.nil?
|
|
24
|
+
|
|
25
|
+
error.backtrace.first(NUM_BACKTRACE_LINES).join "\n"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def node_attrs
|
|
29
|
+
@node_attrs ||= { class: node_classes,
|
|
30
|
+
data: node_data }.compact
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def target_attrs
|
|
34
|
+
@target_attrs ||= { id: node_id }.compact
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def node_id
|
|
38
|
+
return if record.nil?
|
|
39
|
+
|
|
40
|
+
"#{record_model}-#{record.id}-#{node_index}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def node_data
|
|
46
|
+
@node_data ||= { 'embedder-target': target }.merge record_node_data
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def record_node_data
|
|
50
|
+
return {} if record.nil?
|
|
51
|
+
|
|
52
|
+
{ 'record-model': record_model,
|
|
53
|
+
'record-id': record.id }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def record_model
|
|
57
|
+
return if record.nil?
|
|
58
|
+
|
|
59
|
+
@record_model ||= record.model_name.name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def node_classes
|
|
63
|
+
['embedded-content',
|
|
64
|
+
node_selector_class,
|
|
65
|
+
node_added_classes].flatten.compact
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def render_target
|
|
69
|
+
I18n.with_locale(locale) { render_path target_path }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def render_path(path)
|
|
73
|
+
ApplicationController.render rendering_options_for path
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def rendering_options_for(path)
|
|
77
|
+
{ assigns: assigns, template: path, layout: false }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def assigns
|
|
81
|
+
{ template_manager: self }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def warning_node_path
|
|
85
|
+
@warning_node_path ||= status_template_path 'warning'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def status_template_path(status)
|
|
89
|
+
status_dir.join status
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def status_dir
|
|
93
|
+
@status_dir ||= templates_dir.join 'status'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def templates_dir
|
|
97
|
+
@templates_dir ||= Pathname.new('embeddable_content').join 'replacements'
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
|
|
3
|
+
module EmbeddableContent
|
|
4
|
+
module Tex
|
|
5
|
+
class BaseRenderer
|
|
6
|
+
RENDER_TEX_JS_PATH = Pathname.new('lib').join 'tasks/render_tex.js'
|
|
7
|
+
|
|
8
|
+
attr_reader :html
|
|
9
|
+
|
|
10
|
+
def initialize(html)
|
|
11
|
+
@html = html
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
html.replace render_format(target_format) if target_format.present?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def render_format(format)
|
|
21
|
+
output, status = Open3.capture2(render_tex(format), stdin_data: html)
|
|
22
|
+
return output if status.success?
|
|
23
|
+
|
|
24
|
+
Rails.logger.warn "Error calling #{render_tex(format)}: #{status}"
|
|
25
|
+
html
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def render_tex(format)
|
|
29
|
+
[RENDER_TEX_JS_PATH, '--output', format].join(' ')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module EmbeddableContent
|
|
2
|
+
module Tex
|
|
3
|
+
class DocProcessor < EmbeddableContent::DocProcessor
|
|
4
|
+
REPAIRED_MATH_CSS_CLASS = 'math-repaired'.freeze
|
|
5
|
+
REPAIRED_MATH_CSS_SELECTOR = ".#{REPAIRED_MATH_CSS_CLASS}".freeze
|
|
6
|
+
|
|
7
|
+
delegate :remove_repaired_math_spans?, to: :embedder
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def process_nodes?
|
|
12
|
+
remove_repaired_math_spans?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def process_node(node, _node_index)
|
|
16
|
+
remove_repaired_math_span node
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def remove_repaired_math_span(node)
|
|
20
|
+
node.replace node.content
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def post_process
|
|
24
|
+
refresh_html
|
|
25
|
+
render_tex
|
|
26
|
+
fix_mml_fragments if fix_mml_fragments?
|
|
27
|
+
rebuild_document
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def node_selector
|
|
31
|
+
REPAIRED_MATH_CSS_SELECTOR
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def repaired_math_nodes
|
|
35
|
+
@repaired_math_nodes ||= document.css(REPAIRED_MATH_CSS_SELECTOR)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def render_tex
|
|
39
|
+
tex_renderer.new(html).render
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def fix_mml_fragments?
|
|
43
|
+
embedder.fragment? && embedder.xml?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def fix_mml_fragments
|
|
47
|
+
html.replace Nokogiri::HTML(html).at('body').children.to_xml
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def tex_renderer
|
|
51
|
+
"#{module_name}::#{tex_output_format.classify}Renderer".constantize
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
|
|
3
|
+
module EmbeddableContent
|
|
4
|
+
module Tex
|
|
5
|
+
class SchoologyStringRenderer < BaseRenderer
|
|
6
|
+
def target_format
|
|
7
|
+
:schoology_string
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def render_format(_format)
|
|
11
|
+
Mathjax::SchoologyStringRenderer.new(html).render
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|