查看: 66|回复: 3

Python将JavaScript代码转Word并保留语法高亮

[复制链接]
发表于 23 分钟前 | 显示全部楼层 |阅读模式
将 JavaScript 源码整理为可交付的 Word 文档,常见于代码审计报告、技术文档归档和教学材料准备。难点不在写入,而在保真:Word 不能直接理解 JS 语法,纯文本粘贴会丢失缩进、换行和着色。可行路径是把语法理解与文档承载拆开:先用 Pygments 将源码渲染为带内联样式的 HTML,再用 Spire.Doc for Python 构建 .docx 并导入 HTML。整个流程可在 Python 脚本内完成。

依赖安装:
  1. pip install spire.doc
  2. pip install pygments
复制代码

单文件转换实现:
  1. from spire.doc import *
  2. from pygments import highlight
  3. from pygments.lexers import JavascriptLexer
  4. from pygments.formatters import HtmlFormatter
  5. # 将 JavaScript 文件转换为带有语法高亮的 Word 文档
  6. def convert_js_to_word(input_file: str, output_file: str) -> None:
  7.     with open(input_file, 'r', encoding='utf-8') as file:
  8.         js_code = file.read()
  9.     document = Document()
  10.     section = document.AddSection()
  11.     section.PageSetup.Margins.All = 50
  12.     title_paragraph = section.AddParagraph()
  13.     title_text = title_paragraph.AppendText(f'源代码:{input_file}')
  14.     title_text.CharacterFormat.FontName = '微软雅黑'
  15.     title_text.CharacterFormat.FontSize = 14
  16.     title_text.CharacterFormat.Bold = True
  17.     title_paragraph.Format.AfterSpacing = 10
  18.     html_formatter = HtmlFormatter(
  19.         nowrap=True,
  20.         style='colorful',
  21.         noclasses=True
  22.     )
  23.     highlighted_html = highlight(js_code, JavascriptLexer(), html_formatter)
  24.     code_paragraph = section.AddParagraph()
  25.     code_paragraph.AppendHTML(
  26.         f'<pre style="font-family: Consolas; font-size: 10pt;">{highlighted_html}</pre>'
  27.     )
  28.     document.SaveToFile(output_file, FileFormat.Docx)
  29.     document.Close()
  30.     print(f'已将 {input_file} 转换为 {output_file}')
  31. convert_js_to_word('app.js', 'JavaScriptCode.docx')
复制代码

关键参数中,noclasses=True 决定着色能否保留。它把颜色样式以内联方式写入 HTML 标签,而不是输出 class 交给外部样式表。Word 导入 HTML 时通常不加载外部 CSS,省略该参数会导致代码只有文本没有颜色。外层 pre 标签不能省,否则连续空白与换行会被合并,缩进随之塌陷。nowrap=True 用于避免每行末尾额外换行,防止 Word 中出现多余空行。style 可换成 monokai、vim、vs 等内置配色,属于阅读偏好;Margins.All = 50 收窄页边距,为长代码行争取横向空间;Consolas 等宽字体用于保持对齐稳定。

如果源码是 React 的 JSX,JavascriptLexer 对组件标签与 {} 内表达式的切分不够准确,着色可能错位。此时换用 JsxLexer,其余流程不变:
  1. from pygments.lexers import JsxLexer
  2. highlighted_html = highlight(jsx_code, JsxLexer(), html_formatter)
复制代码

这反映出一个更一般的约束:词法器选择直接决定输出质量。Pygments 覆盖范围虽广,但对 TypeScript 装饰器、较新的语法提案等方言仍可能存在识别滞后。转换前确认词法器与源码方言匹配,比事后修补格式更省力。

单文件跑通后,批量处理是自然下一步:遍历目录、按扩展名筛选、逐个调用转换函数。这里有两个容易忽略的工程约束。其一是资源释放,循环中每次都应调用 document.Close(),否则文档对象累积会推高内存占用。其二是编码,非 UTF-8 源文件需显式指定 encoding,带 BOM 的文件用 utf-8-sig 读取,否则中文注释可能乱码。超大文件如上万行会暴露另一层限制:一次性渲染 HTML 并导入,生成过程明显变慢。分块处理是一种折中,但分块会切断跨行的语法结构,多行字符串、块注释、模板字面量都可能在切分点被破坏,因此能否分块取决于这类结构的密度,而非单纯的行数。

除了 Spire.Doc + Pygments,还可以用 python-docx + Pygments 做免费开源方案。python-docx 本身不直接解析 HTML,需要手动把 Pygments token 写入段落:用 lex() 得到 (tokentype, value) 序列,按 token 类型映射字体颜色,再用 add_run() 写入。下面是简化示例,实际应用需更精细的 token 到颜色映射,并处理换行与背景色:
  1. from docx import Document
  2. from docx.shared import Pt, RGBColor
  3. from pygments import lex
  4. from pygments.lexers import JavascriptLexer
  5. from pygments.styles import get_style_by_name
  6. def convert_js_to_word_manual(input_file, output_file):
  7.     with open(input_file, 'r', encoding='utf-8') as f:
  8.         code = f.read()
  9.     doc = Document()
  10.     paragraph = doc.add_paragraph()
  11.     paragraph.style.font.name = 'Consolas'
  12.     paragraph.style.font.size = Pt(10)
  13.     style = get_style_by_name('colorful')
  14.     token_color_map = {
  15.         'Token.Keyword': RGBColor(0x00, 0x00, 0xFF),
  16.         'Token.String': RGBColor(0x00, 0x80, 0x00),
  17.         'Token.Comment': RGBColor(0x80, 0x80, 0x80),
  18.     }
  19.     for token_type, value in lex(code, JavascriptLexer()):
  20.         run = paragraph.add_run(value)
  21.         for token_name, color in token_color_map.items():
  22.             if str(token_type).startswith(token_name):
  23.                 run.font.color.rgb = color
  24.                 break
  25.         run.font.name = 'Consolas'
  26.         run.font.size = Pt(10)
  27.     doc.save(output_file)
复制代码

若目标是批量处理整个项目的代码用于归档或软著申请,并且不需要语法高亮,可考虑 GitHub 上的 export_code_to_docx 工具。先安装 python-docx,再按示例命令运行:
  1. pip install python-docx
  2. python export_code_to_docx.py --include ./src --ext js --output my_code.docx --no-comments
复制代码
该工具支持目录递归、扩展名过滤、排除路径、中文路径等,适合快速生成纯文本形式的代码文档;示例中的 --no-comments 可按实际需求调整。

这套代码到 HTML 再到 Word 的管道,价值在于可复现与可批量化:转换逻辑全部由脚本控制,能嵌入构建流程,源码更新后重跑即可得到同步文档。但能力上限由 Word 对 HTML/CSS 的支持范围决定,侧边标注、折叠区域、跨页断行控制等复杂代码布局无法通过这条路径还原,精细排版仍需在 Word 内二次加工,或改用 LaTeX、Pandoc 等以排版为核心的方案。它适合结构清晰、以内容归档为目的的场景,不适合以版式设计为核心的交付物。
回复

使用道具 举报

发表于 18 分钟前 | 显示全部楼层

Re: Python将JavaScript代码转Word并保留语法高亮

思路拆得挺清楚,“词法着色”和“文档承载”分开处理这个说法我很认同,比一股脑想着怎么在 Word 里直接染色要靠谱得多。 几个关键参数的解释也很到位。noclasses 这个坑我踩过——光看代码不觉得,跑完发现颜色全丢,排查半天才定位到外部 CSS 不被加载。外层 pre 不能省这点同样重要,少了它缩进被合并,代码块基本就没法读了。 关于 python-docx 那条备选路线,如果不想手写 token 到颜色的映射表,可以顺着楼主已经引的 get_style_by_name 往下走:样式对象本身支持按 token 类型取颜色,拿它来给 add_run 设 RGBColor,能省掉一大段硬编码的映射逻辑,改配色时也只需要换样式名。换行和块注释的背景色还是得单独处理,这块确实绕不开。 有两个想请教的:一是 Spire.Doc 免费版在批量转换时会不会有页数或者水印方面的限制,几十上百个文件跑下来是否还稳;二是分块处理那块,楼主说取决于多行字符串、块注释、模板字面量的密度,那实际切分点一般怎么选,按空行还是按函数边界?按函数边界应该能避开大部分跨行结构,但遇到特别长的函数又不好办。 另外词法器匹配这点提醒得好,TypeScript 的装饰器和较新的语法提案确实容易识别滞后,转换前先拿小样本试一遍颜色对不对,比整批跑完再返工省事。
回复 支持 反对

使用道具 举报

发表于 18 分钟前 | 显示全部楼层

Re: Python将JavaScript代码转Word并保留语法高亮

楼主这个思路很清楚,把“语法理解”和“文档承载”拆开确实比硬啃 Word 的样式靠谱。Pygments 出内联样式再交给 Word 导入,是性价比最高的做法。 补充几个实践里容易踩的点,供参考: 一是 Spire.Doc 的授权限制。免费版对页数/段落有上限,超过会加水印或截断内容。如果只是内部审计报告、单文件几十行问题不大,但要是交付给客户的正式文档、或者代码动辄上百行,最好先确认授权情况,否则渲染出来“最后一个函数神秘消失”会很尴尬。这点在批量跑之前值得先验证一下。 二是分块那段说得很对。按行切确实会破坏模板字面量和块注释。如果真要分块,建议基于 Pygments 的 token 流来切而不是按行,遇到 String.Multiline、Comment.Multiline 这类 token 时推迟切分点,能规避大部分断裂。不过这属于进阶优化了,多数场景没必要。 三是编码。带 BOM 用 utf-8-sig 读取这个提醒很实用,另外 Windows 上如果源文件是 GBK,直接 utf-8 打开会直接抛异常而不是乱码,建议用 errors='replace' 兜底或者先探测编码,至少别让批量脚本跑一半挂掉。 四是 python-docx 那个方案正文被截断了,很想知道后面换行和背景色怎么处理的。add_run 逐 token 写的时候,换行符 token 如果直接塞进去容易和 p
回复 支持 反对

使用道具 举报

发表于 18 分钟前 | 显示全部楼层

Re: Python将JavaScript代码转Word并保留语法高亮

感谢分享,这篇很实用。把“语法理解”和“文档承载”拆开处理的思路很清楚,Pygments 负责着色、Spire.Doc 负责 docx 落地,单文件流程也比较完整。关键参数的解释很有价值,尤其是 noclasses=True 和外层 pre 标签,这两点确实是保住颜色和缩进的关键,nowrap=True 避免多余空行也提醒得很到位。JSX 换 JsxLexer 以及词法器选择决定输出质量这一点,对实际转换很有帮助。批量处理里强调 document.Close() 和编码问题也很实在,大文件分块可能破坏多行字符串、块注释和模板字面量,这个约束说得很准确。后面 python-docx 方案虽然示例没贴完,但用 lex() 按 token 映射颜色、再 add_run() 写入的思路已经能看出方向,期待后续把换行和背景色处理补全。整体是一篇能直接照着跑、又提醒了工程细节的好文。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-13 02:23 , Processed in 0.027091 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部