embeddable_content 0.3.2 → 0.4.0.beta7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +2 -1
- data/app/assets/javascripts/geogebra/support.js +1 -0
- data/app/services/embeddable_content/doc_processor.rb +10 -3
- data/app/services/embeddable_content/embedder.rb +1 -1
- data/app/services/embeddable_content/has_moveable_nodes.rb +69 -0
- data/app/services/embeddable_content/images/doc_processor.rb +6 -28
- data/app/services/embeddable_content/presentation_tags/node_processor.rb +29 -1
- data/app/services/embeddable_content/tex/base_renderer.rb +31 -89
- data/app/services/embeddable_content/tex/canvas_renderer.rb +36 -4
- data/app/services/embeddable_content/tex/doc_processor.rb +11 -34
- data/app/services/embeddable_content/tex/mathjax_renderer.rb +8 -2
- data/app/services/embeddable_content/tex/mml_renderer.rb +17 -4
- data/app/services/embeddable_content/tex/svg_renderer.rb +12 -4
- data/app/services/embeddable_content/tex/uri_encode_component.rb +175 -0
- data/app/services/embeddable_content/video_links/doc_processor.rb +13 -1
- data/app/views/embeddable_content/replacements/images/_modal_content.html.slim +2 -2
- data/app/views/embeddable_content/replacements/video_links/_video_embed.html.slim +1 -1
- data/lib/embeddable_content/version.rb +1 -1
- metadata +9 -9
- data/app/services/embeddable_content/tex/schoology_string_renderer.rb +0 -15
- data/app/services/mathjax/api/client.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f519e66cbe92ede8252b5e6c02c619c7f7db67ca24d989c5f3aac51a863ea7d3
|
|
4
|
+
data.tar.gz: de2e69dd5b55b60946677e5ac5f0615926f90da9ef1f675f11e88ea52c90155d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 992589b5decacdf64748ca60472ff1037199c61742457de76816c1888301df318f01e03fe2d43fb067b5d893f5c83125d4ca1a4160062e5abe4a442ed6c607e7
|
|
7
|
+
data.tar.gz: a5c40a06797b30da08365563ba43ce7ef98058954290cd8b843f3571f3c01542e379125bf38666742c9a66c59c1ffd3d3895ba1cf62b49a97375ec2dec7a4ba1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -70,5 +70,6 @@ $ gem push embeddable_content-0.2.0.gem
|
|
|
70
70
|
|
|
71
71
|
| Version | Changes |
|
|
72
72
|
| --- | --- |
|
|
73
|
+
| 0.4.0 | Adapt gem to make full use of TexExpression model.
|
|
73
74
|
| 0.3.1 | Meaningless change as I (EDC) experiment with gem host. |
|
|
74
|
-
| 0.2.0 | NIMAS export now using embedder for TeX. However, the embedder is not yet using the full TexExprssions
|
|
75
|
+
| 0.2.0 | NIMAS export now using embedder for TeX. However, the embedder is not yet using the full TexExprssions model. |
|
|
@@ -9,5 +9,6 @@ function loadGeogebraApplet(elmt) {
|
|
|
9
9
|
dataNode = elmt.getElementsByClassName('ggb-base-64-data')[0],
|
|
10
10
|
parameters = JSON.parse(dataNode.dataset['parameters']),
|
|
11
11
|
applet = new GGBApplet(parameters, '5.0');
|
|
12
|
+
applet.setHTML5Codebase('/GeoGebra/HTML5/5.0/web3d/');
|
|
12
13
|
applet.inject(container.id);
|
|
13
14
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module EmbeddableContent
|
|
2
2
|
class DocProcessor < EmbedderBase
|
|
3
|
-
|
|
3
|
+
include HasMoveableNodes
|
|
4
4
|
|
|
5
|
+
PROCESS_NODES_BY_DEFAULT = true
|
|
5
6
|
attr_reader :embedder
|
|
6
7
|
|
|
7
8
|
delegate :document, :html, :rebuild_document, to: :embedder
|
|
@@ -28,10 +29,16 @@ module EmbeddableContent
|
|
|
28
29
|
private
|
|
29
30
|
|
|
30
31
|
def refresh_html
|
|
31
|
-
html.replace document.
|
|
32
|
+
html.replace document.to_html
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def pre_process
|
|
35
|
+
def pre_process
|
|
36
|
+
update_moveable_nodes if update_moveable_nodes?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def update_moveable_nodes?
|
|
40
|
+
false
|
|
41
|
+
end
|
|
35
42
|
|
|
36
43
|
def process_matching_nodes
|
|
37
44
|
matching_nodes.each.with_index(1) { |node, idx| process_node(node, idx) }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EmbeddableContent
|
|
4
|
+
module HasMoveableNodes
|
|
5
|
+
CSS_CLASS_MOVEABLE_NODE_RELOCATED = 'node-relocated-by-embedder'
|
|
6
|
+
CSS_CLASS_MOVEABLE_NODES_RELOCATED = 'nodes-relocated-by-embedder'
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def update_moveable_nodes?
|
|
11
|
+
false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def update_moveable_nodes
|
|
15
|
+
moveable_nodes.each { |node| update_moveable_node node }
|
|
16
|
+
remove_affected_empty_nodes
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def remove_affected_empty_nodes
|
|
20
|
+
relocated_moveable_nodes.each { |node| node.remove if node.content.blank? }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def update_moveable_node(moveable_node)
|
|
24
|
+
moveable_node.parent.tap do |parent_node|
|
|
25
|
+
moveable_node.add_class CSS_CLASS_MOVEABLE_NODE_RELOCATED
|
|
26
|
+
parent_node.add_class CSS_CLASS_MOVEABLE_NODES_RELOCATED
|
|
27
|
+
relocate_moveable_node moveable_node
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def relocate_moveable_node(_moveable_node)
|
|
32
|
+
raise 'define this method in including class'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def place_moveable_node_before_parent(moveable_node)
|
|
36
|
+
moveable_node.parent.tap do |parent_node|
|
|
37
|
+
parent_node.add_previous_sibling moveable_node
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def place_moveable_node_after_parent(moveable_node)
|
|
42
|
+
moveable_node.parent.tap do |parent_node|
|
|
43
|
+
parent_node.add_next_sibling moveable_node
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def moveable_nodes
|
|
48
|
+
@moveable_nodes ||= document.css moveable_node_selector
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def relocated_moveable_nodes
|
|
52
|
+
@relocated_moveable_nodes ||= document.css(relocated_moveable_node_selector)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def relocated_moveable_node_selector
|
|
56
|
+
@relocated_moveable_node_selector ||=
|
|
57
|
+
"#{parent_node_selector}.#{CSS_CLASS_MOVEABLE_NODES_RELOCATED}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
DEFAULT_PARENT_NODE_SELECTOR = 'p'
|
|
61
|
+
def parent_node_selector
|
|
62
|
+
DEFAULT_PARENT_NODE_SELECTOR
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def moveable_node_selector
|
|
66
|
+
@moveable_node_selector ||= "#{parent_node_selector} > #{node_selector}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -5,12 +5,14 @@ module EmbeddableContent
|
|
|
5
5
|
class DocProcessor < EmbeddableContent::DocProcessor
|
|
6
6
|
delegate :image_catalog, to: :embedder
|
|
7
7
|
|
|
8
|
-
CLASS_IMG_TAG_RELOCATED = 'img-tag-relocated-by-embedder'
|
|
9
|
-
|
|
10
8
|
private
|
|
11
9
|
|
|
12
|
-
def
|
|
13
|
-
|
|
10
|
+
def update_moveable_nodes?
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def relocate_moveable_node(moveable_node)
|
|
15
|
+
place_moveable_node_before_parent moveable_node
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def post_process
|
|
@@ -25,30 +27,6 @@ module EmbeddableContent
|
|
|
25
27
|
def node_selector
|
|
26
28
|
'img'
|
|
27
29
|
end
|
|
28
|
-
|
|
29
|
-
def move_img_tags_out_from_p_tags
|
|
30
|
-
img_tags_inside_p_tags.each do |img_tag|
|
|
31
|
-
move_img_tag_out_from_p_tag img_tag
|
|
32
|
-
end
|
|
33
|
-
remove_affected_empty_p_tags
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def remove_affected_empty_p_tags
|
|
37
|
-
document.css("p.#{CLASS_IMG_TAG_RELOCATED}").each do |p_tag|
|
|
38
|
-
remove_if_empty p_tag
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def move_img_tag_out_from_p_tag(img_tag)
|
|
43
|
-
img_tag.parent.tap do |p_tag|
|
|
44
|
-
p_tag.add_previous_sibling img_tag
|
|
45
|
-
p_tag.add_class CLASS_IMG_TAG_RELOCATED
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def img_tags_inside_p_tags
|
|
50
|
-
@img_tags_inside_p_tags ||= document.css 'p > img'
|
|
51
|
-
end
|
|
52
30
|
end
|
|
53
31
|
end
|
|
54
32
|
end
|
|
@@ -15,7 +15,35 @@ module EmbeddableContent
|
|
|
15
15
|
delegate :template_based?, to: :presentation_tag
|
|
16
16
|
|
|
17
17
|
def replace_node
|
|
18
|
-
template_based? ?
|
|
18
|
+
template_based? ? place_node : modify_parent
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def place_node
|
|
22
|
+
if node_in_p_tag?
|
|
23
|
+
add_empty_p_tag_for_pre_mjpage_compatibility
|
|
24
|
+
place_node_after_parent_node
|
|
25
|
+
else
|
|
26
|
+
place_node_within_parent_node
|
|
27
|
+
end
|
|
28
|
+
remove_node
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def place_node_after_parent_node
|
|
33
|
+
parent_node.add_next_sibling replacement_node
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def place_node_within_parent_node
|
|
37
|
+
parent_node << replacement_node
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_empty_p_tag_for_pre_mjpage_compatibility
|
|
41
|
+
parent_node
|
|
42
|
+
.add_next_sibling '<p class="empty-p-tag-added-for-pre-mjpage-compatability"></p>'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def node_in_p_tag?
|
|
46
|
+
parent_node&.name == 'p'
|
|
19
47
|
end
|
|
20
48
|
|
|
21
49
|
def modify_parent
|
|
@@ -1,124 +1,66 @@
|
|
|
1
|
-
require 'open3'
|
|
2
|
-
|
|
3
1
|
module EmbeddableContent
|
|
4
2
|
module Tex
|
|
5
|
-
class RenderError < StandardError
|
|
6
|
-
attr_reader :script, :stderr, :status
|
|
7
|
-
|
|
8
|
-
def initialize(script, stderr, status, api_errors)
|
|
9
|
-
@script = script
|
|
10
|
-
@stderr = stderr
|
|
11
|
-
@status = status
|
|
12
|
-
super "Unable to resolve error raised calling #{script}: #{status}\n#{stderr}\n#{api_errors}"
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
3
|
class BaseRenderer
|
|
17
|
-
|
|
4
|
+
attr_reader :document, :math_span
|
|
18
5
|
|
|
19
|
-
|
|
6
|
+
delegate :displaystyle?, :mathjax, :mml, :svg, :tex_string, :unadorned_tex_string,
|
|
7
|
+
to: :tex_expression
|
|
20
8
|
|
|
21
|
-
def initialize(
|
|
22
|
-
@
|
|
9
|
+
def initialize(math_span, document)
|
|
10
|
+
@math_span = math_span
|
|
11
|
+
@document = document
|
|
23
12
|
end
|
|
24
13
|
|
|
25
14
|
def render
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
run_script
|
|
15
|
+
rendered_node
|
|
29
16
|
end
|
|
30
17
|
|
|
31
18
|
private
|
|
32
19
|
|
|
33
|
-
def
|
|
34
|
-
|
|
20
|
+
def rendered_node
|
|
21
|
+
@rendered_node ||= math_span.replace replacement
|
|
35
22
|
end
|
|
36
23
|
|
|
37
|
-
def
|
|
38
|
-
|
|
24
|
+
def replacement
|
|
25
|
+
@replacement ||= base_replacement_span.then { |node| node << math_node }
|
|
39
26
|
end
|
|
40
27
|
|
|
41
|
-
def
|
|
42
|
-
|
|
28
|
+
def math_node
|
|
29
|
+
@math_node ||= math_content_node
|
|
43
30
|
end
|
|
44
31
|
|
|
45
|
-
def
|
|
46
|
-
|
|
32
|
+
def math_content_node
|
|
33
|
+
@math_content_node ||= Nokogiri::HTML.fragment(math_content).children.first
|
|
47
34
|
end
|
|
48
35
|
|
|
49
|
-
def
|
|
50
|
-
@
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def run_script
|
|
54
|
-
@run_script ||= Open3.capture3(script, stdin_data: html).tap do |stdout, stderr, status|
|
|
55
|
-
@stdout = stdout
|
|
56
|
-
@stderr = stderr
|
|
57
|
-
@status = status
|
|
36
|
+
def base_replacement_span
|
|
37
|
+
@base_replacement_span ||= blank_span.then do |span|
|
|
38
|
+
span['class'] = replacement_css_classes if replacement_css_classes.present?
|
|
39
|
+
span
|
|
58
40
|
end
|
|
59
|
-
render_failed? ? try_api_client : html.replace(stdout)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def script
|
|
63
|
-
@script ||= [RENDER_TEX_JS_PATH, '--output', target_format].join(' ')
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
REGEX_TEX_STRING = /Formula\s+(?<texstring>.*)\s+contains the following errors:/.freeze
|
|
67
|
-
def offending_tex_string
|
|
68
|
-
@offending_tex_string ||= REGEX_TEX_STRING.match(stderr)[:texstring].strip if
|
|
69
|
-
stderr.present?
|
|
70
41
|
end
|
|
71
42
|
|
|
72
|
-
def
|
|
73
|
-
|
|
43
|
+
def blank_span
|
|
44
|
+
Nokogiri::XML::Node.new('span', document)
|
|
74
45
|
end
|
|
75
46
|
|
|
76
|
-
def
|
|
77
|
-
|
|
47
|
+
def replacement_css_classes
|
|
48
|
+
''
|
|
78
49
|
end
|
|
79
50
|
|
|
80
|
-
def
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def try_api_client
|
|
85
|
-
raise render_error if offending_node.blank?
|
|
86
|
-
raise render_error unless api_client.success?
|
|
87
|
-
|
|
88
|
-
offending_node.content = ''
|
|
89
|
-
offending_node.add_child repaired_content
|
|
90
|
-
renderer_for_repaired_document.render
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def renderer_for_repaired_document
|
|
94
|
-
@renderer_for_repaired_document ||=
|
|
95
|
-
self.class.new html.replace(document.to_html)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def repaired_span
|
|
99
|
-
@repaired_span = %w[<span class="mathjax-api"></span>].tap do |span|
|
|
100
|
-
span << repaired_content
|
|
51
|
+
def emptied_math_span
|
|
52
|
+
@emptied_math_span ||= math_span.dup.then do |empty_span|
|
|
53
|
+
empty_span.content = ''
|
|
54
|
+
math_span.replace empty_span
|
|
101
55
|
end
|
|
102
56
|
end
|
|
103
57
|
|
|
104
|
-
def
|
|
105
|
-
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def api_client
|
|
109
|
-
@api_client ||= Mathjax::Api::Client.new offending_tex_string
|
|
58
|
+
def first_build_math_node
|
|
59
|
+
math_node
|
|
110
60
|
end
|
|
111
61
|
|
|
112
|
-
def
|
|
113
|
-
@
|
|
114
|
-
all_spans.detect { |node| offending_tex_appears_in?(node) }
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
REGEX_NODE_TEX_CONTENT = /\\\(\s*(?<tex_string>.*)\s*\\\)/m.freeze
|
|
118
|
-
def offending_tex_appears_in?(node)
|
|
119
|
-
node.content.match(REGEX_NODE_TEX_CONTENT).then do |md|
|
|
120
|
-
md.present? && md[:tex_string]&.strip.eql?(offending_tex_string)
|
|
121
|
-
end
|
|
62
|
+
def tex_expression
|
|
63
|
+
@tex_expression ||= TexExpression.for_math_span math_span
|
|
122
64
|
end
|
|
123
65
|
end
|
|
124
66
|
end
|
|
@@ -1,14 +1,46 @@
|
|
|
1
|
-
require 'open3'
|
|
2
|
-
|
|
3
1
|
module EmbeddableContent
|
|
4
2
|
module Tex
|
|
5
3
|
class CanvasRenderer < BaseRenderer
|
|
4
|
+
require 'embeddable_content/tex/uri_encode_component'
|
|
5
|
+
|
|
6
6
|
def target_format
|
|
7
7
|
:canvas
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
#################################################
|
|
11
|
+
# EDC: this is the way Canvas likes things done #
|
|
12
|
+
#################################################
|
|
13
|
+
def math_node
|
|
14
|
+
@math_node ||= Nokogiri::XML::Node.new('img', document).tap do |node|
|
|
15
|
+
node['class'] = 'equation_image'
|
|
16
|
+
node['title'] = unadorned_tex_string
|
|
17
|
+
node['src'] = expression_uri
|
|
18
|
+
node['alt'] = alt_expression
|
|
19
|
+
node['data-equation-content'] = unadorned_tex_string
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def rendered_node
|
|
24
|
+
@rendered_node ||= emptied_math_span.then { |span| span << math_node }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def base_replacement_span
|
|
28
|
+
@base_replacement_span ||= blank_span.tap do |span|
|
|
29
|
+
span['class'] = 'math'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def alt_expression
|
|
34
|
+
@alt_expression ||= "LaTeX: #{unadorned_tex_string}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def expression_uri
|
|
38
|
+
@expression_uri ||= "/equation_images/#{doubly_encoded_expression}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def doubly_encoded_expression
|
|
42
|
+
@doubly_encoded_expression ||=
|
|
43
|
+
encodeURIComponent encodeURIComponent unadorned_tex_string
|
|
12
44
|
end
|
|
13
45
|
end
|
|
14
46
|
end
|
|
@@ -1,54 +1,31 @@
|
|
|
1
1
|
module EmbeddableContent
|
|
2
2
|
module Tex
|
|
3
3
|
class DocProcessor < EmbeddableContent::DocProcessor
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
delegate :remove_repaired_math_spans?, to: :embedder
|
|
4
|
+
delegate :remove_repaired_math_spans?, :tex_output_format,
|
|
5
|
+
to: :embedder
|
|
8
6
|
|
|
9
7
|
private
|
|
10
8
|
|
|
11
|
-
def process_nodes?
|
|
12
|
-
remove_repaired_math_spans?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
9
|
def process_node(node, _node_index)
|
|
16
|
-
|
|
10
|
+
tex_renderer_for_node(node).render
|
|
17
11
|
end
|
|
18
12
|
|
|
13
|
+
# TODO: resolve this --- still needed?
|
|
19
14
|
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
|
|
15
|
+
# node.replace node.content
|
|
28
16
|
end
|
|
29
17
|
|
|
30
18
|
def node_selector
|
|
31
|
-
|
|
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?
|
|
19
|
+
Mathjax::Config::MATH_SPAN_SELECTOR
|
|
44
20
|
end
|
|
45
21
|
|
|
46
|
-
def
|
|
47
|
-
|
|
22
|
+
def tex_renderer_for_node(node)
|
|
23
|
+
tex_renderer_class.new node, document
|
|
48
24
|
end
|
|
49
25
|
|
|
50
|
-
def
|
|
51
|
-
|
|
26
|
+
def tex_renderer_class
|
|
27
|
+
@tex_renderer_class ||=
|
|
28
|
+
"#{module_name}::#{tex_output_format.classify}Renderer".constantize
|
|
52
29
|
end
|
|
53
30
|
end
|
|
54
31
|
end
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
require 'open3'
|
|
2
|
-
|
|
3
1
|
module EmbeddableContent
|
|
4
2
|
module Tex
|
|
5
3
|
class MmlRenderer < BaseRenderer
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
# TODO: update this once embedder specs working
|
|
7
|
+
def replacement_css_classes
|
|
8
|
+
@replacement_css_classes ||=
|
|
9
|
+
displaystyle? ? 'mjpage mjpage__block' : 'mjpage'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def math_content
|
|
13
|
+
mml
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def math_node
|
|
17
|
+
super.tap do |node|
|
|
18
|
+
node['display'] = 'block' if displaystyle?
|
|
19
|
+
node['alttext'] = unadorned_tex_string
|
|
20
|
+
end
|
|
8
21
|
end
|
|
9
22
|
end
|
|
10
23
|
end
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
require 'open3'
|
|
2
|
-
|
|
3
1
|
module EmbeddableContent
|
|
4
2
|
module Tex
|
|
5
3
|
class SvgRenderer < BaseRenderer
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def rendered_node
|
|
7
|
+
@rendered_node ||= emptied_math_span.then { |span| span << math_node }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def math_content
|
|
11
|
+
svg
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def base_replacement_span
|
|
15
|
+
emptied_math_span
|
|
8
16
|
end
|
|
9
17
|
end
|
|
10
18
|
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# edc: see
|
|
2
|
+
# https://github.com/bootstraponline/encodeURIComponent_ruby/blob/master/uri_encode_component.rb
|
|
3
|
+
|
|
4
|
+
=begin
|
|
5
|
+
Copyright 2006-2008 the V8 project authors. All rights reserved.
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are
|
|
8
|
+
met:
|
|
9
|
+
|
|
10
|
+
* Redistributions of source code must retain the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
|
12
|
+
* Redistributions in binary form must reproduce the above
|
|
13
|
+
copyright notice, this list of conditions and the following
|
|
14
|
+
disclaimer in the documentation and/or other materials provided
|
|
15
|
+
with the distribution.
|
|
16
|
+
* Neither the name of Google Inc. nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived
|
|
18
|
+
from this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
21
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
22
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
23
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
24
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
25
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
26
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
27
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
28
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
29
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
30
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
31
|
+
=end
|
|
32
|
+
|
|
33
|
+
# This file provides the following methods:
|
|
34
|
+
# encodeURIComponent(componentString)
|
|
35
|
+
# string.charCodeAt(k)
|
|
36
|
+
|
|
37
|
+
# component must be String
|
|
38
|
+
def encodeURIComponent(componentString)
|
|
39
|
+
URI::URIEncodeComponent(componentString)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# define charCodeAt on String
|
|
43
|
+
class String
|
|
44
|
+
def charCodeAt(k)
|
|
45
|
+
return self[k].ord
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module URI; class << self
|
|
50
|
+
# Does the char code correspond to an alpha-numeric char.
|
|
51
|
+
# isAlphaNumeric('a'.ord) => true
|
|
52
|
+
# isAlphaNumeric(''.ord) => false
|
|
53
|
+
def isAlphaNumeric(cc)
|
|
54
|
+
# a - z
|
|
55
|
+
if (97 <= cc && cc <= 122); return true end
|
|
56
|
+
# A - Z
|
|
57
|
+
if (65 <= cc && cc <= 90); return true end
|
|
58
|
+
# 0 - 9
|
|
59
|
+
if (48 <= cc && cc <= 57); return true end
|
|
60
|
+
|
|
61
|
+
return false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def unescapePredicate(cc)
|
|
65
|
+
if (isAlphaNumeric(cc)); return true end
|
|
66
|
+
# !
|
|
67
|
+
if (cc == 33); return true end
|
|
68
|
+
# '()*
|
|
69
|
+
if (39 <= cc && cc <= 42); return true end
|
|
70
|
+
# -.
|
|
71
|
+
if (45 <= cc && cc <= 46); return true end
|
|
72
|
+
# _
|
|
73
|
+
if (cc == 95); return true end
|
|
74
|
+
# ~
|
|
75
|
+
if (cc == 126); return true end
|
|
76
|
+
|
|
77
|
+
return false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def URIEncodeSingle(cc, result, index)
|
|
81
|
+
x = (cc >> 12) & 0xF;
|
|
82
|
+
y = (cc >> 6) & 63;
|
|
83
|
+
z = cc & 63;
|
|
84
|
+
octets = Array.new(3);
|
|
85
|
+
if (cc <= 0x007F)
|
|
86
|
+
octets[0] = cc;
|
|
87
|
+
elsif (cc <= 0x07FF)
|
|
88
|
+
octets[0] = y + 192;
|
|
89
|
+
octets[1] = z + 128;
|
|
90
|
+
else
|
|
91
|
+
octets[0] = x + 224;
|
|
92
|
+
octets[1] = y + 128;
|
|
93
|
+
octets[2] = z + 128;
|
|
94
|
+
end
|
|
95
|
+
return URIEncodeOctets(octets, result, index);
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Lazily initialized.
|
|
99
|
+
@@hexCharCodeArray = 0;
|
|
100
|
+
|
|
101
|
+
def URIAddEncodedOctetToBuffer(octet, result, index)
|
|
102
|
+
result[index] = 37; # Char code of '%'.
|
|
103
|
+
index += 1
|
|
104
|
+
result[index] = @@hexCharCodeArray[octet >> 4];
|
|
105
|
+
index += 1
|
|
106
|
+
result[index] = @@hexCharCodeArray[octet & 0x0F];
|
|
107
|
+
index += 1
|
|
108
|
+
return index;
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def URIEncodeOctets(octets, result, index)
|
|
112
|
+
if (@@hexCharCodeArray == 0)
|
|
113
|
+
@@hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
|
114
|
+
65, 66, 67, 68, 69, 70];
|
|
115
|
+
end
|
|
116
|
+
index = URIAddEncodedOctetToBuffer(octets[0], result, index);
|
|
117
|
+
if (octets[1]); index = URIAddEncodedOctetToBuffer(octets[1], result, index) end
|
|
118
|
+
if (octets[2]); index = URIAddEncodedOctetToBuffer(octets[2], result, index) end
|
|
119
|
+
if (octets[3]); index = URIAddEncodedOctetToBuffer(octets[3], result, index) end
|
|
120
|
+
return index;
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def URIEncodePair(cc1 , cc2, result, index)
|
|
124
|
+
u = ((cc1 >> 6) & 0xF) + 1;
|
|
125
|
+
w = (cc1 >> 2) & 0xF;
|
|
126
|
+
x = cc1 & 3;
|
|
127
|
+
y = (cc2 >> 6) & 0xF;
|
|
128
|
+
z = cc2 & 63;
|
|
129
|
+
octets = Array.new(4);
|
|
130
|
+
octets[0] = (u >> 2) + 240;
|
|
131
|
+
octets[1] = (((u & 3) << 4) | w) + 128;
|
|
132
|
+
octets[2] = ((x << 4) | y) + 128;
|
|
133
|
+
octets[3] = z + 128;
|
|
134
|
+
return URIEncodeOctets(octets, result, index);
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# component must be String
|
|
138
|
+
def URIEncodeComponent(componentString)
|
|
139
|
+
Encode(componentString, :unescapePredicate);
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# ECMA-262, section 15.1.3
|
|
143
|
+
def Encode(uri, unescape)
|
|
144
|
+
uriLength = uri.length;
|
|
145
|
+
# We are going to pass result to %StringFromCharCodeArray
|
|
146
|
+
# which does not expect any getters/setters installed
|
|
147
|
+
# on the incoming array.
|
|
148
|
+
result = Array.new(uriLength);
|
|
149
|
+
index = 0;
|
|
150
|
+
k = -1;
|
|
151
|
+
while ((k+=1) < uriLength) do
|
|
152
|
+
cc1 = uri.charCodeAt(k);
|
|
153
|
+
if (self.send(unescape, cc1))
|
|
154
|
+
result[index] = cc1;
|
|
155
|
+
index += 1
|
|
156
|
+
else
|
|
157
|
+
if (cc1 >= 0xDC00 && cc1 <= 0xDFFF); throw("URI malformed") end
|
|
158
|
+
if (cc1 < 0xD800 || cc1 > 0xDBFF)
|
|
159
|
+
index = URIEncodeSingle(cc1, result, index);
|
|
160
|
+
else
|
|
161
|
+
k+=1;
|
|
162
|
+
if (k == uriLength); throw("URI malformed") end
|
|
163
|
+
cc2 = uri.charCodeAt(k);
|
|
164
|
+
if (cc2 < 0xDC00 || cc2 > 0xDFFF); throw("URI malformed") end
|
|
165
|
+
index = URIEncodePair(cc1, cc2, result, index);
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
# return %StringFromCharCodeArray(result);
|
|
170
|
+
# 'c' = 8 bit signed char
|
|
171
|
+
# http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-pack
|
|
172
|
+
return result.pack 'c*'
|
|
173
|
+
end
|
|
174
|
+
end # class << self
|
|
175
|
+
end # module
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
module EmbeddableContent
|
|
2
2
|
module VideoLinks
|
|
3
|
-
class DocProcessor < EmbeddableContent::DocProcessor
|
|
3
|
+
class DocProcessor < EmbeddableContent::DocProcessor
|
|
4
|
+
TARGETS_FOR_WHICH_NODES_ARE_UNMOVEABLE = %i[cms exported kiddom web].freeze
|
|
5
|
+
|
|
6
|
+
def update_moveable_nodes?
|
|
7
|
+
TARGETS_FOR_WHICH_NODES_ARE_UNMOVEABLE.exclude? target
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def relocate_moveable_node(moveable_node)
|
|
13
|
+
place_moveable_node_after_parent moveable_node
|
|
14
|
+
end
|
|
15
|
+
end
|
|
4
16
|
end
|
|
5
17
|
end
|
|
@@ -15,7 +15,7 @@ div.im-c-modal__content.im-c-content
|
|
|
15
15
|
- if description.present?
|
|
16
16
|
p
|
|
17
17
|
strong> Description:
|
|
18
|
-
|
|
18
|
+
== description
|
|
19
19
|
img *img_tag_attrs
|
|
20
20
|
- if caption.present?
|
|
21
21
|
p id = caption_id
|
|
@@ -24,7 +24,7 @@ div.im-c-modal__content.im-c-content
|
|
|
24
24
|
- if attribution.present?
|
|
25
25
|
p id = attribution_id
|
|
26
26
|
strong> Attribution:
|
|
27
|
-
|
|
27
|
+
==> modal_dialog.attribution_display_text
|
|
28
28
|
a href = attribution.original_url
|
|
29
29
|
| Source
|
|
30
30
|
| .
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: embeddable_content
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0.beta7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Connally
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-11-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -175,6 +175,7 @@ files:
|
|
|
175
175
|
- app/services/embeddable_content/fragment_embedder.rb
|
|
176
176
|
- app/services/embeddable_content/geogebra_files/doc_processor.rb
|
|
177
177
|
- app/services/embeddable_content/geogebra_files/node_processor.rb
|
|
178
|
+
- app/services/embeddable_content/has_moveable_nodes.rb
|
|
178
179
|
- app/services/embeddable_content/html_tags/doc_processor.rb
|
|
179
180
|
- app/services/embeddable_content/html_tags/node_processor.rb
|
|
180
181
|
- app/services/embeddable_content/images/attributions_processor.rb
|
|
@@ -198,8 +199,8 @@ files:
|
|
|
198
199
|
- app/services/embeddable_content/tex/doc_processor.rb
|
|
199
200
|
- app/services/embeddable_content/tex/mathjax_renderer.rb
|
|
200
201
|
- app/services/embeddable_content/tex/mml_renderer.rb
|
|
201
|
-
- app/services/embeddable_content/tex/schoology_string_renderer.rb
|
|
202
202
|
- app/services/embeddable_content/tex/svg_renderer.rb
|
|
203
|
+
- app/services/embeddable_content/tex/uri_encode_component.rb
|
|
203
204
|
- app/services/embeddable_content/token_replacement_map.rb
|
|
204
205
|
- app/services/embeddable_content/tree_based_node_processor.rb
|
|
205
206
|
- app/services/embeddable_content/video_links/doc_processor.rb
|
|
@@ -208,7 +209,6 @@ files:
|
|
|
208
209
|
- app/services/embeddable_content/visual_element_node_processor.rb
|
|
209
210
|
- app/services/embeddable_content/widget_files/doc_processor.rb
|
|
210
211
|
- app/services/embeddable_content/widget_files/node_processor.rb
|
|
211
|
-
- app/services/mathjax/api/client.rb
|
|
212
212
|
- app/views/.keep
|
|
213
213
|
- app/views/embeddable_content/replacements/desmos_files/_applet.html.slim
|
|
214
214
|
- app/views/embeddable_content/replacements/desmos_files/_description.html.slim
|
|
@@ -286,7 +286,7 @@ files:
|
|
|
286
286
|
homepage: https://github.com/illustrativemathematics/embedded_content
|
|
287
287
|
licenses: []
|
|
288
288
|
metadata: {}
|
|
289
|
-
post_install_message:
|
|
289
|
+
post_install_message:
|
|
290
290
|
rdoc_options: []
|
|
291
291
|
require_paths:
|
|
292
292
|
- lib
|
|
@@ -298,12 +298,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
298
298
|
version: '0'
|
|
299
299
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
300
300
|
requirements:
|
|
301
|
-
- - "
|
|
301
|
+
- - ">"
|
|
302
302
|
- !ruby/object:Gem::Version
|
|
303
|
-
version:
|
|
303
|
+
version: 1.3.1
|
|
304
304
|
requirements: []
|
|
305
305
|
rubygems_version: 3.0.3
|
|
306
|
-
signing_key:
|
|
306
|
+
signing_key:
|
|
307
307
|
specification_version: 4
|
|
308
308
|
summary: Embeddable Content functionality extracted from cms-im app.
|
|
309
309
|
test_files: []
|
|
@@ -1,15 +0,0 @@
|
|
|
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
|