Skip to content

Commit c2c0a01

Browse files
committed
fix(text): fix internal links; refactor tests; fixes #180
1 parent 289c459 commit c2c0a01

File tree

7 files changed

+162
-151
lines changed

7 files changed

+162
-151
lines changed

__tests__/htmlToMultiText-hyperlinks.test.ts

Lines changed: 14 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import Automizer, { modify } from '../src/index';
1+
import Automizer, { modify, XmlElement } from '../src/index';
2+
import { HtmlToMultiTextHelper } from '../src/helper/html-to-multitext-helper';
3+
import { ModifyTextHelper } from '../src';
24

35
test('create presentation with external hyperlinks using htmlToMultiText', async () => {
46
const automizer = new Automizer({
@@ -10,7 +12,7 @@ test('create presentation with external hyperlinks using htmlToMultiText', async
1012
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
1113

1214
const html =
13-
'<p>Visit our <a href="https://example.com">website</a> for more information</p>';
15+
'<body><p>Visit our <a href="https://example.com">website</a> for more information</p></body>';
1416

1517
const result = await pres
1618
.addSlide('TextReplace.pptx', 1, (slide) => {
@@ -21,26 +23,6 @@ test('create presentation with external hyperlinks using htmlToMultiText', async
2123
// Test passes if file is written successfully
2224
});
2325

24-
test('create presentation with internal slide hyperlinks using htmlToMultiText', async () => {
25-
const automizer = new Automizer({
26-
templateDir: `${__dirname}/pptx-templates`,
27-
outputDir: `${__dirname}/pptx-output`,
28-
removeExistingSlides: true,
29-
});
30-
31-
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
32-
33-
const html = '<p>See <a href="3">slide 3</a> for details</p>';
34-
35-
const result = await pres
36-
.addSlide('TextReplace.pptx', 1, (slide) => {
37-
slide.modifyElement('setText', modify.htmlToMultiText(html));
38-
})
39-
.write(`htmlToMultiText-internal-hyperlinks.test.pptx`);
40-
41-
// Test passes if file is written successfully
42-
});
43-
4426
test('create presentation with multiple hyperlinks using htmlToMultiText', async () => {
4527
const automizer = new Automizer({
4628
templateDir: `${__dirname}/pptx-templates`,
@@ -50,10 +32,11 @@ test('create presentation with multiple hyperlinks using htmlToMultiText', async
5032

5133
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
5234

35+
// Please make sure that the internally linked slide does exist, otherwise the link will not be active.
5336
const html =
5437
'<html><body>' +
5538
'<p>Check out <a href="https://google.com">Google</a> or <a href="https://github.com">GitHub</a></p>' +
56-
'<p>Jump to <a href="2">slide 2</a> or <a href="5">slide 5</a></p>' +
39+
'<p>Jump to <a href="2">slide 2</a> or <a href="5">slide 5 not existing</a></p>' +
5740
'</body></html>';
5841

5942
const result = await pres
@@ -103,7 +86,7 @@ test('create presentation with hyperlinks in bullet lists using htmlToMultiText'
10386
'<ul>' +
10487
'<li><a href="https://site1.com">First link</a></li>' +
10588
'<li><a href="https://site2.com">Second link</a></li>' +
106-
'<li>Regular bullet with <a href="3">internal link</a></li>' +
89+
'<li>Regular bullet with <a href="1">internal link</a></li>' +
10790
'</ul>' +
10891
'</body></html>';
10992

@@ -130,7 +113,7 @@ test('create presentation with mixed external and internal hyperlinks', async ()
130113
'<p>Visit <a href="https://example.com">example.com</a> or go to <a href="2">slide 2</a></p>' +
131114
'<ul>' +
132115
'<li>External: <a href="https://google.com">Google</a></li>' +
133-
'<li>Internal: <a href="4">Jump to slide 4</a></li>' +
116+
'<li>Internal: <a href="1">Jump to slide 1</a></li>' +
134117
'<li>More info: <a href="https://github.com">GitHub</a></li>' +
135118
'</ul>' +
136119
'</body></html>';
@@ -144,48 +127,6 @@ test('create presentation with mixed external and internal hyperlinks', async ()
144127
// Test passes if file is written successfully
145128
});
146129

147-
test('verify hyperlink relationships are created correctly', async () => {
148-
const automizer = new Automizer({
149-
templateDir: `${__dirname}/pptx-templates`,
150-
outputDir: `${__dirname}/pptx-output`,
151-
removeExistingSlides: true,
152-
});
153-
154-
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
155-
156-
const html = '<p>Visit <a href="https://example.com">our website</a></p>';
157-
158-
const result = await pres
159-
.addSlide('TextReplace.pptx', 1, async (slide) => {
160-
slide.modifyElement('setText', modify.htmlToMultiText(html));
161-
})
162-
.write(`htmlToMultiText-verify-relationships.test.pptx`);
163-
164-
// Test passes if file is written successfully
165-
// Test passes if file is written successfully
166-
});
167-
168-
test('verify internal slide hyperlink relationships are created correctly', async () => {
169-
const automizer = new Automizer({
170-
templateDir: `${__dirname}/pptx-templates`,
171-
outputDir: `${__dirname}/pptx-output`,
172-
removeExistingSlides: true,
173-
});
174-
175-
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
176-
177-
const html = '<p>Go to <a href="3">slide 3</a></p>';
178-
179-
const result = await pres
180-
.addSlide('TextReplace.pptx', 1, async (slide) => {
181-
slide.modifyElement('setText', modify.htmlToMultiText(html));
182-
})
183-
.write(`htmlToMultiText-verify-internal-relationships.test.pptx`);
184-
185-
// Test passes if file is written successfully
186-
// Test passes if file is written successfully
187-
});
188-
189130
test('htmlToMultiText with hyperlinks but no relation element should log warning', async () => {
190131
const automizer = new Automizer({
191132
templateDir: `${__dirname}/pptx-templates`,
@@ -196,14 +137,18 @@ test('htmlToMultiText with hyperlinks but no relation element should log warning
196137

197138
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
198139

199-
const html = '<p>Visit <a href="https://example.com">website</a></p>';
140+
const html = '<body><p>Visit <a href="https://example.com">website</a></p></body>';
200141

201142
// This should complete without error, but hyperlinks won't be created
202143
const result = await pres
203144
.addSlide('TextReplace.pptx', 1, (slide) => {
204145
// Directly calling htmlToMultiText without relation element access
205146
// would normally skip hyperlink creation
206-
slide.modifyElement('setText', modify.htmlToMultiText(html));
147+
// A repair message is displayed on opening in PowerPoint.
148+
const paragraphs = new HtmlToMultiTextHelper().run(html);
149+
return (element: XmlElement): void => {
150+
ModifyTextHelper.setMultiText(paragraphs)(element);
151+
};
207152
})
208153
.write(`htmlToMultiText-no-relation-warning.test.pptx`);
209154

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Automizer, { modify } from '../src/index';
2+
3+
test('create presentation with internal slide hyperlinks using htmlToMultiText', async () => {
4+
const automizer = new Automizer({
5+
templateDir: `${__dirname}/pptx-templates`,
6+
outputDir: `${__dirname}/pptx-output`,
7+
removeExistingSlides: true,
8+
});
9+
10+
const pres = automizer.loadRoot(`RootTemplate.pptx`).load(`TextReplace.pptx`);
11+
12+
// Please note: You need to recalculate the target slide number and
13+
// refer to the final position, including the existing slides.
14+
// Internally, we target to `slide${target}.xml`, which might be a different slide.
15+
// Please make sure that the internally linked slide does exist, otherwise the link will not be active.
16+
17+
const html = '<body><p>See <a href="4">slide 3</a> for details</p></body>';
18+
19+
const result = await pres
20+
.addSlide('TextReplace.pptx', 1)
21+
.addSlide('TextReplace.pptx', 1, (slide) => {
22+
slide.modifyElement('setText', modify.htmlToMultiText(html));
23+
})
24+
.addSlide('TextReplace.pptx', 1)
25+
.addSlide('TextReplace.pptx', 1)
26+
.addSlide('TextReplace.pptx', 1)
27+
.write(`htmlToMultiText-internal-hyperlinks.test.pptx`);
28+
29+
// Test passes if file is written successfully
30+
});

__tests__/replace-multi-text.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ test('create presentation, replace multi text.', async () => {
2323
},
2424
textRuns: [
2525
{
26-
text: 'test 0',
26+
text: 'Internal Hyperlink',
2727
style: {
2828
color: {
2929
type: 'srgbClr',
3030
value: 'CCCCCC',
3131
},
32+
hyperlink: {
33+
isInternal: true,
34+
target: 1
35+
}
3236
},
3337
},
3438
],
@@ -100,6 +104,9 @@ test('create presentation, replace multi text.', async () => {
100104
type: 'srgbClr',
101105
value: '0000FF',
102106
},
107+
hyperlink: {
108+
target: 'https://github.com',
109+
}
103110
},
104111
},
105112
],

src/helper/html-to-multitext-helper.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { TextStyle } from '../types/modify-types';
22
import { MultiTextParagraph } from '../interfaces/imulti-text';
33
import { DOMParser, Node } from '@xmldom/xmldom';
4+
import { log } from './general-helper';
45

56
type TextRun = { text: string; style?: TextStyle };
67

@@ -30,6 +31,8 @@ export class HtmlToMultiTextHelper {
3031
);
3132
}
3233
});
34+
} else {
35+
log('You need to provide a <body> tag for HtmlToMultiText', 0);
3336
}
3437

3538
return paragraphs;
@@ -257,19 +260,16 @@ export class HtmlToMultiTextHelper {
257260
// Internal slide link: <a href="3">Link to slide 3</a>
258261
const slideNumber = parseInt(href);
259262
style.hyperlink = {
260-
url: `slide${slideNumber}.xml`,
263+
target: slideNumber,
261264
isInternal: true,
262-
slideNumber: slideNumber,
263265
};
264266
} else {
265267
// External link: <a href="https://example.com">Link</a>
266268
style.hyperlink = {
267-
url: href,
269+
target: href,
268270
isInternal: false,
269271
};
270272
}
271-
272-
console.log("style", style);
273273
}
274274

275275
/**

src/helper/modify-text-helper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { MultiTextParagraph } from '../interfaces/imulti-text';
77
import { MultiTextHelper } from './multitext-helper';
88
import { HtmlToMultiTextHelper } from './html-to-multitext-helper';
99
import { XmlHelper } from './xml-helper';
10+
import { vd } from './general-helper';
1011

1112
export default class ModifyTextHelper {
1213
/**

0 commit comments

Comments
 (0)