Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 53b1604

Browse files
committed
XML Support
1 parent 6b6a1e1 commit 53b1604

File tree

8 files changed

+100
-11
lines changed

8 files changed

+100
-11
lines changed

runestone/clickableArea/clickable.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
maybeAddToAssignment,
2525
)
2626
from runestone.common.runestonedirective import RunestoneIdDirective, RunestoneIdNode
27+
from runestone.common.xmlcommon import write_substitute, substitute_visitor, substitute_departure
2728

2829

2930
def setup(app):
3031
app.add_directive("clickablearea", ClickableArea)
3132

32-
app.add_node(ClickableAreaNode, html=(visit_ca_html, depart_ca_html))
33+
app.add_node(ClickableAreaNode, html=(visit_ca_html, depart_ca_html),
34+
xml=(substitute_visitor, substitute_departure))
3335

3436
app.add_config_value("clickable_div_class", "runestone alert alert-warning", "html")
3537

runestone/codelens/visualizer.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def setup(app):
3131

3232
app.add_config_value("codelens_div_class", "alert alert-warning cd_section", "html")
3333
app.add_config_value("trace_url", "http://tracer.runestone.academy:5000", "html")
34-
app.add_node(CodeLensNode, html=(visit_codelens_html, depart_codelens_html))
34+
app.add_node(CodeLensNode, html=(visit_codelens_html, depart_codelens_html),
35+
xml=(visit_codelens_xml, depart_codelens_xml))
3536

3637

3738
# data-tracefile="pytutor-embed-demo/java.json"
@@ -65,6 +66,27 @@ class CodeLensNode(nodes.General, nodes.Element, RunestoneIdNode):
6566
pass
6667

6768

69+
def visit_codelens_xml(self, node):
70+
html = VIS
71+
if "caption" not in node["runestone_options"]:
72+
node["runestone_options"]["caption"] = node["runestone_options"]["question_label"]
73+
if "tracedata" in node["runestone_options"]:
74+
node["runestone_options"]["tracedata"] = node["runestone_options"]["tracedata"].replace(
75+
"<", "&lt;").replace(">", "&gt;")
76+
html += DATA
77+
else:
78+
html += "</div>"
79+
html = html % node["runestone_options"]
80+
81+
self.output.append(
82+
"<exercise runestone='{divid}' />".format(**node["runestone_options"]))
83+
with open("rs-substitutes.xml", "a") as subfile:
84+
subfile.write("<substitute xml:id='{divid}'>".format(
85+
**node["runestone_options"]))
86+
subfile.write(html)
87+
subfile.write("</substitute>")
88+
89+
6890
def visit_codelens_html(self, node):
6991
html = VIS
7092
if "caption" not in node["runestone_options"]:
@@ -85,6 +107,10 @@ def depart_codelens_html(self, node):
85107
pass
86108

87109

110+
def depart_codelens_xml(self, node):
111+
pass
112+
113+
88114
# Some documentation to help the author.
89115
# Here's and example of a single stack frame.
90116
# you might ask a qestion about the value of a global variable

runestone/common/xmlcommon.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Common routines for converting to PreTeXt
2+
3+
from asyncore import write
4+
5+
6+
def write_substitute(self, node, html=None):
7+
self.output.append(
8+
"<exercise runestone='{divid}' />".format(**node["runestone_options"]))
9+
with open("rs-substitutes.xml", "a") as subfile:
10+
subfile.write("<substitute xml:id='{divid}'>".format(
11+
**node["runestone_options"]))
12+
if html:
13+
subfile.write(f"""{html}""")
14+
else:
15+
subfile.write(
16+
f"""<dbfetch>{node["runestone_options"]["divid"]}</dbfetch>""")
17+
subfile.write("</substitute>")
18+
19+
20+
def substitute_visitor(self, node):
21+
write_substitute(self, node)
22+
23+
24+
def substitute_departure(self, node):
25+
pass

runestone/dragndrop/dragndrop.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
RunestoneIdDirective,
2828
RunestoneIdNode,
2929
)
30+
from runestone.common.xmlcommon import write_substitute
3031

3132

3233
def setup(app):
@@ -60,13 +61,11 @@ class DragNDropNode(nodes.General, nodes.Element, RunestoneIdNode):
6061

6162

6263
def visit_dnd_xml(self, node):
63-
res = visit_dnd_common(self, node)
64-
self.output.append(res)
64+
write_substitute(self, node)
6565

6666

6767
def depart_dnd_xml(self, node):
68-
res = depart_dnd_common(self, node)
69-
self.output.append(res)
68+
pass
7069

7170

7271
def visit_dnd_html(self, node):

runestone/fitb/fitb.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
RunestoneIdNode,
4040
get_node_line,
4141
)
42+
from runestone.common.xmlcommon import substitute_departure, substitute_visitor
4243

4344

4445
def setup(app):
@@ -47,7 +48,8 @@ def setup(app):
4748
app.add_node(FITBNode, html=(visit_fitb_html, depart_fitb_html))
4849
app.add_node(BlankNode, html=(visit_blank_html, depart_blank_html))
4950
app.add_node(
50-
FITBFeedbackNode, html=(visit_fitb_feedback_html, depart_fitb_feedback_html)
51+
FITBFeedbackNode, html=(visit_fitb_feedback_html, depart_fitb_feedback_html),
52+
xml=(substitute_visitor, substitute_departure)
5153
)
5254

5355
app.add_config_value("fitb_div_class", "runestone", "html")

runestone/poll/poll.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@
1616

1717
__author__ = "isaiahmayerchak"
1818

19+
from asyncore import write
1920
from docutils import nodes
2021
from docutils.parsers.rst import directives
2122
from runestone.common.runestonedirective import RunestoneIdDirective, RunestoneIdNode
2223
from runestone.server.componentdb import addQuestionToDB, addHTMLToDB
24+
from runestone.common.xmlcommon import write_substitute, substitute_departure
2325

2426

2527
def setup(app):
2628
app.add_directive("poll", Poll)
27-
app.add_node(PollNode, html=(visit_poll_html, depart_poll_html))
29+
app.add_node(PollNode, html=(visit_poll_html, depart_poll_html),
30+
xml=(visit_poll_xml, substitute_departure))
2831

2932
app.add_config_value("poll_div_class", "alert alert-warning", "html")
3033

@@ -57,6 +60,11 @@ def visit_poll_html(self, node):
5760
self.body.append(res)
5861

5962

63+
def visit_poll_xml(self, node):
64+
html = visit_poll_common(self, node)
65+
write_substitute(self, node, html)
66+
67+
6068
def depart_poll_html(self, node):
6169
""" This is called at the start of processing a poll node. If poll had recursive nodes
6270
etc and did not want to do all of the processing in visit_poll_html any finishing touches could be

runestone/server/componentdb.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2323
#
2424
from __future__ import print_function
25+
import pdb
2526

2627
from datetime import datetime, timedelta
2728

@@ -120,6 +121,8 @@ def setup(app):
120121

121122
app.connect("env-before-read-docs", reset_questions)
122123
app.connect("build-finished", finalize_updates)
124+
app.connect("env-before-read-docs", init_subs_file)
125+
app.connect("build-finished", finalize_subs_file)
123126
# the `qbank` option is for the QuestionBank
124127
# it allows us to populate the database from the question bank
125128
# but we don't care about populating chapter and subchapter tables and others
@@ -174,13 +177,26 @@ def get_table_meta():
174177
return table_info
175178

176179

180+
def init_subs_file(app, env, docnames):
181+
if app.builder.name == "xml":
182+
with open("rs-substitutes.xml", "w") as subfile:
183+
subfile.write("<substitutes>")
184+
185+
186+
def finalize_subs_file(app, excpt):
187+
if app.builder.name == "xml":
188+
with open("rs-substitutes.xml", "a") as subfile:
189+
subfile.write("</substitutes>")
190+
177191
# Reset Questions
178192
# ---------------
179193
# We need to be able to tell the difference between questions that are
180194
# part of the book and questions that are contributed by instructors
181195
# so wheenver we build the book, we mark all questions for this base course
182196
# with ``from_source = 'F'`` Then as the book is built and questions are updated
183197
# those in the book get ``from_source = 'T'`` set.
198+
199+
184200
def reset_questions(app, env, docnames):
185201
if sess:
186202
logger.info("Resetting questions")

runestone/showeval/showeval.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
#
1616
__author__ = "tconzett"
1717

18+
from asyncore import write
1819
from docutils import nodes
1920
from docutils.parsers.rst import directives
21+
from runestone.common.xmlcommon import substitute_departure
2022
from runestone.server.componentdb import addQuestionToDB, addHTMLToDB
2123
from runestone.common.runestonedirective import RunestoneIdDirective, RunestoneIdNode
24+
from runestone.common.xmlcommon import substitute_departure, write_substitute
2225

2326

2427
def setup(app):
@@ -27,7 +30,8 @@ def setup(app):
2730
app.add_config_value(
2831
"showeval_div_class", "runestone explainer alert alert-warning", "html"
2932
)
30-
app.add_node(ShowEvalNode, html=(visit_showeval_html, depart_showeval_html))
33+
app.add_node(ShowEvalNode, html=(visit_showeval_html, depart_showeval_html),
34+
xml=(visit_showeval_xml, substitute_departure))
3135

3236

3337
# Create visitors, so we can generate HTML after the doctree is resolve (where the question label is determined).
@@ -43,6 +47,11 @@ def visit_showeval_html(self, node):
4347
)
4448

4549

50+
def visit_showeval_xml(self, node):
51+
html = CODE % node["runestone_options"]
52+
write_substitute(self, node, html)
53+
54+
4655
def depart_showeval_html(self, node):
4756
pass
4857

@@ -72,7 +81,8 @@ class ShowEval(RunestoneIdDirective):
7281
more code
7382
~~~~
7483
more {{code}}{{what code becomes in step 1}}
75-
more {{what code becomes in step 1}}{{what code becomes in step2}} ##Optional comment for step 2
84+
##Optional comment for step 2
85+
more {{what code becomes in step 1}}{{what code becomes in step2}}
7686
as many steps as you want {{the first double braces}}{{animate into the second}} wherever.
7787
7888
@@ -108,7 +118,8 @@ def run(self):
108118
~~~~
109119
110120
''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
111-
{{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs) ##I want to put a comment here!
121+
##I want to put a comment here!
122+
{{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)
112123
{{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
113124
'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
114125
{{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

0 commit comments

Comments
 (0)