From 64d2ba2558b0147cc42e258c2fc34776e41a328a Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Tue, 1 Feb 2022 16:11:34 +0000 Subject: [PATCH] Run tidy as part of tests, and fix HTML issues it finds. - Legacy-Id: 19904 --- docker/app.Dockerfile | 1 + ietf/doc/utils.py | 6 +- ietf/doc/views_ballot.py | 12 +- ietf/doc/views_bofreq.py | 4 +- ietf/doc/views_charter.py | 11 +- ietf/doc/views_conflict_review.py | 11 +- ietf/doc/views_status_change.py | 7 +- ietf/secr/meetings/tests.py | 4 +- ietf/secr/templates/base_secr.html | 9 +- ietf/secr/templates/base_secr_bootstrap.html | 6 - ietf/secr/templates/groups/search.html | 6 +- .../includes/sessions_request_form.html | 2 +- .../templates/includes/upload_footer.html | 3 +- ietf/secr/templates/main.html | 42 +- ietf/secr/templates/meetings/add.html | 6 +- ietf/secr/templates/meetings/main.html | 8 +- .../templates/meetings/misc_session_edit.html | 2 +- .../templates/meetings/misc_sessions.html | 3 +- .../meetings/regular_session_edit.html | 24 +- ietf/secr/templates/meetings/rooms.html | 10 +- ietf/secr/templates/meetings/times.html | 1 - ietf/secr/templates/roles/main.html | 8 +- ietf/secr/templates/rolodex/edit.html | 9 +- ietf/secr/templates/rolodex/view.html | 6 +- ietf/secr/templates/sreq/edit.html | 12 +- ietf/secr/templates/sreq/new.html | 12 +- .../templates/telechat/base_telechat.html | 5 +- ietf/secr/templates/telechat/doc.html | 4 +- ietf/secr/templates/telechat/main.html | 4 +- ietf/static/css/list.scss | 2 + ietf/static/js/ietf.js | 10 +- ietf/templates/api/index.html | 16 +- ietf/templates/base.html | 2 +- ietf/templates/base/menu.html | 730 +++++++++--------- ietf/templates/base/menu_active_groups.html | 4 +- ietf/templates/base/menu_user.html | 476 +++++------- ietf/templates/base/menu_wg.html | 2 +- ietf/templates/debug.html | 2 +- .../doc/add_sessionpresentation.html | 4 +- ietf/templates/doc/ballot/edit_position.html | 6 +- .../doc/ballot/irsg_ballot_approve.html | 2 +- ietf/templates/doc/ballot_popup.html | 4 +- ietf/templates/doc/bofreq/bof_requests.html | 2 +- ietf/templates/doc/bofreq/new_bofreq.html | 2 +- ietf/templates/doc/bofreq/upload_content.html | 2 +- .../doc/charter/action_announcement_text.html | 2 +- .../doc/charter/review_announcement_text.html | 5 +- .../doc/document_conflict_review.html | 2 +- ietf/templates/doc/downref_add.html | 2 +- ietf/templates/doc/draft/change_stream.html | 2 +- .../doc/draft/review_possibly_replaces.html | 2 +- .../templates/doc/drafts_in_iesg_process.html | 2 +- ietf/templates/doc/htmlized_base.html | 1 - ietf/templates/doc/search/search.html | 3 + .../doc/search/search_result_row.html | 4 +- ietf/templates/doc/search/search_results.html | 8 +- ietf/templates/doc/status_change/start.html | 2 +- ietf/templates/doc/submit_to_iesg.html | 2 - ietf/templates/group/active_adm.html | 2 +- ietf/templates/group/active_areas.html | 14 +- ietf/templates/group/active_review_dirs.html | 12 +- .../group/change_reviewer_settings.html | 10 +- ietf/templates/group/concluded_groups.html | 6 +- ietf/templates/group/customize_workflow.html | 4 +- .../group/group_about_rendertest.html | 3 +- ietf/templates/group/index.html | 8 +- .../group/manage_review_requests.html | 2 +- ietf/templates/group/review_requests.html | 14 +- ietf/templates/group/reviewer_overview.html | 3 +- ietf/templates/meeting/interim_pending.html | 4 +- ietf/templates/stats/review_stats.html | 31 +- ietf/templates/submit/edit_submission.html | 6 +- ietf/templates/submit/email.html | 2 +- ietf/templates/submit/submission_status.html | 2 +- ietf/templates/submit/upload_submission.html | 1 - ietf/utils/test_utils.py | 43 +- package-lock.json | 130 ++-- requirements.txt | 3 +- 78 files changed, 882 insertions(+), 959 deletions(-) diff --git a/docker/app.Dockerfile b/docker/app.Dockerfile index fba65eee7..5d67868c9 100644 --- a/docker/app.Dockerfile +++ b/docker/app.Dockerfile @@ -38,6 +38,7 @@ RUN apt-get install -qy \ less \ libmagic-dev \ libmariadb-dev \ + libtidy-dev \ locales \ mariadb-client \ netcat \ diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index d266cdbf9..b6af654ef 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -363,7 +363,7 @@ def add_links_in_new_revision_events(doc, events, diff_revisions): links += "" if prev != None: - links += ' (diff from previous)' % (settings.RFCDIFF_BASE_URL, quote(prev, safe="~"), quote(diff_url, safe="~")) + links += ' (diff from previous)' % (settings.RFCDIFF_BASE_URL, quote(prev, safe="~"), quote(diff_url, safe="~")) # replace the bold filename part e.desc = re.sub(r"(.+-[0-9][0-9].txt)", links, e.desc) @@ -1087,7 +1087,7 @@ def build_doc_supermeta_block(doc): items.append(f'[WG]') items.append(f'[Email]') if doc.rev != "00": - items.append(f'[Diff1]') + items.append(f'[Diff1]') items.append(f'[Diff2]') items.append(f'[Nits]') @@ -1321,4 +1321,4 @@ def fuzzy_find_documents(name, rev=None): rev = None # found a doc by name with rev = None, so update that FoundDocuments = namedtuple('FoundDocuments', 'documents matched_name matched_rev') - return FoundDocuments(docs, name, rev) + return FoundDocuments(docs, name, rev) \ No newline at end of file diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index be9223b78..6841e07f5 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -14,7 +14,7 @@ from django.template.defaultfilters import striptags from django.template.loader import render_to_string from django.urls import reverse as urlreverse from django.views.decorators.csrf import csrf_exempt - +from django.utils.html import escape import debug # pyflakes:ignore @@ -527,7 +527,7 @@ def lastcalltext(request, name): if not existing: existing = generate_last_call_announcement(request, doc) - form = LastCallTextForm(initial=dict(last_call_text=existing.text)) + form = LastCallTextForm(initial=dict(last_call_text=escape(existing.text))) if request.method == 'POST': if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST: @@ -612,7 +612,7 @@ def ballot_writeupnotes(request, name): if not existing: existing = generate_ballot_writeup(request, doc) - form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text)) + form = BallotWriteupForm(initial=dict(ballot_writeup=escape(existing.text))) if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST: form = BallotWriteupForm(request.POST) @@ -727,7 +727,7 @@ def ballot_rfceditornote(request, name): if not existing or (existing.text == ""): existing = generate_ballot_rfceditornote(request, doc) - form = BallotRfcEditorNoteForm(auto_id=False, initial=dict(rfc_editor_note=existing.text)) + form = BallotRfcEditorNoteForm(auto_id=False, initial=dict(rfc_editor_note=escape(existing.text))) if request.method == 'POST' and "save_ballot_rfceditornote" in request.POST: form = BallotRfcEditorNoteForm(request.POST) @@ -791,7 +791,7 @@ def ballot_approvaltext(request, name): if not existing: existing = generate_approval_mail(request, doc) - form = ApprovalTextForm(initial=dict(approval_text=existing.text)) + form = ApprovalTextForm(initial=dict(approval_text=escape(existing.text))) if request.method == 'POST': if "save_approval_text" in request.POST: @@ -1206,4 +1206,4 @@ def irsg_ballot_status(request): docs.append(doc) - return render(request, 'doc/irsg_ballot_status.html', {'docs':docs}) + return render(request, 'doc/irsg_ballot_status.html', {'docs':docs}) \ No newline at end of file diff --git a/ietf/doc/views_bofreq.py b/ietf/doc/views_bofreq.py index 28b549537..8ce066670 100644 --- a/ietf/doc/views_bofreq.py +++ b/ietf/doc/views_bofreq.py @@ -10,7 +10,7 @@ from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404, redirect, render from django.template.loader import render_to_string from django.urls import reverse as urlreverse - +from django.utils.html import escape from ietf.doc.mails import (email_bofreq_title_changed, email_bofreq_editors_changed, email_bofreq_new_revision, email_bofreq_responsible_changed) @@ -172,7 +172,7 @@ def new_bof_request(request): return redirect('ietf.doc.views_doc.document_main', name=bofreq.name) else: - init = {'bofreq_content':render_to_string('doc/bofreq/bofreq_template.md',{}), + init = {'bofreq_content':escape(render_to_string('doc/bofreq/bofreq_template.md',{})), 'bofreq_submission':'enter', } form = NewBofreqForm(initial=init) diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 447c72889..29cfa7f8e 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -17,6 +17,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import login_required from django.utils.encoding import force_text +from django.utils.html import escape import debug # pyflakes:ignore @@ -507,7 +508,7 @@ def review_announcement_text(request, name): existing_new_work.text = derive_new_work_text(existing.text,group) existing_new_work.time = datetime.datetime.now() - form = ReviewAnnouncementTextForm(initial=dict(announcement_text=existing.text,new_work_text=existing_new_work.text)) + form = ReviewAnnouncementTextForm(initial=dict(announcement_text=escape(existing.text),new_work_text=escape(existing_new_work.text))) if request.method == 'POST': form = ReviewAnnouncementTextForm(request.POST) @@ -588,7 +589,7 @@ def action_announcement_text(request, name): if not existing: raise Http404 - form = ActionAnnouncementTextForm(initial=dict(announcement_text=existing.text)) + form = ActionAnnouncementTextForm(initial=dict(announcement_text=escape(existing.text))) if request.method == 'POST': form = ActionAnnouncementTextForm(request.POST) @@ -650,7 +651,7 @@ def ballot_writeupnotes(request, name): reissue = charter.latest_event(DocEvent, type="sent_ballot_announcement") - form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text)) + form = BallotWriteupForm(initial=dict(ballot_writeup=escape(existing.text))) if request.method == 'POST' and ("save_ballot_writeup" in request.POST or "send_ballot" in request.POST): form = BallotWriteupForm(request.POST) @@ -802,7 +803,7 @@ def approve(request, name): return render(request, 'doc/charter/approve.html', dict(charter=charter, - announcement=announcement)) + announcement=escape(announcement))) def charter_with_milestones_txt(request, name, rev): charter = get_object_or_404(Document, type="charter", docalias__name=name) @@ -833,4 +834,4 @@ def charter_with_milestones_txt(request, name, rev): return render(request, 'doc/charter/charter_with_milestones.txt', dict(charter_text=charter_text, milestones=milestones), - content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET) + content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET) \ No newline at end of file diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index 85a5a9a72..e42c13872 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -12,6 +12,7 @@ from django.http import HttpResponseRedirect, Http404 from django.urls import reverse from django.template.loader import render_to_string from django.conf import settings +from django.utils.html import escape import debug # pyflakes:ignore @@ -215,7 +216,7 @@ def submit(request, name): elif "reset_text" in request.POST: - init = { "content": render_to_string("doc/conflict_review/review_choices.txt",dict())} + init = { "content": escape(render_to_string("doc/conflict_review/review_choices.txt",dict()))} form = UploadForm(initial=init) # Protect against handcrufted malicious posts @@ -229,9 +230,9 @@ def submit(request, name): init = { "content": ""} if not_uploaded_yet: - init["content"] = render_to_string("doc/conflict_review/review_choices.txt", + init["content"] = escape(render_to_string("doc/conflict_review/review_choices.txt", dict(), - ) + )) else: filename = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (review.canonical_name(), review.rev)) try: @@ -358,7 +359,7 @@ def approve_conflict_review(request, name): else: - init = { "announcement_text" : default_approval_text(review) } + init = { "announcement_text" : escape(default_approval_text(review)) } form = AnnouncementForm(initial=init) return render(request, 'doc/conflict_review/approve.html', @@ -522,4 +523,4 @@ def start_review_as_stream_owner(request, name): {'form': form, 'doc_to_review': doc_to_review, }, - ) + ) \ No newline at end of file diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index eb1d93e12..2484d8645 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -16,6 +16,7 @@ from django.urls import reverse from django.template.loader import render_to_string from django.conf import settings from django.utils.encoding import force_text +from django.utils.html import escape import debug # pyflakes:ignore from ietf.doc.mails import email_ad_approved_status_change @@ -396,7 +397,7 @@ def approve(request, name): init = [] for rel in status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS): - init.append({"announcement_text" : default_approval_text(status_change,rel), + init.append({"announcement_text" : escape(default_approval_text(status_change,rel)), "label": "Announcement text for %s to %s"%(rel.target.document.canonical_name(),newstatus(rel)), }) formset = AnnouncementFormSet(initial=init) @@ -674,7 +675,7 @@ def last_call(request, name): if not last_call_event: last_call_event = generate_last_call_text(request, status_change) - form = LastCallTextForm(initial=dict(last_call_text=last_call_event.text)) + form = LastCallTextForm(initial=dict(last_call_text=escape(last_call_event.text))) if request.method == 'POST': if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST: @@ -724,4 +725,4 @@ def last_call(request, name): last_call_form = form, ), ) - + \ No newline at end of file diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py index 5c440802b..c6576a0cc 100644 --- a/ietf/secr/meetings/tests.py +++ b/ietf/secr/meetings/tests.py @@ -244,7 +244,7 @@ class SecrMeetingTestCase(TestCase): response = self.client.get(url) self.assertEqual(response.status_code, 200) q = PyQuery(response.content) - self.assertEqual(len(q("#id_rooms_table tr input[type='checkbox']")),meeting.room_set.count()) + self.assertEqual(len(q("#id_rooms_table tr input[type='checkbox']")),meeting.room_set.count()+1) # test delete # first unschedule sessions so we can delete @@ -441,4 +441,4 @@ class SecrMeetingTestCase(TestCase): times = get_times(meeting,day) values = [ x[0] for x in times ] self.assertTrue(times) - self.assertTrue(timeslot.time.strftime('%H%M') in values) + self.assertTrue(timeslot.time.strftime('%H%M') in values) \ No newline at end of file diff --git a/ietf/secr/templates/base_secr.html b/ietf/secr/templates/base_secr.html index 95d16f0db..d4ba1fa5d 100644 --- a/ietf/secr/templates/base_secr.html +++ b/ietf/secr/templates/base_secr.html @@ -52,17 +52,11 @@ {% endif %} - {% comment %} - - - - {% endcomment %} - {% if messages %} {% endif %} @@ -83,6 +77,5 @@ {% block footer %}{% endblock %} - \ No newline at end of file diff --git a/ietf/secr/templates/base_secr_bootstrap.html b/ietf/secr/templates/base_secr_bootstrap.html index 653aa98b9..35f9b9dbb 100644 --- a/ietf/secr/templates/base_secr_bootstrap.html +++ b/ietf/secr/templates/base_secr_bootstrap.html @@ -53,12 +53,6 @@ {% endif %} - {% comment %} - - - - {% endcomment %} - {% if messages %} - {% endblock %} \ No newline at end of file diff --git a/ietf/secr/templates/roles/main.html b/ietf/secr/templates/roles/main.html index a07cc7a0b..84db0c85d 100755 --- a/ietf/secr/templates/roles/main.html +++ b/ietf/secr/templates/roles/main.html @@ -40,13 +40,12 @@ {% block content %}
+
{% csrf_token %}

Role Tool


@@ -61,20 +60,19 @@

Add Role

{% with role_form as form %} -
{% csrf_token %} {{ role_form.non_field_errors }} - {{ form.group_acronym.errors }}{{ form.group_acronym }} +
{{ form.group_acronym.errors }}{{ form.group_acronym }} {{ form.name.errors }}{{ form.name }} {{ form.person.errors }}{{ form.person }}{% if form.person.help_text %}
{{ form.person.help_text }}{% endif %}
{{ form.email.errors }}{{ form.email }}{% if form.email.help_text %}
{{ form.email.help_text }}{% endif %}
-
{% endwith %}
+
{% endif %} diff --git a/ietf/templates/doc/downref_add.html b/ietf/templates/doc/downref_add.html index 0d8c01c75..efb5a4fe6 100644 --- a/ietf/templates/doc/downref_add.html +++ b/ietf/templates/doc/downref_add.html @@ -30,7 +30,7 @@ {% endif %} {% endfor %} Cancel + href="{% url "ietf.doc.views_downref.downref_registry" %}">Back

{% endblock %} diff --git a/ietf/templates/doc/draft/change_stream.html b/ietf/templates/doc/draft/change_stream.html index efa0ebee1..243550d75 100644 --- a/ietf/templates/doc/draft/change_stream.html +++ b/ietf/templates/doc/draft/change_stream.html @@ -1,4 +1,4 @@ -[# bs5ok #} +{# bs5ok #} {% extends "base.html" %} {# Copyright The IETF Trust 2015, All Rights Reserved #} {% load origin %} diff --git a/ietf/templates/doc/draft/review_possibly_replaces.html b/ietf/templates/doc/draft/review_possibly_replaces.html index 81891d468..55620eedf 100644 --- a/ietf/templates/doc/draft/review_possibly_replaces.html +++ b/ietf/templates/doc/draft/review_possibly_replaces.html @@ -10,7 +10,7 @@
{% csrf_token %} {% bootstrap_form form %} - Cancel + Back
{% endblock %} \ No newline at end of file diff --git a/ietf/templates/doc/drafts_in_iesg_process.html b/ietf/templates/doc/drafts_in_iesg_process.html index c1a78e946..611abb4b7 100644 --- a/ietf/templates/doc/drafts_in_iesg_process.html +++ b/ietf/templates/doc/drafts_in_iesg_process.html @@ -56,7 +56,7 @@
Action holder{{ doc.documentactionholder_set.all|pluralize }}: {% for action_holder in doc.documentactionholder_set.all %} - {% person_link action_holder.person title=action_holder.role_for_doc %} {{ action_holder|action_holder_badge }} + {% person_link action_holder.person title=action_holder.role_for_doc %} {{ action_holder|action_holder_badge }} {% if not forloop.last %},{% endif %} {% endfor %} {% endif %} diff --git a/ietf/templates/doc/htmlized_base.html b/ietf/templates/doc/htmlized_base.html index ea9be250d..03e3e7479 100644 --- a/ietf/templates/doc/htmlized_base.html +++ b/ietf/templates/doc/htmlized_base.html @@ -143,7 +143,6 @@ {% block content_end %}{% endblock %} {% block footer %}{% endblock %} - {% block js %}{% endblock %} \ No newline at end of file diff --git a/ietf/templates/doc/search/search.html b/ietf/templates/doc/search/search.html index 3ac8f3c6f..5dd4dee55 100644 --- a/ietf/templates/doc/search/search.html +++ b/ietf/templates/doc/search/search.html @@ -2,6 +2,9 @@ {% extends "base.html" %} {# Copyright The IETF Trust 2015, All Rights Reserved #} {% load origin static %} +{% block pagehead %} + +{% endblock %} {% block title %}Document Search{% endblock %} {% block content %} {% origin %} diff --git a/ietf/templates/doc/search/search_result_row.html b/ietf/templates/doc/search/search_result_row.html index 75d1804ab..69f1b5cfc 100644 --- a/ietf/templates/doc/search/search_result_row.html +++ b/ietf/templates/doc/search/search_result_row.html @@ -7,7 +7,7 @@ {% load ballot_icon %} {% load person_filters %} {% load django_bootstrap5 %} - {% elif doc.replaces %} - + {% endif %} {% endif %} {% if doc.get_state_slug == "rfc" %} diff --git a/ietf/templates/doc/search/search_results.html b/ietf/templates/doc/search/search_results.html index 39fb75bba..39ec343eb 100644 --- a/ietf/templates/doc/search/search_results.html +++ b/ietf/templates/doc/search/search_results.html @@ -3,9 +3,6 @@ {% load origin %} {% origin %} {% load ietf_filters static %} -{% block pagehead %} - -{% endblock %} {% if not docs %} {% if not skip_no_matches_warning %}
No documents match your query.
{% endif %} {% endif %} @@ -62,7 +59,4 @@ {% endfor %} {% endfor %} -{% if end_table %}{% endif %} -{% block js %} - -{% endblock %} \ No newline at end of file +{% if end_table %}{% endif %} \ No newline at end of file diff --git a/ietf/templates/doc/status_change/start.html b/ietf/templates/doc/status_change/start.html index c1fcc77bd..0c3326e83 100644 --- a/ietf/templates/doc/status_change/start.html +++ b/ietf/templates/doc/status_change/start.html @@ -23,7 +23,7 @@ class="btn btn-primary" name="submit_response" value="Submit">Submit -
Back + Back {% endblock %} {% block js %} diff --git a/ietf/templates/doc/submit_to_iesg.html b/ietf/templates/doc/submit_to_iesg.html index 2c9218746..425fd4bb6 100644 --- a/ietf/templates/doc/submit_to_iesg.html +++ b/ietf/templates/doc/submit_to_iesg.html @@ -81,7 +81,6 @@ indicates the document might not be ready for submission. Please check each instance carefully to see if changes need to be made to the document's state before submitting.

{% endif %} -

Upon submission:

-

{% csrf_token %} - + Active {% firstof grouptype.grouper.verbose_name grouptype.grouper.name 'Top-level Administration' %} diff --git a/ietf/templates/group/active_areas.html b/ietf/templates/group/active_areas.html index b68df0140..8bc4f360d 100644 --- a/ietf/templates/group/active_areas.html +++ b/ietf/templates/group/active_areas.html @@ -36,14 +36,14 @@

The IESG decides which areas working groups belong to. The charter of each area is listed below: -

+ {% for area in areas %}

{{ area.name }} diff --git a/ietf/templates/group/active_review_dirs.html b/ietf/templates/group/active_review_dirs.html index 5d8deb6d5..aee428f54 100644 --- a/ietf/templates/group/active_review_dirs.html +++ b/ietf/templates/group/active_review_dirs.html @@ -12,12 +12,12 @@ - - - - - - + + + + + + diff --git a/ietf/templates/group/change_reviewer_settings.html b/ietf/templates/group/change_reviewer_settings.html index 7928beb82..0a8f3fb00 100644 --- a/ietf/templates/group/change_reviewer_settings.html +++ b/ietf/templates/group/change_reviewer_settings.html @@ -94,7 +94,7 @@

History of settings

-
+
TeamNameAreaADSecretariesChairsTeamNameAreaADSecretariesChairs
@@ -115,15 +115,15 @@

History of unavailable periods

-
+
- - + - diff --git a/ietf/templates/group/concluded_groups.html b/ietf/templates/group/concluded_groups.html index 9b48eba28..45f7813d2 100644 --- a/ietf/templates/group/concluded_groups.html +++ b/ietf/templates/group/concluded_groups.html @@ -13,7 +13,7 @@ Note that the information on historical groups may be inaccurate.

{% for label, groups in sections.items %} -

{{ label }}

+

{{ label }}

{% if label == "WGs" %} {% elif label == "RGs" %}

@@ -24,8 +24,8 @@

{% endif %} {% if not groups %} -

- No groups found. +

+ No groups found.

{% else %} {% regroup groups by parent as grouped_by_areas %} diff --git a/ietf/templates/group/customize_workflow.html b/ietf/templates/group/customize_workflow.html index bd7f205b4..8d43703b4 100644 --- a/ietf/templates/group/customize_workflow.html +++ b/ietf/templates/group/customize_workflow.html @@ -76,8 +76,8 @@ {% for checked, default, s in state.next_states_checkboxes %}
- -
Date + Date By + Description
- - - + + + + + {% for stream in streams %} diff --git a/ietf/templates/group/manage_review_requests.html b/ietf/templates/group/manage_review_requests.html index cf8c79937..bd88cbadf 100644 --- a/ietf/templates/group/manage_review_requests.html +++ b/ietf/templates/group/manage_review_requests.html @@ -101,7 +101,7 @@ -{{ alatest.reviewed_rev }} {% if alatest.reviewed_rev != r.doc.rev %} - (diff) + (diff) {% endif %} : diff --git a/ietf/templates/group/review_requests.html b/ietf/templates/group/review_requests.html index 25cebb47b..bb7a282a3 100644 --- a/ietf/templates/group/review_requests.html +++ b/ietf/templates/group/review_requests.html @@ -17,7 +17,7 @@ {% endif %} -

Unassigned and open review requests and assignments

+

Unassigned and open review requests and assignments

StreamOwnerStream manager
StreamOwnerStream manager
@@ -33,7 +33,7 @@ {% if unassigned_review_requests %} - + @@ -84,7 +84,7 @@ {% if open_review_assignments %} - + @@ -166,7 +166,7 @@ {% if closed_review_requests %} - @@ -206,7 +206,7 @@ {% if closed_review_assignments %} - @@ -244,8 +244,8 @@ {% endfor %} -
Unassigned review requestsUnassigned review requests
Open review requestsOpen review requests
+ Closed review requests
+ Closed review assignments
- {% endif %} + {% endif %} + {% endblock %} {% block js %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/ietf/templates/stats/review_stats.html b/ietf/templates/stats/review_stats.html index 9458d36d4..b1f93b0e8 100644 --- a/ietf/templates/stats/review_stats.html +++ b/ietf/templates/stats/review_stats.html @@ -139,6 +139,7 @@

Completion status and completion time

+ + {% for row in data %} - {% if forloop.first %} - {% elif forloop.last %} - - + {% if forloop.last %} + + {% endif %} @@ -193,7 +194,7 @@ {% endfor %} - +
{% if level == "team" %} Team @@ -167,13 +168,13 @@ Avg. compl. days {% if count == "pages" %}/page{% endif %}
{{ row.obj }}
{% elif stats_type == "results" %}

@@ -201,6 +202,7 @@

+ {% endfor %} + {% for row in data %} - {% if forloop.first %} - {% elif forloop.last %} - - + {% if forloop.last %} + + {% endif %}
{% if level == "team" %} Team @@ -213,13 +215,13 @@ {{ r.name }}
@@ -240,6 +242,7 @@ + {% endfor %} + {% for row in data %} - {% if forloop.first %} - - {% elif forloop.last %} - - + + {% if forloop.last %} + + {% endif %}
{% if level == "team" %} Team @@ -252,13 +255,13 @@ {{ s.name }}
diff --git a/ietf/templates/submit/edit_submission.html b/ietf/templates/submit/edit_submission.html index 15be01491..aa710a2a7 100644 --- a/ietf/templates/submit/edit_submission.html +++ b/ietf/templates/submit/edit_submission.html @@ -57,7 +57,7 @@ Group {{ submission.group|default:"Individual Submission" }} - {% if submission.group %}({{ submission.group.acronym|upper }}){% endif %} + {% if submission.group %}({{ submission.group.acronym|upper }}){% endif %} {% if errors.group %}

{{ errors.group }} (Note: the Secretariat will be notified of this) @@ -93,9 +93,7 @@ type="submit" value="Submit for manual posting"> -

- {% include "submit/problem-reports-footer.html" %} -

+ {% include "submit/problem-reports-footer.html" %} {% endblock %} {% block js %} {{ all_forms|merge_media:'js' }} diff --git a/ietf/templates/submit/email.html b/ietf/templates/submit/email.html index 784c896fd..fd72bcace 100644 --- a/ietf/templates/submit/email.html +++ b/ietf/templates/submit/email.html @@ -15,7 +15,7 @@
{{ submission.name }} -
+ {% csrf_token %} {% bootstrap_form form %} diff --git a/ietf/templates/submit/submission_status.html b/ietf/templates/submit/submission_status.html index a0be97a2f..872b7f1f7 100644 --- a/ietf/templates/submit/submission_status.html +++ b/ietf/templates/submit/submission_status.html @@ -204,7 +204,7 @@
Group {{ submission.group|default:"Individual Submission" }} - {% if submission.group %}({{ submission.group.acronym|upper }}){% endif %} + {% if submission.group %}({{ submission.group.acronym|upper }}){% endif %} {% if errors.group %}

{{ errors.group }} diff --git a/ietf/templates/submit/upload_submission.html b/ietf/templates/submit/upload_submission.html index f3bcc68e8..a641abfca 100644 --- a/ietf/templates/submit/upload_submission.html +++ b/ietf/templates/submit/upload_submission.html @@ -49,7 +49,6 @@ aria-controls="other-formats"> Submit other formats diff --git a/ietf/utils/test_utils.py b/ietf/utils/test_utils.py index 80bfafec1..0b3789b93 100644 --- a/ietf/utils/test_utils.py +++ b/ietf/utils/test_utils.py @@ -47,8 +47,10 @@ from bs4 import BeautifulSoup from contextlib import contextmanager from pathlib import Path from tempfile import NamedTemporaryFile +from tidylib import tidy_document import django.test +from django.test.client import Client from django.conf import settings from django.utils.text import slugify @@ -151,6 +153,44 @@ class ReverseLazyTest(django.test.TestCase): response = self.client.get('/ipr/update/') self.assertRedirects(response, "/ipr/", status_code=301) +class VerifyingClient(Client): + def __init__(self, test): + super(VerifyingClient, self).__init__() + self.test = test + + def get(self, path, *args, **extra): + r = super(VerifyingClient, self).get(path, *args, **extra) + # print(path, r.status_code, r["content-type"].lower()) + if r.status_code < 300 and r["content-type"].lower().startswith( + "text/html" + ): + document, errors = tidy_document( + r.content, options={"drop-empty-elements": False} + ) + + errors = "\n".join( + [ + e + for e in errors.splitlines() + # FIXME-LARS: django-bootstrap5 incorrectly sets a "required" + # proprietray attribute on some DIVs; remove those errors + if not re.match(r'.*proprietary attribute "required"', e) + # FIXME-LARS: some secretariat templates have this issue, ignore + and not re.match(r".*id and name attribute value mismatch", e) + ] + ) + + if errors: + n = 1 + print("\n") + for line in r.content.decode().splitlines(): + print(f"{n: 6}: {line}") + n += 1 + print(path) + self.test.maxDiff = None + self.test.assertEqual("", errors) + return r + class TestCase(django.test.TestCase): """IETF TestCase class @@ -261,6 +301,7 @@ class TestCase(django.test.TestCase): def setUp(self): # Replace settings paths with temporary directories. super().setUp() + self.client = VerifyingClient(self) # Set up the HTML verifier self._ietf_temp_dirs = {} # trashed during tearDown, DO NOT put paths you care about in this for setting in self.settings_temp_path_overrides: self._ietf_temp_dirs[setting] = self.tempdir(slugify(setting)) @@ -271,4 +312,4 @@ class TestCase(django.test.TestCase): self._ietf_saved_context.disable() for dir in self._ietf_temp_dirs.values(): shutil.rmtree(dir) - super().tearDown() + super().tearDown() \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2cb761774..cb0965a31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1871,9 +1871,9 @@ "peer": true }, "node_modules/@types/node": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.12.tgz", - "integrity": "sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA==", + "version": "17.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz", + "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==", "dev": true }, "node_modules/@types/parse-json": { @@ -2200,9 +2200,9 @@ } }, "node_modules/bootstrap-icons": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.7.2.tgz", - "integrity": "sha512-NiR2PqC73AQOPdVSu6GJfnk+hN2z6powcistXk1JgPnKuoV2FSdSl26w931Oz9HYbKCcKUSB6ncZTYJAYJl3QQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.8.0.tgz", + "integrity": "sha512-plaZQb8tReUULAwQ9M98PyWh5H912eKGVC6etMtc6VqmPmp9Eq0s7Wd0qvPoPLHh0VhXxzdLk1ta5W7lwPIdCQ==", "engines": { "node": ">=10" } @@ -2431,9 +2431,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001303", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz", - "integrity": "sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ==", + "version": "1.0.30001304", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", + "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==", "dev": true, "funding": { "type": "opencollective", @@ -3159,9 +3159,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.54", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.54.tgz", - "integrity": "sha512-jRAoneRdSxnpRHO0ANpnEUtQHXxlgfVjrLOnQSisw1ryjXJXvS0pJaR/v2B7S++/tRjgEDp4Sjn5nmgb6uTySw==", + "version": "1.4.59", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz", + "integrity": "sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg==", "dev": true }, "node_modules/elliptic": { @@ -3321,9 +3321,9 @@ } }, "node_modules/eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", - "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", + "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.5", @@ -4016,9 +4016,9 @@ } }, "node_modules/highcharts": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-9.3.2.tgz", - "integrity": "sha512-I/48gNMvs3hZxZnPRUqLbnlrGZJJ7YPPVr1+fYeZ35p4pSZAOwTmAGbptrjBr7JlF52HmJH9zMbt/I4TPLu9Pg==" + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-9.3.3.tgz", + "integrity": "sha512-QeOvm6cifeZYYdTLm4IxZsXcOE9c4xqfs0z0OJJ0z7hhA9WG0rmcVAyuIp5HBl/znjA/ayYHmpYjBYD/9PG4Fg==" }, "node_modules/highlight.js": { "version": "10.4.1", @@ -5552,14 +5552,14 @@ } }, "node_modules/postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", "dev": true, "dependencies": { - "nanoid": "^3.1.30", + "nanoid": "^3.2.0", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -5570,9 +5570,9 @@ } }, "node_modules/postcss-calc": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.2.tgz", - "integrity": "sha512-B5R0UeB4zLJvxNt1FVCaDZULdzsKLPc6FhjFJ+xwFiq7VG4i9cuaJLxVjNtExNK8ocm3n2o4unXXLiVX1SCqxA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.3.tgz", + "integrity": "sha512-EGM2EBBWqP57N0E7N7WOLT116PJ39dwHVU01WO4XPPQLJfkL2xVgkMZ+TZvCfapj/uJH07UEfKHQNPHzSw/14Q==", "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.2", @@ -6108,9 +6108,9 @@ } }, "node_modules/preact": { - "version": "10.6.4", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.4.tgz", - "integrity": "sha512-WyosM7pxGcndU8hY0OQlLd54tOU+qmG45QXj2dAYrL11HoyU/EzOSTlpJsirbBr1QW7lICxSsVJJmcmUglovHQ==", + "version": "10.6.5", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.5.tgz", + "integrity": "sha512-i+LXM6JiVjQXSt2jG2vZZFapGpCuk1fl8o6ii3G84MA3xgj686FKjs4JFDkmUVhtxyq21+4ay74zqPykz9hU6w==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -6415,9 +6415,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.0.tgz", - "integrity": "sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw==", + "version": "1.49.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.4.tgz", + "integrity": "sha512-xUU5ZlppOjgfEyIIcHpnmY+f+3/ieaadp25S/OqZ5+jBPeTAMJJblkhM6UD9jb4j/lzglz7VOL5kglYt+CvNdQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -6428,7 +6428,7 @@ "sass": "sass.js" }, "engines": { - "node": ">=8.9.0" + "node": ">=12.0.0" } }, "node_modules/select2": { @@ -8524,9 +8524,9 @@ "peer": true }, "@types/node": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.12.tgz", - "integrity": "sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA==", + "version": "17.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz", + "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==", "dev": true }, "@types/parse-json": { @@ -8779,9 +8779,9 @@ } }, "bootstrap-icons": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.7.2.tgz", - "integrity": "sha512-NiR2PqC73AQOPdVSu6GJfnk+hN2z6powcistXk1JgPnKuoV2FSdSl26w931Oz9HYbKCcKUSB6ncZTYJAYJl3QQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.8.0.tgz", + "integrity": "sha512-plaZQb8tReUULAwQ9M98PyWh5H912eKGVC6etMtc6VqmPmp9Eq0s7Wd0qvPoPLHh0VhXxzdLk1ta5W7lwPIdCQ==" }, "brace-expansion": { "version": "1.1.11", @@ -8970,9 +8970,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001303", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz", - "integrity": "sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ==", + "version": "1.0.30001304", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", + "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==", "dev": true }, "chalk": { @@ -9539,9 +9539,9 @@ } }, "electron-to-chromium": { - "version": "1.4.54", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.54.tgz", - "integrity": "sha512-jRAoneRdSxnpRHO0ANpnEUtQHXxlgfVjrLOnQSisw1ryjXJXvS0pJaR/v2B7S++/tRjgEDp4Sjn5nmgb6uTySw==", + "version": "1.4.59", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz", + "integrity": "sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg==", "dev": true }, "elliptic": { @@ -9669,9 +9669,9 @@ "dev": true }, "eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", - "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", + "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "requires": { "@eslint/eslintrc": "^1.0.5", @@ -10205,9 +10205,9 @@ } }, "highcharts": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-9.3.2.tgz", - "integrity": "sha512-I/48gNMvs3hZxZnPRUqLbnlrGZJJ7YPPVr1+fYeZ35p4pSZAOwTmAGbptrjBr7JlF52HmJH9zMbt/I4TPLu9Pg==" + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-9.3.3.tgz", + "integrity": "sha512-QeOvm6cifeZYYdTLm4IxZsXcOE9c4xqfs0z0OJJ0z7hhA9WG0rmcVAyuIp5HBl/znjA/ayYHmpYjBYD/9PG4Fg==" }, "highlight.js": { "version": "10.4.1", @@ -11321,20 +11321,20 @@ "dev": true }, "postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", "dev": true, "requires": { - "nanoid": "^3.1.30", + "nanoid": "^3.2.0", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" } }, "postcss-calc": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.2.tgz", - "integrity": "sha512-B5R0UeB4zLJvxNt1FVCaDZULdzsKLPc6FhjFJ+xwFiq7VG4i9cuaJLxVjNtExNK8ocm3n2o4unXXLiVX1SCqxA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.3.tgz", + "integrity": "sha512-EGM2EBBWqP57N0E7N7WOLT116PJ39dwHVU01WO4XPPQLJfkL2xVgkMZ+TZvCfapj/uJH07UEfKHQNPHzSw/14Q==", "dev": true, "requires": { "postcss-selector-parser": "^6.0.2", @@ -11678,9 +11678,9 @@ } }, "preact": { - "version": "10.6.4", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.4.tgz", - "integrity": "sha512-WyosM7pxGcndU8hY0OQlLd54tOU+qmG45QXj2dAYrL11HoyU/EzOSTlpJsirbBr1QW7lICxSsVJJmcmUglovHQ==" + "version": "10.6.5", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.5.tgz", + "integrity": "sha512-i+LXM6JiVjQXSt2jG2vZZFapGpCuk1fl8o6ii3G84MA3xgj686FKjs4JFDkmUVhtxyq21+4ay74zqPykz9hU6w==" }, "prelude-ls": { "version": "1.2.1", @@ -11899,9 +11899,9 @@ "dev": true }, "sass": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.0.tgz", - "integrity": "sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw==", + "version": "1.49.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.4.tgz", + "integrity": "sha512-xUU5ZlppOjgfEyIIcHpnmY+f+3/ieaadp25S/OqZ5+jBPeTAMJJblkhM6UD9jb4j/lzglz7VOL5kglYt+CvNdQ==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", diff --git a/requirements.txt b/requirements.txt index 9fbfd983d..ebb8e8d7c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -73,4 +73,5 @@ Unidecode>=0.4.18,<1.2.0 xml2rfc>=2.35.0 xym>=0.4.4,!=0.4.7,<1.0 #zxcvbn-python>=4.4.14 # Not needed until we do back-end password entropy validation -djhtml>=1.4.11 # To auto-indent templates via "djlint --profile django --reformat" \ No newline at end of file +djhtml>=1.4.11 # To auto-indent templates via "djlint --profile django --reformat" +pytidylib>=0.3.2 # Used during tests to check validity of generated HTML \ No newline at end of file