feat: export core Hermes skills
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Post-save sweep: strip explicit attributes from WB INS runs when
|
||||
the same-paragraph original runs rely on inheritance (ea=None, hint=None, sz=None).
|
||||
|
||||
Usage: python3 strip-inherited-ins-attrs.py <docx_path>
|
||||
|
||||
Modifies the file in place. Run AFTER ContractEditor.save() and BEFORE
|
||||
wb-ins-font-verify.py to fix the known "ContractEditor默认sz=21与docDefaults继承冲突".
|
||||
|
||||
The pattern: for each paragraph containing WB INS, find the first plain w:r
|
||||
(non-INS, non-DEL) as reference. If that reference run has no explicit
|
||||
eastAsia/hint/sz, strip those from all WB INS runs in the same paragraph.
|
||||
"""
|
||||
import sys
|
||||
import zipfile
|
||||
import tempfile
|
||||
import shutil
|
||||
from lxml import etree
|
||||
|
||||
WNS = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
|
||||
|
||||
|
||||
def strip_inherited_attrs(filepath):
|
||||
with zipfile.ZipFile(filepath, 'r') as z:
|
||||
doc_xml = z.read('word/document.xml')
|
||||
all_files = {n: z.read(n) for n in z.namelist()}
|
||||
|
||||
tree = etree.fromstring(doc_xml)
|
||||
body = tree.find(f'{WNS}body')
|
||||
paras = body.findall(f'{WNS}p')
|
||||
|
||||
fixed = 0
|
||||
for p in paras:
|
||||
# Find first plain run as reference
|
||||
orig_run = None
|
||||
for child in p:
|
||||
if child.tag == f'{WNS}r':
|
||||
orig_run = child
|
||||
break
|
||||
if orig_run is None:
|
||||
continue
|
||||
|
||||
orig_rpr = orig_run.find(f'{WNS}rPr')
|
||||
orig_rf = orig_rpr.find(f'{WNS}rFonts') if orig_rpr is not None else None
|
||||
orig_sz = orig_rpr.find(f'{WNS}sz') if orig_rpr is not None else None
|
||||
orig_ea = orig_rf.get(f'{WNS}eastAsia') if orig_rf is not None else None
|
||||
orig_hint = orig_rf.get(f'{WNS}hint') if orig_rf is not None else None
|
||||
orig_sz_val = orig_sz.get(f'{WNS}val') if orig_sz is not None else None
|
||||
|
||||
for ins in p.findall(f'.//{WNS}ins'):
|
||||
if ins.get(f'{WNS}author') != 'WB':
|
||||
continue
|
||||
for r in ins.findall(f'{WNS}r'):
|
||||
rpr = r.find(f'{WNS}rPr')
|
||||
if rpr is None:
|
||||
continue
|
||||
rf = rpr.find(f'{WNS}rFonts')
|
||||
sz = rpr.find(f'{WNS}sz')
|
||||
|
||||
if orig_ea is None and rf is not None:
|
||||
for attr in ['eastAsia', 'ascii', 'hAnsi']:
|
||||
key = f'{WNS}{attr}'
|
||||
if key in rf.attrib:
|
||||
if orig_rf is None or orig_rf.get(key) is None:
|
||||
del rf.attrib[key]
|
||||
fixed += 1
|
||||
|
||||
if orig_hint is None and rf is not None and f'{WNS}hint' in rf.attrib:
|
||||
del rf.attrib[f'{WNS}hint']
|
||||
fixed += 1
|
||||
|
||||
if orig_sz_val is None and sz is not None:
|
||||
rpr.remove(sz)
|
||||
fixed += 1
|
||||
|
||||
# Save
|
||||
tmp = tempfile.mktemp(suffix='.docx')
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as zout:
|
||||
for name in all_files:
|
||||
if name == 'word/document.xml':
|
||||
new_xml = etree.tostring(tree, xml_declaration=True, encoding='UTF-8', standalone=True)
|
||||
new_str = new_xml.decode('utf-8')
|
||||
new_str = new_str.replace(
|
||||
"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>",
|
||||
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')
|
||||
new_str = new_str.replace('\n', '\r\n')
|
||||
zout.writestr(name, new_str.encode('utf-8'))
|
||||
else:
|
||||
zout.writestr(name, all_files[name])
|
||||
shutil.move(tmp, filepath)
|
||||
return fixed
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} <docx_path>")
|
||||
sys.exit(1)
|
||||
n = strip_inherited_attrs(sys.argv[1])
|
||||
print(f"Fixed {n} inherited attribute issues in {sys.argv[1]}")
|
||||
Reference in New Issue
Block a user