1
1
# This file is part of the QuestionPy SDK. (https://questionpy.org)
2
2
# The QuestionPy SDK is free software released under terms of the MIT license. See LICENSE.md.
3
3
# (c) Technische Universität Berlin, innoCampus <[email protected] >
4
-
4
+ import logging
5
5
import random
6
6
import re
7
7
from enum import StrEnum
24
24
from questionpy_server .worker import Worker
25
25
26
26
27
+ _log = logging .getLogger (__name__ )
28
+ _QPY_URL_PATTERN = re .compile (r"^qpy://static/([a-z_]\w{0,126})/([a-z_]\w{0,126})((?:/[\w\-@:%+.~=]+)+)$" )
29
+
30
+
27
31
class AttemptStatus (StrEnum ):
28
32
STARTED = "STARTED"
29
33
IN_PROGRESS = "IN_PROGRESS"
@@ -46,6 +50,7 @@ class AttemptTemplateContext(TypedDict):
46
50
display_options : QuestionDisplayOptions
47
51
import_map : dict [str , str ]
48
52
javascript_calls : list [JsModuleCall ]
53
+ stylesheet_urls : list [str ]
49
54
50
55
51
56
@dataclass
@@ -154,6 +159,7 @@ async def _render_ui(
154
159
"display_options" : display_options ,
155
160
"import_map" : await self ._get_import_map (),
156
161
"javascript_calls" : self ._get_js_calls (attempt , display_options ),
162
+ "stylesheet_urls" : self ._get_stylesheet_urls (attempt ),
157
163
}
158
164
159
165
render_errors : SectionErrorMap = {}
@@ -199,6 +205,26 @@ def _get_js_calls(self, attempt: AttemptModel, display_options: QuestionDisplayO
199
205
and (call .if_feedback_type is None or feedback_map [call .if_feedback_type ])
200
206
]
201
207
208
+ def _get_stylesheet_urls (self , attempt : AttemptModel ) -> list [str ]:
209
+ urls = []
210
+
211
+ for url in set (attempt .ui .css_files ):
212
+ if match := _QPY_URL_PATTERN .match (url ):
213
+ namespace , short_name , path = match .group (1 , 2 , 3 )
214
+ static_path = f"static{ path } "
215
+ api_url = self .generate_api_url ("file" , namespace = namespace , short_name = short_name , path = static_path )
216
+ urls .append (str (api_url ))
217
+ continue
218
+ if url .startswith ("qpy://" ):
219
+ _log .warning ("Stylesheet URL '%s' looks like a QPy-URL, but could not be parsed." , url )
220
+ continue
221
+ if not url .startswith ("https://" ):
222
+ _log .warning ("Stylesheet URL '%s' does not use a supported scheme." , url )
223
+ continue
224
+ urls .append (url )
225
+
226
+ return urls
227
+
202
228
@property
203
229
def _attempt_template (self ) -> jinja2 .Template :
204
230
loader = jinja2 .PackageLoader ("questionpy_sdk.webserver" )
0 commit comments