Skip to content

Commit

Permalink
feat: allow nested decorations which share an 'edge' with parent (#911)
Browse files Browse the repository at this point in the history
  • Loading branch information
ms264556 authored Jan 30, 2025
1 parent 6a85269 commit 482ad2d
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
12 changes: 6 additions & 6 deletions packages/core/src/transformer-decorations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export function transformerDecorations(): ShikiTransformer {
const lineApplies: (() => void)[] = []

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

for (let j = i + 1; j < items.length; j++) {
const bar = items[j]
const isFooHasBarStart = foo.start.offset < bar.start.offset && bar.start.offset < foo.end.offset
const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset < foo.end.offset
const isBarHasFooStart = bar.start.offset < foo.start.offset && foo.start.offset < bar.end.offset
const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset < bar.end.offset
const isFooHasBarStart = foo.start.offset <= bar.start.offset && bar.start.offset < foo.end.offset
const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset <= foo.end.offset
const isBarHasFooStart = bar.start.offset <= foo.start.offset && foo.start.offset < bar.end.offset
const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset <= bar.end.offset
if (isFooHasBarStart || isFooHasBarEnd || isBarHasFooStart || isBarHasFooEnd) {
if (isFooHasBarEnd && isFooHasBarEnd)
if (isFooHasBarStart && isFooHasBarEnd)
continue // nested
if (isBarHasFooStart && isBarHasFooEnd)
continue // nested
Expand Down
18 changes: 16 additions & 2 deletions packages/core/test/decorations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ describe('decorations', () => {
end: { line: 8, character: 25 },
properties: { class: 'highlighted' },
},
// "hast"
// Testing nested decorations with shared start.
{
start: { line: 8, character: 15 },
end: { line: 8, character: 19 },
properties: { class: 'highlighted' },
},
// "Html"
// Testing nested decorations with shared end.
{
start: { line: 8, character: 21 },
end: { line: 8, character: 25 },
properties: { class: 'highlighted' },
},
// "// final"
// Testing offset === code.length edge case
{
Expand Down Expand Up @@ -117,12 +131,12 @@ describe('decorations errors', () => {
lang: 'ts',
decorations: [
{ start: 0, end: 10 },
{ start: 5, end: 15 },
{ start: 1, end: 11 },
],
})
})
.rejects
.toThrowErrorMatchingInlineSnapshot(`[ShikiError: Decorations {"line":0,"character":0,"offset":0} and {"line":1,"character":1,"offset":5} intersect.]`)
.toThrowErrorMatchingInlineSnapshot(`[ShikiError: Decorations {"line":0,"character":0,"offset":0} and {"line":0,"character":1,"offset":1} intersect.]`)
})

it('throws when lines overflow', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/out/decorations/basic.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 482ad2d

Please sign in to comment.