jsonmd 0.1.0__tar.gz
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.
- jsonmd-0.1.0/PKG-INFO +133 -0
- jsonmd-0.1.0/README.md +120 -0
- jsonmd-0.1.0/setup.cfg +4 -0
- jsonmd-0.1.0/setup.py +14 -0
- jsonmd-0.1.0/src/jsonmd/__init__.py +3 -0
- jsonmd-0.1.0/src/jsonmd/core.py +148 -0
- jsonmd-0.1.0/src/jsonmd.egg-info/PKG-INFO +133 -0
- jsonmd-0.1.0/src/jsonmd.egg-info/SOURCES.txt +9 -0
- jsonmd-0.1.0/src/jsonmd.egg-info/dependency_links.txt +1 -0
- jsonmd-0.1.0/src/jsonmd.egg-info/requires.txt +1 -0
- jsonmd-0.1.0/src/jsonmd.egg-info/top_level.txt +1 -0
jsonmd-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonmd
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: JSON/JSON5 loader and dumper with raw multiline markdown block support
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: json5>=0.12.0
|
|
8
|
+
Dynamic: description
|
|
9
|
+
Dynamic: description-content-type
|
|
10
|
+
Dynamic: requires-dist
|
|
11
|
+
Dynamic: requires-python
|
|
12
|
+
Dynamic: summary
|
|
13
|
+
|
|
14
|
+
# jsonmd
|
|
15
|
+
|
|
16
|
+
# 背景
|
|
17
|
+
|
|
18
|
+
在人机协作时代,提示词和结构化文本配置会被开发者与 AI 代理高频共同编辑。
|
|
19
|
+
可读性和低摩擦编辑能力会直接影响迭代速度与交付质量。
|
|
20
|
+
|
|
21
|
+
`jsonmd` 用来解决 JSON 不支持原生多行字符串的问题。
|
|
22
|
+
|
|
23
|
+
通过 `<md>...</md>` 语法标记,你可以在 JSON/JSON5 中嵌入原始多行文本块
|
|
24
|
+
(例如 Markdown),而不需要使用 `\n` 转义符。
|
|
25
|
+
|
|
26
|
+
这让在配置文件中存储富文本更直观、可读性更高。
|
|
27
|
+
|
|
28
|
+
示例:
|
|
29
|
+
|
|
30
|
+
```json5
|
|
31
|
+
{
|
|
32
|
+
content: <md># Title
|
|
33
|
+
- item
|
|
34
|
+
</md>
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
而不是:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"content": "# Title\n- item"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
安装:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install /path/to/lib/jsonmd
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
开发时可编辑安装:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install -e /path/to/lib/jsonmd
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
使用:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from jsonmd import loads, dumps
|
|
62
|
+
|
|
63
|
+
text = """
|
|
64
|
+
{
|
|
65
|
+
content: <md># Title
|
|
66
|
+
- item
|
|
67
|
+
</md>
|
|
68
|
+
}
|
|
69
|
+
"""
|
|
70
|
+
data = loads(text)
|
|
71
|
+
|
|
72
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
# Background
|
|
76
|
+
|
|
77
|
+
In the era of human-AI collaboration, prompts and structured text configs are
|
|
78
|
+
edited frequently by both developers and AI agents. Readability and low-friction
|
|
79
|
+
editing directly affect iteration speed and quality.
|
|
80
|
+
|
|
81
|
+
`jsonmd` solves the problem that JSON does not support native multiline strings.
|
|
82
|
+
|
|
83
|
+
With `<md>...</md>` block markers, you can embed raw multiline text
|
|
84
|
+
(for example Markdown) in JSON/JSON5 without `\n` escaping.
|
|
85
|
+
|
|
86
|
+
This makes rich text in config files easier to read and maintain.
|
|
87
|
+
|
|
88
|
+
Example:
|
|
89
|
+
|
|
90
|
+
```json5
|
|
91
|
+
{
|
|
92
|
+
content: <md># Title
|
|
93
|
+
- item
|
|
94
|
+
</md>
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
instead of:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"content": "# Title\n- item"
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Install:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install /path/to/lib/jsonmd
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Editable install for development:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install -e /path/to/lib/jsonmd
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Usage:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from jsonmd import loads, dumps
|
|
122
|
+
|
|
123
|
+
text = """
|
|
124
|
+
{
|
|
125
|
+
content: <md># Title
|
|
126
|
+
- item
|
|
127
|
+
</md>
|
|
128
|
+
}
|
|
129
|
+
"""
|
|
130
|
+
data = loads(text)
|
|
131
|
+
|
|
132
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
133
|
+
```
|
jsonmd-0.1.0/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# jsonmd
|
|
2
|
+
|
|
3
|
+
# 背景
|
|
4
|
+
|
|
5
|
+
在人机协作时代,提示词和结构化文本配置会被开发者与 AI 代理高频共同编辑。
|
|
6
|
+
可读性和低摩擦编辑能力会直接影响迭代速度与交付质量。
|
|
7
|
+
|
|
8
|
+
`jsonmd` 用来解决 JSON 不支持原生多行字符串的问题。
|
|
9
|
+
|
|
10
|
+
通过 `<md>...</md>` 语法标记,你可以在 JSON/JSON5 中嵌入原始多行文本块
|
|
11
|
+
(例如 Markdown),而不需要使用 `\n` 转义符。
|
|
12
|
+
|
|
13
|
+
这让在配置文件中存储富文本更直观、可读性更高。
|
|
14
|
+
|
|
15
|
+
示例:
|
|
16
|
+
|
|
17
|
+
```json5
|
|
18
|
+
{
|
|
19
|
+
content: <md># Title
|
|
20
|
+
- item
|
|
21
|
+
</md>
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
而不是:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"content": "# Title\n- item"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
安装:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install /path/to/lib/jsonmd
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
开发时可编辑安装:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install -e /path/to/lib/jsonmd
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
使用:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from jsonmd import loads, dumps
|
|
49
|
+
|
|
50
|
+
text = """
|
|
51
|
+
{
|
|
52
|
+
content: <md># Title
|
|
53
|
+
- item
|
|
54
|
+
</md>
|
|
55
|
+
}
|
|
56
|
+
"""
|
|
57
|
+
data = loads(text)
|
|
58
|
+
|
|
59
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
# Background
|
|
63
|
+
|
|
64
|
+
In the era of human-AI collaboration, prompts and structured text configs are
|
|
65
|
+
edited frequently by both developers and AI agents. Readability and low-friction
|
|
66
|
+
editing directly affect iteration speed and quality.
|
|
67
|
+
|
|
68
|
+
`jsonmd` solves the problem that JSON does not support native multiline strings.
|
|
69
|
+
|
|
70
|
+
With `<md>...</md>` block markers, you can embed raw multiline text
|
|
71
|
+
(for example Markdown) in JSON/JSON5 without `\n` escaping.
|
|
72
|
+
|
|
73
|
+
This makes rich text in config files easier to read and maintain.
|
|
74
|
+
|
|
75
|
+
Example:
|
|
76
|
+
|
|
77
|
+
```json5
|
|
78
|
+
{
|
|
79
|
+
content: <md># Title
|
|
80
|
+
- item
|
|
81
|
+
</md>
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
instead of:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"content": "# Title\n- item"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Install:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install /path/to/lib/jsonmd
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Editable install for development:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pip install -e /path/to/lib/jsonmd
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Usage:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from jsonmd import loads, dumps
|
|
109
|
+
|
|
110
|
+
text = """
|
|
111
|
+
{
|
|
112
|
+
content: <md># Title
|
|
113
|
+
- item
|
|
114
|
+
</md>
|
|
115
|
+
}
|
|
116
|
+
"""
|
|
117
|
+
data = loads(text)
|
|
118
|
+
|
|
119
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
120
|
+
```
|
jsonmd-0.1.0/setup.cfg
ADDED
jsonmd-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from setuptools import find_packages, setup
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
setup(
|
|
5
|
+
name="jsonmd",
|
|
6
|
+
version="0.1.0",
|
|
7
|
+
description="JSON/JSON5 loader and dumper with raw multiline markdown block support",
|
|
8
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
9
|
+
long_description_content_type="text/markdown",
|
|
10
|
+
python_requires=">=3.9",
|
|
11
|
+
package_dir={"": "src"},
|
|
12
|
+
packages=find_packages("src"),
|
|
13
|
+
install_requires=["json5>=0.12.0"],
|
|
14
|
+
)
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
import warnings
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, TextIO
|
|
8
|
+
|
|
9
|
+
import json5
|
|
10
|
+
|
|
11
|
+
_MD_BLOCK_RE = re.compile(
|
|
12
|
+
r"(?P<prefix>:\s*)<<<(?P<tag>[A-Z][A-Z0-9_-]*)[ \t]*\n"
|
|
13
|
+
r"(?P<body>.*?)\n"
|
|
14
|
+
r"(?P=tag)(?=\s*[,}\]])",
|
|
15
|
+
re.S,
|
|
16
|
+
)
|
|
17
|
+
_ANGLE_BLOCK_RE = re.compile(
|
|
18
|
+
r"(?P<prefix>:\s*)<(?P<tag>[a-z][a-z0-9_-]*)>"
|
|
19
|
+
r"(?P<body>.*?)"
|
|
20
|
+
r"</(?P=tag)>(?P<tail>.*?)(?=\s*[,}\]])",
|
|
21
|
+
re.S,
|
|
22
|
+
)
|
|
23
|
+
_IDENT_RE = re.compile(r"^[A-Za-z_$][A-Za-z0-9_$]*$")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _rewrite_markdown_blocks(text: str) -> str:
|
|
27
|
+
def repl_heredoc(match: re.Match[str]) -> str:
|
|
28
|
+
body = match.group("body")
|
|
29
|
+
return match.group("prefix") + json.dumps(body, ensure_ascii=False)
|
|
30
|
+
|
|
31
|
+
def repl_angle(match: re.Match[str]) -> str:
|
|
32
|
+
body = match.group("body")
|
|
33
|
+
tail = match.group("tail")
|
|
34
|
+
if tail.strip():
|
|
35
|
+
tag = match.group("tag")
|
|
36
|
+
warnings.warn(
|
|
37
|
+
f"Potential early </{tag}> close detected; "
|
|
38
|
+
"trailing content before separator was included as text.",
|
|
39
|
+
stacklevel=2,
|
|
40
|
+
)
|
|
41
|
+
body += tail
|
|
42
|
+
return match.group("prefix") + json.dumps(body, ensure_ascii=False)
|
|
43
|
+
|
|
44
|
+
out = _ANGLE_BLOCK_RE.sub(repl_angle, text)
|
|
45
|
+
out = _MD_BLOCK_RE.sub(repl_heredoc, out)
|
|
46
|
+
return out
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def loads(text: str) -> Any:
|
|
50
|
+
rewritten = _rewrite_markdown_blocks(text)
|
|
51
|
+
return json5.loads(rewritten)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def load(path: str | Path, encoding: str = "utf-8") -> Any:
|
|
55
|
+
with open(path, "r", encoding=encoding) as f:
|
|
56
|
+
return loads(f.read())
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _choose_md_tag(text: str, base_tag: str = "MD") -> str:
|
|
60
|
+
lines = set(text.splitlines())
|
|
61
|
+
if base_tag not in lines:
|
|
62
|
+
return base_tag
|
|
63
|
+
|
|
64
|
+
i = 2
|
|
65
|
+
while True:
|
|
66
|
+
candidate = f"{base_tag}{i}"
|
|
67
|
+
if candidate not in lines:
|
|
68
|
+
return candidate
|
|
69
|
+
i += 1
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _choose_angle_tag(text: str, base_tag: str = "md") -> str:
|
|
73
|
+
tag = base_tag
|
|
74
|
+
i = 2
|
|
75
|
+
while f"</{tag}>" in text:
|
|
76
|
+
tag = f"{base_tag}{i}"
|
|
77
|
+
i += 1
|
|
78
|
+
return tag
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _dump_key(key: str) -> str:
|
|
82
|
+
return key if _IDENT_RE.match(key) else json5.dumps(key)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _dump_value(
|
|
86
|
+
value: Any,
|
|
87
|
+
indent: int,
|
|
88
|
+
level: int,
|
|
89
|
+
md_tag: str,
|
|
90
|
+
block_style: str,
|
|
91
|
+
) -> str:
|
|
92
|
+
if isinstance(value, dict):
|
|
93
|
+
if not value:
|
|
94
|
+
return "{}"
|
|
95
|
+
pad = " " * (indent * level)
|
|
96
|
+
child_pad = " " * (indent * (level + 1))
|
|
97
|
+
items = []
|
|
98
|
+
for k, v in value.items():
|
|
99
|
+
items.append(
|
|
100
|
+
f"{child_pad}{_dump_key(str(k))}: "
|
|
101
|
+
f"{_dump_value(v, indent, level + 1, md_tag, block_style)}"
|
|
102
|
+
)
|
|
103
|
+
return "{\n" + ",\n".join(items) + f"\n{pad}}}"
|
|
104
|
+
|
|
105
|
+
if isinstance(value, list):
|
|
106
|
+
if not value:
|
|
107
|
+
return "[]"
|
|
108
|
+
pad = " " * (indent * level)
|
|
109
|
+
child_pad = " " * (indent * (level + 1))
|
|
110
|
+
items = [
|
|
111
|
+
f"{child_pad}{_dump_value(v, indent, level + 1, md_tag, block_style)}"
|
|
112
|
+
for v in value
|
|
113
|
+
]
|
|
114
|
+
return "[\n" + ",\n".join(items) + f"\n{pad}]"
|
|
115
|
+
|
|
116
|
+
if isinstance(value, str) and "\n" in value:
|
|
117
|
+
if block_style == "angle":
|
|
118
|
+
tag = _choose_angle_tag(value, md_tag)
|
|
119
|
+
return f"<{tag}>{value}</{tag}>"
|
|
120
|
+
tag = _choose_md_tag(value, md_tag.upper())
|
|
121
|
+
return f"<<<{tag}\n{value}\n{tag}"
|
|
122
|
+
|
|
123
|
+
return json5.dumps(value, ensure_ascii=False)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def dumps(
|
|
127
|
+
value: Any,
|
|
128
|
+
*,
|
|
129
|
+
indent: int = 2,
|
|
130
|
+
md_tag: str = "md",
|
|
131
|
+
block_style: str = "angle",
|
|
132
|
+
) -> str:
|
|
133
|
+
if block_style not in {"angle", "heredoc"}:
|
|
134
|
+
raise ValueError("block_style must be 'angle' or 'heredoc'")
|
|
135
|
+
return _dump_value(
|
|
136
|
+
value, indent=indent, level=0, md_tag=md_tag, block_style=block_style
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def dump(
|
|
141
|
+
value: Any,
|
|
142
|
+
fp: TextIO,
|
|
143
|
+
*,
|
|
144
|
+
indent: int = 2,
|
|
145
|
+
md_tag: str = "md",
|
|
146
|
+
block_style: str = "angle",
|
|
147
|
+
) -> None:
|
|
148
|
+
fp.write(dumps(value, indent=indent, md_tag=md_tag, block_style=block_style))
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonmd
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: JSON/JSON5 loader and dumper with raw multiline markdown block support
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: json5>=0.12.0
|
|
8
|
+
Dynamic: description
|
|
9
|
+
Dynamic: description-content-type
|
|
10
|
+
Dynamic: requires-dist
|
|
11
|
+
Dynamic: requires-python
|
|
12
|
+
Dynamic: summary
|
|
13
|
+
|
|
14
|
+
# jsonmd
|
|
15
|
+
|
|
16
|
+
# 背景
|
|
17
|
+
|
|
18
|
+
在人机协作时代,提示词和结构化文本配置会被开发者与 AI 代理高频共同编辑。
|
|
19
|
+
可读性和低摩擦编辑能力会直接影响迭代速度与交付质量。
|
|
20
|
+
|
|
21
|
+
`jsonmd` 用来解决 JSON 不支持原生多行字符串的问题。
|
|
22
|
+
|
|
23
|
+
通过 `<md>...</md>` 语法标记,你可以在 JSON/JSON5 中嵌入原始多行文本块
|
|
24
|
+
(例如 Markdown),而不需要使用 `\n` 转义符。
|
|
25
|
+
|
|
26
|
+
这让在配置文件中存储富文本更直观、可读性更高。
|
|
27
|
+
|
|
28
|
+
示例:
|
|
29
|
+
|
|
30
|
+
```json5
|
|
31
|
+
{
|
|
32
|
+
content: <md># Title
|
|
33
|
+
- item
|
|
34
|
+
</md>
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
而不是:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"content": "# Title\n- item"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
安装:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install /path/to/lib/jsonmd
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
开发时可编辑安装:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install -e /path/to/lib/jsonmd
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
使用:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from jsonmd import loads, dumps
|
|
62
|
+
|
|
63
|
+
text = """
|
|
64
|
+
{
|
|
65
|
+
content: <md># Title
|
|
66
|
+
- item
|
|
67
|
+
</md>
|
|
68
|
+
}
|
|
69
|
+
"""
|
|
70
|
+
data = loads(text)
|
|
71
|
+
|
|
72
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
# Background
|
|
76
|
+
|
|
77
|
+
In the era of human-AI collaboration, prompts and structured text configs are
|
|
78
|
+
edited frequently by both developers and AI agents. Readability and low-friction
|
|
79
|
+
editing directly affect iteration speed and quality.
|
|
80
|
+
|
|
81
|
+
`jsonmd` solves the problem that JSON does not support native multiline strings.
|
|
82
|
+
|
|
83
|
+
With `<md>...</md>` block markers, you can embed raw multiline text
|
|
84
|
+
(for example Markdown) in JSON/JSON5 without `\n` escaping.
|
|
85
|
+
|
|
86
|
+
This makes rich text in config files easier to read and maintain.
|
|
87
|
+
|
|
88
|
+
Example:
|
|
89
|
+
|
|
90
|
+
```json5
|
|
91
|
+
{
|
|
92
|
+
content: <md># Title
|
|
93
|
+
- item
|
|
94
|
+
</md>
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
instead of:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"content": "# Title\n- item"
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Install:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install /path/to/lib/jsonmd
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Editable install for development:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install -e /path/to/lib/jsonmd
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Usage:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from jsonmd import loads, dumps
|
|
122
|
+
|
|
123
|
+
text = """
|
|
124
|
+
{
|
|
125
|
+
content: <md># Title
|
|
126
|
+
- item
|
|
127
|
+
</md>
|
|
128
|
+
}
|
|
129
|
+
"""
|
|
130
|
+
data = loads(text)
|
|
131
|
+
|
|
132
|
+
encoded = dumps({"content": "# Title\n- item"})
|
|
133
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json5>=0.12.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jsonmd
|