Skip to content

Commit 609cb6a

Browse files
authored
Merge pull request #2610 from strictdoc-project/stanislaw/html2pdf_forced_break
feat(html2pdf): introduce a new "html2pdf_forced_page_break_nodes" option
2 parents e7992f1 + cf0704b commit 609cb6a

11 files changed

Lines changed: 182 additions & 11 deletions

File tree

docs/strictdoc_01_user_guide.sdoc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3419,7 +3419,7 @@ MID: 225dc4d22c084a67ae049fca1098bc1a
34193419
STATEMENT: >>>
34203420
StrictDoc uses an internal default template when exporting documents in PDF format.
34213421

3422-
If the front page, header, or footer needs to be customised, it is possible to provide a custom template with the `html2pdf_template` option.
3422+
If the front page, header, or footer needs to be customised, it is possible to provide a custom template with the ``html2pdf_template`` option.
34233423

34243424
.. code:: toml
34253425

@@ -4085,6 +4085,36 @@ To activate the HTML2PDF screen in the web interface, add/edit the ``strictdoc.t
40854085
This feature is not enabled by default because the implementation has not been completed yet. The underlying JavaScript library is being improved with respect to how the SDoc HTML content is split between pages, in particular the splitting of HTML ``<table>`` tags is being worked out.
40864086
<<<
40874087

4088+
[[SECTION]]
4089+
MID: 2f3f0488d9564d43a7fdb6f071b1cae9
4090+
TITLE: Forcing a page break for each node
4091+
4092+
[TEXT]
4093+
MID: 202f6fffba9f4000a95cd69933839fc3
4094+
STATEMENT: >>>
4095+
The ``html2pdf_forced_page_break_nodes`` allows specifying which nodes should always start on a new page when printed to PDF using the HTML2PDF feature. It is especially useful for documents that contain very large, descriptive requirement nodes with a lot of text. In such cases, starting each node on a new page helps avoid having the beginning of a node lost in the middle of a page.
4096+
4097+
Example of ``strictdoc_config.py``:
4098+
4099+
.. code-block:: py
4100+
4101+
from strictdoc.core.project_config import ProjectConfig
4102+
4103+
4104+
def create_config() -> ProjectConfig:
4105+
config = ProjectConfig(
4106+
project_features=[
4107+
"HTML2PDF",
4108+
],
4109+
html2pdf_forced_page_break_nodes=[
4110+
"REQUIREMENT"
4111+
]
4112+
)
4113+
return config
4114+
<<<
4115+
4116+
[[/SECTION]]
4117+
40884118
[[/SECTION]]
40894119

40904120
[[SECTION]]

docs/strictdoc_04_release_notes.sdoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ Also, a Pygments lexer for the SDoc markup has been added to the StrictDoc sourc
6666
IMPORT_FROM_FILE: @my_grammar
6767

6868
Thanks to @gregshue for requesting this feature and explaining the need for it.
69+
70+
3\) Based on a user report, the ``html2pdf_forced_page_break_nodes`` option has been added to the StrictDoc configuration. This option allows specifying which nodes should always start on a new page when printed to PDF using the HTML2PDF feature. It is especially useful for documents that contain very large, descriptive requirement nodes with a lot of text. In such cases, starting each node on a new page helps avoid having the beginning of a node lost in the middle of a page. Thanks to @xw-mk for the clear request.
6971
<<<
7072

7173
[[/SECTION]]

strictdoc/core/project_config.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def __init__(
122122
source_nodes: Optional[List[SourceNodesEntry]] = None,
123123
html2pdf_strict: bool = False,
124124
html2pdf_template: Optional[str] = None,
125+
html2pdf_forced_page_break_nodes: Optional[List[str]] = None,
125126
bundle_document_version: Optional[
126127
str
127128
] = ProjectConfigDefault.DEFAULT_BUNDLE_DOCUMENT_VERSION,
@@ -230,6 +231,14 @@ def __init__(
230231

231232
self.html2pdf_strict: bool = html2pdf_strict
232233
self.html2pdf_template: Optional[str] = html2pdf_template
234+
235+
if html2pdf_forced_page_break_nodes is not None:
236+
assert isinstance(html2pdf_forced_page_break_nodes, list)
237+
assert len(html2pdf_forced_page_break_nodes) <= 10
238+
self.html2pdf_forced_page_break_nodes: List[str] = (
239+
html2pdf_forced_page_break_nodes or []
240+
)
241+
233242
self.bundle_document_version: Optional[str] = bundle_document_version
234243
self.bundle_document_date: Optional[str] = bundle_document_date
235244

strictdoc/export/html/generators/view_objects/document_screen_view_object.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,16 +431,20 @@ def get_html2pdf_classes(self, node: SDocNode) -> str:
431431

432432
assert isinstance(node, SDocNode), node
433433

434-
if not node.has_multiline_fields():
435-
html2pdf4doc_classes = []
434+
html2pdf4doc_classes = []
435+
436+
if (
437+
node.node_type
438+
in self.project_config.html2pdf_forced_page_break_nodes
439+
):
440+
html2pdf4doc_classes.append("sdoc-html2pdf4doc-break-before")
436441

442+
if not node.has_multiline_fields():
437443
if node.get_requirement_style_mode() == "narrative":
438444
html2pdf4doc_classes.append("html2pdf4doc-no-break")
439445

440446
# The section that does not break away from its children.
441447
if node.has_child_nodes():
442448
html2pdf4doc_classes.append("html2pdf4doc-no-hanging")
443449

444-
return "".join(html2pdf4doc_classes)
445-
446-
return ""
450+
return " ".join(html2pdf4doc_classes)

strictdoc/export/html/templates/components/node/readonly.jinja

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
{% set node_type_string = sdoc_entity.get_node_type_string() %}
44

55
<sdoc-node
6+
class="{{ view_object.get_html2pdf_classes(sdoc_entity) }}"
67
node-style="readonly"
78
node-role="{{ sdoc_entity.get_type_string() }}"
89
{%- if node_type_string is not none %}
910
show-node-type-name="{{ node_type_string }}"
1011
{%- endif %}
1112
{# FIXME: Is this template always called on SDocNode? Can this check be removed? #}
12-
{% if sdoc_entity.is_requirement() %}
13+
{% if sdoc_entity.is_requirement() -%}
1314
node-view="{{ sdoc_entity.get_requirement_style_mode() }}"
14-
{%- endif -%}
15-
class="{{ view_object.get_html2pdf_classes(sdoc_entity) }}"
15+
{% endif -%}
1616
data-testid="node-{{ sdoc_entity.get_type_string() }}"
1717
>
1818

strictdoc/export/html/templates/screens/document/pdf/index.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
data-preloader-background='#F2F5F9'
3232
data-forced-page-break-selectors=''
3333
data-page-break-after-selectors='.pdf-toc .free_text'
34-
data-page-break-before-selectors='H2'
34+
data-page-break-before-selectors='H2 .sdoc-html2pdf4doc-break-before'
3535
data-no-break-selectors='.html2pdf4doc-no-break sdoc-section-title sdoc-meta sdoc-node-title .pdf-toc-row'
3636
data-no-hanging-selectors='.html2pdf4doc-no-hanging sdoc-section-title sdoc-anchor sdoc-meta .admonition-title sdoc-node-title sdoc-node-field-label strong:only-child'
3737
src="{{ view_object.render_static_url('html2pdf4doc.min.js') }}"></script>

strictdoc_config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def create_config() -> ProjectConfig:
7070
"reports/tests_integration.lit.junit.xml": "tests/integration",
7171
"reports/tests_integration_html2pdf.lit.junit.xml": "tests/integration",
7272
},
73-
html2pdf_strict=True,
73+
# Waiting for a fix to be released soon.
74+
html2pdf_strict=False,
7475
reqif_multiline_is_xhtml=True,
7576
reqif_enable_mid=True,
7677
section_behavior="[[SECTION]]",
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
[DOCUMENT]
2+
MID: 82becec5ace54321b135ed27d5a73c76
3+
TITLE: Dummy Software Requirements Specification #1
4+
OPTIONS:
5+
ENABLE_MID: True
6+
7+
[GRAMMAR]
8+
ELEMENTS:
9+
- TAG: TEXT
10+
FIELDS:
11+
- TITLE: MID
12+
TYPE: String
13+
REQUIRED: False
14+
- TITLE: UID
15+
TYPE: String
16+
REQUIRED: False
17+
- TITLE: STATEMENT
18+
TYPE: String
19+
REQUIRED: True
20+
- TAG: REQUIREMENT
21+
FIELDS:
22+
- TITLE: MID
23+
TYPE: String
24+
REQUIRED: False
25+
- TITLE: UID
26+
TYPE: String
27+
REQUIRED: False
28+
- TITLE: TITLE
29+
TYPE: String
30+
REQUIRED: False
31+
- TITLE: STATEMENT
32+
TYPE: String
33+
REQUIRED: False
34+
RELATIONS:
35+
- TYPE: Parent
36+
- TYPE: File
37+
38+
[REQUIREMENT]
39+
MID: c165cc52af20417e9199e30a4e17f138
40+
UID: REQ-1
41+
TITLE: Dummy high-level requirement #1
42+
STATEMENT: System ABC shall do 1.
43+
RELATIONS:
44+
- TYPE: File
45+
VALUE: file.py
46+
47+
[REQUIREMENT]
48+
MID: 74dddc4c55ac44ae83dc0f73ef8ed2aa
49+
UID: REQ-2
50+
TITLE: Dummy high-level requirement #2
51+
STATEMENT: System ABC shall do 2.
52+
RELATIONS:
53+
- TYPE: File
54+
VALUE: file.py
55+
56+
[REQUIREMENT]
57+
MID: fcbce0c486ac4d3189a7aa1dd646399e
58+
UID: REQ-3
59+
TITLE: Dummy high-level requirement #3
60+
STATEMENT: System ABC shall do 3.
61+
RELATIONS:
62+
- TYPE: File
63+
VALUE: file.py
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from strictdoc.core.project_config import ProjectConfig
2+
3+
4+
def create_config() -> ProjectConfig:
5+
config = ProjectConfig(
6+
project_features=[
7+
"HTML2PDF",
8+
],
9+
html2pdf_forced_page_break_nodes=[
10+
"REQUIREMENT"
11+
]
12+
)
13+
return config
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# @relation(SDOC-SRS-51, scope=file)
2+
3+
REQUIRES: TEST_HTML2PDF
4+
5+
RUN: %strictdoc export %S --formats=html2pdf --output-dir %T | filecheck %s --dump-input=fail
6+
CHECK: html2pdf4doc: JS logs from the print session
7+
8+
RUN: %check_exists --file %T/html2pdf/pdf/input.pdf
9+
10+
RUN: %check_exists --file %T/html2pdf/html/%THIS_TEST_FOLDER/input-PDF.html
11+
RUN: cat %T/html2pdf/html/%THIS_TEST_FOLDER/input-PDF.html | filecheck %s --check-prefix=CHECK-HTML-PDF
12+
CHECK-HTML-PDF: {{<sdoc-node$}}
13+
CHECK-HTML-PDF-NEXT:class="sdoc-html2pdf4doc-break-before"
14+
CHECK-HTML-PDF: {{<sdoc-node$}}
15+
CHECK-HTML-PDF-NEXT:class="sdoc-html2pdf4doc-break-before"
16+
CHECK-HTML-PDF: {{<sdoc-node$}}
17+
CHECK-HTML-PDF-NEXT:class="sdoc-html2pdf4doc-break-before"
18+
19+
RUN: python %S/test_pdf.py

0 commit comments

Comments
 (0)