diff --git a/strictdoc/core/source_tree.py b/strictdoc/core/source_tree.py
index 779341f2e..46b2284e0 100644
--- a/strictdoc/core/source_tree.py
+++ b/strictdoc/core/source_tree.py
@@ -24,6 +24,9 @@ class SourceFileType(Enum):
RST = [".rst"]
SDOC = [".sdoc"]
+ # Structured Text (PLC)
+ STRUCTURED_TEXT = [".st"]
+
UNKNOWN: List[str] = [] # type: ignore[misc]
@classmethod
@@ -52,6 +55,12 @@ def create_from_path(cls, path_to_file: str) -> "SourceFileType":
return cls.RST
if path_to_file.endswith(".sdoc"):
return cls.SDOC
+ # FIXME: .st file could conflict between Structured Text (PLC) and Smalltalk.
+ # No Smalltalk has been requested by users until now but we may
+ # want to set up a general disambiguation procedure for cases like this.
+ # https://github.com/strictdoc-project/strictdoc/issues/2569
+ if path_to_file.endswith(".st"):
+ return cls.STRUCTURED_TEXT
return cls.UNKNOWN
@@ -113,6 +122,9 @@ def is_yaml_file(self) -> bool:
def is_rst_file(self) -> bool:
return self.file_type == SourceFileType.RST
+ def is_st_file(self) -> bool:
+ return self.file_type == SourceFileType.STRUCTURED_TEXT
+
class SourceTree:
def __init__(
diff --git a/strictdoc/export/html/generators/source_file_view_generator.py b/strictdoc/export/html/generators/source_file_view_generator.py
index 817507061..ac7b3434f 100644
--- a/strictdoc/export/html/generators/source_file_view_generator.py
+++ b/strictdoc/export/html/generators/source_file_view_generator.py
@@ -175,6 +175,9 @@ def get_pygmented_source_lines(
lexer = YamlLexer()
elif source_file.is_rst_file():
lexer = RstLexer()
+ elif source_file.is_st_file():
+ # Structured Text syntax doesn't seem to be supported by Pygments.
+ lexer = TextLexer()
else:
try:
lexer = get_lexer_for_filename(source_file.file_name)
diff --git a/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/example.sdoc b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/example.sdoc
new file mode 100644
index 000000000..5b2921a33
--- /dev/null
+++ b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/example.sdoc
@@ -0,0 +1,26 @@
+[DOCUMENT]
+TITLE: Example: Traceability between requirements and source files
+
+[REQUIREMENT]
+UID: REQ-001
+TITLE: Whole file reference
+STATEMENT: This requirement references the whole file.
+RELATIONS:
+- TYPE: File
+ VALUE: file.st
+
+[REQUIREMENT]
+UID: REQ-002
+TITLE: Source range reference
+STATEMENT: This requirement references a range in the file.
+RELATIONS:
+- TYPE: File
+ VALUE: file.st
+
+[REQUIREMENT]
+UID: REQ-003
+TITLE: Source range reference
+STATEMENT: This requirement references a range in the file.
+RELATIONS:
+- TYPE: File
+ VALUE: file.st
diff --git a/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/file.st b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/file.st
new file mode 100644
index 000000000..22ab2ebd4
--- /dev/null
+++ b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/file.st
@@ -0,0 +1,17 @@
+FUNCTION_BLOCK FB_Test
+VAR_INPUT
+ i_xA: BOOL;
+ i_xB: BOOL;
+END_VAR
+VAR_OUTPUT
+ o_xX: BOO;
+END_VAR
+
+// --- BEGIN IMPLEMENTATION ---
+// @relation(REQ-001, scope=range_start)
+IF i_xA AND i_xB THEN
+ o_xX := TRUE;
+ELSE
+ o_xX := FALSE;
+END_IF
+// @relation(REQ-001, scope=range_end)
diff --git a/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/strictdoc.toml b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/strictdoc.toml
new file mode 100644
index 000000000..bf7608a9a
--- /dev/null
+++ b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/strictdoc.toml
@@ -0,0 +1,9 @@
+[project]
+
+features = [
+ "REQUIREMENT_TO_SOURCE_TRACEABILITY",
+]
+
+include_source_paths = [
+ "file.st",
+]
diff --git a/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/test.itest b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/test.itest
new file mode 100644
index 000000000..56c8f3a35
--- /dev/null
+++ b/tests/integration/features/source_code_traceability/_file_types/65_st_structured_text/test.itest
@@ -0,0 +1,25 @@
+#
+# This test verifies that the Structured Text (PLCs) format is properly recognized
+# by StrictDoc.
+#
+# @relation(SDOC-SRS-142, scope=file)
+#
+
+RUN: %strictdoc export %S --output-dir %T | filecheck %s --dump-input=fail
+CHECK: Published: Example: Traceability between requirements and source files
+
+RUN: %check_exists --file "%T/html/_source_files/file.st.html"
+
+RUN: %cat %T/html/%THIS_TEST_FOLDER/example.html | filecheck %s --dump-input=fail --check-prefix CHECK-HTML
+CHECK-HTML:
+CHECK-HTML:
+
+RUN: %cat %T/html/_source_files/file.st.html | filecheck %s --dump-input=fail --check-prefix CHECK-SOURCE-FILE
+
+# Verify that the Text lexer is selected for this file as Pygments does not
+# support the ST syntax at the moment.
+CHECK-SOURCE-FILE: /* Lexer: Text only */
+# Verify that the link that points back to requirement is displayed correctly.
+CHECK-SOURCE-FILE: href="../65_st_structured_text/example.html#REQ-001"
+# Verify that the range link is displayed correctly.
+CHECK-SOURCE-FILE: href="../_source_files/file.st.html#REQ-001#11#17"