Skip to content

Commit 482ad2d

Browse files
authored
feat: allow nested decorations which share an 'edge' with parent (#911)
1 parent 6a85269 commit 482ad2d

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

packages/core/src/transformer-decorations.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export function transformerDecorations(): ShikiTransformer {
166166
const lineApplies: (() => void)[] = []
167167

168168
// Apply decorations in reverse order so the nested ones get applied first.
169-
const sorted = ctx.decorations.sort((a, b) => b.start.offset - a.start.offset)
169+
const sorted = ctx.decorations.sort((a, b) => b.start.offset - a.start.offset || a.end.offset - b.end.offset)
170170
for (const decoration of sorted) {
171171
const { start, end } = decoration
172172
if (start.line === end.line) {
@@ -193,12 +193,12 @@ function verifyIntersections(items: ResolvedDecorationItem[]): void {
193193

194194
for (let j = i + 1; j < items.length; j++) {
195195
const bar = items[j]
196-
const isFooHasBarStart = foo.start.offset < bar.start.offset && bar.start.offset < foo.end.offset
197-
const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset < foo.end.offset
198-
const isBarHasFooStart = bar.start.offset < foo.start.offset && foo.start.offset < bar.end.offset
199-
const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset < bar.end.offset
196+
const isFooHasBarStart = foo.start.offset <= bar.start.offset && bar.start.offset < foo.end.offset
197+
const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset <= foo.end.offset
198+
const isBarHasFooStart = bar.start.offset <= foo.start.offset && foo.start.offset < bar.end.offset
199+
const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset <= bar.end.offset
200200
if (isFooHasBarStart || isFooHasBarEnd || isBarHasFooStart || isBarHasFooEnd) {
201-
if (isFooHasBarEnd && isFooHasBarEnd)
201+
if (isFooHasBarStart && isFooHasBarEnd)
202202
continue // nested
203203
if (isBarHasFooStart && isBarHasFooEnd)
204204
continue // nested

packages/core/test/decorations.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ describe('decorations', () => {
7878
end: { line: 8, character: 25 },
7979
properties: { class: 'highlighted' },
8080
},
81+
// "hast"
82+
// Testing nested decorations with shared start.
83+
{
84+
start: { line: 8, character: 15 },
85+
end: { line: 8, character: 19 },
86+
properties: { class: 'highlighted' },
87+
},
88+
// "Html"
89+
// Testing nested decorations with shared end.
90+
{
91+
start: { line: 8, character: 21 },
92+
end: { line: 8, character: 25 },
93+
properties: { class: 'highlighted' },
94+
},
8195
// "// final"
8296
// Testing offset === code.length edge case
8397
{
@@ -117,12 +131,12 @@ describe('decorations errors', () => {
117131
lang: 'ts',
118132
decorations: [
119133
{ start: 0, end: 10 },
120-
{ start: 5, end: 15 },
134+
{ start: 1, end: 11 },
121135
],
122136
})
123137
})
124138
.rejects
125-
.toThrowErrorMatchingInlineSnapshot(`[ShikiError: Decorations {"line":0,"character":0,"offset":0} and {"line":1,"character":1,"offset":5} intersect.]`)
139+
.toThrowErrorMatchingInlineSnapshot(`[ShikiError: Decorations {"line":0,"character":0,"offset":0} and {"line":0,"character":1,"offset":1} intersect.]`)
126140
})
127141

128142
it('throws when lines overflow', async () => {

packages/core/test/out/decorations/basic.html

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)