From 5f9d7e31c92680c87baed0d9b812784b41d32a68 Mon Sep 17 00:00:00 2001
From: nievax
Date: Mon, 21 Oct 2024 10:02:42 +0200
Subject: [PATCH 1/8] Update utils.py
add function inject_textblocks(); it makes it possible to inject templates into freetext fields via Markdown
---
rdmo/core/utils.py | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/rdmo/core/utils.py b/rdmo/core/utils.py
index 155109c6d..0cee6221f 100644
--- a/rdmo/core/utils.py
+++ b/rdmo/core/utils.py
@@ -9,7 +9,7 @@
from django.conf import settings
from django.http import Http404, HttpResponse, HttpResponseBadRequest
-from django.template.loader import get_template
+from django.template.loader import get_template, render_to_string
from django.utils.dateparse import parse_date
from django.utils.encoding import force_str
from django.utils.formats import get_format
@@ -267,6 +267,18 @@ def markdown2html(markdown_string):
f' ({hide_string})
',
html
)
+ html = inject_textblocks(html)
+ return html
+
+
+def inject_textblocks(html):
+ '''textblocks (e.g. for help texts) can be injected into free text fields as small templates via Markdown'''
+ for textblock_id in re.findall(r'{{(.*?)}}', html): # strings between curly brackets
+ template_path: str = settings.MARKDOWN_TEMPLATES[textblock_id]
+ html = re.sub( '{{' + textblock_id + '}}',
+ render_to_string(template_path),
+ html
+ )
return html
From 7b32f9ed37568b172c107048f23b8de8d2de34c9 Mon Sep 17 00:00:00 2001
From: Axel Nieder-Vahrenholz
Date: Wed, 23 Oct 2024 09:11:02 +0200
Subject: [PATCH 2/8] set data type for MARKDOWN_TEMPLATES
---
rdmo/core/settings.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/rdmo/core/settings.py b/rdmo/core/settings.py
index aaa3fa80e..7af016d94 100644
--- a/rdmo/core/settings.py
+++ b/rdmo/core/settings.py
@@ -415,3 +415,7 @@
# necessary since django 3.2, explicitly set primary key type to avoid warnings
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+
+MARKDOWN_TEMPLATES: dict[str, str] = {
+ # for example: 'not_empty': 'core/text_blocks/template_for_not_empty.html',
+}
From f7285aada1d50cc00b14d962162804f6e34e6504 Mon Sep 17 00:00:00 2001
From: Jochen Klar
Date: Thu, 20 Feb 2025 14:11:49 +0100
Subject: [PATCH 3/8] Slightly refactor inject_textblocks
---
rdmo/core/settings.py | 4 ++++
rdmo/core/utils.py | 15 ++++++++-------
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/rdmo/core/settings.py b/rdmo/core/settings.py
index 7af016d94..29169f9bb 100644
--- a/rdmo/core/settings.py
+++ b/rdmo/core/settings.py
@@ -309,6 +309,10 @@
EXPORT_MIN_REQUIRED_VERSION = '2.1.0'
+MARKDOWN_TEMPLATES: dict[str, str] = {
+ # for example: 'not_empty': 'core/text_blocks/template_for_not_empty.html',
+}
+
PROJECT_TABLE_PAGE_SIZE = 20
PROJECT_VISIBILITY = True
diff --git a/rdmo/core/utils.py b/rdmo/core/utils.py
index 0cee6221f..0f9861347 100644
--- a/rdmo/core/utils.py
+++ b/rdmo/core/utils.py
@@ -267,18 +267,19 @@ def markdown2html(markdown_string):
f' ({hide_string})',
html
)
+
+ # textblocks (e.g. for help texts) can be injected into free text fields as small templates via Markdown
html = inject_textblocks(html)
+
return html
def inject_textblocks(html):
- '''textblocks (e.g. for help texts) can be injected into free text fields as small templates via Markdown'''
- for textblock_id in re.findall(r'{{(.*?)}}', html): # strings between curly brackets
- template_path: str = settings.MARKDOWN_TEMPLATES[textblock_id]
- html = re.sub( '{{' + textblock_id + '}}',
- render_to_string(template_path),
- html
- )
+ # loop over all strings between curly brackets, e.g. {{ test }}
+ for template_code in re.findall(r'{{(.*?)}}', html):
+ template_name = settings.MARKDOWN_TEMPLATES.get(template_code.strip())
+ if template_name:
+ html = re.sub('{{' + template_code + '}}', render_to_string(template_name), html)
return html
From f526b9376c4c5ad2c803cff44eca422cd71fb804 Mon Sep 17 00:00:00 2001
From: Jochen Klar
Date: Thu, 20 Feb 2025 14:49:41 +0100
Subject: [PATCH 4/8] Add useLayoutEffect to execute containing scripts to HTML
component
---
rdmo/core/assets/js/components/Html.js | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/rdmo/core/assets/js/components/Html.js b/rdmo/core/assets/js/components/Html.js
index acd13bbd2..f2400afb2 100644
--- a/rdmo/core/assets/js/components/Html.js
+++ b/rdmo/core/assets/js/components/Html.js
@@ -1,10 +1,28 @@
-import React from 'react'
+import React, { useRef, useLayoutEffect } from 'react'
import PropTypes from 'prop-types'
import { isEmpty } from 'lodash'
const Html = ({ html = '' }) => {
+ const ref = useRef()
+
+ // if html contains any element with `data-execute="true"`, it will be executed
+ // using the method in https://macarthur.me/posts/script-tags-in-react/
+ useLayoutEffect(() => {
+ if (ref.current && !isEmpty(ref.current.querySelectorAll('[data-execute="true"]'))) {
+ // create a range objectm, set it contain the referenced node
+ // and create a new fragment with the html code within that range
+ const range = document.createRange()
+ range.selectNode(ref.current)
+ const documentFragment = range.createContextualFragment(html)
+
+ // remove the rendered html and inject it again, triggering a re-run of the JS code
+ ref.current.innerHTML = ''
+ ref.current.append(documentFragment)
+ }
+ }, [html])
+
return !isEmpty(html) && (
-
+
)
}
From 279e92b185adb45d4c9924dbf9967c805f23dfb4 Mon Sep 17 00:00:00 2001
From: Jochen Klar
Date: Tue, 25 Feb 2025 12:13:50 +0100
Subject: [PATCH 5/8] Add TEMPLATES_EXECUTE_SCRIPT_TAGS to settings to control
JS execution within React
---
rdmo/core/assets/js/components/Html.js | 9 ++++++---
rdmo/core/assets/js/utils/meta.js | 2 ++
rdmo/core/settings.py | 9 ++++-----
rdmo/projects/templates/projects/project_interview.html | 3 ++-
4 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/rdmo/core/assets/js/components/Html.js b/rdmo/core/assets/js/components/Html.js
index f2400afb2..464683114 100644
--- a/rdmo/core/assets/js/components/Html.js
+++ b/rdmo/core/assets/js/components/Html.js
@@ -2,13 +2,16 @@ import React, { useRef, useLayoutEffect } from 'react'
import PropTypes from 'prop-types'
import { isEmpty } from 'lodash'
+import { executeScriptTags } from 'rdmo/core/assets/js/utils/meta'
+
+
const Html = ({ html = '' }) => {
const ref = useRef()
- // if html contains any element with `data-execute="true"`, it will be executed
- // using the method in https://macarthur.me/posts/script-tags-in-react/
+ // if html contains a