ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

md转为docx

md转为docx # -*- coding: utf-8 -*-将软考模拟试卷 Markdown 转为排版良好的 Word 文档。 用法: python md2docx.py input.md [output.docx] 支持: 标题层级、表格、列表、引用、代码块、粗体/行内代码、水平线。 importsysimportosimportioimportre sys.stdoutio.TextIOWrapper(sys.stdout.buffer,encodingutf-8,errorsreplace)importdocxfromdocximportDocumentfromdocx.sharedimportPt,Cm,RGBColorfromdocx.enum.textimportWD_ALIGN_PARAGRAPH,WD_LINE_SPACINGfromdocx.enum.tableimportWD_TABLE_ALIGNMENTfromdocx.oxml.nsimportqnfromdocx.oxmlimportOxmlElementdefset_font(run,name宋体,ascii_fontNone,sizeNone,boldNone,colorNone):统一设置中文字体。run.font.nameascii_fontorname rrun._element.rPrifrisnotNone:rFontsr.find(qn(w:rFonts))ifrFontsisNone:rFontsOxmlElement(w:rFonts)r.append(rFonts)rFonts.set(qn(w:eastAsia),name)ifascii_font:rFonts.set(qn(w:ascii),ascii_font)rFonts.set(qn(w:hAnsi),ascii_font)ifsizeisnotNone:run.font.sizesizeifboldisnotNone:run.font.boldboldifcolorisnotNone:run.font.color.rgbcolordefadd_runs(par,text,base_font宋体,ascii_fontNone,sizeNone,base_boldFalse,colorNone):解析行内 **粗体** 与 代码 标记并写入段落。tokensre.split(r(\*\*.?\*\*|[^]),text)fortokintokens:ifnottok:continueiftok.startswith(**)andtok.endswith(**)andlen(tok)4:runpar.add_run(tok[2:-2])set_font(run,base_font,ascii_font,size,True,color)eliftok.startswith()andtok.endswith()andlen(tok)2:runpar.add_run(tok[1:-1])set_font(run,base_font,Consolas,size,base_bold,color)else:runpar.add_run(tok)set_font(run,base_font,ascii_font,size,base_bold,color)defadd_hr(doc):pdoc.add_paragraph()pPrp._p.get_or_add_pPr()pBdrOxmlElement(w:pBdr)bottomOxmlElement(w:bottom)bottom.set(qn(w:val),single)bottom.set(qn(w:sz),6)bottom.set(qn(w:space),1)bottom.set(qn(w:color),888888)pBdr.append(bottom)pPr.append(pBdr)defset_cell_bg(cell,hexcolor):shdOxmlElement(w:shd)shd.set(qn(w:val),clear)shd.set(qn(w:fill),hexcolor)cell._tc.get_or_add_tcPr().append(shd)defadd_table(doc,rows):n_colsmax(len(r)forrinrows)tabledoc.add_table(rowslen(rows),colsn_cols)table.styleTable Gridtable.alignmentWD_TABLE_ALIGNMENT.CENTERfori,rowinenumerate(rows):forjinrange(n_cols):celltable.cell(i,j)textrow[j]ifjlen(row)elsecell.textparcell.paragraphs[0]par.alignmentWD_ALIGN_PARAGRAPH.CENTERifi0elseWD_ALIGN_PARAGRAPH.LEFT add_runs(par,text,sizePt(9))forruninpar.runs:ifi0:run.font.boldTrueifi0:set_cell_bg(cell,D9E2F3)doc.add_paragraph()defadd_code_block(doc,lines):fori,lineinenumerate(lines):pardoc.add_paragraph()pfpar.paragraph_format pf.space_beforePt(0)pf.space_afterPt(0)pf.line_spacing_ruleWD_LINE_SPACING.SINGLE pf.left_indentCm(0.5)runpar.add_run(lineiflineelse )set_font(run,Consolas,Consolas,Pt(9))INLINE_CODE_REre.compile(r([^]*))defconvert(md_path,docx_path):withopen(md_path,r,encodingutf-8)asf:linesf.read().splitlines()docDocument()# 页面设置: A4secdoc.sections[0]sec.page_widthCm(21.0)sec.page_heightCm(29.7)sec.left_marginCm(2.5)sec.right_marginCm(2.5)sec.top_marginCm(2.5)sec.bottom_marginCm(2.5)# 正文默认字体styledoc.styles[Normal]style.font.name宋体style.font.sizePt(10.5)style.element.rPr.rFonts.set(qn(w:eastAsia),宋体)i0nlen(lines)whilein:linelines[i]strippedline.strip()# 代码块ifstripped.startswith():code_lines[]i1whileinandnotlines[i].strip().startswith():code_lines.append(lines[i])i1i1# skip closing fenceadd_code_block(doc,code_lines)continue# 表格 (| ... |)ifstripped.startswith(|)andi1nandre.match(r^\s*\|[\s:|-]\|\s*$,lines[i1]):rows[]header[c.strip()forcinstripped.strip(|).split(|)]rows.append(header)i2whileinandlines[i].strip().startswith(|):rows.append([c.strip()forcinlines[i].strip().strip(|).split(|)])i1add_table(doc,rows)continue# 水平线ifre.match(r^-{3,}\s*$,stripped)orre.match(r^\*{3,}\s*$,stripped):add_hr(doc)i1continue# 标题mre.match(r^(#{1,6})\s(.*)$,stripped)ifm:levellen(m.group(1))textm.group(2).strip()textINLINE_CODE_RE.sub(r\1,text)texttext.replace(**,)iflevel1:pardoc.add_paragraph()par.alignmentWD_ALIGN_PARAGRAPH.CENTER runpar.add_run(text)set_font(run,黑体,Times New Roman,Pt(16),True)par.paragraph_format.space_afterPt(12)eliflevel2:pardoc.add_paragraph()par.alignmentWD_ALIGN_PARAGRAPH.CENTER runpar.add_run(text)set_font(run,黑体,Times New Roman,Pt(14),True)par.paragraph_format.space_afterPt(10)else:pardoc.add_paragraph()runpar.add_run(text)set_font(run,黑体,Times New Roman,Pt(12),True)par.paragraph_format.space_beforePt(8)par.paragraph_format.space_afterPt(6)i1continue# 引用块ifstripped.startswith():quote_lines[]whileinandlines[i].strip().startswith():quote_lines.append(lines[i].strip().lstrip().strip())i1pardoc.add_paragraph()pfpar.paragraph_format pf.left_indentCm(0.75)pf.space_beforePt(4)pf.space_afterPt(4)add_runs(par, .join(quote_lines),sizePt(9.5),colorRGBColor(0x33,0x33,0x33))continue# 列表- / * / 数字.mre.match(r^(\s*)([-*]|\d\.)\s(.*)$,line)ifmandnotstripped.startswith(**):indent_levellen(m.group(1))//2markerm.group(2)textm.group(3)is_nummarker.rstrip(.)!marker# 1. 形式pardoc.add_paragraph()pfpar.paragraph_format pf.left_indentCm(0.750.75*indent_level)pf.first_line_indentCm(-0.35)pf.space_beforePt(0)pf.space_afterPt(3)prefixmarker ifis_numelse• runpar.add_run(prefix)set_font(run,宋体,None,Pt(10.5),True)add_runs(par,text)i1continue# 空行ifnotstripped:i1continue# 普通段落pardoc.add_paragraph()pfpar.paragraph_format pf.space_beforePt(2)pf.space_afterPt(4)pf.line_spacing1.3# 试卷题干常见 **N.** xxx 或行首加粗编号, add_runs 处理粗体add_runs(par,stripped)i1doc.save(docx_path)print(OK:,docx_path)if__name____main__:iflen(sys.argv)2:print(usage: python md2docx.py input.md [output.docx])sys.exit(1)srcsys.argv[1]dstsys.argv[2]iflen(sys.argv)2elseos.path.splitext(src)[0].docxconvert(src,dst)
返回列表