diff --git a/assets/pg/PGMLLab/PGML-lab.pg b/assets/pg/PGMLLab/PGML-lab.pg index e163e5a2b1..e04e0f6494 100644 --- a/assets/pg/PGMLLab/PGML-lab.pg +++ b/assets/pg/PGMLLab/PGML-lab.pg @@ -2,12 +2,6 @@ DOCUMENT(); loadMacros('PGstandard.pl', 'PGML.pl', 'PGcourse.pl'); -# Hide things that are appropriate for regular problem use -HEADER_TEXT(tag( - 'style', - '#page-title, #message, #message_bottom, #custom_edit_message, #breadcrumb-navigation, #score_summary, #problemFooter {display: none}' -)); - sub EscapeHTML { my $s = shift; $s =~ s/&/~~&/g; @@ -467,6 +461,64 @@ TEXT(tag( ENDPGML ] ], + [ + 'Tags' => [ + <<~ 'END_PG', + loadMacros('parserMultiAnswer.pl', 'parserPopUp.pl'); + $ma = MultiAnswer(DropDown([ [ 'minimum', 'maximum' ] ], 1), 4)->with( + singleResult => 1, + checker => sub { + my ($cor, $stu) = @_; + return $cor->[0] == $stu->[0] && $cor->[1] == $stu->[1] + ? 1 + : 0; + } + ); + END_PG + <<~'ENDPGML' + A tag is a "div" by default. HTML attributes can be set via an array in the + first option. The only other allowed tag type is a span. To switch to a + span add 'span' to the beginning of the attribute array. The second tex + option and the third ptx option are used to set the output for the TeX and + PTX display modes. The format of the tex option is an array containing two + strings. The first string is the TeX code to insert before the content, + and the second the TeX code to insert after the content. The format of the + ptx option is similar to the format for the first html. It is an array with + the tag name (required), optionally followed by an array of attributes, and + optionally a separator. + + []{ + [ 'span', class => 'p-1 alert alert-danger', role => 'alert' ] + }{ + [ '{\color{red}', '}' ] + }{ + ['alert'] + } + + Tags may contain other PGML content and answers. Note that a span tag may + not contain new lines, tables, or anything else that would be invalid in a + span. Basically only text elements are valid. However, div tags may + contain pretty much anything. + + [< + This is an equation [`x + 3 = 5`]. + + The solution to the above equation is [_]{2}. + >]{ [ style => 'border: 1px solid black; padding: 1rem;' ] } + + One useful application is when using the parserMultiAnswer.pl macro with + singleResult answers. Wrap the answers in in a div tag with the + "ww-feedback-container" class to tell PG where to place the feedback + button. The feedback button will be placed at the end of the containing div + tag. + + [< + The [_]{$ma} value of [`f(x)`] is [_]{$ma} for the function + [`f(x) = 4 - x^2`]. + >]{ [ class => 'ww-feedback-container' ] } + ENDPGML + ] + ], ), Examples( 'Inline formatting', @@ -981,7 +1033,8 @@ TEXT(tag( '[@ perl-command @]* (no escaping)', '[@ perl-command @]** (parse results)', '[% comment %]', - '[<url>] (not implemented)', + '[<tag>]{html}{tex}{ptx}', + '[[url]] (not implemented)', '[!image!]{source}{width}{height}', ), Menu( diff --git a/courses.dist/modelCourse/templates/PGMLLab b/courses.dist/modelCourse/templates/PGMLLab deleted file mode 120000 index bc34f0c25f..0000000000 --- a/courses.dist/modelCourse/templates/PGMLLab +++ /dev/null @@ -1 +0,0 @@ -../../../webwork2/assets/pg/PGMLLab \ No newline at end of file diff --git a/assets/pg/PGMLLab/webwork_logo.png b/htdocs/images/webwork_logo.png similarity index 100% rename from assets/pg/PGMLLab/webwork_logo.png rename to htdocs/images/webwork_logo.png diff --git a/htdocs/js/PGProblemEditor/pgproblemeditor.js b/htdocs/js/PGProblemEditor/pgproblemeditor.js index 86daeb8cb6..5f1771916f 100644 --- a/htdocs/js/PGProblemEditor/pgproblemeditor.js +++ b/htdocs/js/PGProblemEditor/pgproblemeditor.js @@ -536,7 +536,6 @@ /text\/html/.test(response.headers.get('content-type')) ) { throw await response.text(); - return; } const data = await response.blob(); @@ -564,4 +563,37 @@ rendering = false; } }; + + const pgmlLabButton = document.getElementById('pgml-lab'); + pgmlLabButton?.addEventListener('click', () => { + const form = document.createElement('form'); + form.style.display = 'none'; + form.target = 'PGML'; + form.action = renderURL; + form.method = 'post'; + + const inputs = [ + ['courseID', document.getElementsByName('courseID')[0]?.value], + ['displayMode', document.getElementById('action_view_displayMode_id')?.value ?? 'MathJax'], + ['fileName', 'PGMLLab/PGML-lab.pg'], + ['uriEncodedProblemSource', pgmlLabButton.dataset.source] + ]; + + const user = document.getElementsByName('user')[0]; + if (user) inputs.push(['user', user.value]); + const sessionKey = document.getElementsByName('key')[0]; + if (sessionKey) inputs.push(['key', sessionKey.value]); + + for (const [name, value] of inputs) { + const input = document.createElement('input'); + input.name = name; + input.value = value; + input.type = 'hidden'; + form.append(input); + } + + document.body.append(form); + form.submit(); + form.remove(); + }); })(); diff --git a/lib/FormatRenderedProblem.pm b/lib/FormatRenderedProblem.pm index 387b6aef04..8ebc3051e1 100644 --- a/lib/FormatRenderedProblem.pm +++ b/lib/FormatRenderedProblem.pm @@ -266,6 +266,7 @@ sub formatRenderedProblem { LTIGradeMessage => $LTIGradeMessage, sourceFilePath => $ws->{inputs_ref}{sourceFilePath} // '', problemSource => $ws->{inputs_ref}{problemSource} // '', + rawProblemSource => $ws->{inputs_ref}{rawProblemSource} // '', uriEncodedProblemSource => $ws->{inputs_ref}{uriEncodedProblemSource} // '', fileName => $ws->{inputs_ref}{fileName} // '', formLanguage => $formLanguage, diff --git a/lib/WeBWorK/ContentGenerator/RenderViaRPC.pm b/lib/WeBWorK/ContentGenerator/RenderViaRPC.pm index 262186eeca..8157353273 100644 --- a/lib/WeBWorK/ContentGenerator/RenderViaRPC.pm +++ b/lib/WeBWorK/ContentGenerator/RenderViaRPC.pm @@ -66,7 +66,8 @@ async sub pre_header_initialize ($c) { return; } - $c->param('displayMode', 'tex') if ($c->param('outputformat') eq 'pdf' || $c->param('outputformat') eq 'tex'); + $c->param('displayMode', 'tex') + if $c->param('outputformat') && ($c->param('outputformat') eq 'pdf' || $c->param('outputformat') eq 'tex'); # Call the WebworkWebservice to render the problem and store the result in $c->return_object. my $rpc_service = WebworkWebservice->new($c); diff --git a/lib/WebworkWebservice.pm b/lib/WebworkWebservice.pm index a9356aa183..14c7e4b959 100644 --- a/lib/WebworkWebservice.pm +++ b/lib/WebworkWebservice.pm @@ -174,7 +174,8 @@ otherwise. sub formatRenderedProblem { my $self = shift; return HardcopyRenderedProblem::hardcopyRenderedProblem($self) - if $self->{inputs_ref}{outputformat} eq 'tex' || $self->{inputs_ref}{outputformat} eq 'pdf'; + if $self->{inputs_ref}{outputformat} + && ($self->{inputs_ref}{outputformat} eq 'tex' || $self->{inputs_ref}{outputformat} eq 'pdf'); return FormatRenderedProblem::formatRenderedProblem($self); } diff --git a/lib/WebworkWebservice/RenderProblem.pm b/lib/WebworkWebservice/RenderProblem.pm index 98367ccdd1..8ccf5f21ff 100644 --- a/lib/WebworkWebservice/RenderProblem.pm +++ b/lib/WebworkWebservice/RenderProblem.pm @@ -24,10 +24,10 @@ use Mojo::Util qw(url_unescape); use WeBWorK::Debug; use WeBWorK::CourseEnvironment; -use WeBWorK::PG::IO; use WeBWorK::DB; use WeBWorK::DB::Utils qw(global2user fake_set fake_problem); use WeBWorK::Utils qw(decode_utf8_base64); +use WeBWorK::Utils::Files qw(readFile); use WeBWorK::Utils::Rendering qw(renderPG); our $UNIT_TESTS_ON = 0; @@ -190,7 +190,7 @@ async sub renderProblem { if ($rh->{problemSource}) { $r_problem_source = \(decode_utf8_base64($rh->{problemSource}) =~ tr/\r/\n/r); $problemRecord->source_file(defined $rh->{fileName} ? $rh->{fileName} : $rh->{sourceFilePath}); - } elsif (defined $rh->{rawProblemSource}) { + } elsif ($rh->{rawProblemSource}) { $r_problem_source = \$rh->{rawProblemSource}; $problemRecord->source_file(defined $rh->{fileName} ? $rh->{fileName} : $rh->{sourceFilePath}); } elsif ($rh->{uriEncodedProblemSource}) { @@ -198,9 +198,7 @@ async sub renderProblem { $problemRecord->source_file(defined $rh->{fileName} ? $rh->{fileName} : $rh->{sourceFilePath}); } elsif (defined $rh->{sourceFilePath} && $rh->{sourceFilePath} =~ /\S/) { $problemRecord->source_file($rh->{sourceFilePath}); - $r_problem_source = - \(WeBWorK::PG::IO::read_whole_file($ce->{courseDirs}{templates} . '/' . $rh->{sourceFilePath})); - $problemRecord->source_file('RenderProblemFooBar') unless defined($problemRecord->source_file); + $r_problem_source = \(readFile($ce->{courseDirs}{templates} . '/' . $rh->{sourceFilePath})); } if ($UNIT_TESTS_ON) { diff --git a/templates/ContentGenerator/Instructor/PGProblemEditor.html.ep b/templates/ContentGenerator/Instructor/PGProblemEditor.html.ep index 524ffff757..6c11e49345 100644 --- a/templates/ContentGenerator/Instructor/PGProblemEditor.html.ep +++ b/templates/ContentGenerator/Instructor/PGProblemEditor.html.ep @@ -1,6 +1,8 @@ % use Mojo::URL; +% use Mojo::Util qw(url_escape); % % use WeBWorK::Utils qw(not_blank x getAssetURL); +% use WeBWorK::Utils::Files qw(readFile); % use WeBWorK::Utils::Sets qw(format_set_name_display); % use WeBWorK::HTML::CodeMirrorEditor % qw(generate_codemirror_html generate_codemirror_controls_html output_codemirror_static_files); @@ -114,24 +116,16 @@ class => 'reference-link btn btn-sm btn-info', data => { bs_toggle => 'tooltip', bs_placement => 'top' } =%> % # PGML lab problem rendered as an unattached problem in a new window. - % if (-e "$ce->{courseDirs}{templates}/PGMLLab/PGML-lab.pg") { - <%= link_to maketext('PGML') => $c->systemLink( - url_for('problem_detail', setID => 'Undefined_Set', problemID => 1), - params => { - displayMode => $ce->{pg}{options}{displayMode}, - problemSeed => 1234, - editMode => 'temporaryFile', - sourceFilePath => 'PGMLLab/PGML-lab.pg' - } - ), - target => 'PGML', - title => maketext( - 'PG markdown syntax used to format WeBWorK questions. ' - . 'This interactive lab can help you to learn the techniques.' - ), - class => 'reference-link btn btn-sm btn-info', - data => { bs_toggle => 'tooltip', bs_placement => 'top' } =%> - % } + % my $pgml_lab_source = readFile("$ce->{webworkDirs}{assets}/pg/PGMLLab/PGML-lab.pg"); + <%= tag 'button', type => 'button', + title => maketext( + 'PG markdown syntax used to format WeBWorK questions. ' + . 'This interactive lab can help you to learn the techniques.' + ), + id => 'pgml-lab', + class => 'reference-link btn btn-sm btn-info', + data => { source => url_escape($pgml_lab_source), bs_toggle => 'tooltip', bs_placement => 'top' }, + 'PGML' =%> % # http://webwork.maa.org/wiki/Category:Authors <%= link_to maketext('Author Info') => $ce->{webworkURLs}{AuthorHelpURL}, target => 'author_info', diff --git a/templates/RPCRenderFormats/default.html.ep b/templates/RPCRenderFormats/default.html.ep index 638f3565e1..83a0ca949e 100644 --- a/templates/RPCRenderFormats/default.html.ep +++ b/templates/RPCRenderFormats/default.html.ep @@ -70,11 +70,12 @@ % %= hidden_field sourceFilePath => $sourceFilePath %= hidden_field problemSource => $problemSource + %= hidden_field rawProblemSource => $rawProblemSource %= hidden_field uriEncodedProblemSource => $uriEncodedProblemSource %= hidden_field problemSeed => $problemSeed %= hidden_field problemUUID => $problemUUID %= hidden_field psvn => $psvn - %= hidden_field pathToProblemFile => $fileName + %= hidden_field fileName => $fileName %= hidden_field courseID => $courseID %= hidden_field user => $user %= hidden_field passwd => $passwd