{
  "$schema": "../_schema.json",
  "format": "pptx",
  "element": "connector",
  "elementAliases": ["connection"],
  "parent": "slide",
  "operations": {
    "add": true,
    "set": true,
    "get": true,
    "query": true,
    "remove": true
  },
  "paths": {
    "positional": ["/slide[N]/connector[M]"]
  },
  "note": "Aliases: connection. Straight / bent / curved connector lines. 'from' and 'to' reference shape paths to auto-attach endpoints; with no explicit x/y/width/height the line is anchored edge-to-edge (auto-picks the facing edges) so it spans the gap instead of crossing both shapes. Use fromSide/toSide to force a specific edge. NOTE: the chosen edge drives only the drawn geometry (offset/extent) — the low-level stCxn/endCxn idx is not yet derived from a side, so after a manual drag in PowerPoint the connector re-anchors to the auto-picked edge.",
  "properties": {
    "shape": {
      "type": "enum",
      "values": ["straight", "elbow", "curve"],
      "description": "Connector geometry preset. Add/Set accept the short names (straight, elbow, curve) or OOXML full names (straightConnector1, bentConnector2, bentConnector3, curvedConnector2, curvedConnector3 — bent/curved 2-segment forms map to the 3-segment primitive). Get readback returns the OOXML full name.",
      "add": true, "set": true, "get": true,
      "examples": ["--prop shape=straight", "--prop shape=elbow", "--prop shape=curve"],
      "readback": "OOXML preset full name (straightConnector1, bentConnector3, curvedConnector3)",
      "enforcement": "report"
    },
    "from": {
      "type": "string",
      "description": "start-point frame reference (Add/Set only). Accepts a frame index (1, 2, …), a positional path /slide[N]/<type>[M], an @id path /slide[N]/<type>[@id=M] (as returned by query/get), or an @name path /slide[N]/<type>[@name=Foo]. <type> may be shape, picture, table, chart, group, connector, etc. — any top-level frame, not only shapes. Reverse path resolution is not implemented.",
      "add": true, "set": true, "get": false,
      "examples": ["--prop from='/slide[1]/shape[1]'", "--prop from='/slide[1]/shape[@id=10001]'", "--prop from='/slide[1]/shape[@name=BoxA]'"],
      "readback": "see startShape/endShape get-only properties for resolved endpoint shape ids",
      "enforcement": "report"
    },
    "to": {
      "type": "string",
      "description": "end-point frame reference (Add/Set only). Accepts a frame index (1, 2, …), a positional path /slide[N]/<type>[M], an @id path /slide[N]/<type>[@id=M] (as returned by query/get), or an @name path /slide[N]/<type>[@name=Foo]. <type> may be shape, picture, table, chart, group, connector, etc. — any top-level frame, not only shapes. Reverse path resolution is not implemented.",
      "add": true, "set": true, "get": false,
      "examples": ["--prop to='/slide[1]/shape[2]'", "--prop to='/slide[1]/shape[@id=10002]'", "--prop to='/slide[1]/shape[@name=BoxB]'"],
      "readback": "see startShape/endShape get-only properties for resolved endpoint shape ids",
      "enforcement": "report"
    },
    "x": {
      "type": "length",
      "add": true, "set": true, "get": true,
      "examples": ["--prop x=1in"],
      "readback": "length in cm (e.g. \"2cm\")",
      "enforcement": "report"
    },
    "y": {
      "type": "length",
      "add": true, "set": true, "get": true,
      "examples": ["--prop y=1in"],
      "readback": "length in cm (e.g. \"2cm\")",
      "enforcement": "report"
    },
    "width": {
      "type": "length",
      "add": true, "set": true, "get": true,
      "examples": ["--prop width=2in"],
      "readback": "length in cm (e.g. \"2cm\")",
      "enforcement": "report"
    },
    "height": {
      "type": "length",
      "add": true, "set": true, "get": true,
      "examples": ["--prop height=1in"],
      "readback": "length in cm (e.g. \"2cm\")",
      "enforcement": "report"
    },
    "color": {
      "type": "color",
      "add": true, "set": true, "get": true,
      "examples": ["--prop color=#000000"],
      "readback": "#-prefixed uppercase hex",
      "enforcement": "report"
    },
    "lineWidth": {
      "type": "length",
      "add": true, "set": true, "get": true,
      "aliases": ["linewidth", "line.width"],
      "examples": ["--prop lineWidth=2pt"],
      "readback": "pt-qualified string",
      "enforcement": "report"
    },
    "lineDash": {
      "type": "enum",
      "values": ["solid", "dot", "dash", "dashDot", "lgDash", "lgDashDot", "lgDashDotDot", "sysDot", "sysDash", "sysDashDot", "sysDashDotDot", "longdash", "longdashdot"],
      "description": "outline dash pattern (drawingML prstDash). Get readback emits the canonical OOXML token (lgDash/lgDashDot/lgDashDotDot/sysDot/...); the long* aliases are accepted on Add/Set only. 'dashDotDot' has no native enum member; it is accepted as an alias for sysDashDotDot (Get readback returns sysDashDotDot).",
      "add": true, "set": true, "get": true,
      "aliases": ["linedash"],
      "examples": ["--prop lineDash=dash", "--prop lineDash=lgDash", "--prop lineDash=sysDash"],
      "readback": "canonical OOXML preset dash token (e.g. lgDash, sysDashDot)",
      "enforcement": "report"
    },
    "lineJoin": {
      "type": "enum",
      "values": ["round", "bevel", "miter"],
      "description": "line join style at connector corners (drawingML <a:ln> child <a:round/> | <a:bevel/> | <a:miter/>). Accepts compound 'miter:<lim>' to also set the miter limit in one key.",
      "add": true, "set": true, "get": true,
      "aliases": ["linejoin", "line.join"],
      "examples": ["--prop lineJoin=miter", "--prop lineJoin=miter:800000", "--prop lineJoin=round"],
      "readback": "round | bevel | miter",
      "enforcement": "report"
    },
    "miterLimit": {
      "type": "number",
      "description": "miter join limit (drawingML <a:miter @lim>) in 1000ths of a percent (e.g. 800000 = 800%). Implies lineJoin=miter when set without an explicit lineJoin.",
      "add": true, "set": true, "get": true,
      "aliases": ["miterlimit", "miter.limit", "line.miterlimit"],
      "examples": ["--prop miterLimit=800000"],
      "readback": "integer (1000ths of a percent)",
      "enforcement": "report"
    },
    "headEnd": {
      "type": "enum",
      "values": ["none", "triangle", "arrow", "stealth", "diamond", "oval"],
      "add": true, "set": true, "get": true,
      "aliases": ["headend"],
      "examples": ["--prop headEnd=triangle"],
      "readback": "OOXML LineEndValues token (canonical)",
      "enforcement": "report"
    },
    "tailEnd": {
      "type": "enum",
      "values": ["none", "triangle", "arrow", "stealth", "diamond", "oval"],
      "add": true, "set": true, "get": true,
      "aliases": ["tailend"],
      "examples": ["--prop tailEnd=arrow"],
      "readback": "OOXML LineEndValues token (canonical)",
      "enforcement": "report"
    },
    "id": {
      "type": "number",
      "description": "cNvPr shape id; @id in /connector[@id=ID]. add honors a caller-supplied id so dump-replay keeps it stable for spTgt animation refs; immutable after creation.",
      "add": true, "set": false, "get": true,
      "readback": "integer shape id",
      "enforcement": "report"
    },
    "name": {
      "type": "string",
      "description": "connector name",
      "add": true, "set": true, "get": true,
      "examples": ["--prop name=\"Arrow1\""],
      "readback": "plain string",
      "enforcement": "report"
    },
    "text": {
      "type": "string",
      "description": "inline text label on the connector (<p:cxnSp> child <p:txBody>). Single-paragraph single-run; Set replaces any existing label. Multi-paragraph labels arrive via subsequent add paragraph/run ops against the connector path.",
      "add": true, "set": true, "get": true,
      "examples": ["--prop text=\"Yes\"", "--prop text=\"No\""],
      "readback": "plain text content of the connector txBody",
      "enforcement": "report"
    },
    "fromSide": {
      "type": "enum",
      "values": ["top", "bottom", "left", "right", "center"],
      "description": "which edge of the 'from' shape the line leaves. Omitted (default) = auto-pick the edge facing the 'to' shape (right↔left for a same-row layout, bottom↔top for stacked) so the line spans the gap instead of crossing both boxes. 'center' pins the endpoint to the shape center (line enters the box), reproducing the legacy center-to-center look on demand. Drives the drawn geometry (offset/extent); the endpoint still follows the shape when it moves, but re-anchors to the auto edge (sides are not persisted).",
      "add": true, "set": true, "get": false,
      "aliases": ["fromside", "startSide", "startside"],
      "examples": ["--prop fromSide=right", "--prop fromSide=bottom", "--prop fromSide=center"],
      "enforcement": "report"
    },
    "toSide": {
      "type": "enum",
      "values": ["top", "bottom", "left", "right", "center"],
      "description": "which edge of the 'to' shape the line enters. See fromSide; default auto-picks the edge facing the 'from' shape.",
      "add": true, "set": true, "get": false,
      "aliases": ["toside", "endSide", "endside"],
      "examples": ["--prop toSide=left", "--prop toSide=top"],
      "enforcement": "report"
    },
    "fromIdx": {
      "type": "number",
      "description": "low-level connection-site index on the 'from' shape (writes <a:stCxn idx>). Prefer fromSide unless you know the preset's cxnLst ordering. 0-based; defaults to 0.",
      "add": true, "set": true, "get": false,
      "aliases": ["fromidx", "startIdx", "startidx"],
      "examples": ["--prop fromIdx=3"],
      "enforcement": "report"
    },
    "toIdx": {
      "type": "number",
      "description": "low-level connection-site index on the 'to' shape (writes <a:endCxn idx>). Prefer toSide. 0-based; defaults to 0.",
      "add": true, "set": true, "get": false,
      "aliases": ["toidx", "endIdx", "endidx"],
      "examples": ["--prop toIdx=1"],
      "enforcement": "report"
    },
    "startShape": { "type":"number", "add":false, "set":false, "get":true, "description":"shape id of the start connection endpoint.", "readback":"integer shape id", "enforcement":"report" },
    "startIdx":   { "type":"number", "add":false, "set":false, "get":true, "description":"connection point index on start shape (0-based; emitted whenever the start endpoint is connected, 0 = default anchor). Get-side readback of fromIdx.", "readback":"integer", "enforcement":"report" },
    "endShape":   { "type":"number", "add":false, "set":false, "get":true, "description":"shape id of the end connection endpoint.", "readback":"integer shape id", "enforcement":"report" },
    "endIdx":     { "type":"number", "add":false, "set":false, "get":true, "description":"connection point index on end shape (0-based; emitted whenever the end endpoint is connected, 0 = default anchor). Get-side readback of toIdx.", "readback":"integer", "enforcement":"report" },
    "zorder": {
      "type": "string",
      "description": "1-based z-order in slide shape tree. Add accepts 'top'/'bottom'/'forward'/'backward'/integer (same vocabulary as shape/picture/group); Get returns the resolved integer position.",
      "aliases": ["z-order", "order"],
      "add": true, "set": false, "get": true,
      "examples": ["--prop zorder=top", "--prop zorder=2"],
      "readback": "integer (1-based position among content elements)",
      "enforcement": "report"
    }
  }
}
