fix: retain links across formatted text runs
This commit is contained in:
@@ -349,6 +349,11 @@ function createTextRuns(
|
|||||||
(style.hyperlinkProtected === true || style.hyperlink === true)
|
(style.hyperlinkProtected === true || style.hyperlink === true)
|
||||||
) {
|
) {
|
||||||
run.href = pendingHref;
|
run.href = pendingHref;
|
||||||
|
} else if (
|
||||||
|
!style.hidden &&
|
||||||
|
style.hyperlinkProtected !== true &&
|
||||||
|
style.hyperlink !== true
|
||||||
|
) {
|
||||||
pendingHref = undefined;
|
pendingHref = undefined;
|
||||||
}
|
}
|
||||||
result.push(run);
|
result.push(run);
|
||||||
|
|||||||
@@ -114,15 +114,20 @@ describe('OneNote rich-content model', () => {
|
|||||||
it('associates only allow-listed hyperlink marker targets', () => {
|
it('associates only allow-listed hyperlink marker targets', () => {
|
||||||
const safe = parseSyntheticLink('https://example.com/path');
|
const safe = parseSyntheticLink('https://example.com/path');
|
||||||
expect(safe.text).toBe('Example');
|
expect(safe.text).toBe('Example');
|
||||||
expect(safe.runs.find((run) => run.text === 'Example')?.href).toBe(
|
expect(
|
||||||
'https://example.com/path'
|
safe.runs
|
||||||
);
|
.filter((run) => !run.style.hidden)
|
||||||
|
.map((run) => [run.text, run.href])
|
||||||
|
).toEqual([
|
||||||
|
['Exam', 'https://example.com/path'],
|
||||||
|
['ple', 'https://example.com/path'],
|
||||||
|
]);
|
||||||
|
|
||||||
const unsafe = parseSyntheticLink('javascript:alert(1)');
|
const unsafe = parseSyntheticLink('javascript:alert(1)');
|
||||||
expect(unsafe.text).toBe('Example');
|
expect(unsafe.text).toBe('Example');
|
||||||
expect(
|
expect(
|
||||||
unsafe.runs.find((run) => run.text === 'Example')?.href
|
unsafe.runs.filter((run) => !run.style.hidden).map((run) => run.href)
|
||||||
).toBeUndefined();
|
).toEqual([undefined, undefined]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('retains an embedded-file node as a downloadable lazy resource', () => {
|
it('retains an embedded-file node as a downloadable lazy resource', () => {
|
||||||
@@ -276,6 +281,7 @@ function parseSyntheticLink(href: string): OneNoteTextBlock {
|
|||||||
const paragraphId = id(guid, 2);
|
const paragraphId = id(guid, 2);
|
||||||
const hiddenId = id(guid, 3);
|
const hiddenId = id(guid, 3);
|
||||||
const visibleId = id(guid, 4);
|
const visibleId = id(guid, 4);
|
||||||
|
const secondVisibleId = id(guid, 5);
|
||||||
const marker = `\ufddfHYPERLINK "${href}"`;
|
const marker = `\ufddfHYPERLINK "${href}"`;
|
||||||
const text = `${marker}Example`;
|
const text = `${marker}Example`;
|
||||||
const objects = [
|
const objects = [
|
||||||
@@ -284,12 +290,15 @@ function parseSyntheticLink(href: string): OneNoteTextBlock {
|
|||||||
JCID.RichTextNode,
|
JCID.RichTextNode,
|
||||||
{
|
{
|
||||||
...emptyProps(),
|
...emptyProps(),
|
||||||
objectIds: [compact(2), compact(3), compact(4)],
|
objectIds: [compact(2), compact(3), compact(4), compact(5)],
|
||||||
properties: {
|
properties: {
|
||||||
entries: [
|
entries: [
|
||||||
referenceEntry(PROPERTY.ParagraphStyle, 'one'),
|
referenceEntry(PROPERTY.ParagraphStyle, 'one'),
|
||||||
referenceEntry(PROPERTY.TextRunFormatting, 'many', 2),
|
referenceEntry(PROPERTY.TextRunFormatting, 'many', 3),
|
||||||
bytesEntry(PROPERTY.TextRunIndex, u32Vector(marker.length)),
|
bytesEntry(
|
||||||
|
PROPERTY.TextRunIndex,
|
||||||
|
u32Vector(marker.length, marker.length + 4)
|
||||||
|
),
|
||||||
bytesEntry(
|
bytesEntry(
|
||||||
PROPERTY.RichEditTextUnicode,
|
PROPERTY.RichEditTextUnicode,
|
||||||
Buffer.from(text, 'utf16le')
|
Buffer.from(text, 'utf16le')
|
||||||
@@ -318,6 +327,15 @@ function parseSyntheticLink(href: string): OneNoteTextBlock {
|
|||||||
),
|
),
|
||||||
guid
|
guid
|
||||||
),
|
),
|
||||||
|
object(
|
||||||
|
secondVisibleId,
|
||||||
|
JCID.ParagraphStyleObject,
|
||||||
|
props(
|
||||||
|
boolEntry(PROPERTY.HyperlinkProtected, true),
|
||||||
|
boolEntry(PROPERTY.Italic, true)
|
||||||
|
),
|
||||||
|
guid
|
||||||
|
),
|
||||||
];
|
];
|
||||||
const space: ObjectSpace = {
|
const space: ObjectSpace = {
|
||||||
id: id(guid, 0),
|
id: id(guid, 0),
|
||||||
|
|||||||
Reference in New Issue
Block a user