Skip to content

Commit 11b9f62

Browse files
committed
simplify code
1 parent 4b32f94 commit 11b9f62

File tree

4 files changed

+20
-29
lines changed

4 files changed

+20
-29
lines changed

web_src/js/features/comp/TextExpander.ts

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,17 @@ const debouncedSuggestIssues = debounce((key: string, text: string) => new Promi
1414
const matches = await matchIssue(issuePathInfo.ownerName, issuePathInfo.repoName, issuePathInfo.indexString, text);
1515
if (!matches.length) return resolve({matched: false});
1616

17-
const ul = document.createElement('ul');
18-
ul.classList.add('suggestions');
17+
const ul = createElementFromAttrs('ul', {class: 'suggestions'});
1918
for (const issue of matches) {
20-
const li = createElementFromAttrs('li', {
21-
role: 'option',
22-
'data-value': `${key}${issue.number}`,
23-
class: 'tw-flex tw-gap-2',
24-
});
25-
26-
const icon = svg(getIssueIcon(issue), 16, ['text', getIssueColor(issue)].join(' '));
27-
li.append(createElementFromHTML(icon));
28-
29-
const id = document.createElement('span');
30-
id.textContent = String(issue.number);
31-
li.append(id);
32-
33-
const nameSpan = document.createElement('span');
34-
nameSpan.textContent = issue.title;
35-
li.append(nameSpan);
36-
19+
const li = createElementFromAttrs(
20+
'li',
21+
{role: 'option', class: 'tw-flex tw-gap-2', 'data-value': `${key}${issue.number}`},
22+
createElementFromHTML(svg(getIssueIcon(issue), 16, ['text', getIssueColor(issue)])),
23+
createElementFromAttrs('span', null, String(issue.number)),
24+
createElementFromAttrs('span', null, issue.title),
25+
);
3726
ul.append(li);
3827
}
39-
4028
resolve({matched: true, fragment: ul});
4129
}), 100);
4230

web_src/js/svg.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ export type SvgName = keyof typeof svgs;
153153
// most of the SVG icons in assets couldn't be used directly.
154154

155155
// retrieve an HTML string for given SVG icon name, size and additional classes
156-
export function svg(name: SvgName, size = 16, className = '') {
156+
export function svg(name: SvgName, size = 16, classNames: string|string[]): string {
157+
const className = Array.isArray(classNames) ? classNames.join(' ') : classNames;
157158
if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`);
158159
if (size === 16 && !className) return svgs[name];
159160

web_src/js/utils/dom.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ test('createElementFromAttrs', () => {
88
const el = createElementFromAttrs('button', {
99
id: 'the-id',
1010
class: 'cls-1 cls-2',
11-
'data-foo': 'the-data',
1211
disabled: true,
1312
checked: false,
1413
required: null,
1514
tabindex: 0,
16-
});
17-
expect(el.outerHTML).toEqual('<button id="the-id" class="cls-1 cls-2" data-foo="the-data" disabled="" tabindex="0"></button>');
15+
'data-foo': 'the-data',
16+
}, 'txt', createElementFromHTML('<span>inner</span>'));
17+
expect(el.outerHTML).toEqual('<button id="the-id" class="cls-1 cls-2" data-foo="the-data" disabled="" tabindex="0">txt<span>inner</span></button>');
1818
});

web_src/js/utils/dom.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,22 +298,24 @@ export function replaceTextareaSelection(textarea: HTMLTextAreaElement, text: st
298298
}
299299

300300
// Warning: Do not enter any unsanitized variables here
301-
export function createElementFromHTML(htmlString: string) {
301+
export function createElementFromHTML(htmlString: string): HTMLElement {
302302
const div = document.createElement('div');
303303
div.innerHTML = htmlString.trim();
304-
return div.firstChild as Element;
304+
return div.firstChild as HTMLElement;
305305
}
306306

307-
export function createElementFromAttrs(tagName: string, attrs: Record<string, any>) {
307+
export function createElementFromAttrs(tagName: string, attrs: Record<string, any>, ...children: (Node|string)[]): HTMLElement {
308308
const el = document.createElement(tagName);
309-
for (const [key, value] of Object.entries(attrs)) {
309+
for (const [key, value] of Object.entries(attrs || {})) {
310310
if (value === undefined || value === null) continue;
311311
if (typeof value === 'boolean') {
312312
el.toggleAttribute(key, value);
313313
} else {
314314
el.setAttribute(key, String(value));
315315
}
316-
// TODO: in the future we could make it also support "textContent" and "innerHTML" properties if needed
316+
}
317+
for (const child of children) {
318+
el.append(child instanceof Node ? child : document.createTextNode(child));
317319
}
318320
return el;
319321
}

0 commit comments

Comments
 (0)