8cb1f9f479
Publish SDK (PyPI) / publish (push) Has been cancelled
Publish SDK (npm) / publish (@aionui/officecli-sdk) (push) Has been cancelled
SDK smoke / smoke (windows-latest) (push) Has been cancelled
Publish SDK (npm) / publish (@officecli/officecli-sdk) (push) Has been cancelled
Publish SDK (npm) / publish (@officecli/sdk) (push) Has been cancelled
Publish SDK (npm) / publish (officecli-sdk) (push) Has been cancelled
SDK smoke / smoke (macos-latest) (push) Has been cancelled
SDK smoke / smoke (ubuntu-latest) (push) Has been cancelled
Skill parity / diff (push) Has been cancelled
212 lines
13 KiB
JSON
212 lines
13 KiB
JSON
{
|
|
"$schema": "../_schema.json",
|
|
"format": "docx",
|
|
"element": "revision",
|
|
"elementAliases": ["ins", "del", "moveto", "movefrom"],
|
|
"parent": "paragraph|run|table|row|cell|section",
|
|
"operations": {
|
|
"add": false,
|
|
"set": true,
|
|
"get": true,
|
|
"query": true,
|
|
"remove": false,
|
|
"note": "`set: true` covers the action verb (revision.action on a /revision selector or native path). `add: false` here means the *revision element itself* has no Add surface — tracked changes are created indirectly via `revision.type` / `revision.author` / `revision.date` / `revision.id` on the host run/paragraph/table/row/cell/section, where they read as `add: true` / `set: true`. Per-property add/set flags below describe behavior on the synthetic /revision node, not on the host."
|
|
},
|
|
"paths": {
|
|
"positional": ["/revision[N]", "/body/p[N]/ins[M]", "/body/p[N]/del[M]"],
|
|
"selector": ["/revision", "/revision[@id=N]", "/revision[@id=N][@type=moveFrom|moveTo]", "/revision[@author=NAME]", "/revision[@type=ins|del|format|moveFrom|moveTo]", "/revision[@author=NAME][@type=TYPE]"]
|
|
},
|
|
"note": "Tracked-change marker. `query revision` enumerates every w:ins / w:del / w:moveFrom / w:moveTo / w:*PrChange in the document. The synthetic Path is `/revision[@id=N]` when the marker carries a stable w:id (true for everything Word/WPS writes), falling back to positional `/revision[N]` only for markers without an id — same precedence as paragraphs (`p[@paraId=…]` → `p[N]`). When the same w:id is shared by more than one marker (canonical case: a moveFrom/moveTo pair binds via shared id), the Path is disambiguated as `/revision[@id=N][@type=moveFrom]` / `[@type=moveTo]` so single-end addressing stays unique. `set /revision[@id=N]` without the type segment still acts on both ends together (pair-wise accept/reject, the usual move-revision intent). Use the @id= form in scripts; positional indexes shift after accept/reject. Both `get /revision[@id=N]` and `set /revision[@id=N] --prop revision.action=…` accept the same path. Two disjoint property namespaces: `revision.type=ins|del|format|moveFrom|moveTo` creates a tracked change (used with add/set on the host run/paragraph/table/row/cell/section), while `revision.action=accept|reject` acts on existing markers via /revision selectors or native paths (/body/p[N], /body/p[N]/r[M], etc.). The two namespaces are mutually exclusive — mixing revision.action with any revision.type/.author/.date/.id key is rejected as ambiguous. Bare `revision=…` is no longer accepted. **Find + revision** (matches Word's Find&Replace with Track Changes on): `set <path> --prop find=PATTERN [--prop regex=true] --prop revision.author=NAME` infers the marker shape from the operation — `--prop replace=NEW` produces a w:del(old) + w:ins(new) pair, `--prop replace=` (empty) produces w:del only, format props (bold, font.color, …) produce one w:rPrChange per matched run, and paragraph-scope props (align, indent, …) produce one w:pPrChange per matched paragraph. The handler auto-allocates a fresh revision.id per marker, so `--prop revision.id=…` is rejected on find (would collide across markers). `revision.type=ins|del|moveFrom|moveTo` and `revision.action=…` are also rejected on find — the shape is inferred and the action verb belongs on the selector, not the creation context. `find` / `replace` / `regex` themselves are cross-cutting Set keywords (not revision-specific properties; not listed below) — pairing any of them with `revision.author` routes the find pass through the track-changes pipeline. Separate from `revisionNumber` on / (document save counter) and `trackChanges` on /settings (track-mode toggle).",
|
|
"properties": {
|
|
"type": {
|
|
"type": "enum",
|
|
"values": ["ins", "del", "moveTo", "moveFrom", "format"],
|
|
"add": false, "set": false, "get": true,
|
|
"examples": ["query revision[@type=ins]"],
|
|
"readback": "revision type (read-only on the revision node; create with --prop revision.type=… on the host element)",
|
|
"enforcement": "report"
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"description": "text content for ins / content marker for del (read-only).",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "concatenated text (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"author": {
|
|
"type": "string",
|
|
"description": "Author of the revision. Surfaced on `query revision` nodes and on host elements (run/paragraph/…) that carry an ins/del/*PrChange ancestor. Supply via --prop revision.author=… on the host element to create. **Run host is stricter:** `set <run> --prop revision.author=X` alone is rejected — without an action to attribute, the legacy fallback wrote an empty-snapshot rPrChange (recording no change). Either pair revision.author with a real format prop (`--prop bold=true`), or pass `--prop revision.type=ins|del|moveFrom|moveTo` so the wrap itself is the action. The same strictness applies to bare `revision.type=format` on Run. Non-Run hosts (paragraph/table/row/cell/section) still accept bare attribution and emit an empty-snapshot *PrChange — needed for dump→batch round-trip of table-level markers whose pre-change baseline can't be reconstructed. Also accepted alongside `find` (and `replace` / format / paragraph props) — the find dispatch wraps each match in the matching marker shape and attributes it to this author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [
|
|
"query revision[@author=Alice]",
|
|
"set /body --prop find=fox --prop replace=cat --prop revision.author=Alice",
|
|
"set /body --prop find=red --prop bold=true --prop revision.author=Bob",
|
|
"set /body --prop find=BAD --prop replace= --prop revision.author=Carol",
|
|
"set /body --prop 'find=\\$\\d+' --prop regex=true --prop bold=true --prop revision.author=Dave"
|
|
],
|
|
"readback": "revision author (read-only on the revision node)",
|
|
"enforcement": "report"
|
|
},
|
|
"date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp (read-only on the revision node). Supply via --prop revision.date=… on the host element to create.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "Date attribute (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"id": {
|
|
"type": "integer",
|
|
"description": "w:id attribute. Stable across save; pair moveFrom/moveTo by reusing the same id. Supply via --prop revision.id=… on the host element.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "revision id (read-only on the revision node)",
|
|
"enforcement": "report"
|
|
},
|
|
"nativePath": {
|
|
"type": "string",
|
|
"description": "Path to the underlying w:ins/w:del/w:moveFrom/w:moveTo/w:*PrChange element in document DOM terms (e.g. /body/p[2]/ins[1]). Use it to address the revision via the action native-path form: `set <nativePath> --prop revision.action=accept|reject`. Emitted on `query revision` synthetic nodes only.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": ["set /body/p[2]/ins[1] --prop revision.action=accept"],
|
|
"readback": "DOM path to the revision element (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"action": {
|
|
"type": "enum",
|
|
"values": ["accept", "reject"],
|
|
"description": "Accept / reject verb. Lives in a disjoint namespace from the creation keys above; mixing with revision.type/.author/.date/.id throws. Walks matching elements in reverse document order so /revision[N] paths don't shift mid-batch.",
|
|
"add": false, "set": true, "get": false,
|
|
"examples": [
|
|
"set /revision --prop revision.action=accept",
|
|
"set '/revision[@author=Alice]' --prop revision.action=reject",
|
|
"set '/revision[@type=ins]' --prop revision.action=accept",
|
|
"set /revision[@id=42] --prop revision.action=accept",
|
|
"set '/revision[@id=42][@type=moveTo]' --prop revision.action=reject",
|
|
"set /revision[3] --prop revision.action=accept",
|
|
"set /body/p[1]/r[2] --prop revision.action=reject"
|
|
],
|
|
"readback": "(action is a verb — not surfaced on get)",
|
|
"enforcement": "strict"
|
|
},
|
|
"paraMarkIns.author": {
|
|
"type": "string",
|
|
"description": "Author of a paragraph-mark-only insertion (w:rPr/w:ins inside the paragraph's pPr/rPr — the ¶ mark itself is part of the inserted change, distinct from a run-level w:ins wrapping content). Surfaced on paragraph nodes via get/query; on dump→batch the emitter rewrites it to bare revision.author on the synthetic paragraph + strips revision.type so the bare-attribution path defaults the type to ins.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "paragraph-mark insertion author (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"paraMarkIns.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to paraMarkIns.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "paragraph-mark insertion date (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"paraMarkIns.id": {
|
|
"type": "int",
|
|
"description": "w:id of the paragraph-mark insertion. Get-only companion to paraMarkIns.author/.date.",
|
|
"add": false, "set": false, "get": true,
|
|
"enforcement": "report"
|
|
},
|
|
"paraMarkDel.author": {
|
|
"type": "string",
|
|
"description": "Author of a paragraph-mark deletion (w:rPr/w:del in pPr/rPr — the ¶ join is tracked as a deletion). Deletion counterpart of paraMarkIns.author. Get-only.",
|
|
"add": false, "set": false, "get": true,
|
|
"enforcement": "report"
|
|
},
|
|
"paraMarkDel.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to paraMarkDel.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"enforcement": "report"
|
|
},
|
|
"paraMarkDel.id": {
|
|
"type": "int",
|
|
"description": "w:id of the paragraph-mark deletion. Get-only.",
|
|
"add": false, "set": false, "get": true,
|
|
"enforcement": "report"
|
|
},
|
|
"revision.beforeLost": {
|
|
"type": "bool",
|
|
"description": "Get-only signal: true when a *PrChange 'before' property snapshot cannot round-trip through dump→batch (the prior-formatting baseline is lost on replay). Lets the batch emitter warn rather than silently drop it.",
|
|
"add": false, "set": false, "get": true,
|
|
"enforcement": "report"
|
|
},
|
|
"sectPrChange.author": {
|
|
"type": "string",
|
|
"description": "Author of a w:sectPrChange on a section (revision.type=format equivalent at section scope; surfaced as a distinct key because the snapshot lives in a different OOXML wrapper than rPrChange/pPrChange).",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "section property-change author (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"sectPrChange.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to sectPrChange.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "section property-change date (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"sectPrChange.id": {
|
|
"type": "string",
|
|
"description": "Stable w:id companion to sectPrChange.author; preserved across dump→batch so the marker's identity survives the round-trip.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "section property-change id (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"tblPrChange.author": {
|
|
"type": "string",
|
|
"description": "Author of a w:tblPrChange on a table (table-properties revision — borders/style/layout snapshot).",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "table property-change author (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"tblPrChange.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to tblPrChange.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "table property-change date (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"trPrChange.author": {
|
|
"type": "string",
|
|
"description": "Author of a w:trPrChange on a table row (row-properties revision — row height/header/cantSplit snapshot). Separate from w:trPr/w:ins (= row insertion as tracked change).",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "row property-change author (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"trPrChange.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to trPrChange.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "row property-change date (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"tcPrChange.author": {
|
|
"type": "string",
|
|
"description": "Author of a w:tcPrChange on a table cell (cell-properties revision — borders/shading/width snapshot). Separate from w:tcPr/w:cellIns/w:cellDel (= cell insertion/deletion).",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "cell property-change author (read-only)",
|
|
"enforcement": "report"
|
|
},
|
|
"tcPrChange.date": {
|
|
"type": "string",
|
|
"description": "ISO-8601 timestamp companion to tcPrChange.author.",
|
|
"add": false, "set": false, "get": true,
|
|
"examples": [],
|
|
"readback": "cell property-change date (read-only)",
|
|
"enforcement": "report"
|
|
}
|
|
}
|
|
}
|