Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
612f381e
Commit
612f381e
authored
Aug 02, 2012
by
Mike Chen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GeneralResponse in Wiki syntax and formularesponse rendering
parent
d256b929
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
237 additions
and
32 deletions
+237
-32
cms/static/grammars/main.jspeg
+187
-21
common/lib/xmodule/xmodule/js/src/capa/edit.coffee
+50
-11
No files found.
cms/static/grammars/main.jspeg
View file @
612f381e
/* null_ is used in JSON parser */
{
null_ = new Object();
}
start
= sections:(Image /
GeneralResponse /
NumericalOrStringResponse /
NumericalResponse /
MultipleChoice /
Paragraph /
PreservedLinebreaks)+
Paragraph
)+
/* GeneralResponse */
KeyValueString
= QuotedString
/ chars:[^: \n]+
{
return chars.join("");
}
KeyValuePair
= key:KeyValueString _ ':' _ value:KeyValueString
{
return {'key': key, 'value': value};
}
InlineGeneralResponse
= CorrectAnswerIdentifier pairs:(' '+ KeyValuePair)+ Linebreak
{
ret = {};
pairs = pairs.map(function (x) { return x[1]; });
for (var i = 0; i < pairs.length; i++) {
console.log(pairs);
if (ret[pairs[i].key] == undefined)
ret[pairs[i].key] = pairs[i].value;
else
throw new SyntaxError("Key " + pairs[i].key + " was used more than once. " );
}
return ret;
}
GeneralResponseValue
= InlineGeneralResponse / JSONDictionary
GeneralResponse
= dic:GeneralResponseValue
{
if (dic.type == undefined) {
throw new SyntaxError("Please define 'type' in response. ")
}
return dic;
}
/* Image */
ImageLink
=
Double
QuotedString
= QuotedString
/ chars:( (!')' [^\n])+)
{
return $.trim(chars.map(function(element) { return element[1]; }).join(""));
...
...
@@ -22,7 +70,7 @@ ImageTitle
}
Image
= ImageIdentifier title:ImageTitle?
OptionalSpaces '(' OptionalSpaces url:ImageLink ')' OptionalSpaces
Linebreak
= ImageIdentifier title:ImageTitle?
_ '(' _ url:ImageLink ')' ' '*
Linebreak
{
return {'type': 'image', 'url': url, 'title': title};
}
...
...
@@ -38,19 +86,19 @@ ChoiceIdentifier
ImageIdentifier
= '!'
StudentProducedResponse
Identifier
CorrectAnswer
Identifier
= '='
/* StringResponse */
StringResponse
=
StudentProducedResponseIdentifier OptionalSpaces !'(' value:Text
Linebreak
=
CorrectAnswerIdentifier _ !'(' value:(QuotedString / Text)
Linebreak
{
return {'type': 'string', 'answer': $.trim(value)};
}
NumericalOrStringResponse
=
StudentProducedResponseIdentifier OptionalSpaces value:NumericalValue OptionalSpaces tolerance:NumericalTolerance? OptionalSpaces
Linebreak
=
CorrectAnswerIdentifier _ value:NumericalValue _ tolerance:NumericalTolerance? _
Linebreak
{
if (tolerance == "")
tolerance = "5%"
...
...
@@ -79,9 +127,11 @@ MultipleChoice
}
/* Paragraph */
LineOrLinebreak
= Line / Linebreak
ParagraphTextLine
= !
ImageIdentifier !ChoiceIdentifier !StudentProducedResponseIdentifier line:Line
= !
JSONDictionary !ImageIdentifier !ChoiceIdentifier !CorrectAnswerIdentifier line:LineOrLinebreak
{
return line;
}
...
...
@@ -89,7 +139,7 @@ ParagraphTextLine
Paragraph
= lines:ParagraphTextLine+
{
return {'type': '
paragraph
', 'text': lines.join("")};
return {'type': '
text
', 'text': lines.join("")};
}
/* Base symbols */
...
...
@@ -106,49 +156,165 @@ Text
return chars.join("");
}
OptionalSpaces
AndLines
_
AndLines
= (' ' / '\n' / '\t')*
OptionalSpaces
_
= (' ' / '\t')*
PreservedLinebreaks
= terminators:('\n')+
{
return {'type': 'linebreaks', 'count': terminators.length}
}
Linebreak
= ('\n')
QuotedString
= DoubleQuotedString / SingleQuotedString
DoubleQuotedString
= "\"\"" { return ""; }
/ "\"" str:(!Unescaped
Quote .)* last:Unescaped
Quote {
/ "\"" str:(!Unescaped
DoubleQuote .)* last:UnescapedDouble
Quote {
return str.map(function(element) { return element[1]; }).join("") + last;
}
UnescapedQuote
Unescaped
Double
Quote
= last:[^\\] "\"" {return last;}
SingleQuotedString
= "''" { return ""; }
/ "'" str:(!UnescapedSingleQuote .)* last:UnescapedSingleQuote {
return str.map(function(element) { return element[1]; }).join("") + last;
}
UnescapedSingleQuote
= last:[^\\] "'" {return last;}
AlphanumericalText
= chars:[a-zA-Z0-9]+
{
return chars.join("");
}
/* JSON */
/* JSON parser based on the grammar described at http://json.org/. */
JSONDictionary
= _ o:object { return o; }
object
= "{" _ "}" _ { return {}; }
/ "{" _ members:members "}" _ { return members; }
members
= head:pair tail:("," _ pair)* {
var result = {};
result[head[0]] = (head[1] === null_ ? null : head[1]);
for (var i = 0; i < tail.length; i++) {
result[tail[i][2][0]] = (tail[i][2][1] === null_ ? null : tail[i][2][1]);
}
return result;
}
pair
= name:string ":" _ value:value { return [name, value]; }
array
= "[" _ "]" _ { return []; }
/ "[" _ elements:elements "]" _ { return elements; }
elements
= head:value tail:("," _ value)* {
var result = [head === null_ ? null : head];
for (var i = 0; i < tail.length; i++) {
result.push(tail[i][2] === null_ ? null : tail[i][2]);
}
return result;
}
value
= string
/ number
/ object
/ array
/ "true" _ { return true; }
/ "false" _ { return false; }
/ "null" _ { return null_; }
string "string"
= '"' '"' _ { return ""; }
/ '"' chars:chars '"' _ { return chars; }
chars
= chars:char+ { return chars.join(""); }
char
// In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character"
= [^"\\\0-\x1F\x7f]
/ '\\"' { return '"'; }
/ "\\\\" { return "\\"; }
/ "\\/" { return "/"; }
/ "\\b" { return "\b"; }
/ "\\f" { return "\f"; }
/ "\\n" { return "\n"; }
/ "\\r" { return "\r"; }
/ "\\t" { return "\t"; }
/ "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit {
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
}
number "number"
= int_:int frac:frac exp:exp _ { return parseFloat(int_ + frac + exp); }
/ int_:int frac:frac _ { return parseFloat(int_ + frac); }
/ int_:int exp:exp _ { return parseFloat(int_ + exp); }
/ int_:int _ { return parseFloat(int_); }
int
= digit19:digit19 digits:digits { return digit19 + digits; }
/ digit:digit
/ "-" digit19:digit19 digits:digits { return "-" + digit19 + digits; }
/ "-" digit:digit { return "-" + digit; }
frac
= "." digits:digits { return "." + digits; }
exp
= e:e digits:digits { return e + digits; }
digits
= digits:digit+ { return digits.join(""); }
e
= e:[eE] sign:[+-]? { return e + sign; }
digit
= [0-9]
digit19
= [1-9]
hexDigit
= [0-9a-fA-F]
_ "whitespace"
= whitespace*
// Whitespace is undefined in the original JSON grammar, so I assume a simple
// conventional definition consistent with ECMA-262, 5th ed.
whitespace
= [ \t\n\r]
/* NumericalResponse */
NumericalToleranceValueType
= decimal / percentage / integer
NumericalTolerance
= '+-'
OptionalSpaces value:NumericalToleranceValueType OptionalSpaces
= '+-'
_ value:NumericalToleranceValueType _
{
return value;
}
NumericalResponse
=
StudentProducedResponseIdentifier OptionalSpaces '(' OptionalSpaces value:NumericalValue OptionalSpaces tolerance:NumericalTolerance? ')' OptionalSpaces
Linebreak
=
CorrectAnswerIdentifier _ '(' _ value:NumericalValue _ tolerance:NumericalTolerance? ')' _
Linebreak
{
if (tolerance == "")
tolerance = "5%"
...
...
common/lib/xmodule/xmodule/js/src/capa/edit.coffee
View file @
612f381e
class
@
CapaDescriptor
constructor
:
(
@
element
)
->
@
problem_text
=
""
@
edit_box
=
$
(
".edit-box.capa-box"
,
@
element
)
@
source_box
=
$
(
".edit-box.source-box"
,
@
element
)
@
message_box
=
$
(
".parser-message-box"
,
@
element
)
@
buildParser
()
@
throttledAutoSave
=
_
.
throttle
(
@
autoSave
,
0
);
@
source_box
.
keyup
=>
@
parse
()
...
...
@@ -20,6 +22,19 @@ class @CapaDescriptor
"Line "
+
e
.
line
+
", column "
+
e
.
column
+
": "
+
e
.
message
else
e
.
message
checkAutoSaveTimeout
:
->
@
auto_save_timer
=
null
@
throttledAutoSave
()
checkAutoSave
:
->
callback
=
_
.
bind
(
@
checkAutoSaveTimeout
,
this
)
if
@
auto_save_timer
@
auto_save_timer
=
window
.
clearTimeout
(
@
auto_save_timer
)
@
auto_save_timer
=
window
.
setTimeout
(
callback
,
1000
)
autoSave
:
(
event
)
->
$
(
".save-update"
).
click
();
parse
:
->
try
source
=
@
source_box
.
val
()
+
"
\n
"
...
...
@@ -34,25 +49,27 @@ class @CapaDescriptor
outputXML
:
(
parsed
)
->
@
edit_box
.
val
@
buildXML
(
parsed
)
@
checkAutoSave
()
dom2capa
:
(
node
)
->
capa
=
new
XMLSerializer
().
serializeToString
(
node
)
capa
=
capa
+
""
return
capa
.
replace
(
/<startouttext>/g
,
'<startouttext />'
)
.
replace
(
/<\/startouttext>/g
,
'<endouttext />'
)
serializer
=
new
XMLSerializer
()
capa
=
serializer
.
serializeToString
(
node
)
buildXML
:
(
parsed
)
->
dom_parser
=
new
DOMParser
()
doc
=
dom_parser
.
parseFromString
(
"<problem
></problem
>"
,
"text/xml"
);
problem
=
$
(
doc
.
getElementsByTagName
(
'problem'
)[
0
]
)
doc
=
dom_parser
.
parseFromString
(
"<problem
/
>"
,
"text/xml"
);
problem
=
$
(
doc
).
find
(
'problem'
)
create_text_element
=
(
content
)
->
el
=
$
(
doc
.
createElement
(
'startouttext'
))
el
.
text
content
el
=
$
(
doc
.
createElement
(
'text'
))
for
line
in
content
.
split
(
'
\n
'
)
el
.
append
doc
.
createTextNode
(
line
)
el
.
append
doc
.
createElement
(
'br'
)
el
.
children
().
last
().
remove
()
return
el
for
section
in
parsed
if
section
.
type
==
'
paragraph
'
if
section
.
type
==
'
text
'
newel
=
create_text_element
(
section
.
text
)
problem
.
append
(
newel
)
...
...
@@ -103,6 +120,8 @@ class @CapaDescriptor
tolerance
=
$
(
doc
.
createElement
(
'responseparam'
))
tolerance
.
attr
'type'
,
'tolerance'
if
section
.
tolerance
==
undefined
section
.
tolerance
=
"5%"
tolerance
.
attr
'default'
,
section
.
tolerance
tolerance
.
attr
'name'
,
'tol'
tolerance
.
attr
'description'
,
'Numerical Tolerance'
...
...
@@ -117,6 +136,27 @@ class @CapaDescriptor
newel
.
append
doc
.
createElement
(
'textline'
)
problem
.
append
(
newel
)
else
if
section
.
type
==
'formula'
formularesponse
=
$
(
doc
.
createElement
(
"formularesponse"
))
formularesponse
.
attr
'samples'
,
section
.
samples
formularesponse
.
attr
'answer'
,
section
.
answer
formularesponse
.
attr
'type'
,
'cs'
tolerance
=
$
(
doc
.
createElement
(
'responseparam'
))
tolerance
.
attr
'type'
,
'tolerance'
if
section
.
tolerance
==
undefined
section
.
tolerance
=
"5%"
tolerance
.
attr
'default'
,
section
.
tolerance
tolerance
.
attr
'name'
,
'tol'
tolerance
.
attr
'description'
,
'Numerical Tolerance'
formularesponse
.
append
tolerance
formularesponse
.
append
doc
.
createElement
(
'textline'
)
problem
.
append
(
formularesponse
)
else
throw
new
SyntaxError
(
"unexpected section type "
+
section
.
type
)
capa
=
@
dom2capa
(
doc
)
console
.
log
capa
return
capa
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment