mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-18 01:43:39 -05:00
feat: initial application release
This commit is contained in:
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""obsidian-metadata test suite."""
|
||||
155
tests/alerts_test.py
Normal file
155
tests/alerts_test.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# type: ignore
|
||||
"""Test alerts and logging."""
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
from obsidian_metadata._utils import alerts
|
||||
from obsidian_metadata._utils.alerts import logger as log
|
||||
from tests.helpers import Regex
|
||||
|
||||
|
||||
def test_dryrun(capsys):
|
||||
"""Test dry run."""
|
||||
alerts.dryrun("This prints in dry run")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "DRYRUN | This prints in dry run\n"
|
||||
|
||||
|
||||
def test_success(capsys):
|
||||
"""Test success."""
|
||||
alerts.success("This prints in success")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "SUCCESS | This prints in success\n"
|
||||
|
||||
|
||||
def test_error(capsys):
|
||||
"""Test success."""
|
||||
alerts.error("This prints in error")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "ERROR | This prints in error\n"
|
||||
|
||||
|
||||
def test_warning(capsys):
|
||||
"""Test warning."""
|
||||
alerts.warning("This prints in warning")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "WARNING | This prints in warning\n"
|
||||
|
||||
|
||||
def test_notice(capsys):
|
||||
"""Test notice."""
|
||||
alerts.notice("This prints in notice")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "NOTICE | This prints in notice\n"
|
||||
|
||||
|
||||
def test_info(capsys):
|
||||
"""Test info."""
|
||||
alerts.info("This prints in info")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "INFO | This prints in info\n"
|
||||
|
||||
|
||||
def test_dim(capsys):
|
||||
"""Test info."""
|
||||
alerts.dim("This prints in dim")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "This prints in dim\n"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("verbosity", "log_to_file"),
|
||||
[(0, False), (1, False), (2, True), (3, True)],
|
||||
)
|
||||
def test_logging(capsys, tmp_path, verbosity, log_to_file) -> None:
|
||||
"""Test logging."""
|
||||
tmp_log = tmp_path / "tmp.log"
|
||||
logging = alerts.LoggerManager(
|
||||
log_file=tmp_log,
|
||||
verbosity=verbosity,
|
||||
log_to_file=log_to_file,
|
||||
)
|
||||
|
||||
assert logging.verbosity == verbosity
|
||||
|
||||
if verbosity >= 3:
|
||||
assert logging.is_trace() is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
assert logging.is_trace("trace text") is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "trace text\n"
|
||||
|
||||
log.trace("This is Trace logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.err == Regex(r"^TRACE \| This is Trace logging \([\w\._:]+:\d+\)$")
|
||||
else:
|
||||
assert logging.is_trace("trace text") is False
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out != "trace text\n"
|
||||
|
||||
log.trace("This is Trace logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.err != Regex(r"^TRACE \| This is Trace logging \([\w\._:]+:\d+\)$")
|
||||
|
||||
if verbosity >= 2:
|
||||
assert logging.is_debug() is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
assert logging.is_debug("debug text") is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "debug text\n"
|
||||
|
||||
log.debug("This is Debug logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.err == Regex(r"^DEBUG \| This is Debug logging \([\w\._:]+:\d+\)$")
|
||||
else:
|
||||
assert logging.is_debug("debug text") is False
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out != "debug text\n"
|
||||
|
||||
log.debug("This is Debug logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.err != Regex(r"^DEBUG \| This is Debug logging \([\w\._:]+:\d+\)$")
|
||||
|
||||
if verbosity >= 1:
|
||||
assert logging.is_info() is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
assert logging.is_info("info text") is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "info text\n"
|
||||
|
||||
log.info("This is Info logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.err == "INFO | This is Info logging\n"
|
||||
else:
|
||||
assert logging.is_info("info text") is False
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out != "info text\n"
|
||||
|
||||
log.info("This is Info logging")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
assert logging.is_default() is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
assert logging.is_default("default text") is True
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "default text\n"
|
||||
|
||||
if log_to_file:
|
||||
assert tmp_log.exists() is True
|
||||
log_file_content = tmp_log.read_text()
|
||||
assert log_file_content == Regex(
|
||||
r"^\d{4}-\d{2}-\d{2} \d+:\d+:\d+\.\d+ \| DEBUG \| [\w\.:]+:\d+ \- Logging to file:",
|
||||
re.MULTILINE,
|
||||
)
|
||||
else:
|
||||
assert tmp_log.exists() is False
|
||||
16
tests/cli_test.py
Normal file
16
tests/cli_test.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# type: ignore
|
||||
"""Test obsidian-metadata CLI."""
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from obsidian_metadata.cli import app
|
||||
from tests.helpers import Regex
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
|
||||
def test_version() -> None:
|
||||
"""Test printing version and then exiting."""
|
||||
result = runner.invoke(app, ["--version"])
|
||||
assert result.exit_code == 0
|
||||
assert result.output == Regex(r"obsidian_metadata: v\d+\.\d+\.\d+$")
|
||||
28
tests/config_test.py
Normal file
28
tests/config_test.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# type: ignore
|
||||
"""Tests for the configuration module."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from obsidian_metadata._config import Config
|
||||
|
||||
|
||||
def test_first_run(tmp_path):
|
||||
"""Test creating a config on first run."""
|
||||
config_file = Path(tmp_path / "config.toml")
|
||||
vault_path = Path(tmp_path / "vault/")
|
||||
vault_path.mkdir()
|
||||
|
||||
config = Config(config_path=config_file, vault_path=vault_path)
|
||||
|
||||
assert config_file.exists() is True
|
||||
config.write_config_value("vault", str(vault_path))
|
||||
content = config_file.read_text()
|
||||
assert config.vault_path == vault_path
|
||||
assert re.search(str(vault_path), content) is not None
|
||||
|
||||
|
||||
def test_parse_config():
|
||||
"""Test parsing a config file."""
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=None)
|
||||
assert config.vault_path == Path(Path.cwd() / "tests/fixtures/test_vault")
|
||||
74
tests/conftest.py
Normal file
74
tests/conftest.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# type: ignore
|
||||
"""Fixtures for tests."""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def remove_all(root: Path):
|
||||
"""Remove all files and directories in a directory."""
|
||||
for path in root.iterdir():
|
||||
if path.is_file():
|
||||
print(f"Deleting the file: {path}")
|
||||
path.unlink()
|
||||
else:
|
||||
remove_all(path)
|
||||
print(f"Deleting the empty dir: {root}")
|
||||
root.rmdir()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_note(tmp_path) -> Path:
|
||||
"""Fixture which creates a temporary note file."""
|
||||
source_file: Path = Path("tests/fixtures/test_vault/test1.md")
|
||||
if not source_file.exists():
|
||||
raise FileNotFoundError(f"Original file not found: {source_file}")
|
||||
|
||||
dest_file: Path = Path(tmp_path / source_file.name)
|
||||
shutil.copy(source_file, dest_file)
|
||||
yield dest_file
|
||||
|
||||
# after test - remove fixtures
|
||||
dest_file.unlink()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_vault(tmp_path) -> Path:
|
||||
"""Fixture which creates a sample vault."""
|
||||
source_dir = Path(__file__).parent / "fixtures" / "sample_vault"
|
||||
dest_dir = Path(tmp_path / "vault")
|
||||
backup_dir = Path(f"{dest_dir}.bak")
|
||||
|
||||
if not source_dir.exists():
|
||||
raise FileNotFoundError(f"Sample vault not found: {source_dir}")
|
||||
|
||||
shutil.copytree(source_dir, dest_dir)
|
||||
yield dest_dir
|
||||
|
||||
# after test - remove fixtures
|
||||
shutil.rmtree(dest_dir)
|
||||
|
||||
if backup_dir.exists():
|
||||
shutil.rmtree(backup_dir)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def test_vault(tmp_path) -> Path:
|
||||
"""Fixture which creates a sample vault."""
|
||||
source_dir = Path(__file__).parent / "fixtures" / "test_vault"
|
||||
dest_dir = Path(tmp_path / "vault")
|
||||
backup_dir = Path(f"{dest_dir}.bak")
|
||||
|
||||
if not source_dir.exists():
|
||||
raise FileNotFoundError(f"Sample vault not found: {source_dir}")
|
||||
|
||||
shutil.copytree(source_dir, dest_dir)
|
||||
yield dest_dir
|
||||
|
||||
# after test - remove fixtures
|
||||
shutil.rmtree(dest_dir)
|
||||
|
||||
if backup_dir.exists():
|
||||
shutil.rmtree(backup_dir)
|
||||
39
tests/fixtures/sample_note.md
vendored
Normal file
39
tests/fixtures/sample_note.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
date_created: 2022-12-22
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- dinner
|
||||
- breakfast
|
||||
- not_food
|
||||
author: John Doe
|
||||
nested_list:
|
||||
nested_list_one:
|
||||
- nested_list_one_a
|
||||
- nested_list_one_b
|
||||
type:
|
||||
- article
|
||||
- note
|
||||
---
|
||||
|
||||
area:: mixed
|
||||
date_modified:: 2022-12-22
|
||||
status:: new
|
||||
type:: book
|
||||
inline_key:: inline_key_value
|
||||
type:: [[article]]
|
||||
tags:: from_inline_metadata
|
||||
**bold_key**:: **bold** key value
|
||||
|
||||
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, [in_text_key:: in-text value] eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? #inline_tag
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, #inline_tag2 cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
|
||||
#food/fruit/pear
|
||||
#food/fruit/orange
|
||||
#dinner #breakfast
|
||||
#brunch
|
||||
9
tests/fixtures/sample_vault/+inbox/Untitled.md
vendored
Normal file
9
tests/fixtures/sample_vault/+inbox/Untitled.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: note
|
||||
tags:
|
||||
- foo
|
||||
- bar
|
||||
- baz
|
||||
- food/fruit/apple
|
||||
---
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
3
tests/fixtures/sample_vault/.obsidian/app.json
vendored
Normal file
3
tests/fixtures/sample_vault/.obsidian/app.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"alwaysUpdateLinks": true
|
||||
}
|
||||
3
tests/fixtures/sample_vault/.obsidian/appearance.json
vendored
Normal file
3
tests/fixtures/sample_vault/.obsidian/appearance.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"accentColor": ""
|
||||
}
|
||||
3
tests/fixtures/sample_vault/.obsidian/community-plugins.json
vendored
Normal file
3
tests/fixtures/sample_vault/.obsidian/community-plugins.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
"templater-obsidian"
|
||||
]
|
||||
29
tests/fixtures/sample_vault/.obsidian/core-plugins-migration.json
vendored
Normal file
29
tests/fixtures/sample_vault/.obsidian/core-plugins-migration.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"file-explorer": true,
|
||||
"global-search": true,
|
||||
"switcher": true,
|
||||
"graph": true,
|
||||
"backlink": true,
|
||||
"canvas": true,
|
||||
"outgoing-link": true,
|
||||
"tag-pane": true,
|
||||
"page-preview": true,
|
||||
"daily-notes": true,
|
||||
"templates": true,
|
||||
"note-composer": true,
|
||||
"command-palette": true,
|
||||
"slash-command": false,
|
||||
"editor-status": true,
|
||||
"starred": true,
|
||||
"markdown-importer": false,
|
||||
"zk-prefixer": false,
|
||||
"random-note": false,
|
||||
"outline": true,
|
||||
"word-count": true,
|
||||
"slides": false,
|
||||
"audio-recorder": false,
|
||||
"workspaces": false,
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": false
|
||||
}
|
||||
20
tests/fixtures/sample_vault/.obsidian/core-plugins.json
vendored
Normal file
20
tests/fixtures/sample_vault/.obsidian/core-plugins.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
[
|
||||
"file-explorer",
|
||||
"global-search",
|
||||
"switcher",
|
||||
"graph",
|
||||
"backlink",
|
||||
"canvas",
|
||||
"outgoing-link",
|
||||
"tag-pane",
|
||||
"page-preview",
|
||||
"daily-notes",
|
||||
"templates",
|
||||
"note-composer",
|
||||
"command-palette",
|
||||
"editor-status",
|
||||
"starred",
|
||||
"outline",
|
||||
"word-count",
|
||||
"file-recovery"
|
||||
]
|
||||
1
tests/fixtures/sample_vault/.obsidian/hotkeys.json
vendored
Normal file
1
tests/fixtures/sample_vault/.obsidian/hotkeys.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
5617
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/main.js
vendored
Normal file
5617
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/main.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/manifest.json
vendored
Normal file
10
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "templater-obsidian",
|
||||
"name": "Templater",
|
||||
"version": "1.16.0",
|
||||
"description": "Create and use templates",
|
||||
"minAppVersion": "0.11.13",
|
||||
"author": "SilentVoid",
|
||||
"authorUrl": "https://github.com/SilentVoid13",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
281
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/styles.css
vendored
Normal file
281
tests/fixtures/sample_vault/.obsidian/plugins/templater-obsidian/styles.css
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
.templater_search {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.templater_div {
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.templater_div > .setting-item {
|
||||
border-top: none !important;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.templater_div > .setting-item > .setting-item-control {
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.templater_div
|
||||
> .setting-item
|
||||
> .setting-item-control
|
||||
> .setting-editor-extra-setting-button {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.templater_donating {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.templater_title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.templater_template {
|
||||
align-self: center;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.templater_cmd {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.templater_div2 > .setting-item {
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.templater-prompt-div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.templater-prompt-form {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.templater-prompt-input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.templater-button-div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
textarea.templater-prompt-input {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
textarea.templater-prompt-input:focus {
|
||||
border-color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.cm-s-obsidian .templater-command-bg {
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background-color: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.cm-s-obsidian .cm-templater-command {
|
||||
font-size: 0.85em;
|
||||
font-family: var(--font-monospace);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.cm-s-obsidian .templater-inline .cm-templater-command {
|
||||
background-color: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.cm-s-obsidian .cm-templater-command.cm-templater-opening-tag {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cm-s-obsidian .cm-templater-command.cm-templater-closing-tag {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cm-s-obsidian .cm-templater-command.cm-templater-interpolation-tag {
|
||||
color: #008bff;
|
||||
}
|
||||
|
||||
.cm-s-obsidian .cm-templater-command.cm-templater-execution-tag {
|
||||
color: #c0d700;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-keyword {
|
||||
color: #00a7aa;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-atom {
|
||||
color: #f39b35;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-number {
|
||||
color: #a06fca;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-type {
|
||||
color: #a06fca;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-def {
|
||||
color: #98e342;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-property {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-variable {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-variable-2 {
|
||||
color: #da7dae;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-variable-3 {
|
||||
color: #a06fca;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-type.cm-def {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-property.cm-def {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-callee {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-operator {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-qualifier {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-tag {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-tag.cm-bracket {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-attribute {
|
||||
color: #a06fca;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-comment {
|
||||
color: #696d70;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-comment.cm-tag {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-comment.cm-attribute {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-string {
|
||||
color: #e6db74;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-string-2 {
|
||||
color: #f39b35;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-meta {
|
||||
color: #d4d4d4;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-builtin {
|
||||
color: #fc4384;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-header {
|
||||
color: #da7dae;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-hr {
|
||||
color: #98e342;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-link {
|
||||
color: #696d70;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.cm-error {
|
||||
border-bottom: 1px solid #c42412;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-keyword {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.theme-dark
|
||||
.cm-s-obsidian
|
||||
.cm-templater-command.CodeMirror-activeline-background {
|
||||
background: #272727;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian .cm-templater-command.CodeMirror-matchingbracket {
|
||||
outline: 1px solid grey;
|
||||
color: #d4d4d4 !important;
|
||||
}
|
||||
|
||||
.CodeMirror-hints {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
|
||||
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 3px;
|
||||
border: 1px solid silver;
|
||||
|
||||
background: white;
|
||||
font-size: 90%;
|
||||
font-family: monospace;
|
||||
|
||||
max-height: 20em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-hint {
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
white-space: pre;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
background: #08f;
|
||||
color: white;
|
||||
}
|
||||
155
tests/fixtures/sample_vault/.obsidian/workspace.json
vendored
Normal file
155
tests/fixtures/sample_vault/.obsidian/workspace.json
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"main": {
|
||||
"id": "5f828621a37b21ab",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "2f3322f01c16279b",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "d16a705340a291b0",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "empty",
|
||||
"state": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
},
|
||||
"left": {
|
||||
"id": "aeebc2581160842a",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "cd71abd49c3ceb86",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "fe51579e3e74af15",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {
|
||||
"sortOrder": "alphabetical"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2a7187c7c8d51306",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "574f0713150d5067",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "starred",
|
||||
"state": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 300
|
||||
},
|
||||
"right": {
|
||||
"id": "b20cf1cec7ad8379",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "e4268aea52a4b751",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "495261df1eda8469",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
"showSearch": false,
|
||||
"searchQuery": "",
|
||||
"backlinkCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "a552a9e316c497c2",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outgoing-link",
|
||||
"state": {
|
||||
"linksCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "49ac9a323fc7a3bb",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "tag",
|
||||
"state": {
|
||||
"sortOrder": "frequency",
|
||||
"useHierarchy": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "93bd91c8147876e4",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 300,
|
||||
"collapsed": true
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"switcher:Open quick switcher": false,
|
||||
"graph:Open graph view": false,
|
||||
"canvas:Create new canvas": false,
|
||||
"daily-notes:Open today's daily note": false,
|
||||
"templates:Insert template": false,
|
||||
"command-palette:Open command palette": false,
|
||||
"templater-obsidian:Templater": false
|
||||
}
|
||||
},
|
||||
"active": "d16a705340a291b0",
|
||||
"lastOpenFiles": [
|
||||
"00 meta/templates/daily note.md",
|
||||
"+inbox/Untitled.md",
|
||||
"01 frontmatter/frontmatter 1.md",
|
||||
"01 frontmatter/frontmatter 2.md",
|
||||
"01 frontmatter/frontmatter 3.md",
|
||||
"01 frontmatter/frontmatter 4.md",
|
||||
"02 inline/inline 1.md",
|
||||
"02 inline/inline 2.md",
|
||||
"02 inline/inline 3.md",
|
||||
"02 inline/inline 4.md"
|
||||
]
|
||||
}
|
||||
19
tests/fixtures/sample_vault/00 meta/templates/daily note.md
vendored
Normal file
19
tests/fixtures/sample_vault/00 meta/templates/daily note.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<%* let title = tp.file.title
|
||||
if (title.startsWith("Untitled")) {
|
||||
title = await tp.system.prompt("Title");
|
||||
await tp.file.rename(title);
|
||||
}
|
||||
-%>
|
||||
<%*
|
||||
let result = title.replace(/-/g, ' ')
|
||||
result = result.charAt(0).toUpperCase() + result.slice(1);
|
||||
tR += "---"
|
||||
%>
|
||||
title: <%* tR += "\"" + result + "\"" %>
|
||||
tags:
|
||||
<% tp.file.cursor(1) %>
|
||||
programming-languagues:
|
||||
created: <% tp.date.now("YYYY-MM-DD") %>
|
||||
---
|
||||
# <%* tR += result %>
|
||||
---
|
||||
17
tests/fixtures/sample_vault/00 meta/templates/data sample.md
vendored
Normal file
17
tests/fixtures/sample_vault/00 meta/templates/data sample.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
area:
|
||||
date_created: 2022-12-21
|
||||
date_modified: 2022-12-20
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- food/fruit/pear
|
||||
- dinner
|
||||
- lunch
|
||||
- breakfast
|
||||
author: John Doe
|
||||
status: new
|
||||
type:
|
||||
- book
|
||||
- article
|
||||
- note
|
||||
---
|
||||
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 1.md
vendored
Normal file
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 1.md
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
---
|
||||
area: frontmatter
|
||||
date_created: 2022-12-22
|
||||
date_modified: 2022-12-22
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- food/fruit/pear
|
||||
- dinner
|
||||
- lunch
|
||||
- breakfast
|
||||
thoughts:
|
||||
rating: 8
|
||||
reviewable: false
|
||||
levels:
|
||||
level1:
|
||||
- level1a
|
||||
- level1b
|
||||
level2:
|
||||
- level2a
|
||||
- level2b
|
||||
author: John Doe
|
||||
status: new
|
||||
type: ["book", "article", "note", "one-off"]
|
||||
---
|
||||
# Page Title H1
|
||||
|
||||
# Headings
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Heading 2
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
### Heading 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
#### Heading 4
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
##### Heading 5
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
###### Heading 6
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Text styles
|
||||
|
||||
Lorem ipsum **dolor sit amet**, consectetur adipisicing elit, sed do _eiusmod tempor incididunt_ ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud [[internal link]] exercitation ullamco laboris nisi ut [external link](https://google.com) aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. [[frontmatter 1]] Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Lorem ipsum `inline code looks like this` dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
```css
|
||||
This is a code block
|
||||
```
|
||||
|
||||
## Bold
|
||||
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
<strong>The quick brown fox jumps over the lazy dog.</strong>
|
||||
|
||||
## Italic
|
||||
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
<em>The quick brown fox jumps over the lazy dog.</em>
|
||||
|
||||
## Bold and Italic
|
||||
|
||||
**_The quick brown fox jumps over the lazy dog._**
|
||||
<strong><em>The quick brown fox jumps over the lazy dog.</em></strong>
|
||||
|
||||
## Blockquotes
|
||||
|
||||
> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
|
||||
|
||||
> The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||
|
||||
> **The quick brown fox** _jumps over the lazy dog._
|
||||
|
||||
## Monospaced
|
||||
|
||||
<samp>The quick brown fox jumps over the lazy dog.</samp>
|
||||
|
||||
## Underlined
|
||||
|
||||
<ins>The quick brown fox jumps over the lazy dog.</ins>
|
||||
|
||||
## Strike-through
|
||||
|
||||
~~The quick brown fox jumps over the lazy dog.~~
|
||||
|
||||
## sub and super
|
||||
|
||||
Subscript <sub>The quick brown fox jumps over the lazy dog.</sub>
|
||||
Superscript <sup>The quick brown fox jumps over the lazy dog.</sup>
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
A class method is an instance method of the class object. When a new class is created, an object of type `Class` is initialized and assigned to a global constant (Mobile in this case).
|
||||
|
||||
```
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```java
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```css
|
||||
button.mod-cta a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
| one | two | three |
|
||||
| ---- | :--: | ----- |
|
||||
| 9999 | 9999 | 9999 |
|
||||
| 1 | 2 | 3 |
|
||||
| 44 | 55 | 66 |
|
||||
|
||||
| Default | Left align | Center align | Right align |
|
||||
| ---------- | :--------- | :----------: | ----------: |
|
||||
| 9999999999 | 9999999999 | 9999999999 | 9999999999 |
|
||||
| 999999999 | 999999999 | 999999999 | 999999999 |
|
||||
| 99999999 | 99999999 | 99999999 | 99999999 |
|
||||
| 9999999 | 9999999 | 9999999 | 9999999 |
|
||||
|
||||
| A | B | C |
|
||||
| --- | --- | ----------------- |
|
||||
| 1 | 2 | 3 <br/> 4 <br/> 5 |
|
||||
|
||||
## Links
|
||||
|
||||
[The-Ultimate-Markdown-Cheat-Sheet](https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet)
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][reference text]
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][1]
|
||||
[Markdown-Cheat-Sheet]
|
||||
|
||||
[reference text]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[1]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[markdown-cheat-sheet]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
|
||||
[Example of a relative link](rl.md)
|
||||
Visit https://github.com/
|
||||
|
||||
## Images
|
||||
|
||||
![alt text][image]
|
||||
|
||||
<img src="https://media.giphy.com/media/qLHzYjlA2FW8g/giphy.gif" />
|
||||
|
||||
<img src="https://img.shields.io/badge/theultimatemarkdowncheatsheet-brightgreen.svg" />
|
||||
## Lists
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
1. One
|
||||
2. Two
|
||||
3. Three
|
||||
|
||||
## Multi-level Lists
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
1. First level
|
||||
1. Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
2. First level
|
||||
1. Second level
|
||||
3. First level
|
||||
1. Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- First level
|
||||
- Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
- First level
|
||||
- Second level
|
||||
- First level
|
||||
- Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- [x] Fix Bug 223 ✅ 2022-08-08
|
||||
- [x] Add Feature 33 ✅ 2022-08-08
|
||||
- [x] Add unit tests ✅ 2022-08-08
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
<!--
|
||||
Lorem ipsum dolor sit amet
|
||||
-->
|
||||
|
||||
- Asterisk
|
||||
\ Backslash
|
||||
` Backtick
|
||||
{} Curly braces
|
||||
. Dot
|
||||
! Exclamation mark
|
||||
|
||||
## Hash symbol
|
||||
|
||||
- Hyphen symbol
|
||||
() Parentheses
|
||||
|
||||
* Plus symbol
|
||||
[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
\* Asterisk
|
||||
\\ Backslash
|
||||
\` Backtick
|
||||
\{} Curly braces
|
||||
\. Dot
|
||||
\! Exclamation mark
|
||||
\# Hash symbol
|
||||
\- Hyphen symbol
|
||||
\() Parentheses
|
||||
\+ Plus symbol
|
||||
\[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
:octocat:
|
||||
|
||||
@lifeparticle
|
||||
|
||||
\#
|
||||
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 2.md
vendored
Normal file
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 2.md
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
---
|
||||
area: frontmatter
|
||||
date_created: 2022-12-22
|
||||
date_modified: 2022-11-14
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- food/fruit/pear
|
||||
- dinner
|
||||
- lunch
|
||||
- breakfast
|
||||
thoughts:
|
||||
rating: 8
|
||||
reviewable: false
|
||||
levels:
|
||||
level1:
|
||||
- level1a
|
||||
- level1b
|
||||
level2:
|
||||
- level2a
|
||||
- level2b
|
||||
author: John Doe
|
||||
status: new
|
||||
type: ["book", "article", "note"]
|
||||
---
|
||||
# Page Title H1
|
||||
|
||||
# Headings
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Heading 2
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
### Heading 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
#### Heading 4
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
##### Heading 5
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
###### Heading 6
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Text styles
|
||||
|
||||
Lorem ipsum **dolor sit amet**, consectetur adipisicing elit, sed do _eiusmod tempor incididunt_ ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud [[internal link]] exercitation ullamco laboris nisi ut [external link](https://google.com) aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. [[frontmatter 1]] Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Lorem ipsum `inline code looks like this` dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
```css
|
||||
This is a code block
|
||||
```
|
||||
|
||||
## Bold
|
||||
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
<strong>The quick brown fox jumps over the lazy dog.</strong>
|
||||
|
||||
## Italic
|
||||
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
<em>The quick brown fox jumps over the lazy dog.</em>
|
||||
|
||||
## Bold and Italic
|
||||
|
||||
**_The quick brown fox jumps over the lazy dog._**
|
||||
<strong><em>The quick brown fox jumps over the lazy dog.</em></strong>
|
||||
|
||||
## Blockquotes
|
||||
|
||||
> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
|
||||
|
||||
> The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||
|
||||
> **The quick brown fox** _jumps over the lazy dog._
|
||||
|
||||
## Monospaced
|
||||
|
||||
<samp>The quick brown fox jumps over the lazy dog.</samp>
|
||||
|
||||
## Underlined
|
||||
|
||||
<ins>The quick brown fox jumps over the lazy dog.</ins>
|
||||
|
||||
## Strike-through
|
||||
|
||||
~~The quick brown fox jumps over the lazy dog.~~
|
||||
|
||||
## sub and super
|
||||
|
||||
Subscript <sub>The quick brown fox jumps over the lazy dog.</sub>
|
||||
Superscript <sup>The quick brown fox jumps over the lazy dog.</sup>
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
A class method is an instance method of the class object. When a new class is created, an object of type `Class` is initialized and assigned to a global constant (Mobile in this case).
|
||||
|
||||
```
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```java
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```css
|
||||
button.mod-cta a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
| one | two | three |
|
||||
| ---- | :--: | ----- |
|
||||
| 9999 | 9999 | 9999 |
|
||||
| 1 | 2 | 3 |
|
||||
| 44 | 55 | 66 |
|
||||
|
||||
| Default | Left align | Center align | Right align |
|
||||
| ---------- | :--------- | :----------: | ----------: |
|
||||
| 9999999999 | 9999999999 | 9999999999 | 9999999999 |
|
||||
| 999999999 | 999999999 | 999999999 | 999999999 |
|
||||
| 99999999 | 99999999 | 99999999 | 99999999 |
|
||||
| 9999999 | 9999999 | 9999999 | 9999999 |
|
||||
|
||||
| A | B | C |
|
||||
| --- | --- | ----------------- |
|
||||
| 1 | 2 | 3 <br/> 4 <br/> 5 |
|
||||
|
||||
## Links
|
||||
|
||||
[The-Ultimate-Markdown-Cheat-Sheet](https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet)
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][reference text]
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][1]
|
||||
[Markdown-Cheat-Sheet]
|
||||
|
||||
[reference text]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[1]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[markdown-cheat-sheet]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
|
||||
[Example of a relative link](rl.md)
|
||||
Visit https://github.com/
|
||||
|
||||
## Images
|
||||
|
||||
![alt text][image]
|
||||
|
||||
<img src="https://media.giphy.com/media/qLHzYjlA2FW8g/giphy.gif" />
|
||||
|
||||
<img src="https://img.shields.io/badge/theultimatemarkdowncheatsheet-brightgreen.svg" />
|
||||
## Lists
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
1. One
|
||||
2. Two
|
||||
3. Three
|
||||
|
||||
## Multi-level Lists
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
1. First level
|
||||
1. Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
2. First level
|
||||
1. Second level
|
||||
3. First level
|
||||
1. Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- First level
|
||||
- Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
- First level
|
||||
- Second level
|
||||
- First level
|
||||
- Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- [x] Fix Bug 223 ✅ 2022-08-08
|
||||
- [x] Add Feature 33 ✅ 2022-08-08
|
||||
- [x] Add unit tests ✅ 2022-08-08
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
<!--
|
||||
Lorem ipsum dolor sit amet
|
||||
-->
|
||||
|
||||
- Asterisk
|
||||
\ Backslash
|
||||
` Backtick
|
||||
{} Curly braces
|
||||
. Dot
|
||||
! Exclamation mark
|
||||
|
||||
## Hash symbol
|
||||
|
||||
- Hyphen symbol
|
||||
() Parentheses
|
||||
|
||||
* Plus symbol
|
||||
[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
\* Asterisk
|
||||
\\ Backslash
|
||||
\` Backtick
|
||||
\{} Curly braces
|
||||
\. Dot
|
||||
\! Exclamation mark
|
||||
\# Hash symbol
|
||||
\- Hyphen symbol
|
||||
\() Parentheses
|
||||
\+ Plus symbol
|
||||
\[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
:octocat:
|
||||
|
||||
@lifeparticle
|
||||
|
||||
\#
|
||||
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 3.md
vendored
Normal file
255
tests/fixtures/sample_vault/01 frontmatter/frontmatter 3.md
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
---
|
||||
area: frontmatter
|
||||
date_created: 2022-12-22
|
||||
date_modified: 2022-10-01
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- food/fruit/pear
|
||||
- dinner
|
||||
- lunch
|
||||
- breakfast
|
||||
thoughts:
|
||||
rating: 8
|
||||
reviewable: false
|
||||
levels:
|
||||
level1:
|
||||
- level1a
|
||||
- level1b
|
||||
level2:
|
||||
- level2a
|
||||
- level2b
|
||||
author: John Doe
|
||||
status: new
|
||||
type: ["book", "article", "note"]
|
||||
---
|
||||
# Page Title H1
|
||||
|
||||
# Headings
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Heading 2
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
### Heading 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
#### Heading 4
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
##### Heading 5
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
###### Heading 6
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
## Text styles
|
||||
|
||||
Lorem ipsum **dolor sit amet**, consectetur adipisicing elit, sed do _eiusmod tempor incididunt_ ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud [[internal link]] exercitation ullamco laboris nisi ut [external link](https://google.com) aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. [[frontmatter 1]] Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Lorem ipsum `inline code looks like this` dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
```css
|
||||
This is a code block
|
||||
```
|
||||
|
||||
## Bold
|
||||
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
**The quick brown fox jumps over the lazy dog.**
|
||||
<strong>The quick brown fox jumps over the lazy dog.</strong>
|
||||
|
||||
## Italic
|
||||
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
_The quick brown fox jumps over the lazy dog._
|
||||
<em>The quick brown fox jumps over the lazy dog.</em>
|
||||
|
||||
## Bold and Italic
|
||||
|
||||
**_The quick brown fox jumps over the lazy dog._**
|
||||
<strong><em>The quick brown fox jumps over the lazy dog.</em></strong>
|
||||
|
||||
## Blockquotes
|
||||
|
||||
> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
|
||||
|
||||
> The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||
|
||||
> **The quick brown fox** _jumps over the lazy dog._
|
||||
|
||||
## Monospaced
|
||||
|
||||
<samp>The quick brown fox jumps over the lazy dog.</samp>
|
||||
|
||||
## Underlined
|
||||
|
||||
<ins>The quick brown fox jumps over the lazy dog.</ins>
|
||||
|
||||
## Strike-through
|
||||
|
||||
~~The quick brown fox jumps over the lazy dog.~~
|
||||
|
||||
## sub and super
|
||||
|
||||
Subscript <sub>The quick brown fox jumps over the lazy dog.</sub>
|
||||
Superscript <sup>The quick brown fox jumps over the lazy dog.</sup>
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
A class method is an instance method of the class object. When a new class is created, an object of type `Class` is initialized and assigned to a global constant (Mobile in this case).
|
||||
|
||||
```
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```java
|
||||
public static String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
```
|
||||
|
||||
```css
|
||||
button.mod-cta a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
| one | two | three |
|
||||
| ---- | :--: | ----- |
|
||||
| 9999 | 9999 | 9999 |
|
||||
| 1 | 2 | 3 |
|
||||
| 44 | 55 | 66 |
|
||||
|
||||
| Default | Left align | Center align | Right align |
|
||||
| ---------- | :--------- | :----------: | ----------: |
|
||||
| 9999999999 | 9999999999 | 9999999999 | 9999999999 |
|
||||
| 999999999 | 999999999 | 999999999 | 999999999 |
|
||||
| 99999999 | 99999999 | 99999999 | 99999999 |
|
||||
| 9999999 | 9999999 | 9999999 | 9999999 |
|
||||
|
||||
| A | B | C |
|
||||
| --- | --- | ----------------- |
|
||||
| 1 | 2 | 3 <br/> 4 <br/> 5 |
|
||||
|
||||
## Links
|
||||
|
||||
[The-Ultimate-Markdown-Cheat-Sheet](https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet)
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][reference text]
|
||||
[The-Ultimate-Markdown-Cheat-Sheet][1]
|
||||
[Markdown-Cheat-Sheet]
|
||||
|
||||
[reference text]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[1]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
[markdown-cheat-sheet]: https://github.com/lifeparticle/The-Ultimate-Markdown-Cheat-Sheet
|
||||
|
||||
[Example of a relative link](rl.md)
|
||||
Visit https://github.com/
|
||||
|
||||
## Images
|
||||
|
||||
![alt text][image]
|
||||
|
||||
<img src="https://media.giphy.com/media/qLHzYjlA2FW8g/giphy.gif" />
|
||||
|
||||
<img src="https://img.shields.io/badge/theultimatemarkdowncheatsheet-brightgreen.svg" />
|
||||
## Lists
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
1. One
|
||||
2. Two
|
||||
3. Three
|
||||
|
||||
## Multi-level Lists
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
1. First level
|
||||
1. Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
2. First level
|
||||
1. Second level
|
||||
3. First level
|
||||
1. Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- First level
|
||||
- Second level
|
||||
- Third level
|
||||
- Fourth level
|
||||
- First level
|
||||
- Second level
|
||||
- First level
|
||||
- Second level
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
- [x] Fix Bug 223 ✅ 2022-08-08
|
||||
- [x] Add Feature 33 ✅ 2022-08-08
|
||||
- [x] Add unit tests ✅ 2022-08-08
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
<!--
|
||||
Lorem ipsum dolor sit amet
|
||||
-->
|
||||
|
||||
- Asterisk
|
||||
\ Backslash
|
||||
` Backtick
|
||||
{} Curly braces
|
||||
. Dot
|
||||
! Exclamation mark
|
||||
|
||||
## Hash symbol
|
||||
|
||||
- Hyphen symbol
|
||||
() Parentheses
|
||||
|
||||
* Plus symbol
|
||||
[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
\* Asterisk
|
||||
\\ Backslash
|
||||
\` Backtick
|
||||
\{} Curly braces
|
||||
\. Dot
|
||||
\! Exclamation mark
|
||||
\# Hash symbol
|
||||
\- Hyphen symbol
|
||||
\() Parentheses
|
||||
\+ Plus symbol
|
||||
\[] Square brackets
|
||||
\_ Underscore
|
||||
|
||||
:octocat:
|
||||
|
||||
@lifeparticle
|
||||
|
||||
\#
|
||||
29
tests/fixtures/sample_vault/01 frontmatter/frontmatter 4.md
vendored
Normal file
29
tests/fixtures/sample_vault/01 frontmatter/frontmatter 4.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
area: frontmatter
|
||||
date_created: 2022-12-22
|
||||
date_modified: 2022-12-22
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- food/fruit/pear
|
||||
- dinner
|
||||
- lunch
|
||||
- breakfast
|
||||
thoughts:
|
||||
rating: 8
|
||||
reviewable: false
|
||||
levels:
|
||||
level1:
|
||||
- level1a
|
||||
- level1b
|
||||
level2:
|
||||
- level2a
|
||||
- level2b
|
||||
author: John Doe
|
||||
status: new
|
||||
type: ["book", "article", "note"]
|
||||
something_new_here: I-am-new
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
18
tests/fixtures/sample_vault/02 inline/inline 1.md
vendored
Normal file
18
tests/fixtures/sample_vault/02 inline/inline 1.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
area:: frontmatter
|
||||
date_created:: 2022-12-22
|
||||
date_modified:: 2022-12-22
|
||||
author:: John Doe
|
||||
status:: new
|
||||
type:: book
|
||||
type:: article
|
||||
#food/fruit/apple
|
||||
#food/fruit/pear
|
||||
#dinner #lunch #breakfast
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
18
tests/fixtures/sample_vault/02 inline/inline 2.md
vendored
Normal file
18
tests/fixtures/sample_vault/02 inline/inline 2.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
area:: frontmatter
|
||||
date_created:: 2022-12-22
|
||||
date_modified:: 2022-12-22
|
||||
author:: John Doe
|
||||
status:: new
|
||||
type:: book
|
||||
type:: article
|
||||
#food/fruit/apple
|
||||
#food/fruit/pear
|
||||
#dinner #lunch #breakfast
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
18
tests/fixtures/sample_vault/02 inline/inline 3.md
vendored
Normal file
18
tests/fixtures/sample_vault/02 inline/inline 3.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
area:: frontmatter
|
||||
date_created:: 2022-12-22
|
||||
date_modified:: 2022-12-22
|
||||
author:: John Doe
|
||||
status:: new
|
||||
type:: book
|
||||
type:: article
|
||||
#food/fruit/apple
|
||||
#food/fruit/pear
|
||||
#dinner #lunch #breakfast
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
18
tests/fixtures/sample_vault/02 inline/inline 4.md
vendored
Normal file
18
tests/fixtures/sample_vault/02 inline/inline 4.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
area:: frontmatter
|
||||
date_created:: 2022-12-22
|
||||
date_modified:: 2022-12-22
|
||||
author:: John Doe
|
||||
status:: new
|
||||
type:: book
|
||||
type:: article
|
||||
#food/fruit/apple
|
||||
#food/fruit/pear
|
||||
#dinner #lunch #breakfast
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
39
tests/fixtures/sample_vault/03 mixed/mixed 1.md
vendored
Normal file
39
tests/fixtures/sample_vault/03 mixed/mixed 1.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
date_created: 2022-12-22
|
||||
tags:
|
||||
- food/fruit/apple
|
||||
- dinner
|
||||
- breakfast
|
||||
- not_food
|
||||
author: John Doe
|
||||
nested_list:
|
||||
nested_list_one:
|
||||
- nested_list_one_a
|
||||
- nested_list_one_b
|
||||
type:
|
||||
- article
|
||||
- note
|
||||
---
|
||||
|
||||
area:: mixed
|
||||
date_modified:: 2022-12-22
|
||||
status:: new
|
||||
type:: book
|
||||
inline_key:: inline_key_value
|
||||
type:: [[article]]
|
||||
tags:: from_inline_metadata
|
||||
**bold_key**:: **bold** key value
|
||||
|
||||
|
||||
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, [in_text_key:: in-text value] eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? #inline_tag
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, #inline_tag2 cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
|
||||
|
||||
#food/fruit/pear
|
||||
#food/fruit/orange
|
||||
#dinner #breakfast
|
||||
#brunch
|
||||
5
tests/fixtures/sample_vault/04 no metadata/no_metadata_1.md
vendored
Normal file
5
tests/fixtures/sample_vault/04 no metadata/no_metadata_1.md
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.lLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repella
|
||||
8
tests/fixtures/sample_vault_config.toml
vendored
Normal file
8
tests/fixtures/sample_vault_config.toml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
vault = "tests/fixtures/sample_vault"
|
||||
|
||||
# folders to ignore when parsing content
|
||||
exclude_paths = [".git", ".obsidian", "ignore_folder"]
|
||||
|
||||
[metadata]
|
||||
metadata_location = "frontmatter" # "frontmatter", "top", "bottom"
|
||||
tags_location = "top" # "frontmatter", "top", "bottom"
|
||||
39
tests/fixtures/test_vault/ignore_folder/file_to_ignore.md
vendored
Normal file
39
tests/fixtures/test_vault/ignore_folder/file_to_ignore.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
date_created: 2022-12-22
|
||||
tags:
|
||||
- shared_tag
|
||||
- frontmatter_tag1
|
||||
- frontmatter_tag2
|
||||
- frontmatter_tag3
|
||||
- ignored_file_tag1
|
||||
author: author name
|
||||
type: ["article", "note"]
|
||||
---
|
||||
#inline_tag_top1 #inline_tag_top2
|
||||
#ignored_file_tag2
|
||||
|
||||
top_key1:: top_key1_value
|
||||
top_key2:: top_key2_value
|
||||
|
||||
# Heading 1
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. #intext_tag1 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla (#intext_tag2) pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est lab
|
||||
|
||||
```python
|
||||
#ffffff
|
||||
# This is sample text with tags and metadata
|
||||
#in_codeblock_tag1
|
||||
#ffffff;
|
||||
codeblock_key:: some text
|
||||
The quick brown fox jumped over the #in_codeblock_tag2
|
||||
```
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab `this is #inline_code_tag1` illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? `this is #inline_code_tag2` Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pari
|
||||
|
||||
|
||||
|
||||
bottom_key1:: bottom_key1_value
|
||||
bottom_key2:: bottom_key2_value
|
||||
|
||||
#inline_tag_bottom1
|
||||
#inline_tag_bottom2
|
||||
#shared_tag
|
||||
3
tests/fixtures/test_vault/no_metadata.md
vendored
Normal file
3
tests/fixtures/test_vault/no_metadata.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla paria
|
||||
44
tests/fixtures/test_vault/test1.md
vendored
Normal file
44
tests/fixtures/test_vault/test1.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
date_created: 2022-12-22
|
||||
tags:
|
||||
- shared_tag
|
||||
- frontmatter_tag1
|
||||
- frontmatter_tag2
|
||||
-
|
||||
- 📅/frontmatter_tag3
|
||||
frontmatter_Key1: author name
|
||||
frontmatter_Key2: ["article", "note"]
|
||||
shared_key1: shared_key1_value
|
||||
shared_key2: shared_key2_value1
|
||||
---
|
||||
|
||||
#inline_tag_top1 #inline_tag_top2
|
||||
|
||||
top_key1:: top_key1_value
|
||||
**top_key2:: top_key2_value**
|
||||
top_key3:: [[top_key3_value_as_link]]
|
||||
shared_key1:: shared_key1_value
|
||||
shared_key2:: shared_key2_value2
|
||||
emoji_📅_key:: emoji_📅_key_value
|
||||
|
||||
# Heading 1
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. #intext_tag1 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu [intext_key:: intext_value] fugiat nulla (#intext_tag2) pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est lab
|
||||
|
||||
```python
|
||||
#ffffff
|
||||
# This is sample text with tags and metadata
|
||||
#in_codeblock_tag1
|
||||
#ffffff;
|
||||
codeblock_key:: some text
|
||||
in_codeblock_key:: in_codeblock_value
|
||||
The quick brown fox jumped over the #in_codeblock_tag2
|
||||
```
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab `this is #inline_code_tag1` illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? `this is #inline_code_tag2` Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pari
|
||||
|
||||
bottom_key1:: bottom_key1_value
|
||||
bottom_key2:: bottom_key2_value
|
||||
|
||||
#inline_tag_bottom1
|
||||
#inline_tag_bottom2
|
||||
#shared_tag
|
||||
8
tests/fixtures/test_vault_config.toml
vendored
Normal file
8
tests/fixtures/test_vault_config.toml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
vault = "tests/fixtures/test_vault"
|
||||
|
||||
# folders to ignore when parsing content
|
||||
exclude_paths = [".git", ".obsidian", "ignore_folder"]
|
||||
|
||||
[metadata]
|
||||
metadata_location = "frontmatter" # "frontmatter", "top", "bottom"
|
||||
tags_location = "top" # "frontmatter", "top", "bottom"
|
||||
32
tests/helpers.py
Normal file
32
tests/helpers.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# type: ignore
|
||||
"""Helper functions for tests."""
|
||||
|
||||
import re
|
||||
|
||||
|
||||
class Regex:
|
||||
"""Assert that a given string meets some expectations.
|
||||
|
||||
Usage:
|
||||
from tests.helpers import Regex
|
||||
|
||||
assert caplog.text == Regex(r"^.*$", re.I)
|
||||
"""
|
||||
|
||||
def __init__(self, pattern, flags=0):
|
||||
self._regex = re.compile(pattern, flags)
|
||||
|
||||
def __eq__(self, actual):
|
||||
"""Define equality.
|
||||
|
||||
Args:
|
||||
actual (str): String to be matched to the regex
|
||||
|
||||
Returns:
|
||||
bool: True if the actual string matches the regex, False otherwise.
|
||||
"""
|
||||
return bool(self._regex.search(actual))
|
||||
|
||||
def __repr__(self):
|
||||
"""Error printed on failed tests."""
|
||||
return f"Regex: '{self._regex.pattern}'"
|
||||
491
tests/metadata_test.py
Normal file
491
tests/metadata_test.py
Normal file
@@ -0,0 +1,491 @@
|
||||
# type: ignore
|
||||
"""Test metadata.py."""
|
||||
from pathlib import Path
|
||||
|
||||
from obsidian_metadata.models.metadata import (
|
||||
Frontmatter,
|
||||
InlineMetadata,
|
||||
InlineTags,
|
||||
VaultMetadata,
|
||||
)
|
||||
from tests.helpers import Regex
|
||||
|
||||
FILE_CONTENT: str = Path("tests/fixtures/test_vault/test1.md").read_text()
|
||||
METADATA: dict[str, list[str]] = {
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["note", "article"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 2", "tag 1", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
}
|
||||
FRONTMATTER_CONTENT: str = """
|
||||
---
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
-
|
||||
- 📅/tag_3
|
||||
frontmatter_Key1: "frontmatter_Key1_value"
|
||||
frontmatter_Key2: ["note", "article"]
|
||||
shared_key1: "shared_key1_value"
|
||||
---
|
||||
more content
|
||||
|
||||
---
|
||||
horizontal: rule
|
||||
---
|
||||
"""
|
||||
INLINE_CONTENT = """\
|
||||
repeated_key:: repeated_key_value1
|
||||
|
||||
#inline_tag_top1,#inline_tag_top2
|
||||
**bold_key1**:: bold_key1_value
|
||||
**bold_key2:: bold_key2_value**
|
||||
link_key:: [[link_key_value]]
|
||||
tag_key:: #tag_key_value
|
||||
emoji_📅_key:: emoji_📅_key_value
|
||||
**#bold_tag**
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. [in_text_key1:: in_text_key1_value] Ut enim ad minim veniam, quis nostrud exercitation [in_text_key2:: in_text_key2_value] ullamco laboris nisi ut aliquip ex ea commodo consequat. #in_text_tag Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
```python
|
||||
#ffffff
|
||||
# This is sample text [no_key:: value]with tags and metadata
|
||||
#in_codeblock_tag1
|
||||
#ffffff;
|
||||
in_codeblock_key:: in_codeblock_value
|
||||
The quick brown fox jumped over the #in_codeblock_tag2
|
||||
```
|
||||
repeated_key:: repeated_key_value2
|
||||
"""
|
||||
|
||||
|
||||
def test_vault_metadata(capsys) -> None:
|
||||
"""Test VaultMetadata class."""
|
||||
vm = VaultMetadata()
|
||||
assert vm.dict == {}
|
||||
|
||||
vm.add_metadata(METADATA)
|
||||
assert vm.dict == {
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 1", "tag 2", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
}
|
||||
|
||||
vm.print_keys()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"frontmatter_Key1 +frontmatter_Key2 +intext_key")
|
||||
|
||||
vm.print_tags()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"tag 1 +tag 2 +tag 3")
|
||||
|
||||
vm.print_metadata()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"┃ Keys +┃ Values +┃")
|
||||
assert captured.out == Regex(r"│ +│ tag 3 +│")
|
||||
assert captured.out == Regex(r"│ frontmatter_Key1 +│ author name +│")
|
||||
|
||||
new_metadata = {"added_key": ["added_value"], "frontmatter_Key2": ["new_value"]}
|
||||
vm.add_metadata(new_metadata)
|
||||
assert vm.dict == {
|
||||
"added_key": ["added_value"],
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "new_value", "note"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 1", "tag 2", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
}
|
||||
|
||||
|
||||
def test_vault_metadata_contains() -> None:
|
||||
"""Test contains method."""
|
||||
vm = VaultMetadata()
|
||||
vm.add_metadata(METADATA)
|
||||
assert vm.dict == {
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 1", "tag 2", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
}
|
||||
|
||||
assert vm.contains("frontmatter_Key1") is True
|
||||
assert vm.contains("frontmatter_Key2", "article") is True
|
||||
assert vm.contains("frontmatter_Key3") is False
|
||||
assert vm.contains("frontmatter_Key2", "no value") is False
|
||||
assert vm.contains("1$", is_regex=True) is True
|
||||
assert vm.contains("5$", is_regex=True) is False
|
||||
assert vm.contains("tags", r"\d", is_regex=True) is True
|
||||
assert vm.contains("tags", r"^\d", is_regex=True) is False
|
||||
|
||||
|
||||
def test_vault_metadata_delete() -> None:
|
||||
"""Test delete method."""
|
||||
vm = VaultMetadata()
|
||||
vm.add_metadata(METADATA)
|
||||
assert vm.dict == {
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 1", "tag 2", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
}
|
||||
|
||||
assert vm.delete("no key") is False
|
||||
assert vm.delete("tags", "no value") is False
|
||||
assert vm.delete("tags", "tag 2") is True
|
||||
assert vm.dict["tags"] == ["tag 1", "tag 3"]
|
||||
assert vm.delete("tags") is True
|
||||
assert "tags" not in vm.dict
|
||||
|
||||
|
||||
def test_vault_metadata_rename() -> None:
|
||||
"""Test rename method."""
|
||||
vm = VaultMetadata()
|
||||
vm.add_metadata(METADATA)
|
||||
assert vm.dict == {
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"intext_key": ["intext_key_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value"],
|
||||
"tags": ["tag 1", "tag 2", "tag 3"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value"],
|
||||
}
|
||||
|
||||
assert vm.rename("no key", "new key") is False
|
||||
assert vm.rename("tags", "no tag", "new key") is False
|
||||
assert vm.rename("tags", "tag 2", "new tag") is True
|
||||
assert vm.dict["tags"] == ["new tag", "tag 1", "tag 3"]
|
||||
assert vm.rename("tags", "old_tags") is True
|
||||
assert vm.dict["old_tags"] == ["new tag", "tag 1", "tag 3"]
|
||||
assert "tags" not in vm.dict
|
||||
|
||||
|
||||
def test_frontmatter_create() -> None:
|
||||
"""Test frontmatter creation."""
|
||||
frontmatter = Frontmatter(INLINE_CONTENT)
|
||||
assert frontmatter.dict == {}
|
||||
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.dict == {
|
||||
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
||||
}
|
||||
assert frontmatter.dict_original == {
|
||||
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
||||
}
|
||||
|
||||
|
||||
def test_frontmatter_contains() -> None:
|
||||
"""Test frontmatter contains."""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
|
||||
assert frontmatter.contains("frontmatter_Key1") is True
|
||||
assert frontmatter.contains("frontmatter_Key2", "article") is True
|
||||
assert frontmatter.contains("frontmatter_Key3") is False
|
||||
assert frontmatter.contains("frontmatter_Key2", "no value") is False
|
||||
|
||||
assert frontmatter.contains(r"\d$", is_regex=True) is True
|
||||
assert frontmatter.contains(r"^\d", is_regex=True) is False
|
||||
assert frontmatter.contains("key", r"_\d", is_regex=True) is False
|
||||
assert frontmatter.contains("key", r"\w\d_", is_regex=True) is True
|
||||
|
||||
|
||||
def test_frontmatter_rename() -> None:
|
||||
"""Test frontmatter rename."""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.dict == {
|
||||
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
||||
}
|
||||
|
||||
assert frontmatter.rename("no key", "new key") is False
|
||||
assert frontmatter.rename("tags", "no tag", "new key") is False
|
||||
|
||||
assert frontmatter.has_changes() is False
|
||||
assert frontmatter.rename("tags", "tag_2", "new tag") is True
|
||||
|
||||
assert frontmatter.dict["tags"] == ["new tag", "tag_1", "📅/tag_3"]
|
||||
assert frontmatter.rename("tags", "old_tags") is True
|
||||
assert frontmatter.dict["old_tags"] == ["new tag", "tag_1", "📅/tag_3"]
|
||||
assert "tags" not in frontmatter.dict
|
||||
|
||||
assert frontmatter.has_changes() is True
|
||||
|
||||
|
||||
def test_frontmatter_delete() -> None:
|
||||
"""Test Frontmatter delete method."""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.dict == {
|
||||
"frontmatter_Key1": ["frontmatter_Key1_value"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"tags": ["tag_1", "tag_2", "📅/tag_3"],
|
||||
}
|
||||
|
||||
assert frontmatter.delete("no key") is False
|
||||
assert frontmatter.delete("tags", "no value") is False
|
||||
assert frontmatter.delete(r"\d{3}") is False
|
||||
assert frontmatter.has_changes() is False
|
||||
assert frontmatter.delete("tags", "tag_2") is True
|
||||
assert frontmatter.dict["tags"] == ["tag_1", "📅/tag_3"]
|
||||
assert frontmatter.delete("tags") is True
|
||||
assert "tags" not in frontmatter.dict
|
||||
assert frontmatter.has_changes() is True
|
||||
assert frontmatter.delete("shared_key1", r"\w+") is True
|
||||
assert frontmatter.dict["shared_key1"] == []
|
||||
assert frontmatter.delete(r"\w.tter") is True
|
||||
assert frontmatter.dict == {"shared_key1": []}
|
||||
|
||||
|
||||
def test_frontmatter_yaml_conversion():
|
||||
"""Test Frontmatter to_yaml method."""
|
||||
new_frontmatter: str = """\
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
- 📅/tag_3
|
||||
frontmatter_Key1: frontmatter_Key1_value
|
||||
frontmatter_Key2:
|
||||
- article
|
||||
- note
|
||||
shared_key1: shared_key1_value
|
||||
"""
|
||||
new_frontmatter_sorted: str = """\
|
||||
frontmatter_Key1: frontmatter_Key1_value
|
||||
frontmatter_Key2:
|
||||
- article
|
||||
- note
|
||||
shared_key1: shared_key1_value
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
- 📅/tag_3
|
||||
"""
|
||||
frontmatter = Frontmatter(FRONTMATTER_CONTENT)
|
||||
assert frontmatter.to_yaml() == new_frontmatter
|
||||
assert frontmatter.to_yaml(sort_keys=True) == new_frontmatter_sorted
|
||||
|
||||
|
||||
def test_inline_metadata_create() -> None:
|
||||
"""Test inline metadata creation."""
|
||||
inline = InlineMetadata(FRONTMATTER_CONTENT)
|
||||
assert inline.dict == {}
|
||||
inline = InlineMetadata(INLINE_CONTENT)
|
||||
assert inline.dict == {
|
||||
"bold_key1": ["bold_key1_value"],
|
||||
"bold_key2": ["bold_key2_value"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
assert inline.dict_original == {
|
||||
"bold_key1": ["bold_key1_value"],
|
||||
"bold_key2": ["bold_key2_value"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
|
||||
|
||||
def test_inline_contains() -> None:
|
||||
"""Test inline metadata contains method."""
|
||||
inline = InlineMetadata(INLINE_CONTENT)
|
||||
|
||||
assert inline.contains("bold_key1") is True
|
||||
assert inline.contains("bold_key2", "bold_key2_value") is True
|
||||
assert inline.contains("bold_key3") is False
|
||||
assert inline.contains("bold_key2", "no value") is False
|
||||
|
||||
assert inline.contains(r"\w{4}_key", is_regex=True) is True
|
||||
assert inline.contains(r"^\d", is_regex=True) is False
|
||||
assert inline.contains("1$", r"\d_value", is_regex=True) is True
|
||||
assert inline.contains("key", r"^\d_value", is_regex=True) is False
|
||||
|
||||
|
||||
def test_inline_metadata_rename() -> None:
|
||||
"""Test inline metadata rename."""
|
||||
inline = InlineMetadata(INLINE_CONTENT)
|
||||
assert inline.dict == {
|
||||
"bold_key1": ["bold_key1_value"],
|
||||
"bold_key2": ["bold_key2_value"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
|
||||
assert inline.rename("no key", "new key") is False
|
||||
assert inline.rename("repeated_key", "no value", "new key") is False
|
||||
assert inline.has_changes() is False
|
||||
assert inline.rename("repeated_key", "repeated_key_value1", "new value") is True
|
||||
assert inline.dict["repeated_key"] == ["new value", "repeated_key_value2"]
|
||||
assert inline.rename("repeated_key", "old_key") is True
|
||||
assert inline.dict["old_key"] == ["new value", "repeated_key_value2"]
|
||||
assert "repeated_key" not in inline.dict
|
||||
assert inline.has_changes() is True
|
||||
|
||||
|
||||
def test_inline_metadata_delete() -> None:
|
||||
"""Test inline metadata delete."""
|
||||
inline = InlineMetadata(INLINE_CONTENT)
|
||||
assert inline.dict == {
|
||||
"bold_key1": ["bold_key1_value"],
|
||||
"bold_key2": ["bold_key2_value"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"repeated_key": ["repeated_key_value1", "repeated_key_value2"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
|
||||
assert inline.delete("no key") is False
|
||||
assert inline.delete("repeated_key", "no value") is False
|
||||
assert inline.has_changes() is False
|
||||
assert inline.delete("repeated_key", "repeated_key_value1") is True
|
||||
assert inline.dict["repeated_key"] == ["repeated_key_value2"]
|
||||
assert inline.delete("repeated_key") is True
|
||||
assert "repeated_key" not in inline.dict
|
||||
assert inline.has_changes() is True
|
||||
assert inline.delete(r"\d{3}") is False
|
||||
assert inline.delete(r"bold_key\d") is True
|
||||
assert inline.dict == {
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
assert inline.delete("emoji_📅_key", ".*📅.*") is True
|
||||
assert inline.dict == {
|
||||
"emoji_📅_key": [],
|
||||
"in_text_key1": ["in_text_key1_value"],
|
||||
"in_text_key2": ["in_text_key2_value"],
|
||||
"link_key": ["link_key_value"],
|
||||
"tag_key": ["tag_key_value"],
|
||||
}
|
||||
|
||||
|
||||
def test_inline_tags_create() -> None:
|
||||
"""Test inline tags creation."""
|
||||
tags = InlineTags(FRONTMATTER_CONTENT)
|
||||
tags.metadata_key
|
||||
assert tags.list == []
|
||||
|
||||
tags = InlineTags(INLINE_CONTENT)
|
||||
assert tags.list == [
|
||||
"bold_tag",
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"tag_key_value",
|
||||
]
|
||||
assert tags.list_original == [
|
||||
"bold_tag",
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"tag_key_value",
|
||||
]
|
||||
|
||||
|
||||
def test_inline_tags_contains() -> None:
|
||||
"""Test inline tags contains."""
|
||||
tags = InlineTags(INLINE_CONTENT)
|
||||
assert tags.contains("bold_tag") is True
|
||||
assert tags.contains("no tag") is False
|
||||
|
||||
assert tags.contains(r"\w_\w", is_regex=True) is True
|
||||
assert tags.contains(r"\d_\d", is_regex=True) is False
|
||||
|
||||
|
||||
def test_inline_tags_rename() -> None:
|
||||
"""Test inline tags rename."""
|
||||
tags = InlineTags(INLINE_CONTENT)
|
||||
assert tags.list == [
|
||||
"bold_tag",
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"tag_key_value",
|
||||
]
|
||||
|
||||
assert tags.rename("no tag", "new tag") is False
|
||||
assert tags.has_changes() is False
|
||||
assert tags.rename("bold_tag", "new tag") is True
|
||||
assert tags.list == [
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"new tag",
|
||||
"tag_key_value",
|
||||
]
|
||||
assert tags.has_changes() is True
|
||||
|
||||
|
||||
def test_inline_tags_delete() -> None:
|
||||
"""Test inline tags delete."""
|
||||
tags = InlineTags(INLINE_CONTENT)
|
||||
assert tags.list == [
|
||||
"bold_tag",
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"tag_key_value",
|
||||
]
|
||||
|
||||
assert tags.delete("no tag") is False
|
||||
assert tags.has_changes() is False
|
||||
assert tags.delete("bold_tag") is True
|
||||
assert tags.list == [
|
||||
"in_text_tag",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"tag_key_value",
|
||||
]
|
||||
assert tags.has_changes() is True
|
||||
assert tags.delete(r"\d{3}") is False
|
||||
assert tags.delete(r"inline_tag_top\d") is True
|
||||
assert tags.list == ["in_text_tag", "tag_key_value"]
|
||||
358
tests/notes_test.py
Normal file
358
tests/notes_test.py
Normal file
@@ -0,0 +1,358 @@
|
||||
# type: ignore
|
||||
"""Test notes.py."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import typer
|
||||
|
||||
from obsidian_metadata.models.notes import Note
|
||||
from tests.helpers import Regex
|
||||
|
||||
|
||||
def test_note_not_exists() -> None:
|
||||
"""Test target not found."""
|
||||
with pytest.raises(typer.Exit):
|
||||
note = Note(note_path="nonexistent_file.md")
|
||||
|
||||
assert note.note_path == "tests/test_data/test_note.md"
|
||||
assert note.file_content == "This is a test note."
|
||||
assert note.frontmatter == {}
|
||||
assert note.inline_tags == []
|
||||
assert note.inline_metadata == {}
|
||||
assert note.dry_run is False
|
||||
|
||||
|
||||
def test_note_create(sample_note) -> None:
|
||||
"""Test creating note class."""
|
||||
note = Note(note_path=sample_note, dry_run=True)
|
||||
assert note.note_path == Path(sample_note)
|
||||
|
||||
assert note.dry_run is True
|
||||
assert "Lorem ipsum dolor" in note.file_content
|
||||
assert note.frontmatter.dict == {
|
||||
"date_created": ["2022-12-22"],
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value1"],
|
||||
"tags": [
|
||||
"frontmatter_tag1",
|
||||
"frontmatter_tag2",
|
||||
"shared_tag",
|
||||
"📅/frontmatter_tag3",
|
||||
],
|
||||
}
|
||||
|
||||
assert note.inline_tags.list == [
|
||||
"inline_tag_bottom1",
|
||||
"inline_tag_bottom2",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"intext_tag1",
|
||||
"intext_tag2",
|
||||
"shared_tag",
|
||||
]
|
||||
assert note.inline_metadata.dict == {
|
||||
"bottom_key1": ["bottom_key1_value"],
|
||||
"bottom_key2": ["bottom_key2_value"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"intext_key": ["intext_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value2"],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value_as_link"],
|
||||
}
|
||||
|
||||
with sample_note.open():
|
||||
content = sample_note.read_text()
|
||||
|
||||
assert note.file_content == content
|
||||
assert note.original_file_content == content
|
||||
|
||||
|
||||
def test_append(sample_note) -> None:
|
||||
"""Test appending to note."""
|
||||
note = Note(note_path=sample_note)
|
||||
assert note.dry_run is False
|
||||
|
||||
string = "This is a test string."
|
||||
string2 = "Lorem ipsum dolor sit"
|
||||
|
||||
note.append(string_to_append=string)
|
||||
assert string in note.file_content
|
||||
assert len(re.findall(re.escape(string), note.file_content)) == 1
|
||||
|
||||
note.append(string_to_append=string)
|
||||
assert string in note.file_content
|
||||
assert len(re.findall(re.escape(string), note.file_content)) == 1
|
||||
|
||||
note.append(string_to_append=string, allow_multiple=True)
|
||||
assert string in note.file_content
|
||||
assert len(re.findall(re.escape(string), note.file_content)) == 2
|
||||
|
||||
note.append(string_to_append=string2)
|
||||
assert string2 in note.file_content
|
||||
assert len(re.findall(re.escape(string2), note.file_content)) == 1
|
||||
|
||||
note.append(string_to_append=string2, allow_multiple=True)
|
||||
assert string2 in note.file_content
|
||||
assert len(re.findall(re.escape(string2), note.file_content)) == 2
|
||||
|
||||
|
||||
def test_contains_inline_tag(sample_note) -> None:
|
||||
"""Test contains inline tag."""
|
||||
note = Note(note_path=sample_note)
|
||||
assert note.contains_inline_tag("intext_tag1") is True
|
||||
assert note.contains_inline_tag("nonexistent_tag") is False
|
||||
assert note.contains_inline_tag(r"\d$", is_regex=True) is True
|
||||
assert note.contains_inline_tag(r"^\d", is_regex=True) is False
|
||||
|
||||
|
||||
def test_contains_metadata(sample_note) -> None:
|
||||
"""Test contains metadata."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.contains_metadata("no key") is False
|
||||
assert note.contains_metadata("frontmatter_Key2") is True
|
||||
assert note.contains_metadata(r"^\d", is_regex=True) is False
|
||||
assert note.contains_metadata(r"^[\w_]+\d", is_regex=True) is True
|
||||
assert note.contains_metadata("frontmatter_Key2", "no value") is False
|
||||
assert note.contains_metadata("frontmatter_Key2", "article") is True
|
||||
assert note.contains_metadata("bottom_key1", "bottom_key1_value") is True
|
||||
assert note.contains_metadata(r"bottom_key\d$", r"bottom_key\d_value", is_regex=True) is True
|
||||
|
||||
|
||||
def test_delete_inline_metadata(sample_note) -> None:
|
||||
"""Test deleting inline metadata."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
note._delete_inline_metadata("nonexistent_key")
|
||||
assert note.file_content == note.original_file_content
|
||||
note._delete_inline_metadata("frontmatter_Key1")
|
||||
assert note.file_content == note.original_file_content
|
||||
|
||||
note._delete_inline_metadata("intext_key")
|
||||
assert note.file_content == Regex(r"dolore eu fugiat", re.DOTALL)
|
||||
|
||||
note._delete_inline_metadata("bottom_key2", "bottom_key2_value")
|
||||
assert note.file_content != Regex(r"bottom_key2_value")
|
||||
assert note.file_content == Regex(r"bottom_key2::")
|
||||
note._delete_inline_metadata("bottom_key1")
|
||||
assert note.file_content != Regex(r"bottom_key1::")
|
||||
|
||||
|
||||
def test_delete_inline_tag(sample_note) -> None:
|
||||
"""Test deleting inline tags."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.delete_inline_tag("not_a_tag") is False
|
||||
assert note.delete_inline_tag("intext_tag[1]") is True
|
||||
assert "intext_tag1" not in note.inline_tags.list
|
||||
assert note.file_content == Regex("consequat. Duis")
|
||||
|
||||
|
||||
def test_delete_metadata(sample_note) -> Note:
|
||||
"""Test deleting metadata."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.delete_metadata("nonexistent_key") is False
|
||||
assert note.delete_metadata("frontmatter_Key1", "no value") is False
|
||||
assert note.delete_metadata("frontmatter_Key1") is True
|
||||
assert "frontmatter_Key1" not in note.frontmatter.dict
|
||||
|
||||
assert note.delete_metadata("frontmatter_Key2", "article") is True
|
||||
assert note.frontmatter.dict["frontmatter_Key2"] == ["note"]
|
||||
|
||||
assert note.delete_metadata("bottom_key1", "bottom_key1_value") is True
|
||||
assert note.inline_metadata.dict["bottom_key1"] == []
|
||||
assert note.file_content == Regex(r"bottom_key1::\n")
|
||||
|
||||
assert note.delete_metadata("bottom_key2") is True
|
||||
assert "bottom_key2" not in note.inline_metadata.dict
|
||||
assert note.file_content != Regex(r"bottom_key2")
|
||||
|
||||
|
||||
def test_has_changes(sample_note) -> None:
|
||||
"""Test has changes."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.has_changes() is False
|
||||
note.append("This is a test string.")
|
||||
assert note.has_changes() is True
|
||||
|
||||
note = Note(note_path=sample_note)
|
||||
assert note.has_changes() is False
|
||||
note.delete_metadata("frontmatter_Key1")
|
||||
assert note.has_changes() is True
|
||||
|
||||
note = Note(note_path=sample_note)
|
||||
assert note.has_changes() is False
|
||||
note.delete_metadata("bottom_key2")
|
||||
assert note.has_changes() is True
|
||||
|
||||
note = Note(note_path=sample_note)
|
||||
assert note.has_changes() is False
|
||||
note.delete_inline_tag("intext_tag1")
|
||||
assert note.has_changes() is True
|
||||
|
||||
|
||||
def test_print_note(sample_note, capsys) -> None:
|
||||
"""Test printing note."""
|
||||
note = Note(note_path=sample_note)
|
||||
note.print_note()
|
||||
captured = capsys.readouterr()
|
||||
assert "```python" in captured.out
|
||||
assert "---" in captured.out
|
||||
assert "#shared_tag" in captured.out
|
||||
|
||||
|
||||
def test_print_diff(sample_note, capsys) -> None:
|
||||
"""Test printing diff."""
|
||||
note = Note(note_path=sample_note)
|
||||
note.print_diff()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
note.append("This is a test string.")
|
||||
note.print_diff()
|
||||
captured = capsys.readouterr()
|
||||
assert "+ This is a test string." in captured.out
|
||||
|
||||
note.sub("The quick brown fox", "The quick brown hedgehog")
|
||||
note.print_diff()
|
||||
captured = capsys.readouterr()
|
||||
assert "- The quick brown fox" in captured.out
|
||||
assert "+ The quick brown hedgehog" in captured.out
|
||||
|
||||
|
||||
def test_sub(sample_note) -> None:
|
||||
"""Test substituting text in a note."""
|
||||
note = Note(note_path=sample_note)
|
||||
note.sub("#shared_tag", "#unshared_tags", is_regex=True)
|
||||
assert note.file_content != Regex(r"#shared_tag")
|
||||
assert note.file_content == Regex(r"#unshared_tags")
|
||||
|
||||
note.sub(" ut ", "")
|
||||
assert note.file_content != Regex(r" ut ")
|
||||
assert note.file_content == Regex(r"laboriosam, nisialiquid ex ea")
|
||||
|
||||
|
||||
def test_rename_inline_tag(sample_note) -> None:
|
||||
"""Test renaming an inline tag."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.rename_inline_tag("no_note_tag", "intext_tag2") is False
|
||||
assert note.rename_inline_tag("intext_tag1", "intext_tag26") is True
|
||||
assert note.inline_tags.list == [
|
||||
"inline_tag_bottom1",
|
||||
"inline_tag_bottom2",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"intext_tag2",
|
||||
"intext_tag26",
|
||||
"shared_tag",
|
||||
]
|
||||
assert note.file_content == Regex(r"#intext_tag26")
|
||||
assert note.file_content != Regex(r"#intext_tag1")
|
||||
|
||||
|
||||
def test_rename_inline_metadata(sample_note) -> None:
|
||||
"""Test renaming inline metadata."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
note._rename_inline_metadata("nonexistent_key", "new_key")
|
||||
assert note.file_content == note.original_file_content
|
||||
note._rename_inline_metadata("bottom_key1", "no_value", "new_value")
|
||||
assert note.file_content == note.original_file_content
|
||||
|
||||
note._rename_inline_metadata("bottom_key1", "new_key")
|
||||
assert note.file_content != Regex(r"bottom_key1::")
|
||||
assert note.file_content == Regex(r"new_key::")
|
||||
|
||||
note._rename_inline_metadata("emoji_📅_key", "emoji_📅_key_value", "new_value")
|
||||
assert note.file_content != Regex(r"emoji_📅_key:: ?emoji_📅_key_value")
|
||||
assert note.file_content == Regex(r"emoji_📅_key:: ?new_value")
|
||||
|
||||
|
||||
def test_rename_metadata(sample_note) -> None:
|
||||
"""Test renaming metadata."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
assert note.rename_metadata("nonexistent_key", "new_key") is False
|
||||
assert note.rename_metadata("frontmatter_Key1", "nonexistent_value", "article") is False
|
||||
|
||||
assert note.rename_metadata("frontmatter_Key1", "new_key") is True
|
||||
assert "frontmatter_Key1" not in note.frontmatter.dict
|
||||
assert "new_key" in note.frontmatter.dict
|
||||
assert note.frontmatter.dict["new_key"] == ["author name"]
|
||||
assert note.file_content == Regex(r"new_key: author name")
|
||||
|
||||
assert note.rename_metadata("frontmatter_Key2", "article", "new_key") is True
|
||||
assert note.frontmatter.dict["frontmatter_Key2"] == ["new_key", "note"]
|
||||
assert note.file_content == Regex(r" - new_key")
|
||||
assert note.file_content != Regex(r" - article")
|
||||
|
||||
assert note.rename_metadata("bottom_key1", "new_key") is True
|
||||
assert "bottom_key1" not in note.inline_metadata.dict
|
||||
assert "new_key" in note.inline_metadata.dict
|
||||
assert note.file_content == Regex(r"new_key:: bottom_key1_value")
|
||||
|
||||
assert note.rename_metadata("new_key", "bottom_key1_value", "new_value") is True
|
||||
assert note.inline_metadata.dict["new_key"] == ["new_value"]
|
||||
assert note.file_content == Regex(r"new_key:: new_value")
|
||||
|
||||
|
||||
def test_replace_frontmatter(sample_note) -> None:
|
||||
"""Test replacing frontmatter."""
|
||||
note = Note(note_path=sample_note)
|
||||
|
||||
note.rename_metadata("frontmatter_Key1", "author name", "some_new_key_here")
|
||||
note.replace_frontmatter()
|
||||
new_frontmatter = """---
|
||||
date_created: '2022-12-22'
|
||||
tags:
|
||||
- frontmatter_tag1
|
||||
- frontmatter_tag2
|
||||
- shared_tag
|
||||
- 📅/frontmatter_tag3
|
||||
frontmatter_Key1: some_new_key_here
|
||||
frontmatter_Key2:
|
||||
- article
|
||||
- note
|
||||
shared_key1: shared_key1_value
|
||||
shared_key2: shared_key2_value1
|
||||
---"""
|
||||
assert new_frontmatter in note.file_content
|
||||
assert "# Heading 1" in note.file_content
|
||||
assert "```python" in note.file_content
|
||||
|
||||
note2 = Note(note_path="tests/fixtures/test_vault/no_metadata.md")
|
||||
note2.replace_frontmatter()
|
||||
note2.frontmatter.dict = {"key1": "value1", "key2": "value2"}
|
||||
note2.replace_frontmatter()
|
||||
new_frontmatter = """---
|
||||
key1: value1
|
||||
key2: value2
|
||||
---"""
|
||||
assert new_frontmatter in note2.file_content
|
||||
assert "Lorem ipsum dolor sit amet" in note2.file_content
|
||||
|
||||
|
||||
def test_write(sample_note, tmp_path) -> None:
|
||||
"""Test writing note to file."""
|
||||
note = Note(note_path=sample_note)
|
||||
note.sub(pattern="Heading 1", replacement="Heading 2")
|
||||
|
||||
note.write()
|
||||
note = Note(note_path=sample_note)
|
||||
assert "Heading 2" in note.file_content
|
||||
assert "Heading 1" not in note.file_content
|
||||
|
||||
new_path = Path(tmp_path / "new_note.md")
|
||||
note.write(new_path)
|
||||
note2 = Note(note_path=new_path)
|
||||
assert "Heading 2" in note2.file_content
|
||||
assert "Heading 1" not in note2.file_content
|
||||
112
tests/patterns_test.py
Normal file
112
tests/patterns_test.py
Normal file
@@ -0,0 +1,112 @@
|
||||
# type: ignore
|
||||
"""Tests for the regex module."""
|
||||
|
||||
import pytest
|
||||
|
||||
from obsidian_metadata.models.patterns import Patterns
|
||||
|
||||
TAG_CONTENT: str = "#1 #2 **#3** [[#4]] [[#5|test]] #6#notag #7_8 #9/10 #11-12 #13; #14, #15. #16: #17* #18(#19) #20[#21] #22\\ #23& #24# #25 **#26** #📅/tag"
|
||||
INLINE_METADATA: str = """
|
||||
**1:: 1**
|
||||
2_2:: [[2_2]] | 2
|
||||
asdfasdf [3:: 3] asdfasdf [7::7] asdf
|
||||
[4:: 4] [5:: 5]
|
||||
> 6:: 6
|
||||
**8**:: **8**
|
||||
10::
|
||||
📅11:: 11/📅/11
|
||||
emoji_📅_key:: 📅emoji_📅_key_value
|
||||
"""
|
||||
FRONTMATTER_CONTENT: str = """
|
||||
---
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
-
|
||||
- 📅/tag_3
|
||||
frontmatter_Key1: "frontmatter_Key1_value"
|
||||
frontmatter_Key2: ["note", "article"]
|
||||
shared_key1: 'shared_key1_value'
|
||||
---
|
||||
more content
|
||||
|
||||
---
|
||||
horizontal: rule
|
||||
---
|
||||
"""
|
||||
CORRECT_FRONTMATTER_WITH_SEPARATORS: str = """---
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
-
|
||||
- 📅/tag_3
|
||||
frontmatter_Key1: "frontmatter_Key1_value"
|
||||
frontmatter_Key2: ["note", "article"]
|
||||
shared_key1: 'shared_key1_value'
|
||||
---"""
|
||||
CORRECT_FRONTMATTER_NO_SEPARATORS: str = """
|
||||
tags:
|
||||
- tag_1
|
||||
- tag_2
|
||||
-
|
||||
- 📅/tag_3
|
||||
frontmatter_Key1: "frontmatter_Key1_value"
|
||||
frontmatter_Key2: ["note", "article"]
|
||||
shared_key1: 'shared_key1_value'
|
||||
"""
|
||||
|
||||
|
||||
def test_regex():
|
||||
"""Test regexes."""
|
||||
pattern = Patterns()
|
||||
|
||||
assert pattern.find_inline_tags.findall(TAG_CONTENT) == [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7_8",
|
||||
"9/10",
|
||||
"11-12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
"17",
|
||||
"18",
|
||||
"19",
|
||||
"20",
|
||||
"21",
|
||||
"22",
|
||||
"23",
|
||||
"24",
|
||||
"25",
|
||||
"26",
|
||||
"📅/tag",
|
||||
]
|
||||
|
||||
result = pattern.find_inline_metadata.findall(INLINE_METADATA)
|
||||
assert result == [
|
||||
("", "", "1", "1**"),
|
||||
("", "", "2_2", "[[2_2]] | 2"),
|
||||
("3", "3", "", ""),
|
||||
("7", "7", "", ""),
|
||||
("", "", "4", "4] [5:: 5]"),
|
||||
("", "", "8**", "**8**"),
|
||||
("", "", "11", "11/📅/11"),
|
||||
("", "", "emoji_📅_key", "📅emoji_📅_key_value"),
|
||||
]
|
||||
|
||||
found = pattern.frontmatt_block_with_separators.search(FRONTMATTER_CONTENT).group("frontmatter")
|
||||
assert found == CORRECT_FRONTMATTER_WITH_SEPARATORS
|
||||
|
||||
found = pattern.frontmatt_block_no_separators.search(FRONTMATTER_CONTENT).group("frontmatter")
|
||||
assert found == CORRECT_FRONTMATTER_NO_SEPARATORS
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
pattern.frontmatt_block_no_separators.search(TAG_CONTENT).group("frontmatter")
|
||||
|
||||
assert pattern.validate_tag_text.search("test_tag") is None
|
||||
assert pattern.validate_tag_text.search("#asdf").group(0) == "#"
|
||||
116
tests/utilities_test.py
Normal file
116
tests/utilities_test.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# type: ignore
|
||||
"""Test the utilities module."""
|
||||
|
||||
|
||||
from obsidian_metadata._utils import (
|
||||
clean_dictionary,
|
||||
dict_contains,
|
||||
dict_values_to_lists_strings,
|
||||
remove_markdown_sections,
|
||||
vault_validation,
|
||||
)
|
||||
|
||||
|
||||
def test_dict_contains() -> None:
|
||||
"""Test dict_contains."""
|
||||
d = {"key1": ["value1", "value2"], "key2": ["value3", "value4"], "key3": ["value5", "value6"]}
|
||||
|
||||
assert dict_contains(d, "key1") is True
|
||||
assert dict_contains(d, "key5") is False
|
||||
assert dict_contains(d, "key1", "value1") is True
|
||||
assert dict_contains(d, "key1", "value5") is False
|
||||
assert dict_contains(d, "key[1-2]", is_regex=True) is True
|
||||
assert dict_contains(d, "^1", is_regex=True) is False
|
||||
assert dict_contains(d, r"key\d", r"value\d", is_regex=True) is True
|
||||
assert dict_contains(d, "key1$", "^alue", is_regex=True) is False
|
||||
assert dict_contains(d, r"key\d", "value5", is_regex=True) is True
|
||||
|
||||
|
||||
def test_dict_values_to_lists_strings():
|
||||
"""Test converting dictionary values to lists of strings."""
|
||||
dictionary = {
|
||||
"key1": "value1",
|
||||
"key2": ["value2", "value3", None],
|
||||
"key3": {"key4": "value4"},
|
||||
"key5": {"key6": {"key7": "value7"}},
|
||||
"key6": None,
|
||||
"key8": [1, 3, None, 4],
|
||||
"key9": [None, "", "None"],
|
||||
"key10": "None",
|
||||
"key11": "",
|
||||
}
|
||||
|
||||
result = dict_values_to_lists_strings(dictionary)
|
||||
assert result == {
|
||||
"key1": ["value1"],
|
||||
"key10": ["None"],
|
||||
"key11": [""],
|
||||
"key2": ["None", "value2", "value3"],
|
||||
"key3": {"key4": ["value4"]},
|
||||
"key5": {"key6": {"key7": ["value7"]}},
|
||||
"key6": ["None"],
|
||||
"key8": ["1", "3", "4", "None"],
|
||||
"key9": ["", "None", "None"],
|
||||
}
|
||||
|
||||
result = dict_values_to_lists_strings(dictionary, strip_null_values=True)
|
||||
assert result == {
|
||||
"key1": ["value1"],
|
||||
"key10": [],
|
||||
"key11": [],
|
||||
"key2": ["value2", "value3"],
|
||||
"key3": {"key4": ["value4"]},
|
||||
"key5": {"key6": {"key7": ["value7"]}},
|
||||
"key6": [],
|
||||
"key8": ["1", "3", "4"],
|
||||
"key9": ["", "None"],
|
||||
}
|
||||
|
||||
|
||||
def test_vault_validation():
|
||||
"""Test vault validation."""
|
||||
assert vault_validation("tests/") is True
|
||||
assert "Path is not a directory" in vault_validation("pyproject.toml")
|
||||
assert "Path does not exist" in vault_validation("tests/vault2")
|
||||
|
||||
|
||||
def test_remove_markdown_sections():
|
||||
"""Test removing markdown sections."""
|
||||
text: str = """
|
||||
---
|
||||
key: value
|
||||
---
|
||||
|
||||
Lorem ipsum `dolor sit` amet.
|
||||
|
||||
```bash
|
||||
echo "Hello World"
|
||||
```
|
||||
---
|
||||
dd
|
||||
---
|
||||
"""
|
||||
result = remove_markdown_sections(
|
||||
text,
|
||||
strip_codeblocks=True,
|
||||
strip_frontmatter=True,
|
||||
strip_inlinecode=True,
|
||||
)
|
||||
assert "```bash" not in result
|
||||
assert "`dolor sit`" not in result
|
||||
assert "---\nkey: value" not in result
|
||||
assert "`" not in result
|
||||
|
||||
result = remove_markdown_sections(text)
|
||||
assert "```bash" in result
|
||||
assert "`dolor sit`" in result
|
||||
assert "---\nkey: value" in result
|
||||
assert "`" in result
|
||||
|
||||
|
||||
def test_clean_dictionary():
|
||||
"""Test cleaning a dictionary."""
|
||||
dictionary = {" *key* ": ["**value**", "[[value2]]", "#value3"]}
|
||||
|
||||
new_dict = clean_dictionary(dictionary)
|
||||
assert new_dict == {"key": ["value", "value2", "value3"]}
|
||||
248
tests/vault_test.py
Normal file
248
tests/vault_test.py
Normal file
@@ -0,0 +1,248 @@
|
||||
# type: ignore
|
||||
"""Tests for the Vault module."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from obsidian_metadata._config import Config
|
||||
from obsidian_metadata.models import Vault
|
||||
from tests.helpers import Regex
|
||||
|
||||
|
||||
def test_vault_creation(test_vault):
|
||||
"""Test creating a Vault object."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.vault_path == vault_path
|
||||
assert vault.backup_path == Path(f"{vault_path}.bak")
|
||||
assert vault.new_vault_path == Path(f"{vault_path}.new")
|
||||
assert vault.dry_run is False
|
||||
assert str(vault.exclude_paths[0]) == Regex(r".*\.git")
|
||||
assert vault.num_notes() == 2
|
||||
|
||||
assert vault.metadata.dict == {
|
||||
"Inline Tags": [
|
||||
"inline_tag_bottom1",
|
||||
"inline_tag_bottom2",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"intext_tag1",
|
||||
"intext_tag2",
|
||||
"shared_tag",
|
||||
],
|
||||
"bottom_key1": ["bottom_key1_value"],
|
||||
"bottom_key2": ["bottom_key2_value"],
|
||||
"date_created": ["2022-12-22"],
|
||||
"emoji_📅_key": ["emoji_📅_key_value"],
|
||||
"frontmatter_Key1": ["author name"],
|
||||
"frontmatter_Key2": ["article", "note"],
|
||||
"intext_key": ["intext_value"],
|
||||
"shared_key1": ["shared_key1_value"],
|
||||
"shared_key2": ["shared_key2_value1", "shared_key2_value2"],
|
||||
"tags": [
|
||||
"frontmatter_tag1",
|
||||
"frontmatter_tag2",
|
||||
"shared_tag",
|
||||
"📅/frontmatter_tag3",
|
||||
],
|
||||
"top_key1": ["top_key1_value"],
|
||||
"top_key2": ["top_key2_value"],
|
||||
"top_key3": ["top_key3_value_as_link"],
|
||||
}
|
||||
|
||||
|
||||
def test_get_filtered_notes(sample_vault) -> None:
|
||||
"""Test filtering notes."""
|
||||
vault_path = sample_vault
|
||||
config = Config(config_path="tests/fixtures/sample_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config, path_filter="front")
|
||||
|
||||
assert vault.num_notes() == 4
|
||||
|
||||
vault_path = sample_vault
|
||||
config = Config(config_path="tests/fixtures/sample_vault_config.toml", vault_path=vault_path)
|
||||
vault2 = Vault(config=config, path_filter="mixed")
|
||||
|
||||
assert vault2.num_notes() == 1
|
||||
|
||||
|
||||
def test_backup(test_vault, capsys):
|
||||
"""Test backing up the vault."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config, dry_run=False)
|
||||
|
||||
vault.backup()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert Path(f"{vault_path}.bak").exists() is True
|
||||
assert captured.out == Regex(r"SUCCESS +| backed up to")
|
||||
|
||||
vault.info()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"Backup path +\│[\s ]+/[\d\w]+")
|
||||
|
||||
|
||||
def test_backup_dryrun(test_vault, capsys):
|
||||
"""Test backing up the vault."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config, dry_run=True)
|
||||
|
||||
print(f"vault.dry_run: {vault.dry_run}")
|
||||
vault.backup()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert vault.backup_path.exists() is False
|
||||
assert captured.out == Regex(r"DRYRUN +| Backup up vault to")
|
||||
|
||||
|
||||
def test_delete_backup(test_vault, capsys):
|
||||
"""Test deleting the vault backup."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config, dry_run=False)
|
||||
|
||||
vault.backup()
|
||||
vault.delete_backup()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"Backup deleted")
|
||||
assert vault.backup_path.exists() is False
|
||||
|
||||
vault.info()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"Backup +\│ None")
|
||||
|
||||
|
||||
def test_delete_backup_dryrun(test_vault, capsys):
|
||||
"""Test deleting the vault backup."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config, dry_run=True)
|
||||
|
||||
Path.mkdir(vault.backup_path)
|
||||
vault.delete_backup()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"DRYRUN +| Delete backup")
|
||||
assert vault.backup_path.exists() is True
|
||||
|
||||
|
||||
def test_info(test_vault, capsys):
|
||||
"""Test printing vault information."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
vault.info()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == Regex(r"Vault +\│ /[\d\w]+")
|
||||
assert captured.out == Regex(r"Notes being edited +\│ \d+")
|
||||
assert captured.out == Regex(r"Backup +\│ None")
|
||||
|
||||
|
||||
def test_contains_inline_tag(test_vault) -> None:
|
||||
"""Test if the vault contains an inline tag."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.contains_inline_tag("tag") is False
|
||||
assert vault.contains_inline_tag("intext_tag2") is True
|
||||
|
||||
|
||||
def test_contains_metadata(test_vault) -> None:
|
||||
"""Test if the vault contains a metadata key."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.contains_metadata("key") is False
|
||||
assert vault.contains_metadata("top_key1") is True
|
||||
assert vault.contains_metadata("top_key1", "no_value") is False
|
||||
assert vault.contains_metadata("top_key1", "top_key1_value") is True
|
||||
|
||||
|
||||
def test_delete_inline_tag(test_vault) -> None:
|
||||
"""Test deleting an inline tag."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.delete_inline_tag("no tag") is False
|
||||
assert vault.delete_inline_tag("intext_tag2") is True
|
||||
assert vault.metadata.dict["Inline Tags"] == [
|
||||
"inline_tag_bottom1",
|
||||
"inline_tag_bottom2",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"intext_tag1",
|
||||
"shared_tag",
|
||||
]
|
||||
|
||||
|
||||
def test_delete_metadata(test_vault) -> None:
|
||||
"""Test deleting a metadata key/value."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.delete_metadata("no key") == 0
|
||||
assert vault.delete_metadata("top_key1", "no_value") == 0
|
||||
|
||||
assert vault.delete_metadata("top_key1", "top_key1_value") == 1
|
||||
assert vault.metadata.dict["top_key1"] == []
|
||||
|
||||
assert vault.delete_metadata("top_key2") == 1
|
||||
assert "top_key2" not in vault.metadata.dict
|
||||
|
||||
|
||||
def test_rename_inline_tag(test_vault) -> None:
|
||||
"""Test renaming an inline tag."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.rename_inline_tag("no tag", "new_tag") is False
|
||||
assert vault.rename_inline_tag("intext_tag2", "new_tag") is True
|
||||
assert vault.metadata.dict["Inline Tags"] == [
|
||||
"inline_tag_bottom1",
|
||||
"inline_tag_bottom2",
|
||||
"inline_tag_top1",
|
||||
"inline_tag_top2",
|
||||
"intext_tag1",
|
||||
"new_tag",
|
||||
"shared_tag",
|
||||
]
|
||||
|
||||
|
||||
def test_rename_metadata(test_vault) -> None:
|
||||
"""Test renaming a metadata key/value."""
|
||||
vault_path = test_vault
|
||||
config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path)
|
||||
vault = Vault(config=config)
|
||||
|
||||
assert vault.rename_metadata("no key", "new_key") is False
|
||||
assert vault.rename_metadata("tags", "nonexistent_value", "new_vaule") is False
|
||||
|
||||
assert vault.rename_metadata("tags", "frontmatter_tag1", "new_vaule") is True
|
||||
assert vault.metadata.dict["tags"] == [
|
||||
"frontmatter_tag2",
|
||||
"new_vaule",
|
||||
"shared_tag",
|
||||
"📅/frontmatter_tag3",
|
||||
]
|
||||
|
||||
assert vault.rename_metadata("tags", "new_key") is True
|
||||
assert "tags" not in vault.metadata.dict
|
||||
assert vault.metadata.dict["new_key"] == [
|
||||
"frontmatter_tag2",
|
||||
"new_vaule",
|
||||
"shared_tag",
|
||||
"📅/frontmatter_tag3",
|
||||
]
|
||||
Reference in New Issue
Block a user