@@ -1871,7 +1871,14 @@ def layers_dict_to_files(outfiles, layers):
18711871 json .dump (layers ["ics-attack" ], open (ics_attack_layer_file , "w" ), indent = 4 )
18721872
18731873
1874- def write_detailed_html (html_file_detailed : str , diffStix : DiffStix ):
1874+ def _get_additional_format_href (filename : str , additional_formats_prefix : str = "" ) -> str :
1875+ """Return a link to an additional changelog output file."""
1876+ if not additional_formats_prefix :
1877+ return filename
1878+ return f"{ additional_formats_prefix .rstrip ('/' )} /{ filename } "
1879+
1880+
1881+ def write_detailed_html (html_file_detailed : str , diffStix : DiffStix , additional_formats_prefix : str = "" ):
18751882 """Write a detailed HTML report of changes between ATT&CK versions.
18761883
18771884 Parameters
@@ -1880,6 +1887,8 @@ def write_detailed_html(html_file_detailed: str, diffStix: DiffStix):
18801887 File to write HTML for the detailed changelog.
18811888 diffStix : DiffStix
18821889 An instance of a DiffStix object.
1890+ additional_formats_prefix : str, optional
1891+ Prefix for links to generated layer and JSON files, by default "".
18831892 """
18841893 old_version = diffStix .data ["old" ]["enterprise-attack" ]["attack_release_version" ]
18851894 new_version = diffStix .data ["new" ]["enterprise-attack" ]["attack_release_version" ]
@@ -1889,6 +1898,11 @@ def write_detailed_html(html_file_detailed: str, diffStix: DiffStix):
18891898 else :
18901899 header = f"<h1>ATT&CK Changes Between v{ old_version } and new content</h1>"
18911900
1901+ enterprise_layer_href = _get_additional_format_href ("layer-enterprise.json" , additional_formats_prefix )
1902+ mobile_layer_href = _get_additional_format_href ("layer-mobile.json" , additional_formats_prefix )
1903+ ics_layer_href = _get_additional_format_href ("layer-ics.json" , additional_formats_prefix )
1904+ changelog_json_href = _get_additional_format_href ("changelog.json" , additional_formats_prefix )
1905+
18921906 frontmatter = [
18931907 textwrap .dedent (
18941908 """\
@@ -1913,7 +1927,7 @@ def write_detailed_html(html_file_detailed: str, diffStix: DiffStix):
19131927 header ,
19141928 markdown .markdown (diffStix .get_md_key ()),
19151929 textwrap .dedent (
1916- """\
1930+ f """\
19171931 <table class=diff summary=Legends>
19181932 <tr>
19191933 <td>
@@ -1929,11 +1943,11 @@ def write_detailed_html(html_file_detailed: str, diffStix: DiffStix):
19291943 <h2>Additional formats</h2>
19301944 <p>These ATT&CK Navigator layer files can be uploaded to ATT&CK Navigator manually.</p>
19311945 <ul>
1932- <li><a href="layer-enterprise.json ">Enterprise changes</a></li>
1933- <li><a href="layer-mobile.json ">Mobile changes</a></li>
1934- <li><a href="layer-ics.json ">ICS changes</a></li>
1946+ <li><a href="{ enterprise_layer_href } ">Enterprise changes</a></li>
1947+ <li><a href="{ mobile_layer_href } ">Mobile changes</a></li>
1948+ <li><a href="{ ics_layer_href } ">ICS changes</a></li>
19351949 </ul>
1936- <p>This JSON file contains the machine readble output used to create this page: <a href="changelog.json ">changelog.json</a></p>
1950+ <p>This JSON file contains the machine readble output used to create this page: <a href="{ changelog_json_href } ">changelog.json</a></p>
19371951 """
19381952 ),
19391953 ]
@@ -2256,6 +2270,13 @@ def get_parsed_args():
22562270 help = "Prefix links in markdown output, e.g. [prefix]/techniques/T1484" ,
22572271 )
22582272
2273+ parser .add_argument (
2274+ "--additional-formats-prefix" ,
2275+ type = str ,
2276+ default = "" ,
2277+ help = "Prefix detailed HTML links to generated layers and changelog JSON." ,
2278+ )
2279+
22592280 parser .add_argument (
22602281 "--unchanged" ,
22612282 action = "store_true" ,
@@ -2331,6 +2352,7 @@ def get_new_changelog_md(
23312352 markdown_file : Optional [str ] = None ,
23322353 html_file : Optional [str ] = None ,
23332354 html_file_detailed : Optional [str ] = None ,
2355+ additional_formats_prefix : str = "" ,
23342356 json_file : Optional [str ] = None ,
23352357) -> str :
23362358 """Get a Markdown string representation of differences between two ATT&CK versions.
@@ -2365,6 +2387,8 @@ def get_new_changelog_md(
23652387 If set, writes an HTML file from the parsed markdown, by default None
23662388 html_file_detailed : str, optional
23672389 If set, writes a more detailed HTML page, by default None
2390+ additional_formats_prefix : str, optional
2391+ Prefix for detailed HTML links to generated layer and JSON files, by default "".
23682392 json_file : str, optional
23692393 If set, writes JSON file of the changes, by default None
23702394
@@ -2414,7 +2438,11 @@ def get_new_changelog_md(
24142438 if html_file_detailed :
24152439 Path (html_file_detailed ).parent .mkdir (parents = True , exist_ok = True )
24162440 logger .info ("Writing detailed updates to file" )
2417- write_detailed_html (html_file_detailed = html_file_detailed , diffStix = diffStix )
2441+ write_detailed_html (
2442+ html_file_detailed = html_file_detailed ,
2443+ diffStix = diffStix ,
2444+ additional_formats_prefix = additional_formats_prefix ,
2445+ )
24182446
24192447 if layers :
24202448 if len (layers ) == 0 :
@@ -2457,6 +2485,7 @@ def main():
24572485 markdown_file = args .markdown_file ,
24582486 html_file = args .html_file ,
24592487 html_file_detailed = args .html_file_detailed ,
2488+ additional_formats_prefix = args .additional_formats_prefix ,
24602489 json_file = args .json_file ,
24612490 )
24622491
0 commit comments