提交 d0e60e3c 编写于 作者: L luxin

add keywords_must and keywords_forbid

上级 33fdf4a7
{ {
"node_id": "gml-62c30f9c31f64a1d96af732c47c93f04", "node_id": "gml-62c30f9c31f64a1d96af732c47c93f04",
"keywords": [ "keywords": [
"Git历史", "Git历史",
"你了解版本控制系统吗?", "你了解版本控制系统吗?",
"什么是本地版本控制系统", "什么是本地版本控制系统",
"什么是集中化的版本控制系统", "什么是集中化的版本控制系统",
"什么是分布式版本控制系统", "什么是分布式版本控制系统",
"Git 诞生的故事" "Git 诞生的故事"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
"简介",
"历史"
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-17121b66f9a942629bc455f320b28910", "node_id": "gml-17121b66f9a942629bc455f320b28910",
"keywords": [ "keywords": [
"msys git", "msys git",
"5分钟教你学会 git 安装", "5分钟教你学会 git 安装",
"不同操作系统的安装介绍", "不同操作系统的安装介绍",
"Git 的环境配置", "Git 的环境配置",
"Git 的自定义设置", "Git 的自定义设置",
"Git 自定义别名" "Git 自定义别名"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
"安装",
"环境配置"
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-598d225d1a78453d8992345f8f7902ba", "node_id": "gml-598d225d1a78453d8992345f8f7902ba",
"keywords": [ "keywords": [
"Git基本用法", "Git基本用法",
"创建仓库: git init / git clone", "创建仓库: git init / git clone",
"添加文件: git add / git commit", "添加文件: git add / git commit",
"查看修改: git status / git diff", "查看修改: git status / git diff",
"恢复文件: git log / git reset" "恢复文件: git log / git reset"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"Git",
"基本用法"
],
[
"git",
"使用"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-f0d68868583b48d0851c7add33e2f8ff", "node_id": "gml-f0d68868583b48d0851c7add33e2f8ff",
"keywords": [ "keywords": [
"Git 撤销", "Git 撤销",
"Git 删除" "Git 删除"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"git",
"撤销"
],
[
"git",
"删除"
],
[
"git",
"版本管理"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -13,5 +13,12 @@ ...@@ -13,5 +13,12 @@
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"git",
"分支管理"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-7b2351b6989f4ec19655498bbb4bafb1", "node_id": "gml-7b2351b6989f4ec19655498bbb4bafb1",
"keywords": [ "keywords": [
"git tag" "git tag"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
"标签"
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-426d7dad0f844c6d9bc1d6c4c860585c", "node_id": "gml-426d7dad0f844c6d9bc1d6c4c860585c",
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,10 +2,17 @@ ...@@ -2,10 +2,17 @@
"node_id": "gml-e67e64c1c880432ab6bc1b0452124ec0", "node_id": "gml-e67e64c1c880432ab6bc1b0452124ec0",
"keywords": [ "keywords": [
"认识 Markdown", "认识 Markdown",
"使用 Markdown 的误区" "使用 Markdown 的误区"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"介绍"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,13 +2,36 @@ ...@@ -2,13 +2,36 @@
"node_id": "gml-627f564073834c8d86e45f126ac628df", "node_id": "gml-627f564073834c8d86e45f126ac628df",
"keywords": [ "keywords": [
"MarkDown段落", "MarkDown段落",
"MarkDown段落的换行", "MarkDown段落的换行",
"MarkDown斜体", "MarkDown斜体",
"MarkDown粗体", "MarkDown粗体",
"MarkDown删除线" "MarkDown删除线"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"段落"
],
[
"MarkDown",
"斜体"
],
[
"MarkDown",
"粗体"
],
[
"MarkDown",
"删除线"
],
[
"MarkDown",
"强调"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,10 +2,17 @@ ...@@ -2,10 +2,17 @@
"node_id": "gml-30e9989f9a5f44fab349734a8e4479a3", "node_id": "gml-30e9989f9a5f44fab349734a8e4479a3",
"keywords": [ "keywords": [
"Setext 标题", "Setext 标题",
"Atx 标题" "Atx 标题"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"标题"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,10 +2,17 @@ ...@@ -2,10 +2,17 @@
"node_id": "gml-3cb459e3d1a147a8b89291c1ef4147c7", "node_id": "gml-3cb459e3d1a147a8b89291c1ef4147c7",
"keywords": [ "keywords": [
"行内链接", "行内链接",
"参考样式链接" "参考样式链接"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"链接"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,10 +2,17 @@ ...@@ -2,10 +2,17 @@
"node_id": "gml-2f1e2810b721429dba664414438b6d87", "node_id": "gml-2f1e2810b721429dba664414438b6d87",
"keywords": [ "keywords": [
"行内图片", "行内图片",
"参考样式图片" "参考样式图片"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"图片"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,11 +2,18 @@ ...@@ -2,11 +2,18 @@
"node_id": "gml-b4a4f06aa5114c3fa6a590d659037370", "node_id": "gml-b4a4f06aa5114c3fa6a590d659037370",
"keywords": [ "keywords": [
"无序列表", "无序列表",
"有序列表", "有序列表",
"任务列表" "任务列表"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"列表"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,10 +2,21 @@ ...@@ -2,10 +2,21 @@
"node_id": "gml-b6b6f01fb86141768c5b242327f1e0fa", "node_id": "gml-b6b6f01fb86141768c5b242327f1e0fa",
"keywords": [ "keywords": [
"分隔线", "分隔线",
"区块引用" "区块引用"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"分隔线"
],
[
"MarkDown",
"引用"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -2,12 +2,19 @@ ...@@ -2,12 +2,19 @@
"node_id": "gml-2e87affacacd4078a3ba55a5a15a8f7a", "node_id": "gml-2e87affacacd4078a3ba55a5a15a8f7a",
"keywords": [ "keywords": [
"行内代码", "行内代码",
"代码缩进", "代码缩进",
"代码高亮", "代码高亮",
"代码 Diff" "代码 Diff"
], ],
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"代码块"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -7,5 +7,12 @@ ...@@ -7,5 +7,12 @@
"children": [], "children": [],
"export": [ "export": [
"learn.json" "learn.json"
] ],
"keywords_must": [
[
"MarkDown",
"表格"
]
],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-e5b1eb56008b451699a9e7e6d941c8ca", "node_id": "gml-e5b1eb56008b451699a9e7e6d941c8ca",
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-3acda6f103e94664800f91494aff4099", "node_id": "gml-3acda6f103e94664800f91494aff4099",
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-a94f8931a29e42749c65af33b5f00ffa", "node_id": "gml-a94f8931a29e42749c65af33b5f00ffa",
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"node_id": "gml-ec7eb3a512204261a14eafc36bc55188", "node_id": "gml-ec7eb3a512204261a14eafc36bc55188",
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
{ {
"tree_name": "gml", "tree_name": "gml",
"keywords": [], "keywords": [],
"node_id": "gml-2edf9242568f4812bda2dd5913c09bd3" "node_id": "gml-2edf9242568f4812bda2dd5913c09bd3",
"keywords_must": [],
"keywords_forbid": []
} }
\ No newline at end of file
...@@ -24,7 +24,12 @@ ...@@ -24,7 +24,12 @@
"什么是分布式版本控制系统", "什么是分布式版本控制系统",
"Git 诞生的故事" "Git 诞生的故事"
], ],
"children": [] "children": [],
"keywords_must": [
"简介",
"历史"
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -38,7 +43,12 @@ ...@@ -38,7 +43,12 @@
"Git 的自定义设置", "Git 的自定义设置",
"Git 自定义别名" "Git 自定义别名"
], ],
"children": [] "children": [],
"keywords_must": [
"安装",
"环境配置"
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -51,7 +61,18 @@ ...@@ -51,7 +61,18 @@
"查看修改: git status / git diff", "查看修改: git status / git diff",
"恢复文件: git log / git reset" "恢复文件: git log / git reset"
], ],
"children": [] "children": [],
"keywords_must": [
[
"Git",
"基本用法"
],
[
"git",
"使用"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -61,7 +82,22 @@ ...@@ -61,7 +82,22 @@
"Git 撤销", "Git 撤销",
"Git 删除" "Git 删除"
], ],
"children": [] "children": [],
"keywords_must": [
[
"git",
"撤销"
],
[
"git",
"删除"
],
[
"git",
"版本管理"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -77,7 +113,14 @@ ...@@ -77,7 +113,14 @@
"cherry-pick 介绍及用法", "cherry-pick 介绍及用法",
"git 的多人协作" "git 的多人协作"
], ],
"children": [] "children": [],
"keywords_must": [
[
"git",
"分支管理"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -86,10 +129,16 @@ ...@@ -86,10 +129,16 @@
"keywords": [ "keywords": [
"git tag" "git tag"
], ],
"children": [] "children": [],
"keywords_must": [
"标签"
],
"keywords_forbid": []
} }
} }
] ],
"keywords_must": [],
"keywords_forbid": []
} }
}, },
{ {
...@@ -104,7 +153,14 @@ ...@@ -104,7 +153,14 @@
"认识 Markdown", "认识 Markdown",
"使用 Markdown 的误区" "使用 Markdown 的误区"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"介绍"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -117,7 +173,30 @@ ...@@ -117,7 +173,30 @@
"MarkDown粗体", "MarkDown粗体",
"MarkDown删除线" "MarkDown删除线"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"段落"
],
[
"MarkDown",
"斜体"
],
[
"MarkDown",
"粗体"
],
[
"MarkDown",
"删除线"
],
[
"MarkDown",
"强调"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -127,7 +206,14 @@ ...@@ -127,7 +206,14 @@
"Setext 标题", "Setext 标题",
"Atx 标题" "Atx 标题"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"标题"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -137,7 +223,14 @@ ...@@ -137,7 +223,14 @@
"行内链接", "行内链接",
"参考样式链接" "参考样式链接"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"链接"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -147,7 +240,14 @@ ...@@ -147,7 +240,14 @@
"行内图片", "行内图片",
"参考样式图片" "参考样式图片"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"图片"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -158,7 +258,14 @@ ...@@ -158,7 +258,14 @@
"有序列表", "有序列表",
"任务列表" "任务列表"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"列表"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -168,7 +275,18 @@ ...@@ -168,7 +275,18 @@
"分隔线", "分隔线",
"区块引用" "区块引用"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"分隔线"
],
[
"MarkDown",
"引用"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -180,7 +298,14 @@ ...@@ -180,7 +298,14 @@
"代码高亮", "代码高亮",
"代码 Diff" "代码 Diff"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"代码块"
]
],
"keywords_forbid": []
} }
}, },
{ {
...@@ -190,29 +315,46 @@ ...@@ -190,29 +315,46 @@
"创建MarkDown表格", "创建MarkDown表格",
"MarkDown表格对齐" "MarkDown表格对齐"
], ],
"children": [] "children": [],
"keywords_must": [
[
"MarkDown",
"表格"
]
],
"keywords_forbid": []
} }
} }
] ],
"keywords_must": [],
"keywords_forbid": []
} }
} }
] ],
"keywords_must": [],
"keywords_forbid": []
} }
}, },
{ {
"gml中阶": { "gml中阶": {
"node_id": "gml-a94f8931a29e42749c65af33b5f00ffa", "node_id": "gml-a94f8931a29e42749c65af33b5f00ffa",
"keywords": [], "keywords": [],
"children": [] "children": [],
"keywords_must": [],
"keywords_forbid": []
} }
}, },
{ {
"gml高阶": { "gml高阶": {
"node_id": "gml-ec7eb3a512204261a14eafc36bc55188", "node_id": "gml-ec7eb3a512204261a14eafc36bc55188",
"keywords": [], "keywords": [],
"children": [] "children": [],
"keywords_must": [],
"keywords_forbid": []
} }
} }
] ],
"keywords_must": [],
"keywords_forbid": []
} }
} }
\ No newline at end of file
...@@ -2,10 +2,11 @@ import json ...@@ -2,10 +2,11 @@ import json
import logging import logging
import os import os
import re import re
import subprocess
import sys import sys
import uuid import uuid
import re import re
import git
id_set = set() id_set = set()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -14,11 +15,19 @@ handler = logging.StreamHandler(sys.stdout) ...@@ -14,11 +15,19 @@ handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter) handler.setFormatter(formatter)
logger.addHandler(handler) logger.addHandler(handler)
repo = git.Repo(".")
def user_name(): def user_name(md_file, author_dict):
return repo.config_reader().get_value("user", "name") ret = subprocess.Popen([
"git", "log", md_file
], stdout=subprocess.PIPE)
lines = list(map(lambda l: l.decode(), ret.stdout.readlines()))
author_lines = []
for line in lines:
if line.startswith('Author'):
author_lines.append(line.split(' ')[1])
author_nick_name = author_lines[-1]
return author_dict.get(author_nick_name, "")
def load_json(p): def load_json(p):
...@@ -77,7 +86,18 @@ def check_export(base, cfg): ...@@ -77,7 +86,18 @@ def check_export(base, cfg):
class TreeWalker: class TreeWalker:
def __init__(self, root, tree_name, title=None, log=None): def __init__(
self, root,
tree_name,
title=None,
log=None,
authors=None,
enable_notebook=None,
ignore_keywords=False
):
self.ignore_keywords = ignore_keywords
self.authors = authors if authors else {}
self.enable_notebook = enable_notebook
self.name = tree_name self.name = tree_name
self.root = root self.root = root
self.title = tree_name if title is None else title self.title = tree_name if title is None else title
...@@ -89,7 +109,9 @@ class TreeWalker: ...@@ -89,7 +109,9 @@ class TreeWalker:
root_node = { root_node = {
"node_id": root["node_id"], "node_id": root["node_id"],
"keywords": root["keywords"], "keywords": root["keywords"],
"children": [] "children": [],
"keywords_must": root["keywords_must"],
"keywords_forbid": root["keywords_forbid"]
} }
self.tree[root["tree_name"]] = root_node self.tree[root["tree_name"]] = root_node
self.load_levels(root_node) self.load_levels(root_node)
...@@ -144,6 +166,8 @@ class TreeWalker: ...@@ -144,6 +166,8 @@ class TreeWalker:
"node_id": config["node_id"], "node_id": config["node_id"],
"keywords": config["keywords"], "keywords": config["keywords"],
"children": [], "children": [],
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
} }
} }
...@@ -195,6 +219,8 @@ class TreeWalker: ...@@ -195,6 +219,8 @@ class TreeWalker:
"tree_name": self.name, "tree_name": self.name,
"keywords": [], "keywords": [],
"node_id": self.gen_node_id(), "node_id": self.gen_node_id(),
"keywords_must": [],
"keywords_forbid": []
} }
dump_json(config_path, config, exist_ok=True, override=True) dump_json(config_path, config, exist_ok=True, override=True)
else: else:
...@@ -224,7 +250,9 @@ class TreeWalker: ...@@ -224,7 +250,9 @@ class TreeWalker:
if not os.path.exists(config_path): if not os.path.exists(config_path):
config = { config = {
"node_id": self.gen_node_id(), "node_id": self.gen_node_id(),
"keywords": [] "keywords": [],
"keywords_must": [],
"keywords_forbid": []
} }
dump_json(config_path, config, exist_ok=True, override=True) dump_json(config_path, config, exist_ok=True, override=True)
else: else:
...@@ -290,6 +318,8 @@ class TreeWalker: ...@@ -290,6 +318,8 @@ class TreeWalker:
"node_id": config["node_id"], "node_id": config["node_id"],
"keywords": config["keywords"], "keywords": config["keywords"],
"children": [], "children": [],
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
} }
} }
return num, result return num, result
...@@ -301,7 +331,9 @@ class TreeWalker: ...@@ -301,7 +331,9 @@ class TreeWalker:
name: { name: {
"node_id": config["node_id"], "node_id": config["node_id"],
"keywords": config["keywords"], "keywords": config["keywords"],
"children": config.get("children", []) "children": config.get("children", []),
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
} }
} }
# if "children" in config: # if "children" in config:
...@@ -318,7 +350,8 @@ class TreeWalker: ...@@ -318,7 +350,8 @@ class TreeWalker:
continue continue
mfile = base + ".json" mfile = base + ".json"
meta_path = os.path.join(section_path, mfile) meta_path = os.path.join(section_path, mfile)
self.ensure_exercises_meta(meta_path, source) md_file = os.path.join(section_path, e)
self.ensure_exercises_meta(meta_path, source, md_file)
export = config.get("export", []) export = config.get("export", [])
if mfile not in export and self.name != "algorithm": if mfile not in export and self.name != "algorithm":
export.append(mfile) export.append(mfile)
...@@ -339,7 +372,7 @@ class TreeWalker: ...@@ -339,7 +372,7 @@ class TreeWalker:
else: else:
id_set.add(exercise["exercise_id"]) id_set.add(exercise["exercise_id"])
def ensure_exercises_meta(self, meta_path, source): def ensure_exercises_meta(self, meta_path, source, md_file):
_, mfile = os.path.split(meta_path) _, mfile = os.path.split(meta_path)
meta = None meta = None
if os.path.exists(meta_path): if os.path.exists(meta_path):
...@@ -354,26 +387,31 @@ class TreeWalker: ...@@ -354,26 +387,31 @@ class TreeWalker:
if "source" not in meta: if "source" not in meta:
meta["source"] = source meta["source"] = source
if "author" not in meta: if "author" not in meta:
meta["author"] = user_name() meta["author"] = user_name(md_file, self.authors)
if "type" not in meta: if "type" not in meta:
meta["type"] = "code_options" meta["type"] = "code_options"
if meta is None:
meta = { if meta is None:
"type": "code_options", meta = {
"author": user_name(), "type": "code_options",
"source": source, "author": user_name(md_file, self.authors),
"notebook_enable": self.default_notebook(), "source": source,
"exercise_id": uuid.uuid4().hex "notebook_enable": self.default_notebook(),
} "exercise_id": uuid.uuid4().hex
}
dump_json(meta_path, meta, True, True) dump_json(meta_path, meta, True, True)
def default_notebook(self): def default_notebook(self):
if self.enable_notebook is not None:
return self.enable_notebook
if self.name in ["python", "java", "c"]: if self.name in ["python", "java", "c"]:
return True return True
else: else:
return False return False
def check_section_keywords(self, full_path): def check_section_keywords(self, full_path):
if self.ignore_keywords:
return
config = self.ensure_section_config(full_path) config = self.ensure_section_config(full_path)
if not config.get("keywords", []): if not config.get("keywords", []):
self.logger.error(f"节点 [{full_path}] 的关键字为空,请修改配置文件写入关键字") self.logger.error(f"节点 [{full_path}] 的关键字为空,请修改配置文件写入关键字")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册