From 30009ada8f485561970fd87c9e01f219528bf52f Mon Sep 17 00:00:00 2001 From: Nathaniel Landau Date: Wed, 17 May 2023 09:07:47 -0400 Subject: [PATCH] fix: allow markdown inline code in metadata values --- src/obsidian_metadata/models/notes.py | 23 ++++++++++++----------- tests/notes/note_init_test.py | 6 ++++++ tests/parsers_test.py | 21 ++++++++++++++++++--- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/obsidian_metadata/models/notes.py b/src/obsidian_metadata/models/notes.py index b8cce06..b85c7e7 100644 --- a/src/obsidian_metadata/models/notes.py +++ b/src/obsidian_metadata/models/notes.py @@ -87,7 +87,7 @@ class Note: yield "encoding", self.encoding yield "note_path", self.note_path - def _grab_all_metadata(self, text: str) -> list[InlineField]: + def _grab_all_metadata(self, text: str) -> list[InlineField]: # noqa: C901 """Grab all metadata from the note and create list of InlineField objects.""" all_metadata = [] # List of all metadata to be returned @@ -124,17 +124,9 @@ class Note: ) ) - # Then strip all frontmatter, code blocks, and inline code from the text and parse tags and inline metadata - text = P.strip_frontmatter(P.strip_code_blocks(P.strip_inline_code(text))) - - # Parse text line by line + # strip frontmatter and code blocks from the text and parse inline metadata + text = P.strip_frontmatter(P.strip_code_blocks(text)) for _line in text.splitlines(): - tags = [ - InlineField(meta_type=MetadataType.TAGS, key=None, value=tag.lstrip("#")) - for tag in P.return_tags(_line) - ] - all_metadata.extend(tags) - inline_metadata = P.return_inline_metadata(_line) if inline_metadata: # for item in inline_metadata: @@ -148,6 +140,15 @@ class Note: ) ) + # Then strip all inline code and parse tags + text = P.strip_inline_code(text) + for _line in text.splitlines(): + tags = [ + InlineField(meta_type=MetadataType.TAGS, key=None, value=tag.lstrip("#")) + for tag in P.return_tags(_line) + ] + all_metadata.extend(tags) + return list(set(all_metadata)) def _delete_inline_metadata(self, source: InlineField) -> bool: diff --git a/tests/notes/note_init_test.py b/tests/notes/note_init_test.py index 79c974b..d6a2249 100644 --- a/tests/notes/note_init_test.py +++ b/tests/notes/note_init_test.py @@ -153,17 +153,23 @@ foo [key3::value3] bar key4::value4 foo (key4::value) bar key5::value5 +key6:: `value6` +`key7::value7` +`key8`::`value8` """ ) note = Note(note_path=note_path) assert sorted(note.metadata, key=lambda x: (x.key, x.value)) == [ + InlineField(meta_type=MetadataType.INLINE, key="`key7", value="value7`"), + InlineField(meta_type=MetadataType.INLINE, key="`key8`", value="`value8`"), InlineField(meta_type=MetadataType.INLINE, key="key1", value="value1"), InlineField(meta_type=MetadataType.INLINE, key="key2", value="2022-12-22"), InlineField(meta_type=MetadataType.INLINE, key="key3", value="value3"), InlineField(meta_type=MetadataType.INLINE, key="key4", value="value"), InlineField(meta_type=MetadataType.INLINE, key="key4", value="value4"), InlineField(meta_type=MetadataType.INLINE, key="key5", value="value5"), + InlineField(meta_type=MetadataType.INLINE, key="key6", value=" `value6`"), ] diff --git a/tests/parsers_test.py b/tests/parsers_test.py index d8618b2..69abe66 100644 --- a/tests/parsers_test.py +++ b/tests/parsers_test.py @@ -172,6 +172,10 @@ def test_return_inline_metadata_2(string, returned): ("_foo_::bar baz", [("_foo_", "bar baz", Wrapping.NONE)]), ("**foo**::bar_baz", [("**foo**", "bar_baz", Wrapping.NONE)]), ("`foo`::`bar baz`", [("`foo`", "`bar baz`", Wrapping.NONE)]), + ("`foo`:: `bar baz`", [("`foo`", " `bar baz`", Wrapping.NONE)]), + ("`foo::bar baz`", [("`foo", "bar baz`", Wrapping.NONE)]), + ("`foo:: bar baz`", [("`foo", " bar baz`", Wrapping.NONE)]), + ("**URL**::`https://example.com`", [("**URL**", "`https://example.com`", Wrapping.NONE)]), ], ) def test_return_inline_metadata_3(string, returned): @@ -347,15 +351,26 @@ key: value assert P.strip_frontmatter(content, data_only=True) == content -def test_strip_inline_code_1(): +@pytest.mark.parametrize( + ("content", "expected"), + [ + ("Foo `bar` baz `Qux` ```bar\n```", "Foo baz ```bar\n```"), + ("foo", "foo"), + ("foo `bar` baz `qux`", "foo baz "), + ("key:: `value`", "key:: "), + ("foo\nbar\n`baz`", "foo\nbar\n"), + ("foo\nbar::baz\n`qux`", "foo\nbar::baz\n"), + ("`foo::bar`", ""), + ], +) +def test_strip_inline_code_1(content, expected): """Test the strip_inline_code method. GIVEN a string with inline code WHEN the strip_inline_code method is called THEN the inline code is removed """ - assert P.strip_inline_code("Foo `bar` baz `Qux` ```bar\n```") == "Foo baz ```bar\n```" - assert P.strip_inline_code("Foo `bar` baz `Qux` ```bar\n```") == "Foo baz ```bar\n```" + assert P.strip_inline_code(content) == expected def test_validators():