* Parse a single text paragraph (`a:p`).
(pNode: SafeXmlNode)
| 67 | * Parse a single text paragraph (`a:p`). |
| 68 | */ |
| 69 | function parseParagraph(pNode: SafeXmlNode): TextParagraph { |
| 70 | const pPr = pNode.child('pPr') |
| 71 | const level = pPr.numAttr('lvl') ?? 0 |
| 72 | |
| 73 | // Re-scan in document order to get correct interleaving of r, br, fld |
| 74 | const orderedRuns: TextRun[] = [] |
| 75 | for (const child of pNode.allChildren()) { |
| 76 | const ln = child.localName |
| 77 | if (ln === 'r') { |
| 78 | const rPr = child.child('rPr') |
| 79 | const tNode = child.child('t') |
| 80 | orderedRuns.push({ |
| 81 | text: tNode.text(), |
| 82 | properties: rPr.exists() ? rPr : undefined, |
| 83 | }) |
| 84 | } else if (ln === 'br') { |
| 85 | const rPr = child.child('rPr') |
| 86 | orderedRuns.push({ |
| 87 | text: '\n', |
| 88 | properties: rPr.exists() ? rPr : undefined, |
| 89 | }) |
| 90 | } else if (ln === 'fld') { |
| 91 | const rPr = child.child('rPr') |
| 92 | const tNode = child.child('t') |
| 93 | orderedRuns.push({ |
| 94 | text: tNode.text(), |
| 95 | properties: rPr.exists() ? rPr : undefined, |
| 96 | }) |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | const endParaRPrNode = pNode.child('endParaRPr') |
| 101 | return { |
| 102 | properties: pPr.exists() ? pPr : undefined, |
| 103 | runs: orderedRuns, |
| 104 | level, |
| 105 | endParaRPr: endParaRPrNode.exists() ? endParaRPrNode : undefined, |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Parse a text body (`p:txBody` or `a:txBody`). |
no test coverage detected