Skip to content

Commit af44bf9

Browse files
sealer3antfu
andauthored
feat: allow negative character positions for denoting end of line offsets (#1051)
Co-authored-by: Anthony Fu <[email protected]>
1 parent 84a6513 commit af44bf9

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

docs/guide/decorations.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ const x = 10
6363
console.log(x)
6464
```
6565

66+
Negative character positions denote characters from the end of a line, starting with the line end:
67+
68+
```ts twoslash
69+
import { DecorationItem } from 'shiki'
70+
// ---cut---
71+
const item: DecorationItem = {
72+
start: { line: 0, character: 0 },
73+
end: { line: 0, character: -1 },
74+
properties: { class: 'highlighted-word' }
75+
}
76+
```
77+
78+
This highlights the entire first line:
79+
80+
```ts
81+
// @decorations:[{"start":{"line":0,"character":0},"end":{"line":0,"character":-1},"properties":{"class":"highlighted-word"}}]
82+
const x = 10
83+
console.log(x)
84+
```
85+
6686
## Use Decorations in Transformers
6787

6888
For advanced use cases, you can use the [Transformers API](./transformers.md) to have full access to the tokens and the HAST tree.

packages/core/src/transformer-decorations.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,19 @@ export function transformerDecorations(): ShikiTransformer {
4242
const line = converter.lines[p.line]
4343
if (line === undefined)
4444
throw new ShikiError(`Invalid decoration position ${JSON.stringify(p)}. Lines length: ${converter.lines.length}`)
45-
if (p.character < 0 || p.character > line.length)
45+
46+
let character = p.character
47+
// Negative numbers are positions from the end of the line
48+
if (character < 0)
49+
character = line.length + character
50+
51+
if (character < 0 || character > line.length)
4652
throw new ShikiError(`Invalid decoration position ${JSON.stringify(p)}. Line ${p.line} length: ${line.length}`)
4753

4854
return {
4955
...p,
50-
offset: converter.posToIndex(p.line, p.character),
56+
character,
57+
offset: converter.posToIndex(p.line, character),
5158
}
5259
}
5360
}

packages/core/test/decorations.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ describe('decorations', () => {
102102
end: code.length,
103103
properties: { class: 'highlighted' },
104104
},
105+
// "ult" from "return result"
106+
// Testing negative character positions
107+
{
108+
start: { line: 9, character: -4 },
109+
end: { line: 9, character: -1 },
110+
properties: { class: 'highlighted' },
111+
},
105112
],
106113
})
107114

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)