Skip to content

Commit 09852e3

Browse files
wolfibDevtools-frontend LUCI CQ
authored andcommitted
Use heading elements for headings in MarkdownInsightRenderer
Use HTML heading elements instead of `<strong>` for rendering markdown headings in the MarkdownInsightRenderer. All `<h1>` - `<h6>` tags are styled to match the previous `<strong>` styling. Bug: 365835615 Change-Id: I07cf6189c3c3124fbbdd42098e2cf6ddd08f6c69 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6179443 Commit-Queue: Alex Rudenko <[email protected]> Auto-Submit: Wolfgang Beyer <[email protected]> Reviewed-by: Alex Rudenko <[email protected]>
1 parent 4ccc690 commit 09852e3

File tree

4 files changed

+43
-14
lines changed

4 files changed

+43
-14
lines changed

front_end/ui/components/markdown_view/MarkdownView.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describeWithEnvironment('MarkdownView', () => {
176176
assert.isTrue(renderResult.includes('<em'));
177177
});
178178
it('sets custom classes on the token types', () => {
179-
renderer.setCustomClasses({em: 'custom-class'});
179+
renderer.addCustomClasses({em: 'custom-class'});
180180

181181
const renderResult = renderer.renderToken(getFakeToken({type: 'em', text: 'em text'}));
182182
const container = renderTemplateResult(renderResult);
@@ -211,9 +211,11 @@ describeWithEnvironment('MarkdownView', () => {
211211
renderer.renderToken({type: 'image', text: 'learn more', href: 'https://example.com'} as Marked.Marked.Token);
212212
assert((result.values[0] as HTMLElement).tagName === 'X-LINK');
213213
});
214-
it('renders headers as a strong element', () => {
215-
const result = renderer.renderToken({type: 'heading', text: 'learn more'} as Marked.Marked.Token);
216-
assert(result.strings.join('').includes('<strong>'));
214+
it('renders headings as headings with the `insight` class', () => {
215+
const renderResult = renderer.renderToken(getFakeToken({type: 'heading', text: 'a heading text', depth: 3}));
216+
const container = renderTemplateResult(renderResult);
217+
assert.isTrue(
218+
container.querySelector('h3')?.classList.contains('insight'), 'Expected `insight`-class to be applied');
217219
});
218220
it('renders unsupported tokens', () => {
219221
const result = renderer.renderToken({type: 'html', raw: '<!DOCTYPE html>'} as Marked.Marked.Token);

front_end/ui/components/markdown_view/MarkdownView.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ export class MarkdownView extends HTMLElement {
4242

4343
if (data.animationEnabled) {
4444
this.#animationEnabled = true;
45-
this.#renderer.setCustomClasses({
45+
this.#renderer.addCustomClasses({
4646
paragraph: 'pending',
4747
heading: 'pending',
4848
list_item: 'pending',
4949
});
5050
} else {
5151
this.#animationEnabled = false;
52-
this.#renderer.setCustomClasses({});
52+
this.#renderer.removeCustomClasses({
53+
paragraph: 'pending',
54+
heading: 'pending',
55+
list_item: 'pending',
56+
});
5357
}
5458

5559
this.#update();
@@ -67,7 +71,11 @@ export class MarkdownView extends HTMLElement {
6771
}
6872
this.#isAnimating = false;
6973
this.#animationEnabled = false;
70-
this.#renderer.setCustomClasses({});
74+
this.#renderer.removeCustomClasses({
75+
paragraph: 'pending',
76+
heading: 'pending',
77+
list_item: 'pending',
78+
});
7179
}
7280

7381
#animate(): void {
@@ -127,16 +135,29 @@ declare global {
127135
* Default renderer is used for the IssuesPanel and allows only well-known images and links to be embedded.
128136
*/
129137
export class MarkdownLitRenderer {
130-
#customClasses: Record<string, string> = {};
138+
#customClasses: Record<string, Set<string>> = {};
139+
140+
addCustomClasses(customClasses: Record<Marked.Marked.Token['type'], string>): void {
141+
for (const [type, className] of Object.entries(customClasses)) {
142+
if (!this.#customClasses[type]) {
143+
this.#customClasses[type] = new Set();
144+
}
145+
this.#customClasses[type].add(className);
146+
}
147+
}
131148

132-
setCustomClasses(customClasses: Record<Marked.Marked.Token['type'], string>): void {
133-
this.#customClasses = customClasses;
149+
removeCustomClasses(customClasses: Record<Marked.Marked.Token['type'], string>): void {
150+
for (const [type, className] of Object.entries(customClasses)) {
151+
if (this.#customClasses[type]) {
152+
this.#customClasses[type].delete(className);
153+
}
154+
}
134155
}
135156

136157
#customClassMapForToken(type: Marked.Marked.Token['type']): LitHtml.Directive.DirectiveResult {
137-
return LitHtml.Directives.classMap({
138-
[this.#customClasses[type]]: this.#customClasses[type],
139-
});
158+
const classNames = this.#customClasses[type] || new Set();
159+
const classInfo = Object.fromEntries([...classNames].map(className => [className, true]));
160+
return LitHtml.Directives.classMap(classInfo);
140161
}
141162

142163
renderChildTokens(token: Marked.Marked.Token): LitHtml.TemplateResult[] {
@@ -265,6 +286,7 @@ export class MarkdownInsightRenderer extends MarkdownLitRenderer {
265286
constructor(citationClickHandler?: (index: number) => void) {
266287
super();
267288
this.#citationClickHandler = citationClickHandler || (() => {});
289+
this.addCustomClasses({heading: 'insight'});
268290
}
269291

270292
override renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult {
@@ -305,7 +327,7 @@ export class MarkdownInsightRenderer extends MarkdownLitRenderer {
305327
override templateForToken(token: Marked.Marked.Token): LitHtml.TemplateResult|null {
306328
switch (token.type) {
307329
case 'heading':
308-
return html`<strong>${this.renderText(token)}</strong>`;
330+
return this.renderHeading(token as Marked.Marked.Tokens.Heading);
309331
case 'link':
310332
case 'image': {
311333
const sanitizedUrl = this.sanitizeUrl(token.href);

front_end/ui/components/markdown_view/markdownView.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,8 @@ devtools-code-block {
7979
text-decoration: underline;
8080
cursor: pointer;
8181
}
82+
83+
h1.insight, h2.insight, h3.insight, h4.insight, h5.insight, h6.insight {
84+
font: var(--sys-typescale-body4-bold);
85+
margin: var(--sys-size-1) 0 10px;
86+
}
97 Bytes
Loading

0 commit comments

Comments
 (0)