Skip to main content

Modify Text

You can select and import generic shapes from any loaded template. It is possible to update the containing text in several ways:

import { ModifyTextHelper, XmlElement } from 'pptx-automizer';

pres.addSlide('SlideWithImages.pptx', 1, (slide) => {
// You can directly modify the child nodes of <p:sp>
slide.addElement('shapes', 2, 'Arrow', (element: XmlElement) => {
element.getElementsByTagName('a:t').item(0).textContent = 'Custom content';
});

// You might prefer a built-in function to set text:
slide.addElement('shapes', 2, 'Arrow', [
ModifyTextHelper.setText('This is my text'),
]);
});

Replace tagged text

pptx-automizer also provides a powerful helper to replace tagged text. You can use e.g. {{myTag}} on your slide and apply a modifier to insert dynamic text. Font style can be inherited from template or updated by the modifier.

import { modify } from 'pptx-automizer';

pres.addSlide('TextReplace.pptx', 1, (slide) => {
slide.modifyElement(
// This is the name of the target element on slide #1 of
// 'TextReplace.pptx
'replaceText',
// This will look for a string `{{replace}}` inside the text
// contents of 'replaceText' shape
modify.replaceText([
{
replace: 'replace',
by: {
text: 'Apples',
},
},
]),
);
});

MultiText: styled paragraphs and lists

You can use modify.setMultiText to replace all text contents of an existing textfield by styled paragraphs, bulleted lists and text runs:

import { modify } from 'pptx-automizer';

pres.addSlide('TextReplace.pptx', 1, (slide) => {
slide.modifyElement(
'setText',
modify.setMultiText([
{
paragraph: {
bullet: true,
level: 0,
marginLeft: 41338,
indent: -87325,
alignment: 'l',
},
textRuns: [
{
text: 'Bullet point level 0',
style: {
isItalics: true,
color: {
type: 'srgbClr',
value: 'CCCCCC',
},
},
},
],
},
]),
);
});

Within a text run, \n and \v (U+000B, the character PowerPoint itself uses for a soft line break created with Shift+Enter) are converted into an <a:br/> line break inside the same paragraph. Add another entry to the array if you need a real paragraph with its own bullet, level and alignment.

paragraph.lineSpacing, spaceBefore and spaceAfter take points as a plain number, or { percent: 100 } for spacing relative to the line height (100 = one line) — the relative form scales with the paragraph's font size.

Convert HTML to text contents

It is also possible to directly convert an HTML page into pptx text contents. HTML code will be flattened and converted into a MultiText array.

import { modify } from 'pptx-automizer';

const html =
'<html><body>' +
'<h2 style="text-align: center">Quarterly report</h2>' +
'<p>Plain text with <strong>bold</strong>, <em>italics</em> and ' +
'<span style="color: #ff0000; font-size: 12pt">styling</span>.</p>' +
'<ul>' +
'<li>bullet level 0' +
'<ul><li>bullet level 1</li></ul>' +
'</li>' +
'</ul>' +
'<ol><li>numbered</li><li>list</li></ol>' +
'<p><a href="https://example.com">external link</a> and ' +
'<a href="3">a link to slide 3</a></p>' +
'</body></html>';

pres.addSlide('TextReplace.pptx', 1, (slide) => {
slide.modifyElement('setText', modify.htmlToMultiText(html));
});

What HTML is supported

PPTX text is strictly flat: a text body is a list of paragraphs, each a list of text runs, with no nesting anywhere. HTML hierarchy is therefore projected onto that — nested inline tags become one run with accumulated character properties, nested lists become paragraphs with a 0-based level, and a block inside a block (<li><p>…</p></li>) yields a single paragraph, with the innermost block winning.

Supported
Paragraphs<p>, <div>, <h1><h6>, <blockquote>, <pre>, <section> & friends
Lists<ul>, <ol>, <li>, nested to 9 levels. <ol> renders as real automatic numbering (1. / a. / i. per level)
Inline<strong>/<b>, <em>/<i>, <u>/<ins>, <s>/<strike>/<del>, <sub>, <sup>, <code>/<kbd>/<samp> (monospace), <mark>, <br>, <span>, <a>, <font>
Links<a href="https://…"> external, <a href="3"> to slide 3
CSS (on any element)font-size (px converted at 96dpi, or pt), color, background-color (highlight), font-weight, font-style, text-decoration, font-family, text-align

Both list-nesting styles work and produce identical output — properly nested (<li>text<ul>…</ul></li>) and the sibling form CKEditor emits (<ul><li/><ul>…</ul></ul>).

Good to know:

  • The input has to be wrapped in <html><body>…</body></html>, and is parsed as XML: quote your attributes and close your container tags, as WYSIWYG editors do. &nbsp;, &amp; and an unclosed <br> are fine.
  • Colors can be written in any CSS notation (#f00, red, rgb(255,0,0)) and are normalized to the 6-digit hex OOXML requires.
  • Relative font sizes (em, %) are ignored rather than guessed, leaving the size inherited from the template.
  • Whitespace collapses the way a browser collapses it; &nbsp; survives.
  • Vertical spacing mirrors the browser's default stylesheet: <p>, headings and the outer edges of lists get one collapsed gap of one line height (spaceBefore: { percent: 100 }, so it scales with each paragraph's font size), while items of the same list sit tight. A trailing <br> before a closing block tag is dropped, exactly as a browser renders it; a deliberate <br><br> keeps its one empty line.
  • Alignment is only written when the HTML asks for it — otherwise the target shape's layout keeps deciding.
  • Font size and color of the target shape's existing text are used as the fallback style, so generated text keeps the template's look.
  • <table> markup has no equivalent in a single text shape: the cell text is kept, but flattened into one paragraph. Use modify.setTableData for tables.
  • <a href="4"> is a slide number in the finished output deck, counting the root template's existing slides — not the index of your addSlide() calls. The target slide has to exist, or the relationship dangles and PowerPoint shows the text underlined but unlinked, without a warning.
  • A color on an <a> element is written to the run, but PowerPoint paints hyperlink text in the theme's <a:hlink> color regardless. To restyle links, change that theme color; per-link colors are not achievable in PPTX.

Text helpers (MultiText/HTML)

Generate complex text (multiple runs, links, bullets) either from a structured value or directly from HTML.

// From structured paragraphs
slide.modifyElement('TextBox', [
ModifyTextHelper.setMultiText([
{
paragraph: { bullet: false },
textRuns: [
{ text: 'Hello ', style: { isBold: true } },
{ text: 'World' },
],
},
]),
]);

// From HTML - note the required <html><body> wrapper
const html =
'<html><body><p><b>Bold</b> and ' +
'<a href="https://example.com">link</a></p></body></html>';
slide.modifyElement('TextBox', [ModifyTextHelper.htmlToMultiText(html)]);

HtmlToMultiTextHelper and MultiTextHelper also support hyperlinks: an external target (<a href="https://...">) or a slide number for an internal link (<a href="3">). See What HTML is supported above for the full tag and CSS coverage, and the tests:

Find out more