qparse 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.
- qmd_cli.py +262 -0
- qparse/__init__.py +16 -0
- qparse/docx_render/__init__.py +3 -0
- qparse/docx_render/docx_render.py +68 -0
- qparse/docx_render/write_buffer.py +412 -0
- qparse/markdwon_document/__init__.py +28 -0
- qparse/markdwon_document/analysis_document.py +40 -0
- qparse/markdwon_document/base_document.py +87 -0
- qparse/markdwon_document/markdwon_document.py +16 -0
- qparse/markdwon_document/nodes/__init__.py +5 -0
- qparse/markdwon_document/nodes/answer_node.py +97 -0
- qparse/markdwon_document/nodes/base_node.py +51 -0
- qparse/markdwon_document/nodes/img_node.py +31 -0
- qparse/markdwon_document/nodes/text_node.py +139 -0
- qparse/markdwon_document/question_document.py +17 -0
- qparse/markdwon_document/stem_document.py +64 -0
- qparse/markdwon_document/table_document.py +126 -0
- qparse/markdwon_loader.py +189 -0
- qparse/markdwon_render.py +123 -0
- qparse/qmd_packer.py +475 -0
- qparse/qmd_unpacker.py +169 -0
- qparse/render_option/__init__.py +40 -0
- qparse/render_option/default_render_option.py +86 -0
- qparse/render_option/default_render_template.md +21 -0
- qparse/render_option/referance.docx +0 -0
- qparse/render_option/theme.json +245 -0
- qparse/utils/__init__.py +3 -0
- qparse/utils/html_full_protector.py +154 -0
- qparse-0.1.0.dist-info/METADATA +454 -0
- qparse-0.1.0.dist-info/RECORD +34 -0
- qparse-0.1.0.dist-info/WHEEL +5 -0
- qparse-0.1.0.dist-info/entry_points.txt +2 -0
- qparse-0.1.0.dist-info/licenses/LICENSE +21 -0
- qparse-0.1.0.dist-info/top_level.txt +2 -0
qparse/qmd_unpacker.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""将 .qmd 文件解包为可编辑的工作目录。"""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import shutil
|
|
9
|
+
import zipfile
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, List, Optional
|
|
12
|
+
from uuid import uuid4
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class QmdUnpacker:
|
|
16
|
+
"""
|
|
17
|
+
解压 .qmd 包:
|
|
18
|
+
1. 展开 documents / resources / themes / templates
|
|
19
|
+
2. 按 manifest 将资源复制到对应 Markdown 同级的 assets/
|
|
20
|
+
3. 返回解包目录与入口 render.md 路径
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
IMAGE_PATTERN = re.compile(r"!\[([^\]]*)\]\(([^)]+)\)")
|
|
24
|
+
HTML_IMG_PATTERN = re.compile(
|
|
25
|
+
r'<img\b[^>]*\bsrc\s*=\s*["\']([^"\']+)["\'][^>]*>',
|
|
26
|
+
re.IGNORECASE,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def __init__(self, package: str):
|
|
30
|
+
self.package_path = Path(package).resolve()
|
|
31
|
+
if not self.package_path.exists():
|
|
32
|
+
raise FileNotFoundError(f"qmd 包不存在: {self.package_path}")
|
|
33
|
+
if not zipfile.is_zipfile(self.package_path):
|
|
34
|
+
raise ValueError(f"不是有效的 qmd 压缩包: {self.package_path}")
|
|
35
|
+
|
|
36
|
+
self.manifest: dict = {}
|
|
37
|
+
self.target_dir: Optional[Path] = None
|
|
38
|
+
|
|
39
|
+
def unpack(self, target: Optional[str] = None) -> Path:
|
|
40
|
+
"""
|
|
41
|
+
解包到目标目录。
|
|
42
|
+
|
|
43
|
+
:param target: 目标目录。为空时创建到包旁的 .qmd_runtime/<uuid>
|
|
44
|
+
:return: 解包后的根目录
|
|
45
|
+
"""
|
|
46
|
+
if target:
|
|
47
|
+
self.target_dir = Path(target).resolve()
|
|
48
|
+
else:
|
|
49
|
+
self.target_dir = (
|
|
50
|
+
self.package_path.parent
|
|
51
|
+
/ ".qmd_runtime"
|
|
52
|
+
/ uuid4().hex
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if self.target_dir.exists():
|
|
56
|
+
shutil.rmtree(self.target_dir)
|
|
57
|
+
self.target_dir.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
with zipfile.ZipFile(self.package_path, "r") as zf:
|
|
60
|
+
zf.extractall(self.target_dir)
|
|
61
|
+
|
|
62
|
+
manifest_path = self.target_dir / "manifest.json"
|
|
63
|
+
if not manifest_path.exists():
|
|
64
|
+
raise FileNotFoundError(
|
|
65
|
+
f"缺少 manifest.json: {manifest_path}"
|
|
66
|
+
)
|
|
67
|
+
self.manifest = json.loads(
|
|
68
|
+
manifest_path.read_text(encoding="utf-8")
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
self._materialize_document_assets()
|
|
72
|
+
return self.target_dir
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def entry_path(self) -> Path:
|
|
76
|
+
if self.target_dir is None:
|
|
77
|
+
raise RuntimeError("请先调用 unpack()")
|
|
78
|
+
entry = self.manifest.get("entry", "render.md")
|
|
79
|
+
path = self.target_dir / entry
|
|
80
|
+
if not path.exists():
|
|
81
|
+
raise FileNotFoundError(f"入口文件不存在: {path}")
|
|
82
|
+
return path
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def resources_dir(self) -> Path:
|
|
86
|
+
if self.target_dir is None:
|
|
87
|
+
raise RuntimeError("请先调用 unpack()")
|
|
88
|
+
return self.target_dir / "resources"
|
|
89
|
+
|
|
90
|
+
def get_resource_path(self, sha256: str) -> Optional[Path]:
|
|
91
|
+
resources = self.manifest.get("resources", {})
|
|
92
|
+
item = resources.get(sha256)
|
|
93
|
+
if not item:
|
|
94
|
+
return None
|
|
95
|
+
path = self.target_dir / item["path"]
|
|
96
|
+
return path if path.exists() else None
|
|
97
|
+
|
|
98
|
+
def _materialize_document_assets(self) -> None:
|
|
99
|
+
"""
|
|
100
|
+
按需将 resources 中的文件复制到文档同级 assets/,
|
|
101
|
+
方便编辑器直接预览图片。
|
|
102
|
+
"""
|
|
103
|
+
document_assets: Dict[str, List[str]] = self.manifest.get(
|
|
104
|
+
"document_assets",
|
|
105
|
+
{},
|
|
106
|
+
)
|
|
107
|
+
resources: Dict[str, dict] = self.manifest.get("resources", {})
|
|
108
|
+
|
|
109
|
+
if document_assets:
|
|
110
|
+
for doc_rel, sha_list in document_assets.items():
|
|
111
|
+
doc_path = self.target_dir / doc_rel
|
|
112
|
+
if not doc_path.exists():
|
|
113
|
+
continue
|
|
114
|
+
assets_dir = doc_path.parent / "assets"
|
|
115
|
+
assets_dir.mkdir(parents=True, exist_ok=True)
|
|
116
|
+
for sha in sha_list:
|
|
117
|
+
item = resources.get(sha)
|
|
118
|
+
if not item:
|
|
119
|
+
continue
|
|
120
|
+
source = self.target_dir / item["path"]
|
|
121
|
+
if not source.exists():
|
|
122
|
+
continue
|
|
123
|
+
target = assets_dir / Path(item["path"]).name
|
|
124
|
+
if not target.exists():
|
|
125
|
+
shutil.copy2(source, target)
|
|
126
|
+
return
|
|
127
|
+
|
|
128
|
+
# 兼容没有 document_assets 字段的旧包:扫描 Markdown 中的 ./assets/ 引用
|
|
129
|
+
for md_path in self.target_dir.rglob("*.md"):
|
|
130
|
+
text = md_path.read_text(encoding="utf-8")
|
|
131
|
+
names = set()
|
|
132
|
+
for match in self.IMAGE_PATTERN.finditer(text):
|
|
133
|
+
url = match.group(2).strip().split(" ", 1)[0]
|
|
134
|
+
name = self._asset_name_from_url(url)
|
|
135
|
+
if name:
|
|
136
|
+
names.add(name)
|
|
137
|
+
for match in self.HTML_IMG_PATTERN.finditer(text):
|
|
138
|
+
name = self._asset_name_from_url(match.group(1))
|
|
139
|
+
if name:
|
|
140
|
+
names.add(name)
|
|
141
|
+
if not names:
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
assets_dir = md_path.parent / "assets"
|
|
145
|
+
assets_dir.mkdir(parents=True, exist_ok=True)
|
|
146
|
+
for name in names:
|
|
147
|
+
source = self.resources_dir / name
|
|
148
|
+
if not source.exists():
|
|
149
|
+
# 也可能在 templates/
|
|
150
|
+
alt = self.target_dir / "templates" / name
|
|
151
|
+
source = alt if alt.exists() else source
|
|
152
|
+
if source.exists():
|
|
153
|
+
target = assets_dir / name
|
|
154
|
+
if not target.exists():
|
|
155
|
+
shutil.copy2(source, target)
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _asset_name_from_url(url: str) -> Optional[str]:
|
|
159
|
+
value = url.strip().strip('"').strip("'")
|
|
160
|
+
if not value:
|
|
161
|
+
return None
|
|
162
|
+
if value.startswith("http://") or value.startswith("https://"):
|
|
163
|
+
return None
|
|
164
|
+
path = Path(value.replace("\\", "/"))
|
|
165
|
+
if path.parts and path.parts[0] in {".", "..", "assets"}:
|
|
166
|
+
return path.name
|
|
167
|
+
if "assets/" in value.replace("\\", "/"):
|
|
168
|
+
return path.name
|
|
169
|
+
return None
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import json
|
|
4
|
+
from .default_render_option import get_default_render_option,SafeGetRenderOption,default_referance_path
|
|
5
|
+
from jinja2 import Environment
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
# 全局复用jinja环境,不要每次新建
|
|
8
|
+
_qeditor_jinja_env = Environment(
|
|
9
|
+
variable_start_string="[%",
|
|
10
|
+
variable_end_string="%]",
|
|
11
|
+
block_start_string="{%",
|
|
12
|
+
block_end_string="%}",
|
|
13
|
+
comment_start_string="{#",
|
|
14
|
+
comment_end_string="#}",
|
|
15
|
+
autoescape=True,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def render_template(template_text: str, context: dict) -> str:
|
|
19
|
+
"""
|
|
20
|
+
模板渲染,占位符:[% var_name %]
|
|
21
|
+
:param template_text: 原始模板字符串,包含 [% label %] [% text %]
|
|
22
|
+
:param context: 字典 {"label":"xxx","text":"yyy"}
|
|
23
|
+
:return: 渲染完成后的字符串
|
|
24
|
+
"""
|
|
25
|
+
tpl = _qeditor_jinja_env.from_string(template_text)
|
|
26
|
+
return tpl.render(**context)
|
|
27
|
+
|
|
28
|
+
def get_default_theme():
|
|
29
|
+
fdir = Path(__file__).parent/"theme.json"
|
|
30
|
+
with open(fdir,'r',encoding='utf-8') as fp:
|
|
31
|
+
themes = json.load(fp=fp)
|
|
32
|
+
for theme_key,option in themes.items():
|
|
33
|
+
|
|
34
|
+
option['docx'].update({"referance":default_referance_path.as_posix()})
|
|
35
|
+
return themes
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
DEFAULT_RENDER_OPTION = get_default_render_option()
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import copy
|
|
3
|
+
from typing import List
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
default_referance_path = Path(__file__).parent / "referance.docx"
|
|
6
|
+
|
|
7
|
+
def SafeGetRenderOption(option:dict,path:List[str],default=None):
|
|
8
|
+
node_option = option
|
|
9
|
+
for p in path:
|
|
10
|
+
if node_option:= node_option.get(p,None):
|
|
11
|
+
pass
|
|
12
|
+
else:
|
|
13
|
+
return default
|
|
14
|
+
return node_option
|
|
15
|
+
|
|
16
|
+
def get_default_render_option():
|
|
17
|
+
default_render_option = {
|
|
18
|
+
"docx":{
|
|
19
|
+
'referance':default_referance_path.as_posix(),
|
|
20
|
+
"markdwon-table": {
|
|
21
|
+
"width_percent": 100,
|
|
22
|
+
"style": "Table Grid",
|
|
23
|
+
"header_bold": True,
|
|
24
|
+
"header_shading": "D9EAF7",
|
|
25
|
+
"border_color": "B7C9D6",
|
|
26
|
+
"cell_alignment": "center",
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"markdown": {
|
|
30
|
+
"head": {
|
|
31
|
+
"downgrade_heading_level": True,
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"question": {
|
|
35
|
+
"show_answer": False,
|
|
36
|
+
"stem": {
|
|
37
|
+
"show": True,
|
|
38
|
+
"keep_together":True,
|
|
39
|
+
"::first-text-visible": {
|
|
40
|
+
"template": "[%question_id%]、[%text%]",
|
|
41
|
+
'[answer_types="multiple-choice"]':{
|
|
42
|
+
"template": "[%question_id%](多选)、[%text%]"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
'[answer_types="multiple-choice"]':{
|
|
46
|
+
"template": "[%text%]"
|
|
47
|
+
},
|
|
48
|
+
'[answer_types="choice"]':{
|
|
49
|
+
"template": "[%text%]"
|
|
50
|
+
},
|
|
51
|
+
'[answer_types="blank"]':{
|
|
52
|
+
"template": "[%text%]\n\n\n\n"
|
|
53
|
+
},
|
|
54
|
+
'[answer_types="answer"]':{
|
|
55
|
+
"template": "[%text%]\n\n\n\n"
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
"analysis": {
|
|
59
|
+
"show": False,
|
|
60
|
+
"::first-text-visible": {
|
|
61
|
+
"template": "[% text %]"
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
".answer": {
|
|
65
|
+
":show_answer": {"template": "[%text%]"},
|
|
66
|
+
":not_show_answer": {"template": ""},
|
|
67
|
+
},
|
|
68
|
+
".blank": {
|
|
69
|
+
":show_answer": {"template": "[%text%]"},
|
|
70
|
+
":not_show_answer": {"template": " $\\underline{\\hspace{1.8cm}}$ "},
|
|
71
|
+
},
|
|
72
|
+
".choise": {
|
|
73
|
+
":show_answer": {"template": "( [% text %] )"},
|
|
74
|
+
":not_show_answer": {"template": "( )"},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
".multiple-choice": {
|
|
78
|
+
":show_answer": {"template": "([%text%])"},
|
|
79
|
+
":not_show_answer": {"template": "( )"},
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
return copy.deepcopy(default_render_option)
|
|
85
|
+
|
|
86
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<params>
|
|
2
|
+
<var name="markdwon_src" value="[%markdwon_src%]" type="str">
|
|
3
|
+
<!--markdwon 主文件入口-->
|
|
4
|
+
</var>
|
|
5
|
+
<var name="docx_referance" value="[%docx_referance%]" type="str">
|
|
6
|
+
<!--markdwon docx模板样式-->
|
|
7
|
+
</var>
|
|
8
|
+
<var name="render_options" value="[%render_options%]" type="str">
|
|
9
|
+
<!--渲染主题,一般用json 格式存储-->
|
|
10
|
+
</var>
|
|
11
|
+
|
|
12
|
+
</params>
|
|
13
|
+
<system-params>
|
|
14
|
+
<!--markdwon 系统变量方便取用-->
|
|
15
|
+
<var name="docDir" desc="markdwon_src所在目录">
|
|
16
|
+
<var name="docStem" desc="markdwon_src所在目录的文件名">
|
|
17
|
+
</system-params>
|
|
18
|
+
|
|
19
|
+
<render to="[%docDir%]\[%docStem%]">
|
|
20
|
+
|
|
21
|
+
|
|
Binary file
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Worksheet": {
|
|
3
|
+
"docx": {
|
|
4
|
+
"referance": "./referance.docx",
|
|
5
|
+
"markdwon-table": {
|
|
6
|
+
"width_percent": 100,
|
|
7
|
+
"style": "Table Grid",
|
|
8
|
+
"header_bold": true,
|
|
9
|
+
"header_shading": "D9EAF7",
|
|
10
|
+
"border_color": "B7C9D6",
|
|
11
|
+
"cell_alignment": "center"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"markdown": {
|
|
15
|
+
"head": {
|
|
16
|
+
"downgrade_heading_level": true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"question": {
|
|
20
|
+
"show_answer": false,
|
|
21
|
+
"stem": {
|
|
22
|
+
"show": true,
|
|
23
|
+
"keep_together": true,
|
|
24
|
+
"::first-text-visible": {
|
|
25
|
+
"template": "[%question_id%]、[%text%]",
|
|
26
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
27
|
+
"template": "[%question_id%](多选)、[%text%]"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
31
|
+
"template": "[%text%]"
|
|
32
|
+
},
|
|
33
|
+
"[answer_types=\"choice\"]": {
|
|
34
|
+
"template": "[%text%]"
|
|
35
|
+
},
|
|
36
|
+
"[answer_types=\"blank\"]": {
|
|
37
|
+
"template": "[%text%]\n\n\n\n"
|
|
38
|
+
},
|
|
39
|
+
"[answer_types=\"answer\"]": {
|
|
40
|
+
"template": "[%text%]\n\n\n\n"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"analysis": {
|
|
44
|
+
"show": false,
|
|
45
|
+
"::first-text-visible": {
|
|
46
|
+
"template": "[% text %]"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
".answer": {
|
|
50
|
+
":show_answer": {
|
|
51
|
+
"template": "[%text%]"
|
|
52
|
+
},
|
|
53
|
+
":not_show_answer": {
|
|
54
|
+
"template": ""
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
".blank": {
|
|
58
|
+
":show_answer": {
|
|
59
|
+
"template": "[%text%]"
|
|
60
|
+
},
|
|
61
|
+
":not_show_answer": {
|
|
62
|
+
"template": " $\\underline{\\hspace{1.8cm}}$ "
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
".choise": {
|
|
66
|
+
":show_answer": {
|
|
67
|
+
"template": "( [% text %] )"
|
|
68
|
+
},
|
|
69
|
+
":not_show_answer": {
|
|
70
|
+
"template": "( )"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
".multiple-choice": {
|
|
74
|
+
":show_answer": {
|
|
75
|
+
"template": "([%text%])"
|
|
76
|
+
},
|
|
77
|
+
":not_show_answer": {
|
|
78
|
+
"template": "( )"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"SolutionSheet": {
|
|
84
|
+
"docx": {
|
|
85
|
+
"referance": "./referance.docx",
|
|
86
|
+
"markdwon-table": {
|
|
87
|
+
"width_percent": 100,
|
|
88
|
+
"style": "Table Grid",
|
|
89
|
+
"header_bold": true,
|
|
90
|
+
"header_shading": "D9EAF7",
|
|
91
|
+
"border_color": "B7C9D6",
|
|
92
|
+
"cell_alignment": "center"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"markdown": {
|
|
96
|
+
"head": {
|
|
97
|
+
"downgrade_heading_level": true
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"question": {
|
|
101
|
+
"show_answer": false,
|
|
102
|
+
"stem": {
|
|
103
|
+
"show": false,
|
|
104
|
+
"keep_together": true,
|
|
105
|
+
"::first-text-visible": {
|
|
106
|
+
"template": "[%question_id%]、[%text%]",
|
|
107
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
108
|
+
"template": "[%question_id%](多选)、[%text%]"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
112
|
+
"template": "[%text%]"
|
|
113
|
+
},
|
|
114
|
+
"[answer_types=\"choice\"]": {
|
|
115
|
+
"template": "[%text%]"
|
|
116
|
+
},
|
|
117
|
+
"[answer_types=\"blank\"]": {
|
|
118
|
+
"template": "[%text%]\n\n\n\n"
|
|
119
|
+
},
|
|
120
|
+
"[answer_types=\"answer\"]": {
|
|
121
|
+
"template": "[%text%]\n\n\n\n"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"analysis": {
|
|
125
|
+
"show": true,
|
|
126
|
+
"::first-text-visible": {
|
|
127
|
+
"template": "[% text %]"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
".answer": {
|
|
131
|
+
":show_answer": {
|
|
132
|
+
"template": "[%text%]"
|
|
133
|
+
},
|
|
134
|
+
":not_show_answer": {
|
|
135
|
+
"template": ""
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
".blank": {
|
|
139
|
+
":show_answer": {
|
|
140
|
+
"template": "[%text%]"
|
|
141
|
+
},
|
|
142
|
+
":not_show_answer": {
|
|
143
|
+
"template": " $\\underline{\\hspace{1.8cm}}$ "
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
".choise": {
|
|
147
|
+
":show_answer": {
|
|
148
|
+
"template": "( [% text %] )"
|
|
149
|
+
},
|
|
150
|
+
":not_show_answer": {
|
|
151
|
+
"template": "( )"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
".multiple-choice": {
|
|
155
|
+
":show_answer": {
|
|
156
|
+
"template": "([%text%])"
|
|
157
|
+
},
|
|
158
|
+
":not_show_answer": {
|
|
159
|
+
"template": "( )"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"AnnotatedWorksheet": {
|
|
165
|
+
"docx": {
|
|
166
|
+
"referance": "./referance.docx",
|
|
167
|
+
"markdwon-table": {
|
|
168
|
+
"width_percent": 100,
|
|
169
|
+
"style": "Table Grid",
|
|
170
|
+
"header_bold": true,
|
|
171
|
+
"header_shading": "D9EAF7",
|
|
172
|
+
"border_color": "B7C9D6",
|
|
173
|
+
"cell_alignment": "center"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"markdown": {
|
|
177
|
+
"head": {
|
|
178
|
+
"downgrade_heading_level": true
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"question": {
|
|
182
|
+
"show_answer": true,
|
|
183
|
+
"stem": {
|
|
184
|
+
"show": true,
|
|
185
|
+
"keep_together": true,
|
|
186
|
+
"::first-text-visible": {
|
|
187
|
+
"template": "[%question_id%]、[%text%]",
|
|
188
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
189
|
+
"template": "[%question_id%](多选)、[%text%]"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"[answer_types=\"multiple-choice\"]": {
|
|
193
|
+
"template": "[%text%]"
|
|
194
|
+
},
|
|
195
|
+
"[answer_types=\"choice\"]": {
|
|
196
|
+
"template": "[%text%]"
|
|
197
|
+
},
|
|
198
|
+
"[answer_types=\"blank\"]": {
|
|
199
|
+
"template": "[%text%]\n\n\n\n"
|
|
200
|
+
},
|
|
201
|
+
"[answer_types=\"answer\"]": {
|
|
202
|
+
"template": "[%text%]\n\n\n\n"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"analysis": {
|
|
206
|
+
"show": true,
|
|
207
|
+
"::first-text-visible": {
|
|
208
|
+
"template": "[% text %]"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
".answer": {
|
|
212
|
+
":show_answer": {
|
|
213
|
+
"template": "[%text%]"
|
|
214
|
+
},
|
|
215
|
+
":not_show_answer": {
|
|
216
|
+
"template": ""
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
".blank": {
|
|
220
|
+
":show_answer": {
|
|
221
|
+
"template": "[%text%]"
|
|
222
|
+
},
|
|
223
|
+
":not_show_answer": {
|
|
224
|
+
"template": " $\\underline{\\hspace{1.8cm}}$ "
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
".choise": {
|
|
228
|
+
":show_answer": {
|
|
229
|
+
"template": "( [% text %] )"
|
|
230
|
+
},
|
|
231
|
+
":not_show_answer": {
|
|
232
|
+
"template": "( )"
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
".multiple-choice": {
|
|
236
|
+
":show_answer": {
|
|
237
|
+
"template": "([%text%])"
|
|
238
|
+
},
|
|
239
|
+
":not_show_answer": {
|
|
240
|
+
"template": "( )"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
qparse/utils/__init__.py
ADDED