logseq-md 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
logseq_md/__init__.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Read and write file-based Logseq markdown graphs.
|
|
2
|
+
|
|
3
|
+
A Logseq file graph is a directory of markdown: `pages/` for topics, `journals/`
|
|
4
|
+
for dates, one block per bullet, nested by indentation. This package reads that
|
|
5
|
+
shape and writes back into it without reformatting the parts it did not touch.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|
|
11
|
+
|
|
12
|
+
#: Resolved from the installed distribution rather than written here, so there is
|
|
13
|
+
#: one version in the repository and the release job owns it. A source checkout
|
|
14
|
+
#: that was never installed has no distribution metadata, and reports that rather
|
|
15
|
+
#: than guessing.
|
|
16
|
+
try: # pragma: no cover - the except branch needs an uninstalled checkout
|
|
17
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
18
|
+
|
|
19
|
+
__version__ = version("logseq-md")
|
|
20
|
+
except PackageNotFoundError: # pragma: no cover
|
|
21
|
+
__version__ = "0.0.0+unknown"
|
logseq_md/__main__.py
ADDED
logseq_md/cli.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""The command line entry point.
|
|
2
|
+
|
|
3
|
+
Nothing reads a graph yet. What is here is the parser, the version flag and the
|
|
4
|
+
exit convention, which is what the packaging, the entry point and the smoke test
|
|
5
|
+
in CI need in order to be checked before there is anything to check them on.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import sys
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
|
|
14
|
+
from logseq_md import __version__
|
|
15
|
+
|
|
16
|
+
#: Exit codes. `2` is argparse's own code for a usage error and is not reused
|
|
17
|
+
#: here for anything else, so a caller can tell "you asked wrongly" from "the
|
|
18
|
+
#: graph said no".
|
|
19
|
+
OK = 0
|
|
20
|
+
FAILED = 1
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
24
|
+
"""The argument parser, built separately so a test can inspect it."""
|
|
25
|
+
parser = argparse.ArgumentParser(
|
|
26
|
+
prog="logseq-md",
|
|
27
|
+
description="Read and write file-based Logseq markdown graphs.",
|
|
28
|
+
)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--version",
|
|
31
|
+
action="version",
|
|
32
|
+
version=f"%(prog)s {__version__}",
|
|
33
|
+
)
|
|
34
|
+
return parser
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
38
|
+
"""Run the command and return its exit code.
|
|
39
|
+
|
|
40
|
+
Returning rather than exiting keeps the whole command testable in-process;
|
|
41
|
+
`run` is the thin wrapper the console script points at.
|
|
42
|
+
"""
|
|
43
|
+
parser = build_parser()
|
|
44
|
+
parser.parse_args(argv)
|
|
45
|
+
parser.print_help()
|
|
46
|
+
return OK
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def run() -> None:
|
|
50
|
+
"""Console script entry point."""
|
|
51
|
+
sys.exit(main())
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: logseq-md
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Read and write file-based Logseq markdown graphs from the command line
|
|
5
|
+
Project-URL: Homepage, https://github.com/ftschindler/logseq-md
|
|
6
|
+
Project-URL: Source, https://github.com/ftschindler/logseq-md
|
|
7
|
+
Project-URL: Issues, https://github.com/ftschindler/logseq-md/issues
|
|
8
|
+
Author: Felix Schindler
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,logseq,markdown,notes,outliner
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# logseq-md
|
|
27
|
+
|
|
28
|
+
Read and write file-based Logseq markdown graphs from the command line.
|
|
29
|
+
|
|
30
|
+
A Logseq file graph is a directory of markdown: `pages/` for topics, `journals/` for dates, one
|
|
31
|
+
block per bullet, nested by indentation, with `property:: value` lines, `[[page]]` links and
|
|
32
|
+
`((uuid))` block references. Ordinary tools read it well enough. Writing back into it is where
|
|
33
|
+
they go wrong.
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
uvx logseq-md --help
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
That needs no install beyond [uv](https://docs.astral.sh/uv/).
|
|
40
|
+
|
|
41
|
+
**Pre-alpha.** The packaging, the entry point and the guard suite are in place. Nothing reads a
|
|
42
|
+
graph yet.
|
|
43
|
+
|
|
44
|
+
## What this is for
|
|
45
|
+
|
|
46
|
+
Agents and scripts that work against a graph the owner also edits by hand, in the app, on more
|
|
47
|
+
than one machine.
|
|
48
|
+
|
|
49
|
+
The constraint that shapes everything here: **a write changes the bytes it meant to change and
|
|
50
|
+
no others.** Every library in this space parses a page into a tree and serialises the tree back
|
|
51
|
+
over the file, which is correct in the sense that Logseq still reads it, and wrong in three
|
|
52
|
+
ways that matter.
|
|
53
|
+
|
|
54
|
+
- A one-line status append arrives as a thousand-line diff, so nobody reviews it.
|
|
55
|
+
- A graph is usually not a git repository, so a reflow is damage with no way back.
|
|
56
|
+
- A graph that syncs between devices gets conflicts, and a conflict between two files that each
|
|
57
|
+
changed one line is a mechanical merge, while a conflict where one side reflowed everything
|
|
58
|
+
cannot be merged by anything, including a person.
|
|
59
|
+
|
|
60
|
+
So the write path here splices lines into the file it was given. The round-trip test is the
|
|
61
|
+
acceptance criterion rather than a nicety: parse every file in a graph, write it back unchanged,
|
|
62
|
+
and assert the bytes are identical.
|
|
63
|
+
|
|
64
|
+
## What it will not do
|
|
65
|
+
|
|
66
|
+
It knows about blocks, markers, properties, references, pages, journals and ids. It knows
|
|
67
|
+
nothing about what you use them for. There is no notion of a task queue, no integration with any
|
|
68
|
+
forge, no opinion about which of your graphs is private, and no daemon resolving sync conflicts.
|
|
69
|
+
|
|
70
|
+
The test of that boundary: every verb and flag is expressible in Logseq's own vocabulary. A flag
|
|
71
|
+
that needs a word Logseq does not have belongs in whatever is calling this, not here.
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
make bootstrap # install the pre-commit hooks into this clone
|
|
77
|
+
make test # run the suite
|
|
78
|
+
make check # run the full guard suite over every file
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) has the system requirements.
|
|
82
|
+
|
|
83
|
+
## Licence
|
|
84
|
+
|
|
85
|
+
[MIT](LICENSE).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
logseq_md/__init__.py,sha256=VxWAMuCSP1NKvAHLthpKq6WEIPO0-GET3Q89YhSFenQ,887
|
|
2
|
+
logseq_md/__main__.py,sha256=1WBom-HwSw32_q7LRYvEByKypNtzbol9eT3gdQ1h2Xw,170
|
|
3
|
+
logseq_md/cli.py,sha256=pUmqpEKibSOk3C2OrlrFr3sfbD4ws-WacDYdMehj7MI,1436
|
|
4
|
+
logseq_md-0.1.0.dist-info/METADATA,sha256=mIZs40ukkZvYUyWW8lO2Luq2gqqQ4WZyplGkC149mx0,3456
|
|
5
|
+
logseq_md-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
6
|
+
logseq_md-0.1.0.dist-info/entry_points.txt,sha256=N3sfgVSFJmrXiVnp2fWkr3nxZZRgv7NnhZNtEUugDHc,48
|
|
7
|
+
logseq_md-0.1.0.dist-info/licenses/LICENSE,sha256=45jm7nlf5VUNKHLwv_-x2ouCadL8HXXC5BVs6Pw_NsM,1079
|
|
8
|
+
logseq_md-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 logseq-md contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|