Skip to content

Commit 61ea95f

Browse files
committed
Fix: Line numbers and highlighting rendering
1 parent d33b796 commit 61ea95f

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed

packages/components/src/components/hds/code-block/index.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
SPDX-License-Identifier: MPL-2.0
44
}}
55

6-
<div class={{this.classNames}} ...attributes>
6+
<div class={{this.classNames}} ...attributes {{this._setUpObserver}}>
77
<div class="hds-code-block__header">
88
{{~yield (hash Title=(component "hds/code-block/title"))~}}
99
{{~yield (hash Description=(component "hds/code-block/description"))~}}
@@ -17,7 +17,7 @@
1717
data-start={{@lineNumberStart}}
1818
id={{this._preCodeId}}
1919
tabindex="0"
20-
><code {{did-insert this.setPrismCode}} {{did-update this.setPrismCode this.code @language}}>
20+
><code {{this._setUpCodeBlockCode}}>
2121
{{~this._prismCode~}}
2222
</code></pre>
2323

packages/components/src/components/hds/code-block/index.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { assert } from '@ember/debug';
1010
import { next, schedule } from '@ember/runloop';
1111
import { htmlSafe } from '@ember/template';
1212
import { guidFor } from '@ember/object/internals';
13+
import { modifier } from 'ember-modifier';
1314

1415
import Prism from 'prismjs';
1516

@@ -75,6 +76,31 @@ export default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {
7576

7677
// Generates a unique ID for the code content
7778
private _preCodeId = 'pre-code-' + guidFor(this);
79+
private _preCodeElement!: HTMLPreElement;
80+
private _observer!: IntersectionObserver;
81+
82+
// If a code block is hidden from view, and made visible after load, the Prism code needs to be re-run
83+
private _setUpObserver = modifier((element: HTMLElement) => {
84+
const codeBlock = element.querySelector('code') as HTMLElement;
85+
this._observer = new IntersectionObserver((entries) => {
86+
entries.forEach((entry) => {
87+
if (entry.isIntersecting) {
88+
this.setPrismCode(codeBlock);
89+
}
90+
});
91+
});
92+
this._observer.observe(element);
93+
94+
return () => {
95+
this._observer.disconnect();
96+
};
97+
});
98+
99+
private _setUpCodeBlockCode = modifier((element: HTMLElement) => {
100+
this._preCodeElement = element.querySelector('pre') as HTMLPreElement;
101+
this.setPrismCode(element);
102+
return () => {};
103+
});
78104

79105
// code text content for the CodeBlock
80106
get code(): string {
@@ -152,24 +178,26 @@ export default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {
152178
element,
153179
});
154180

155-
// Get the actual height & the content height of the preCodeElement
156181
// eslint-disable-next-line ember/no-runloop
157182
schedule('afterRender', (): void => {
158-
const preCodeElement = document.getElementById(this._preCodeId);
159-
this._codeContentHeight = preCodeElement?.scrollHeight ?? 0;
160-
this._codeContainerHeight = preCodeElement?.clientHeight ?? 0;
161-
});
162-
163-
// Force prism-line-highlight plugin initialization
164-
// Context: https://github.com/hashicorp/design-system/pull/1749#discussion_r1374288785
165-
if (this.args.highlightLines) {
166-
// we need to delay re-evaluating the context for prism-line-highlight for as much as possible, and `afterRender` is the 'latest' we can use in the component lifecycle
167-
// eslint-disable-next-line ember/no-runloop
168-
schedule('afterRender', (): void => {
183+
// Get the actual height & the content height of the preCodeElement
184+
this._codeContentHeight = this._preCodeElement?.scrollHeight ?? 0;
185+
this._codeContainerHeight = this._preCodeElement?.clientHeight ?? 0;
186+
187+
// we need to re-trigger the line numbers generation as late as possible to account for any line wrapping styles that are applied
188+
if (this.args.hasLineWrapping && Prism?.plugins?.['lineNumbers']) {
189+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
190+
Prism.plugins['lineNumbers'].highlight(this._preCodeElement);
191+
}
192+
193+
// Force prism-line-highlight plugin initialization
194+
// Context: https://github.com/hashicorp/design-system/pull/1749#discussion_r1374288785
195+
if (this.args.highlightLines) {
196+
// we need to delay re-evaluating the context for prism-line-highlight for as much as possible, and `afterRender` is the 'latest' we can use in the component lifecycle
169197
// we piggy-back on the plugin's `resize` event listener to trigger a new call of the `highlightLines` function: https://github.com/PrismJS/prism/blob/master/plugins/line-highlight/prism-line-highlight.js#L337
170198
if (window) window.dispatchEvent(new Event('resize'));
171-
});
172-
}
199+
}
200+
});
173201
});
174202
}
175203
}

0 commit comments

Comments
 (0)