diff --git a/api/README.md b/api/README.md
index f944542edd0..d55f0b9fc08 100644
--- a/api/README.md
+++ b/api/README.md
@@ -67,6 +67,8 @@ can also be used. (See [Diff Route](#diff-route).) Any non-empty YAML will do e.
- `seed`: Seed to choose a question variant. Must be contained in the list of deployed variants. If
no seed is provided, the first deployed variant is used.
- `renderInputs`: String. Response will include HTML renders of the inputs if value other than ''. The input divs will have the value added as a prefix to their name attribute.
+- `fullRender`: Array consisting of a string prefix for validation divs and a string prefix for feedback divs e.g. `['validationprefix','feedbackprefix']` (`renderInputs` must also be set.) Response `questionrender` and `questionsamplesolutiontext` will be the full HTML render of the question with the inputs inserted in the correct place, full plot URLs, placeholders replaced with HTML and iframes included. Iframes will still need to be registered on the front
+end to be displayed properly. (`stackjsvle.js->register_iframe()` using the first array entry for each iframe in the response as the iframeid.)
- `readOnly`: boolean. Determines whether rendered inputs are read only.
The response is again a JSON document, with the following fields:
@@ -79,6 +81,7 @@ The response is again a JSON document, with the following fields:
- an int array `questionvariants` containing all variant seeds of the question
- an array of arrays `iframes` of arguments to create iframes to hold JS panels e.g. JSXGraph, GeoGebra
- a boolean field `isinteractive`, indicating if the question contains elements preventing a static representation. If true, a printed version of the question would make no sense
+- a string field `questionnote`, containing the rendered questionnote of the question
The input configuration consists of the following fields:
diff --git a/api/controller/RenderController.php b/api/controller/RenderController.php
index fcef706e31b..3e96258ff3e 100644
--- a/api/controller/RenderController.php
+++ b/api/controller/RenderController.php
@@ -45,7 +45,6 @@ class RenderController {
public function __invoke(Request $request, Response $response, array $args): Response {
// TO-DO: Validate.
$data = $request->getParsedBody();
-
$question = StackQuestionLoader::loadxml($data["questionDefinition"])['question'];
StackSeedHelper::initialize_seed($question, $data["seed"]);
@@ -134,15 +133,66 @@ public function __invoke(Request $request, Response $response, array $args): Res
// Necessary, as php will otherwise encode this as an empty array, instead of an empty object.
$renderresponse->questioninputs = (object) $inputs;
-
- $renderresponse->questionassets = (object) $plots;
-
$renderresponse->questionseed = $question->seed;
$renderresponse->questionvariants = $question->deployedseeds;
$renderresponse->iframes = StackIframeHolder::$iframes;
$renderresponse->isinteractive = $question->is_interactive();
+ $renderresponse->questionnote = $question->get_question_summary();
+ StackPlotReplacer::replace_plots($plots, $renderresponse->questionnote, "note-" . $name, $storeprefix);
+ $renderresponse->questionassets = (object) $plots;
+
+ if (!empty($data['fullRender'])) {
+ // Request for full rendering. We replace placeholders with input renders and basic feedback and validation divs.
+ // Iframes are rendered but will still need to be registered on the front end.
+ $uri = $request->getUri();
+ $baseurl = $uri->getScheme() . '://' . $uri->getHost();
+ $port = $uri->getPort();
+ if ($port && !in_array($port, [80, 443], true)) {
+ $baseurl .= ':' . $port;
+ }
+
+ [$validationprefix, $feedbackprefix] = $data['fullRender'];
+ $validationprefix = trim($validationprefix);
+ $feedbackprefix = trim($feedbackprefix);
+ preg_match_all('/\[\[input:([^\]]*)\]\]/', $renderresponse->questionrender, $inputtags);
+ foreach ($inputtags[1] as $tag) {
+ $renderresponse->questionrender = str_replace("[[input:{$tag}]]", $renderresponse->questioninputs->$tag->render, $renderresponse->questionrender);
+ $renderresponse->questionrender = str_replace("[[validation:{$tag}]]", "", $renderresponse->questionrender);
+ }
+ foreach ($renderresponse->iframes as $iframe) {
+ $iframe[1] = str_replace('