def __store_with_attachments(dst_dir, filename, text, all_docs, ref, root_dir): """ Store text in dst_dir/filename, create dir if necessary and copy attachments. """ path = __store_file(dst_dir, filename, text) root_doc = XML.xpath_node(all_docs, ".//document[.//*/@ref='"+ref+"']") rel_dir = XML.xpath_plain(root_doc, "@dir") src_dir = os.path.join(root_dir, rel_dir) attachments = XML.xpath_list(root_doc, "_meta/attachment") for att in attachments: att_path = XML.xpath_plain(att, "@to_path") att_rel_path = os.path.relpath(att_path, start=rel_dir) src_att = os.path.join(src_dir, att_rel_path) dst_att = os.path.join(dst_dir, att_rel_path) dst_dir_att = os.path.dirname(dst_att) if not os.path.exists(dst_dir_att): os.makedirs(dst_dir_att) try: if not os.path.exists(dst_att): print("Storing attachment : " + dst_att) shutil.copyfile(src_att, dst_att) except: #LIB.debug_error() meta = XML.xpath_node(all_docs, ".//document[.//*/@ref='"+ref+"']/_meta") XML.add_error(meta, "__store_with_attachments()", "warning", "missing_file", "can't copy attachment, missing file", 0, src_att) return path
def __build_index_section(base_url, all_docs, cat_ref, github_url, domain_refs): """ Build an HTML section for ref entity in all_docs. """ cat = XML.xpath_node(all_docs, (".//*[@ref='"+cat_ref+"']")) cat_title = XML.xpath_plain(cat, "title/text()") cat_about_html = XML.xpath_md(cat, "about/text()") all_items = XML.xpath_list(all_docs, ".//*[@cat='"+cat_ref+"']") rows = "" for itm in all_items: itm_ref = XML.xpath_plain(itm, "@ref") if (not (itm_ref in domain_refs)) : continue itm_icon = XML.xpath_plain(itm, "@icon") doc = XML.xpath_node(itm, "ancestor::document") itm_src_path = os.path.join(XML.xpath_plain(doc, "@dir"), XML.xpath_plain(doc, "@file")) itm_ttl_html = XML.xpath_md(itm, "@title") itm_about_html = XML.xpath_md(itm, "about/text()") itm_src_url = __to_github(github_url, itm_src_path) link_ref = __build_ref_link(base_url, all_docs, itm_ref) rows += f""" <tr> <td class="icon"><img class="icon" alt="[icon]" src='{itm_ref}/{itm_icon}'/></td> <td>{link_ref}</td> <td>{itm_ttl_html}</td> <td>(<a href="{itm_src_url}" target="_blank">Github</a>)</td> </tr>\n """ ret = f""" <div class="MenuContent"> <div id="primary"> <section class="comonSection singlefoliodetails"> <div class="container-fluid"> <div class="col-lg-12 noPadding"> <section class="col-md-10"> <div class="sectionTitle smTitle"> <h2>{cat_title} index</h2> <div class="titleBar"></div> </div> <p>{cat_about_html}</p> <table class="table table-bordered"> {rows} </table> </section> </div> </div> </section> </div> </div> """ return __comment_html(ret)
def __build_content_attachments(base_url, all_docs, item): """ Build an HTML attached documents list for given ref. """ try: root_doc = XML.xpath_node(item, "ancestor::document") root_dir = XML.xpath_plain(root_doc, "@dir") exts = "|".join([LIB.DOC_EXT[t] for t in ["txt","doc","slide","data"]]) attachments = XML.xpath_list(root_doc, "_meta/attachment[contains('"+exts+"', @ext)]") inner_html = "" for att in attachments: att_path = XML.xpath_plain(att, "@to_path") att_title = XML.xpath_plain(att, "@file") att_ext = XML.xpath_plain(att, "@ext") rel_path = os.path.relpath(att_path, start=root_dir) link = f""" <a title="{att_title}" href='{rel_path}' target="_blank" class="link_for_{att_ext}">{att_title}</a> """ inner_html += link ret = f""" <h2>Attached documents</h2> <p>{inner_html}</p> """ if inner_html > "" else "" except: ret = "" return __comment_html(ret)
def __build_content_gallery(base_url, all_docs, item): """ Build an HTML image gallery for given ref. """ try: root_doc = XML.xpath_node(item, "ancestor::document") root_dir = XML.xpath_plain(root_doc, "@dir") exts = LIB.DOC_EXT["img"] images = XML.xpath_list(root_doc, "_meta/attachment[contains('"+exts+"', @ext)]") inner_html = "" for image in images: img_path = XML.xpath_plain(image, "@to_path") img_file = XML.xpath_plain(image, "@file") rel_path = os.path.relpath(img_path, start=root_dir) link = f""" <span class="icon"><a title="{img_file}" href="{rel_path}"><img alt="[image]" src="{rel_path}"/></a></span> """ inner_html += link ret = f""" <h2>Image gallery</h2> <p>{inner_html}</p> """ if inner_html > "" else "" except: ret = "" return __comment_html(ret)
def __build_content_text(base_url, all_docs, node, github_url, domain_cats): """ Build an HTML text /!\ Links to refs broken by Markdown transformation NEED to replace refs in md with good links BEFORE transformation. """ raw_content = "" #### XML.xpath_plain(node, "../raw_content/text()") if raw_content > "" : ref = XML.xpath_plain(node, "@ref") doc = XML.xpath_node(node, "ancestor::document") src_path = os.path.join(XML.xpath_plain(doc, "@dir"), XML.xpath_plain(doc, "@file")) src_url = __to_github(github_url, src_path) github = f"""<a href="{src_url}" target="_blank">Github</a>""" md_html = MD.markdown(raw_content) ret = f""" <div class="sectionTitle smTitle"> <h6>{ref} ({github})</h6> <div class="titleBar"></div> </div> {md_html} """ else: ret = __build_content_chapter(base_url, all_docs, 2, node, github_url, domain_cats) return ret
def __md_parse(xml_doc, text): """ Return the DOM from multiline markdown text. Headers (#..., ##..., ###...) are interpreted as nodes name and the following text as the content of these nodes. /!\ plusieurs noeuds de même nom au même niveau ??? """ lines = text.splitlines() context = xml_doc if LIB.sanitize(lines[0]) == "---": # Markdown with yaml meta-data block yaml_block = "" for i in range(1, len(lines)): if LIB.sanitize(lines[i]) == "---": break yaml_block += lines[i] + "\n" meta_dict = yaml.load(yaml_block) XML.add_dict_as_xml(context, meta_dict) raw_content_text = "" for j in range(i + 1, len(lines)): raw_content_text += lines[j] + "\n" node_raw = ET.SubElement(context, "raw_content") node_raw.text = str(raw_content_text) else: # Structured Markdown cur_level = 0 code_fence_on = False for i in range(len(lines)): line = lines[i] match_code_fence = re.match(r"^ *```", line) if match_code_fence: code_fence_on = not code_fence_on match_title = re.match(r"^ *(#+)(.+)", line) if match_title and not code_fence_on: new_level = len(match_title.group(1)) node_txt = match_title.group(2) node_name = __extract_node_name(node_txt) attributes = __extract_attributes(node_txt) if new_level > cur_level + 1: meta = XML.xpath_node(xml_doc, ".//_meta") XML.add_error(meta, "__md_parse()", "fatal", "md_level_mismatch", "level mismatch", i, line) else: for lev in range(new_level, cur_level + 1): context = context.getparent() context = ET.SubElement(context, node_name, attributes) cur_level = new_level else: context.text = (context.text if context.text else "") + line + "\n" node_raw = ET.SubElement(xml_doc, "raw_content") node_raw.text = text return xml_doc
def __update_refs(base_url, all_docs, text, node, domain_cats): """ Replace all Markdown link pattern [`CAT-xxxxxx`](../../interfaces/ITF-A_gnd) ) with correct url relative to base_url. """ #find all distinct ref patterns refs = re.findall('\[`([A-Z]{2,6}-[\w_]+)`\]', text) for ref in refs: try: itm = XML.xpath_node(all_docs, ".//*[@ref='"+ref+"']") cat_ref = "CAT-" + itm.tag if cat_ref in domain_cats: url = base_url + cat_ref + "/" + ref + "/content.html" else: url="" ttl = XML.xpath_plain(itm, "@title") md_link = f"""[`{ref}`]({url} "{ttl}")""" text = re.sub("\[`" + ref + "`\] *(\([^)]*\)|)", md_link, text) except: meta = XML.xpath_node(node, "ancestor::document/_meta") XML.add_error(meta, "__update_refs()", "warning", "unknown_ref", "unknown reference", 0, ref) return text
def __build_content_chapter(base_url, all_docs, level, node, github_url, domain_cats): """ Build recursively an HTML chapter at level for given node. TODO : if level 2 produce : <div class="sectionTitle smTitle"> <h2>configuration</h2> <h6>CFG-sweeping_probe (<a href="https://github.com/Olivierff/PRJ-medtec_kit//tree/master/configurations/CFG-sweeping_probe" target="_blank">Github</a>)</h6> <div class="titleBar"></div> </div> """ try: children = XML.xpath_list(node, "node()") children_html = "" for child in children: if (ET.iselement(child)): children_html += __build_content_chapter(base_url, all_docs, level+1, child, github_url, domain_cats) else: child = __update_refs(base_url, all_docs, child, node, domain_cats) children_html += MD.markdown(child) title = node.tag if (level==2): ref = XML.xpath_plain(node, "@ref") doc = XML.xpath_node(node, "ancestor::document") src_path = os.path.join(XML.xpath_plain(doc, "@dir"), XML.xpath_plain(doc, "@file")) src_url = __to_github(github_url, src_path) github = f"""<a href="{src_url}" target="_blank">Github</a>""" ret = f""" <div class="sectionTitle smTitle"> <h2>{title}</h2> <h6>{ref} ({github})</h6> <div class="titleBar"></div> </div> {children_html} """ else: ret = f""" <h{level}>{title}</h{level}> {children_html} """ except: ret = """ <p><strong>Error here !!! </strong></p> """ return ret
def __csv_parse(xml_doc, text): """ Return the DOM from csv text. Headers (#..., ##..., ###...) are interpreted as nodes name and the columns text as the content of these nodes. """ lines = text.splitlines() reader = csv.reader(lines) l = -1 for row in reader: l += 1 if (l == 0): header = row elif (header[0].startswith("#")): context = xml_doc cur_level = 0 for i in range(len(header)): ttl = header[i] txt = row[i] match_title = re.match(r" *(#+)(.+)", ttl) if match_title: new_level = len(match_title.group(1)) node_txt = match_title.group(2) node_name = __extract_node_name(node_txt) attributes = __extract_attributes(node_txt) if new_level > cur_level + 1: meta = XML.xpath_node(xml_doc, ".//_meta") XML.add_error(meta, "__csv_parse()", "fatal", "csv_level_mismatch", "level mismatch", i, li) else: for lev in range(new_level, cur_level + 1): context = context.getparent() context = ET.SubElement(context, node_name, attributes) cur_level = new_level context.text = txt else: # not an error, not parsable as structured csv #XML.add_error(meta, "__csv_parse()", "info", "csv_not_parsable", "not parsable header csv file", 0, header) xml_doc.text = text break return xml_doc
def __build_ref_link(base_url, all_docs, ref): """ Build an HTML link for ref entity. """ try: itm = XML.xpath_node(all_docs, ".//*[@ref='"+ref+"']") cat_ref = "CAT-" + itm.tag url = base_url + cat_ref + "/" + ref + "/content.html" title = XML.xpath_plain(itm, "@title") except: url="" title="Not found" ret = f""" <a href="{url}" title="{title}"><code>{ref}</code></a> """ return ret
def __build_content_section(base_url, all_docs, ref, github_url, domain_cats, domain_refs): """ Build an HTML section for ref entity in all_docs. """ try: item = XML.xpath_node(all_docs, ".//*[@ref='"+ref+"']") content = __build_content_text(base_url, all_docs, item, github_url, domain_cats) gallery = __build_content_gallery(base_url, all_docs, item) attachments = __build_content_attachments(base_url, all_docs, item) crossref = __build_content_crossref(base_url, all_docs, ref, domain_refs) ret = f""" <div class="MenuContent"> <div id="primary"> <section class="comonSection singlefoliodetails"> <div class="container-fluid"> <div class="col-lg-12 noPadding"> <section class="col-md-10"> {content} <hr/> {gallery} {attachments} {crossref} </section> </div> </div> </section> </div> </div> """ except: ret = """ <section class="col-md-10"> <h2>Unknown entity</h2> <p>?!?</p> </section> """ return __comment_html(ret)
def register_attachments(all_docs): """ register any attached "binary" document to its master document. Based on the file path """ attachments = XML.xpath_list(all_docs, "//document[count(*) <= 1]") for att in attachments: att_dir = XML.xpath_plain(att, "@dir") att_path = XML.xpath_plain(att, "@path") att_name = XML.xpath_plain(att, "@file") att_ext = XML.xpath_plain( att, "@ext" ) # vvvv Not very smart, but it's late and it works .... vvvv root_pathes = XML.xpath_list( all_docs, "//document[count(*) > 1][@file='readme.md' or @file='Readme.md' or @file='README.md' or @file='readme.MD' or @file='Readme.MD' or @file='README.MD'][starts-with('" + att_dir + "', @dir)]/@path") max_root_path = max(root_pathes, key=len, default="") meta = XML.xpath_node( all_docs, "//document[@path='" + max_root_path + "']/_meta") XML.add_attachment(meta, att_path, att_ext, att_name) return all_docs