Skip to content

Commit 73b6c41

Browse files
committed
Add support for Markdown files with frontmatter
1 parent e95a008 commit 73b6c41

File tree

3 files changed

+201
-1
lines changed

3 files changed

+201
-1
lines changed

src/reuse/comment.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
# SPDX-FileCopyrightText: 2024 Anthony Loiseau <[email protected]>
2121
# SPDX-FileCopyrightText: 2025 Raphael Schlarb <[email protected]>
2222
# SPDX-FileCopyrightText: 2025 Kiko Fernandez-Reyes <[email protected]>
23+
# SPDX-FileCopyrightText: 2025 Matthias Schoettle <[email protected]>
2324
#
2425
# SPDX-License-Identifier: GPL-3.0-or-later
2526

@@ -386,6 +387,16 @@ class FortranCommentStyle(CommentStyle):
386387
INDENT_AFTER_SINGLE = " "
387388

388389

390+
class FrontmatterCommentStyle(CommentStyle):
391+
"""Frontmatter comment style."""
392+
393+
SHORTHAND = "frontmatter"
394+
395+
SINGLE_LINE = "#"
396+
INDENT_AFTER_SINGLE = " "
397+
SHEBANGS = ["---"]
398+
399+
389400
class ModernFortranCommentStyle(CommentStyle):
390401
"""Fortran (free form) comment style."""
391402

src/reuse/header.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# SPDX-FileCopyrightText: 2022 Yaman Qalieh
1111
# SPDX-FileCopyrightText: 2022 Carmen Bianca Bakker <[email protected]>
1212
# SPDX-FileCopyrightText: 2025 Rivos Inc.
13+
# SPDX-FileCopyrightText: 2025 Matthias Schoettle <[email protected]>
1314
#
1415
# SPDX-License-Identifier: GPL-3.0-or-later
1516

@@ -24,7 +25,7 @@
2425
from license_expression import ExpressionError
2526

2627
from . import ReuseInfo
27-
from .comment import CommentStyle, EmptyCommentStyle, PythonCommentStyle
28+
from .comment import CommentStyle, EmptyCommentStyle, FrontmatterCommentStyle, HtmlCommentStyle, PythonCommentStyle
2829
from .copyright import merge_copyright_lines
2930
from .exceptions import (
3031
CommentCreateError,
@@ -279,6 +280,9 @@ def find_and_replace_header(
279280
if style is EmptyCommentStyle:
280281
after = ""
281282

283+
if style is HtmlCommentStyle and text.startswith(FrontmatterCommentStyle.SHEBANGS[0]):
284+
style = FrontmatterCommentStyle
285+
282286
_LOGGER.debug(f"before = {repr(before)}")
283287
_LOGGER.debug(f"header = {repr(header)}")
284288
_LOGGER.debug(f"after = {repr(after)}")

tests/test_cli_annotate.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,191 @@ def test_shebang_wrong_comment_style(self, fake_repository):
393393
assert result.exit_code == 0
394394
assert simple_file.read_text() == expected
395395

396+
def test_xml(self, fake_repository):
397+
"""Keep the XML header when annotating."""
398+
simple_file = fake_repository / "foo.xml"
399+
simple_file.write_text(
400+
cleandoc(
401+
"""
402+
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
403+
<root>
404+
</root>
405+
"""
406+
)
407+
)
408+
expected = cleandoc(
409+
"""
410+
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
411+
412+
<!--
413+
SPDX-License-Identifier: MIT
414+
-->
415+
416+
<root>
417+
</root>
418+
"""
419+
)
420+
421+
result = CliRunner().invoke(
422+
main,
423+
[
424+
"annotate",
425+
"--license",
426+
"MIT",
427+
"foo.xml",
428+
],
429+
)
430+
431+
assert result.exit_code == 0
432+
assert simple_file.read_text() == expected
433+
434+
def test_xml_wrong_comment_style(self, fake_repository):
435+
"""If a comment style does not support the XML header at the top, don't
436+
treat the shebang as special.
437+
"""
438+
simple_file = fake_repository / "foo.sh"
439+
simple_file.write_text(
440+
cleandoc(
441+
"""
442+
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
443+
<root>
444+
</root>
445+
"""
446+
)
447+
)
448+
expected = cleandoc(
449+
"""
450+
# SPDX-License-Identifier: MIT
451+
452+
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
453+
<root>
454+
</root>
455+
"""
456+
)
457+
458+
result = CliRunner().invoke(
459+
main,
460+
[
461+
"annotate",
462+
"--license",
463+
"MIT",
464+
"foo.sh",
465+
],
466+
)
467+
468+
assert result.exit_code == 0
469+
assert simple_file.read_text() == expected
470+
471+
def test_markdown(self, fake_repository):
472+
"""Markdown uses the HTML comment style."""
473+
simple_file = fake_repository / "foo.md"
474+
simple_file.write_text(
475+
cleandoc(
476+
"""
477+
# Heading
478+
"""
479+
)
480+
)
481+
expected = cleandoc(
482+
"""
483+
<!--
484+
SPDX-License-Identifier: MIT
485+
-->
486+
487+
# Heading
488+
"""
489+
)
490+
491+
result = CliRunner().invoke(
492+
main,
493+
[
494+
"annotate",
495+
"--license",
496+
"MIT",
497+
"foo.md",
498+
],
499+
)
500+
501+
assert result.exit_code == 0
502+
assert simple_file.read_text() == expected
503+
504+
def test_frontmatter(self, fake_repository):
505+
"""Keep the frontmatter when annotating."""
506+
simple_file = fake_repository / "foo.md"
507+
simple_file.write_text(
508+
cleandoc(
509+
"""
510+
---
511+
description: test
512+
---
513+
# Heading
514+
"""
515+
)
516+
)
517+
expected = cleandoc(
518+
"""
519+
---
520+
521+
# SPDX-License-Identifier: MIT
522+
523+
description: test
524+
---
525+
# Heading
526+
"""
527+
)
528+
529+
result = CliRunner().invoke(
530+
main,
531+
[
532+
"annotate",
533+
"--license",
534+
"MIT",
535+
"foo.md",
536+
],
537+
)
538+
539+
assert result.exit_code == 0
540+
assert simple_file.read_text() == expected
541+
542+
def test_frontmatter_wrong_comment_style(self, fake_repository):
543+
"""If a comment style does not support the frontmatter header at the top, don't
544+
treat the shebang as special.
545+
"""
546+
simple_file = fake_repository / "foo.sh"
547+
simple_file.write_text(
548+
cleandoc(
549+
"""
550+
---
551+
description: test
552+
---
553+
# Heading
554+
"""
555+
)
556+
)
557+
expected = cleandoc(
558+
"""
559+
# SPDX-License-Identifier: MIT
560+
561+
---
562+
description: test
563+
---
564+
# Heading
565+
"""
566+
)
567+
568+
result = CliRunner().invoke(
569+
main,
570+
[
571+
"annotate",
572+
"--license",
573+
"MIT",
574+
"foo.sh",
575+
],
576+
)
577+
578+
assert result.exit_code == 0
579+
assert simple_file.read_text() == expected
580+
396581
def test_contributors_only(
397582
self, fake_repository, mock_date_today, contributors
398583
):

0 commit comments

Comments
 (0)