redlining-content #41
Replies: 2 comments
|
"""Redline an uploaded Word .docx submission against a provided .dotx template. Produces a .docx based on the template, where every textual difference between No PDF/visual conversion is performed: the template is already a perfect Word Usage: If no template is given, the single .dotx/.docx bundled in assets/ is The diff is word-level over the whole document: both sides are flattened to Pure lxml + standard library for .docx; .pdf additionally uses pdfplumber from lxml import etree Directory holding the bundled template asset shipped with this skill.ASSETS_DIR = os.path.join( def find_default_template(): --- OOXML namespaces ------------------------------------------------------W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" AUTHOR = "Copilot Studio AI" DOC_PART = "/word/document.xml" _rev_id = 0 def next_id(): def wq(name): def el(name): --- text helpers ----------------------------------------------------------def para_text(p): def tokenize(text): def words(text): def tbl_text(tbl): def first_rpr(p): --- run / revision builders ----------------------------------------------def make_run(text, rpr=None, deleted=False): def wrap_revision(kind, runs): --- global word-level diff engine -----------------------------------------Rationale (validated against real Copilot Studio runs): a paragraph-leveldiff is fragile because PDFs wrap a single logical paragraph across severallines with no blank line between them, so line-per-paragraph splittingproduces hundreds of false paragraph mismatches. Instead we flatten BOTHsides to a single stream of words and diff once. Line-wrap and paragraphboundaries become irrelevant -- only real word differences matter. Thetemplate's paragraph structure and formatting are still preserved by mappingeach template word back to its source paragraph and only rebuilding theparagraphs that actually changed.def build_paragraph(ppr, base_rpr, tokens): def redline_body(tpl_body, sub_words, stats): def template_table_words(tpl_body): def strip_table_words(sub_words, table_words): --- table-cell redlining (.docx submissions only) -------------------------A .docx submission preserves table structure, so we can align the template'stables to the submission's tables by position (table -> row -> cell) and diffeach cell's text word-by-word, injecting tracked changes directly into thetemplate cell while preserving its <w:tcPr> (width, borders, shading). A PDFhas no table structure to align, so tables remain passthrough for PDFs.def diff_tokens(tpl_words, sub_words): def cell_words(tc): def redline_cell(tpl_cell, sub_cell, stats): def redline_tables(tpl_body, sub_body, stats): --- packaging -------------------------------------------------------------def read_part(path, part): def enable_track_changes(settings_bytes): def convert_content_types(ct_bytes): def write_output(template_path, out_path, new_doc_xml): --- submission readers (the only docx/pdf fork) ---------------------------Body paragraph text is always diffed as a flat word list. For .docx thesubmission body element is also returned so its tables can be diffed againstthe template's tables (see redline_tables). For .pdf there is no structure, sotable content is instead stripped from the flat word list.def read_docx_body(path): def body_paragraph_words(body): def read_pdf_words(path): def read_submission(path): --- entry point -----------------------------------------------------------def redline(submission_path, template_path=None, out_path=None): if name == "main": |
|
📣 Looks like someone found the first red flag—time for you to show us how to really 'redline' this discussion! Andrew Hess (@AndrewHessMSFT) — you're the author of Redlining Content, and someone just poked your skill. 👀 Mind swinging by to take a look? |
Uh oh!
There was an error while loading. Please reload this page.
redlining-content
Redlines a document based on changes from a template with Track Changes.
https://microsoft.github.io/cat-agent-skills/skills/redlining-content/
All reactions