diff --git a/strictdoc/backend/sdoc/models/free_text.py b/strictdoc/backend/sdoc/models/free_text.py index 5d4054fa1..9723218bb 100644 --- a/strictdoc/backend/sdoc/models/free_text.py +++ b/strictdoc/backend/sdoc/models/free_text.py @@ -1,4 +1,3 @@ -import html from typing import Any, List, Optional from strictdoc.backend.sdoc.models.anchor import Anchor @@ -55,9 +54,6 @@ def get_parts_as_text(self) -> str: raise NotImplementedError(part) return text - def get_parts_as_text_escaped(self) -> str: - return html.escape(self.get_parts_as_text()) - class FreeTextContainer(FreeText): def __init__(self, parts: List[Any]) -> None: diff --git a/strictdoc/backend/sdoc/models/node.py b/strictdoc/backend/sdoc/models/node.py index 3cb99e824..dd77427c7 100644 --- a/strictdoc/backend/sdoc/models/node.py +++ b/strictdoc/backend/sdoc/models/node.py @@ -1,5 +1,4 @@ # mypy: disable-error-code="union-attr" -import html from collections import OrderedDict from typing import Any, Generator, List, Optional, Tuple, Union @@ -92,9 +91,6 @@ def get_text_value(self) -> str: raise NotImplementedError(part) return text - def get_text_value_escaped(self) -> str: - return html.escape(self.get_text_value()) - @auto_described class SDocNode(SDocObject): @@ -456,13 +452,6 @@ def enumerate_all_fields( meta_field_value = field.get_text_value() yield field, field.field_name, meta_field_value - def enumerate_all_fields_escaped( - self, - ) -> Generator[Tuple[SDocNodeField, str, str], None, None]: - for field in self.enumerate_fields(): - meta_field_value = field.get_text_value_escaped() - yield field, field.field_name, meta_field_value - def enumerate_meta_fields( self, skip_single_lines: bool = False, skip_multi_lines: bool = False ) -> Generator[Tuple[str, SDocNodeField], None, None]: diff --git a/strictdoc/core/document_iterator.py b/strictdoc/core/document_iterator.py index c3cb3d4d7..3bd6ed90c 100644 --- a/strictdoc/core/document_iterator.py +++ b/strictdoc/core/document_iterator.py @@ -1,5 +1,5 @@ # mypy: disable-error-code="arg-type,attr-defined,no-any-return,no-untyped-call,no-untyped-def,operator,type-arg" -from typing import Optional, Tuple +from typing import Optional, Tuple, Union from strictdoc.backend.sdoc.models.document import SDocDocument from strictdoc.backend.sdoc.models.document_from_file import DocumentFromFile @@ -9,6 +9,16 @@ ) from strictdoc.backend.sdoc.models.section import FreeText, SDocSection +AnyDocumentContent = Union[ + DocumentFromFile, + FreeText, + SDocSection, + SDocCompositeNode, + SDocNode, + SDocDocument, + str, +] + class DocumentCachingIterator: def __init__(self, document): @@ -37,7 +47,7 @@ def all_content( self, print_fragments: bool = False, print_fragments_from_files: bool = False, - ): + ) -> AnyDocumentContent: root_node = self.document yield from self._all_content( @@ -53,7 +63,7 @@ def all_content_from_node( node, print_fragments: bool = False, print_fragments_from_files: bool = False, - ): + ) -> AnyDocumentContent: document = node if isinstance(node, SDocDocument) else node.document yield from self._all_content( node, @@ -70,7 +80,7 @@ def _all_content( print_fragments_from_files: bool = False, level_stack: Optional[Tuple] = (), custom_level: bool = False, - ): + ) -> AnyDocumentContent: def get_level_string_(node_) -> str: if isinstance(node_, SDocNode) and node_.requirement_type == "TEXT": return "" diff --git a/strictdoc/core/transforms/create_requirement.py b/strictdoc/core/transforms/create_requirement.py index 2a2e617ce..2ee0db079 100644 --- a/strictdoc/core/transforms/create_requirement.py +++ b/strictdoc/core/transforms/create_requirement.py @@ -108,14 +108,14 @@ def perform(self): ) = RstToHtmlFragmentWriter( path_to_output_dir=self.project_config.export_output_dir, context_document=document, - ).write_with_validation(field_.field_unescaped_value) + ).write_with_validation(field_.field_value) if parsed_html is None: errors[field_.field_name].append(rst_error) else: try: free_text_container: Optional[FreeTextContainer] = ( - SDFreeTextReader.read(field_.field_unescaped_value) - if len(field_.field_unescaped_value) > 0 + SDFreeTextReader.read(field_.field_value) + if len(field_.field_value) > 0 else None ) map_form_to_requirement_fields[field_] = ( @@ -208,7 +208,7 @@ def perform(self): requirement.set_field_value( field_name=form_field_name, form_field_index=form_field_index, - value=form_field.field_unescaped_value, + value=form_field.field_value, ) continue diff --git a/strictdoc/core/transforms/update_requirement.py b/strictdoc/core/transforms/update_requirement.py index 6bbae3501..2d217e877 100644 --- a/strictdoc/core/transforms/update_requirement.py +++ b/strictdoc/core/transforms/update_requirement.py @@ -114,14 +114,14 @@ def perform(self): ) = RstToHtmlFragmentWriter( path_to_output_dir=self.project_config.export_output_dir, context_document=self.context_document, - ).write_with_validation(field_.field_unescaped_value) + ).write_with_validation(field_.field_value) if parsed_html is None: form_object.add_error(field_.field_name, rst_error) else: try: free_text_container: Optional[FreeTextContainer] = ( - SDFreeTextReader.read(field_.field_unescaped_value) - if len(field_.field_unescaped_value) > 0 + SDFreeTextReader.read(field_.field_value) + if len(field_.field_value) > 0 else None ) map_form_to_requirement_fields[field_] = ( @@ -455,7 +455,7 @@ def populate_node_fields_from_form_object( node.set_field_value( field_name=form_field_name, form_field_index=form_field_index, - value=form_field.field_unescaped_value, + value=form_field.field_value, ) continue diff --git a/strictdoc/export/html/form_objects/requirement_form_object.py b/strictdoc/export/html/form_objects/requirement_form_object.py index 650a624d3..c0c818519 100644 --- a/strictdoc/export/html/form_objects/requirement_form_object.py +++ b/strictdoc/export/html/form_objects/requirement_form_object.py @@ -1,5 +1,4 @@ # mypy: disable-error-code="arg-type,attr-defined,no-redef,no-untyped-call,no-untyped-def,union-attr,type-arg" -import html from collections import defaultdict from enum import Enum from typing import Dict, List, Optional, Set, Union @@ -57,15 +56,12 @@ def __init__( field_mid: str, field_name: str, field_type: RequirementFormFieldType, - field_unescaped_value: str, - field_escaped_value: str, + field_value: str, ): - assert isinstance(field_unescaped_value, str) - assert isinstance(field_escaped_value, str) + assert isinstance(field_value, str) self.field_mid: str = field_mid self.field_name: str = field_name - self.field_unescaped_value: str = field_unescaped_value - self.field_escaped_value: str = field_escaped_value + self.field_value: str = field_value self.field_type = field_type def is_singleline(self): @@ -85,18 +81,12 @@ def create_from_grammar_field( *, grammar_field: GrammarElementField, multiline: bool, - value_unescaped: str, - value_escaped: str, + value: str, ) -> "RequirementFormField": - assert isinstance(value_unescaped, str), ( - grammar_field, - multiline, - value_unescaped, - ) - assert isinstance(value_escaped, str), ( + assert isinstance(value, str), ( grammar_field, multiline, - value_escaped, + value, ) if grammar_field.gef_type in ( RequirementFieldType.STRING, @@ -111,8 +101,7 @@ def create_from_grammar_field( if multiline else RequirementFormFieldType.SINGLELINE ), - field_unescaped_value=value_unescaped, - field_escaped_value=value_escaped, + field_value=value, ) raise NotImplementedError(grammar_field) @@ -128,7 +117,6 @@ def create_existing_from_grammar_field( RequirementFieldType.MULTIPLE_CHOICE, ): field_value = requirement_field.get_text_value() - escaped_field_value = html.escape(field_value) return RequirementFormField( field_mid=MID.create(), field_name=grammar_field.title, @@ -137,8 +125,7 @@ def create_existing_from_grammar_field( if multiline else RequirementFormFieldType.SINGLELINE ), - field_unescaped_value=field_value, - field_escaped_value=escaped_field_value, + field_value=field_value, ) raise NotImplementedError(grammar_field) @@ -148,8 +135,7 @@ def create_mid_field(mid: MID) -> "RequirementFormField": field_mid=MID.create(), field_name="MID", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=mid, - field_escaped_value=html.escape(mid), + field_value=mid, ) @@ -327,8 +313,7 @@ def create_from_request( form_field = RequirementFormField.create_from_grammar_field( grammar_field=field, multiline=multiline, - value_unescaped=sanitized_field_value, - value_escaped=html.escape(sanitized_field_value), + value=sanitized_field_value, ) form_fields.append(form_field) @@ -381,21 +366,14 @@ def create_new( RequirementFormField.create_from_grammar_field( grammar_field=field, multiline=field_idx >= content_field_idx, - value_unescaped="", - value_escaped="", + value="", ) ) form_fields.append(form_field) if form_field.field_name == "UID" and next_uid is not None: - form_field.field_unescaped_value = next_uid - form_field.field_escaped_value = next_uid + form_field.field_value = next_uid elif form_field.field_name == "MID" and document.config.enable_mid: - form_field.field_unescaped_value = ( - new_requirement_mid.get_string_value() - ) - form_field.field_escaped_value = ( - new_requirement_mid.get_string_value() - ) + form_field.field_value = new_requirement_mid.get_string_value() return RequirementFormObject( is_new=True, @@ -455,8 +433,7 @@ def create_from_requirement( form_field = RequirementFormField.create_from_grammar_field( grammar_field=field, multiline=multiline, - value_unescaped="", - value_escaped="", + value="", ) form_fields.append(form_field) @@ -515,8 +492,7 @@ def clone_from_requirement( for field_name, fields_ in form_object.fields.items(): if field_name == "UID": field: RequirementFormField = fields_[0] - field.field_unescaped_value = clone_uid - field.field_escaped_value = clone_uid + field.field_value = clone_uid form_object.requirement_mid = MID.create() return form_object @@ -613,7 +589,7 @@ def validate( FIXME: MID uniqueness if a node is updated. """ if self.is_new and "MID" in self.fields: - new_node_mid = self.fields["MID"][0].field_unescaped_value + new_node_mid = self.fields["MID"][0].field_value if len(new_node_mid) > 0: existing_node_with_this_mid = ( traceability_index.get_node_by_mid_weak(MID(new_node_mid)) @@ -633,7 +609,7 @@ def validate( """ new_node_uid_or_none: Optional[str] = None if "UID" in self.fields: - new_node_uid = self.fields["UID"][0].field_unescaped_value + new_node_uid = self.fields["UID"][0].field_value if len(new_node_uid) > 0: new_node_uid_or_none = new_node_uid @@ -689,9 +665,7 @@ def validate( """ requirement_element = self.grammar.elements_by_type[self.element_type] statement_field_name = requirement_element.content_field[0] - requirement_statement = self.fields[statement_field_name][ - 0 - ].field_unescaped_value + requirement_statement = self.fields[statement_field_name][0].field_value if requirement_statement is None or len(requirement_statement) == 0: self.add_error( statement_field_name, @@ -717,7 +691,7 @@ def validate( and grammar_element_field_.required ): for form_field_ in self.fields[grammar_element_field_.title]: - field_value = form_field_.field_unescaped_value + field_value = form_field_.field_value if field_value is None or len(field_value) == 0: self.add_error( grammar_element_field_.title, @@ -735,9 +709,7 @@ def validate( self._validate_choice(grammar_element_field_) requirement_uid: Optional[str] = ( - self.fields["UID"][0].field_unescaped_value - if "UID" in self.fields - else None + self.fields["UID"][0].field_value if "UID" in self.fields else None ) if len(self.reference_fields) > 0 and ( requirement_uid is None or len(requirement_uid) == 0 @@ -862,10 +834,7 @@ def child_lambda(requirement_id_) -> List[str]: def _validate_choice(self, grammar_element_field: GrammarElementField): field_0 = self.fields[grammar_element_field.title][0] - if ( - len(field_0.field_unescaped_value) == 0 - and not grammar_element_field.required - ): + if len(field_0.field_value) == 0 and not grammar_element_field.required: # The empty choice fields are allowed if the field is not REQUIRED. return @@ -881,8 +850,7 @@ def _validate_choice(self, grammar_element_field: GrammarElementField): ) if ( grammar_element_field.gef_type == RequirementFieldType.SINGLE_CHOICE - and field_0.field_unescaped_value - not in choice_grammar_element_field.options + and field_0.field_value not in choice_grammar_element_field.options ): self.add_error( grammar_element_field.title, @@ -896,14 +864,13 @@ def _validate_choice(self, grammar_element_field: GrammarElementField): == RequirementFieldType.MULTIPLE_CHOICE ): choices = [ - choice.strip() - for choice in field_0.field_unescaped_value.split(",") + choice.strip() for choice in field_0.field_value.split(",") ] if all( choice in choice_grammar_element_field.options for choice in choices ): - field_0.field_unescaped_value = ", ".join(choices) + field_0.field_value = ", ".join(choices) else: self.add_error( grammar_element_field.title, diff --git a/strictdoc/export/html/form_objects/section_form_object.py b/strictdoc/export/html/form_objects/section_form_object.py index b24748547..4c65edc91 100644 --- a/strictdoc/export/html/form_objects/section_form_object.py +++ b/strictdoc/export/html/form_objects/section_form_object.py @@ -1,5 +1,4 @@ # mypy: disable-error-code="arg-type,no-untyped-call,no-untyped-def,type-arg" -import html from collections import defaultdict from typing import Dict @@ -41,11 +40,11 @@ def __init__( @property def section_uid(self): - return self.section_uid_field.field_unescaped_value + return self.section_uid_field.field_value @property def section_title(self): - return self.section_title_field.field_unescaped_value + return self.section_title_field.field_value @staticmethod def create_new(context_document_mid: str): @@ -55,15 +54,13 @@ def create_new(context_document_mid: str): field_mid=MID.create(), field_name="UID", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value="", - field_escaped_value="", + field_value="", ), section_title_field=RequirementFormField( field_mid=MID.create(), field_name="TITLE", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value="", - field_escaped_value="", + field_value="", ), context_document_mid=context_document_mid, ) @@ -73,10 +70,7 @@ def create_from_section(*, section: SDocSection, context_document_mid: str): uid_field_value = ( section.reserved_uid if section.reserved_uid is not None else "" ) - uid_escaped_field_value = html.escape(uid_field_value) - title_field_value = section.title if section.title is not None else "" - title_escaped_field_value = html.escape(title_field_value) return SectionFormObject( section_mid=section.reserved_mid, @@ -84,15 +78,13 @@ def create_from_section(*, section: SDocSection, context_document_mid: str): field_mid=MID.create(), field_name="UID", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=uid_field_value, - field_escaped_value=uid_escaped_field_value, + field_value=uid_field_value, ), section_title_field=RequirementFormField( field_mid=MID.create(), field_name="TITLE", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=title_field_value, - field_escaped_value=title_escaped_field_value, + field_value=title_field_value, ), context_document_mid=context_document_mid, ) @@ -128,8 +120,7 @@ def create_from_request( field_mid=MID.create(), field_name="UID", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=sanitized_uid_field_value, - field_escaped_value=html.escape(sanitized_uid_field_value), + field_value=sanitized_uid_field_value, ) title_field_value = requirement_fields["TITLE"][0] @@ -140,8 +131,7 @@ def create_from_request( field_mid=MID.create(), field_name="TITLE", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=sanitized_title_field_value, - field_escaped_value=html.escape(sanitized_title_field_value), + field_value=sanitized_title_field_value, ) form_object = SectionFormObject( diff --git a/strictdoc/export/html/generators/source_file_view_generator.py b/strictdoc/export/html/generators/source_file_view_generator.py index 934b9768f..38445f7a3 100644 --- a/strictdoc/export/html/generators/source_file_view_generator.py +++ b/strictdoc/export/html/generators/source_file_view_generator.py @@ -1,7 +1,7 @@ # mypy: disable-error-code="no-untyped-call,no-untyped-def,operator" -import html from typing import List +from markupsafe import escape from pygments import highlight from pygments.formatters.html import HtmlFormatter from pygments.lexers import get_lexer_for_filename @@ -202,12 +202,9 @@ def get_pygmented_source_lines( assert closing_bracket_index is not None after_line = source_line[closing_bracket_index:].rstrip() - before_line = html.escape(before_line) - after_line = html.escape(after_line) - pygmented_source_file_lines[pragma_line - 1] = ( - before_line, - after_line, + escape(before_line), + escape(after_line), pragma, ) pygments_styles = ( diff --git a/strictdoc/export/html/generators/view_objects/diff_screen_results_view_object.py b/strictdoc/export/html/generators/view_objects/diff_screen_results_view_object.py index 938b02ddb..98439cef6 100644 --- a/strictdoc/export/html/generators/view_objects/diff_screen_results_view_object.py +++ b/strictdoc/export/html/generators/view_objects/diff_screen_results_view_object.py @@ -60,7 +60,9 @@ def __init__( self.error_message: Optional[str] = None def render_screen(self, jinja_environment: Environment): - template = jinja_environment.get_template("screens/git/index.jinja") + template = jinja_environment.overlay(autoescape=False).get_template( + "screens/git/index.jinja" + ) return template.render(view_object=self) def render_url(self, url: str): diff --git a/strictdoc/export/html/generators/view_objects/search_screen_view_object.py b/strictdoc/export/html/generators/view_objects/search_screen_view_object.py index f7a4ec304..124e7e2d1 100644 --- a/strictdoc/export/html/generators/view_objects/search_screen_view_object.py +++ b/strictdoc/export/html/generators/view_objects/search_screen_view_object.py @@ -8,6 +8,7 @@ from strictdoc import __version__ from strictdoc.backend.sdoc.models.document import SDocDocument from strictdoc.backend.sdoc.models.document_view import DocumentView +from strictdoc.core.document_iterator import AnyDocumentContent from strictdoc.core.document_tree_iterator import DocumentTreeIterator from strictdoc.core.project_config import ProjectConfig from strictdoc.core.traceability_index import TraceabilityIndex @@ -25,8 +26,8 @@ def __init__( traceability_index: TraceabilityIndex, project_config: ProjectConfig, templates: HTMLTemplates, - search_results, - search_value, + search_results: AnyDocumentContent, + search_value: str, error, ): self.traceability_index: TraceabilityIndex = traceability_index diff --git a/strictdoc/export/html/html_templates.py b/strictdoc/export/html/html_templates.py index 04f1e11be..5769b7731 100644 --- a/strictdoc/export/html/html_templates.py +++ b/strictdoc/export/html/html_templates.py @@ -105,6 +105,7 @@ def __init__(self): loader=FileSystemLoader(environment.get_path_to_html_templates()), undefined=StrictUndefined, extensions=[AssertExtension], + autoescape=True, ) def jinja_environment(self) -> Environment: diff --git a/strictdoc/export/html/renderers/markup_renderer.py b/strictdoc/export/html/renderers/markup_renderer.py index a0d418143..1949e3860 100644 --- a/strictdoc/export/html/renderers/markup_renderer.py +++ b/strictdoc/export/html/renderers/markup_renderer.py @@ -1,6 +1,8 @@ # mypy: disable-error-code="attr-defined,no-untyped-call,no-untyped-def,var-annotated" from typing import Optional, Type, Union +from markupsafe import Markup + from strictdoc.backend.sdoc.models.anchor import Anchor from strictdoc.backend.sdoc.models.document import SDocDocument from strictdoc.backend.sdoc.models.inline_link import InlineLink @@ -141,7 +143,7 @@ def render_node_field( output = self.fragment_writer.write(parts_output) self.cache[(document_type, node_field, truncated)] = output - return output + return Markup(output) def render_free_text(self, document_type, free_text): assert isinstance(free_text, FreeText) diff --git a/strictdoc/export/html/renderers/text_to_html_writer.py b/strictdoc/export/html/renderers/text_to_html_writer.py index dd519e1df..dc11e5542 100644 --- a/strictdoc/export/html/renderers/text_to_html_writer.py +++ b/strictdoc/export/html/renderers/text_to_html_writer.py @@ -1,11 +1,11 @@ # mypy: disable-error-code="no-untyped-def" -import html +from markupsafe import Markup, escape class TextToHtmlWriter: @staticmethod def write(text_fragment): - return html.escape(text_fragment, quote=True).replace("\n", "
\n") + return escape(text_fragment).replace("\n", Markup("
\n")) @staticmethod def write_link(title, _): diff --git a/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/example.jinja.html b/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/example.jinja.html index bb960d7b7..e7d9cd07a 100644 --- a/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/example.jinja.html +++ b/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/example.jinja.html @@ -7,7 +7,7 @@ {% set text_field_row_context.field = field_ %} {% set text_field_row_context.field_type = "singleline" %} {% set text_field_row_context.reference_mid = form_object.requirement_mid %} - {%- if field_.field_name == "UID" and field_.field_escaped_value == "" -%} + {%- if field_.field_name == "UID" and field_.field_value == "" -%} {# this template is turbo-frame and has a button to reset to the default value: #} {% include "components/form/row/row_uid_with_reset/frame.jinja" %} diff --git a/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/frame.jinja b/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/frame.jinja index 7cc1cf04f..928b30430 100644 --- a/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/frame.jinja +++ b/strictdoc/export/html/templates/components/form/row/row_uid_with_reset/frame.jinja @@ -41,7 +41,7 @@ field_label = text_field_row_context.field.field_name, field_placeholder = "Enter "~placeholder_name~" here...", field_type = text_field_row_context.field_type, - field_value = text_field_row_context.field.field_escaped_value, + field_value = text_field_row_context.field.field_value, testid_postfix = text_field_row_context.field.field_name %} {%- include "components/form/field/contenteditable/index.jinja" %} diff --git a/strictdoc/export/html/templates/components/form/row/row_with_comment.jinja b/strictdoc/export/html/templates/components/form/row/row_with_comment.jinja index 7790493a7..b75cc05b6 100644 --- a/strictdoc/export/html/templates/components/form/row/row_with_comment.jinja +++ b/strictdoc/export/html/templates/components/form/row/row_with_comment.jinja @@ -36,7 +36,7 @@ field_label = comment_field_row_context.field.field_name, field_placeholder = "Enter comment here...", field_type = "multiline", - field_value = comment_field_row_context.field.field_escaped_value, + field_value = comment_field_row_context.field.field_value, mid = comment_field_row_context.field.field_mid, testid_postfix = "COMMENT" %} diff --git a/strictdoc/export/html/templates/components/form/row/row_with_text_field.jinja b/strictdoc/export/html/templates/components/form/row/row_with_text_field.jinja index 039dfe5f9..d145cadd6 100644 --- a/strictdoc/export/html/templates/components/form/row/row_with_text_field.jinja +++ b/strictdoc/export/html/templates/components/form/row/row_with_text_field.jinja @@ -39,7 +39,7 @@ field_label = text_field_row_context.field.field_name, field_placeholder = "Enter "~placeholder_name~" here...", field_type = text_field_row_context.field_type, - field_value = text_field_row_context.field.field_escaped_value, + field_value = text_field_row_context.field.field_value, testid_postfix = text_field_row_context.field.field_name %} {%- include "components/form/field/contenteditable/index.jinja" %} diff --git a/strictdoc/export/html/templates/components/node_field/section_h/index.jinja b/strictdoc/export/html/templates/components/node_field/section_h/index.jinja index f2a3445a6..ab81f3988 100644 --- a/strictdoc/export/html/templates/components/node_field/section_h/index.jinja +++ b/strictdoc/export/html/templates/components/node_field/section_h/index.jinja @@ -14,7 +14,7 @@ {%- if sdoc_entity.context.title_number_string -%} {#- add title 'number' part to the accumulator -#} - {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". " -%} + {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". "|safe -%} {%- endif -%} {%- set title = sdoc_entity.reserved_title if sdoc_entity.is_requirement else sdoc_entity.title -%} diff --git a/strictdoc/export/html/templates/components/node_field/section_title/index.jinja b/strictdoc/export/html/templates/components/node_field/section_title/index.jinja index 6c6ba8804..4b5a2cc42 100644 --- a/strictdoc/export/html/templates/components/node_field/section_title/index.jinja +++ b/strictdoc/export/html/templates/components/node_field/section_title/index.jinja @@ -9,7 +9,7 @@ {%- if sdoc_entity.context.title_number_string -%} {#- add title 'number' part to the accumulator -#} - {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". " -%} + {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". "|safe -%} {%- endif -%} {%- set title = sdoc_entity.reserved_title if sdoc_entity.is_requirement else sdoc_entity.title -%} diff --git a/strictdoc/export/html/templates/components/node_field/title/index.jinja b/strictdoc/export/html/templates/components/node_field/title/index.jinja index 5f115c90e..77934acad 100644 --- a/strictdoc/export/html/templates/components/node_field/title/index.jinja +++ b/strictdoc/export/html/templates/components/node_field/title/index.jinja @@ -8,7 +8,7 @@ {%- if title_number is true -%} {%- if sdoc_entity.context.title_number_string %} {#- add title 'number' part to the accumulator -#} - {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". " -%} + {%- set field_content_ = field_content_ + sdoc_entity.context.title_number_string + ". "|safe -%} {%- endif -%} {%- endif -%} diff --git a/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja b/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja index fec5903e2..62145cd50 100644 --- a/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja +++ b/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja @@ -35,7 +35,7 @@ {% set text_field_row_context.field_editable = true %} {% set text_field_row_context.field_type = "singleline" %} {% set text_field_row_context.reference_mid = form_object.requirement_mid %} - {%- if form_object.element_type != "TEXT" and field_.field_name == "UID" and field_.field_escaped_value == "" -%} + {%- if form_object.element_type != "TEXT" and field_.field_name == "UID" and field_.field_value == "" -%} {# this template is turbo-frame and has a button to reset to the default value: #} {% include "components/form/row/row_uid_with_reset/frame.jinja" %} @@ -95,7 +95,7 @@ {# If comments have not yet been added, show only the add field button below, and do not display the code of the field itself: #} - {%- if field_.field_escaped_value|length > 0 -%} + {%- if field_.field_value|length > 0 -%} {% set comment_field_row_context.field = field_ %} {% set comment_field_row_context.field_editable = true %} {% set comment_field_row_context.errors = form_object.get_errors(field_.field_name) %} diff --git a/strictdoc/export/html/templates/screens/document/document/frame_section_form.jinja b/strictdoc/export/html/templates/screens/document/document/frame_section_form.jinja index 9292a3e7c..bd7f26595 100644 --- a/strictdoc/export/html/templates/screens/document/document/frame_section_form.jinja +++ b/strictdoc/export/html/templates/screens/document/document/frame_section_form.jinja @@ -37,7 +37,7 @@ {% set text_field_row_context.field_editable = true %} {% set text_field_row_context.field_type = "singleline" %} {% set text_field_row_context.reference_mid = form_object.section_mid %} - {%- if not is_new_section and form_object.section_uid_field.field_escaped_value == "" -%} + {%- if not is_new_section and form_object.section_uid_field.field_value == "" -%} {# this template is turbo-frame and has a button to reset to the default value: #} {% include "components/form/row/row_uid_with_reset/frame.jinja" %} diff --git a/strictdoc/export/html/templates/screens/git/fields/requirement_fields.jinja b/strictdoc/export/html/templates/screens/git/fields/requirement_fields.jinja index 3e234ee8e..0f11508d5 100644 --- a/strictdoc/export/html/templates/screens/git/fields/requirement_fields.jinja +++ b/strictdoc/export/html/templates/screens/git/fields/requirement_fields.jinja @@ -13,7 +13,7 @@ {% endif %}
- {%- for requirement_field_triple_ in requirement.enumerate_all_fields_escaped() -%} + {%- for requirement_field_triple_ in requirement.enumerate_all_fields() -%} {%- set is_multiline = requirement_field_triple_[0].is_multiline() -%} {% if requirement_change is not none -%} diff --git a/strictdoc/export/html/templates/screens/source_file_view/main.jinja b/strictdoc/export/html/templates/screens/source_file_view/main.jinja index 1e627a751..10f4a0994 100644 --- a/strictdoc/export/html/templates/screens/source_file_view/main.jinja +++ b/strictdoc/export/html/templates/screens/source_file_view/main.jinja @@ -21,7 +21,7 @@ {%- endfor -%}{{ replacement_after }} {%- elif line != "" -%} {# #} -
{{ line }}
+
{{ line|safe }}
{%- else -%}
 
{%- endif -%} diff --git a/strictdoc/server/routers/main_router.py b/strictdoc/server/routers/main_router.py index 54c72f8bb..6d9a42aa2 100644 --- a/strictdoc/server/routers/main_router.py +++ b/strictdoc/server/routers/main_router.py @@ -1,6 +1,5 @@ # mypy: disable-error-code="arg-type,attr-defined,no-any-return,no-redef,no-untyped-call,no-untyped-def,union-attr" import copy -import html import os import re from mimetypes import guess_type @@ -1074,8 +1073,7 @@ def reset_uid(reference_mid: str): field_mid=MID.create(), field_name="UID", field_type=RequirementFormFieldType.SINGLELINE, - field_unescaped_value=next_uid, - field_escaped_value=next_uid, + field_value=next_uid, ) template = env().get_template( "components/form/row/row_uid_with_reset/stream.jinja" @@ -1814,8 +1812,7 @@ def document__add_comment( field_mid=MID.create(), field_name="COMMENT", field_type=RequirementFormFieldType.MULTILINE, - field_unescaped_value="", - field_escaped_value="", + field_value="", ), ) return HTMLResponse( @@ -2722,14 +2719,12 @@ def get_search(q: Optional[str] = None): except (AttributeError, NameError, TypeError) as attribute_error_: error = attribute_error_.args[0] - search_value = html.escape(q) if q is not None else "" - view_object = SearchScreenViewObject( traceability_index=export_action.traceability_index, project_config=project_config, templates=html_templates, search_results=search_results, - search_value=search_value, + search_value=q if q is not None else "", error=error, ) output = view_object.render_screen(html_templates.jinja_environment()) diff --git a/tests/end2end/project_index/import_document_from_reqif/UC55_G1_validations/UC55_G1_T01_not_a_reqif_format/test_UC55_G1_T01_not_a_reqif_file.py b/tests/end2end/project_index/import_document_from_reqif/UC55_G1_validations/UC55_G1_T01_not_a_reqif_format/test_UC55_G1_T01_not_a_reqif_file.py index a3961f8c4..3b001901b 100644 --- a/tests/end2end/project_index/import_document_from_reqif/UC55_G1_validations/UC55_G1_T01_not_a_reqif_format/test_UC55_G1_T01_not_a_reqif_file.py +++ b/tests/end2end/project_index/import_document_from_reqif/UC55_G1_validations/UC55_G1_T01_not_a_reqif_format/test_UC55_G1_T01_not_a_reqif_file.py @@ -33,5 +33,5 @@ def test(self): form_import.do_form_submit_and_catch_error( "Cannot parse ReqIF file: " - "Start tag expected, '<' not found, line 1, column 1 (, line 1)" + "Start tag expected, '<' not found, line 1, column 1 (, line 1)" ) diff --git a/tests/integration/options/options_per_document/MARKUP/02_options_markup_is_text/test.itest b/tests/integration/options/options_per_document/MARKUP/02_options_markup_is_text/test.itest index ee7253725..d3663fe73 100644 --- a/tests/integration/options/options_per_document/MARKUP/02_options_markup_is_text/test.itest +++ b/tests/integration/options/options_per_document/MARKUP/02_options_markup_is_text/test.itest @@ -3,4 +3,4 @@ CHECK: Published: Hello world doc RUN: %cat %S/Output/html/02_options_markup_is_text/input.html | filecheck %s --dump-input=fail --check-prefix CHECK-HTML CHECK-HTML: **This text will not be converted to strong tag** -CHECK-HTML: <a href="url">link</a> +CHECK-HTML: <a href="url">link</a> diff --git a/tests/unit/strictdoc/export/html/renderers/test_text_to_html_fragment_writer.py b/tests/unit/strictdoc/export/html/renderers/test_text_to_html_fragment_writer.py index 4d85db40c..da7196a03 100644 --- a/tests/unit/strictdoc/export/html/renderers/test_text_to_html_fragment_writer.py +++ b/tests/unit/strictdoc/export/html/renderers/test_text_to_html_fragment_writer.py @@ -7,7 +7,7 @@ def test_01_escapes_html_tags(): """.strip() html_output = TextToHtmlWriter.write(text_input) - assert "<a href="url">link</a>" == html_output + assert "<a href="url">link</a>" == html_output def test_02_replaces_newlines_with_br():