Skip to content

Commit 8806b30

Browse files
Aashish-Jha-11Aashish_Jha_1107
andauthored
fix: enable decorations for structure: inline (#1103)
Co-authored-by: Aashish_Jha_1107 <user.email:"aashishjha1107@gmail.com>
1 parent 4bf5be3 commit 8806b30

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

packages/core/src/highlight/code-to-hast.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ export function tokensToHast(
207207
lineNodes.push(lineNode)
208208
lines.push(lineNode)
209209
}
210+
else if (structure === 'inline') {
211+
lineNodes.push(lineNode)
212+
}
210213
})
211214

212215
if (structure === 'classic') {
@@ -220,6 +223,55 @@ export function tokensToHast(
220223

221224
root.children.push(preNode)
222225
}
226+
else if (structure === 'inline') {
227+
// For inline structure, we need to invoke code hooks for transformers like decorations
228+
// Build a synthetic code structure from the root's children
229+
const syntheticLines: Element[] = []
230+
let currentLine: Element = {
231+
type: 'element',
232+
tagName: 'span',
233+
properties: { class: 'line' },
234+
children: [],
235+
}
236+
237+
for (const child of root.children) {
238+
if (child.type === 'element' && child.tagName === 'br') {
239+
syntheticLines.push(currentLine)
240+
currentLine = {
241+
type: 'element',
242+
tagName: 'span',
243+
properties: { class: 'line' },
244+
children: [],
245+
}
246+
}
247+
else if (child.type === 'element' || child.type === 'text') {
248+
currentLine.children.push(child)
249+
}
250+
}
251+
syntheticLines.push(currentLine)
252+
253+
const syntheticCode: Element = {
254+
type: 'element',
255+
tagName: 'code',
256+
properties: {},
257+
children: syntheticLines,
258+
}
259+
260+
let transformedCode = syntheticCode
261+
for (const transformer of transformers)
262+
transformedCode = transformer?.code?.call(context, transformedCode) || transformedCode
263+
264+
// Extract the transformed children back to root
265+
root.children = []
266+
for (let i = 0; i < transformedCode.children.length; i++) {
267+
if (i > 0)
268+
root.children.push({ type: 'element', tagName: 'br', properties: {}, children: [] })
269+
270+
const line = transformedCode.children[i]
271+
if (line.type === 'element')
272+
root.children.push(...line.children)
273+
}
274+
}
223275

224276
let result = root
225277
for (const transformer of transformers)

packages/core/test/decorations.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,64 @@ describe('decorations', () => {
153153
await expect(style + html)
154154
.toMatchFileSnapshot('./out/decorations/adjacent.html')
155155
})
156+
157+
it('works with structure inline', async () => {
158+
const html = await codeToHtml('const foo = "bar"', {
159+
theme: 'vitesse-light',
160+
lang: 'ts',
161+
structure: 'inline',
162+
decorations: [
163+
{
164+
start: { line: 0, character: 6 },
165+
end: { line: 0, character: 9 },
166+
properties: { class: 'highlighted' },
167+
},
168+
{
169+
start: { line: 0, character: 12 },
170+
end: { line: 0, character: 17 },
171+
properties: { class: 'highlighted-body' },
172+
},
173+
],
174+
})
175+
176+
await expect(style + html)
177+
.toMatchFileSnapshot('./out/decorations/inline.html')
178+
})
179+
180+
it('works with structure inline multiline', async () => {
181+
const multilineCode = `const x = 1
182+
const y = 2
183+
const z = 3`
184+
185+
const html = await codeToHtml(multilineCode, {
186+
theme: 'vitesse-light',
187+
lang: 'ts',
188+
structure: 'inline',
189+
decorations: [
190+
// Highlight "x" in first line
191+
{
192+
start: { line: 0, character: 6 },
193+
end: { line: 0, character: 7 },
194+
properties: { class: 'highlighted' },
195+
},
196+
// Highlight "y" in second line
197+
{
198+
start: { line: 1, character: 6 },
199+
end: { line: 1, character: 7 },
200+
properties: { class: 'highlighted-body' },
201+
},
202+
// Highlight across lines
203+
{
204+
start: { line: 1, character: 10 },
205+
end: { line: 2, character: 6 },
206+
properties: { class: 'highlighted-border' },
207+
},
208+
],
209+
})
210+
211+
await expect(style + html)
212+
.toMatchFileSnapshot('./out/decorations/inline-multiline.html')
213+
})
156214
})
157215

158216
describe('decorations errors', () => {

packages/core/test/out/decorations/inline-multiline.html

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)