Skip to content

Commit 2cf91d5

Browse files
silverwindGusted
authored andcommitted
[PORT] Enable no-jquery/no-parse-html-literal and fix violation (gitea#31684)
Tested it, path segment creation works just like before. --- Conflict resolution: trivial, also ported code from go-gitea/gitea#31283
1 parent 22de4ae commit 2cf91d5

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

.eslintrc.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ rules:
460460
no-jquery/no-param: [2]
461461
no-jquery/no-parent: [0]
462462
no-jquery/no-parents: [2]
463-
no-jquery/no-parse-html-literal: [0]
463+
no-jquery/no-parse-html-literal: [2]
464464
no-jquery/no-parse-html: [2]
465465
no-jquery/no-parse-json: [2]
466466
no-jquery/no-parse-xml: [2]

web_src/js/features/repo-editor.js

+31-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import $ from 'jquery';
22
import {htmlEscape} from 'escape-goat';
33
import {createCodeEditor} from './codeeditor.js';
4-
import {hideElem, showElem} from '../utils/dom.js';
4+
import {hideElem, showElem, createElementFromHTML} from '../utils/dom.js';
55
import {initMarkupContent} from '../markup/content.js';
66
import {attachRefIssueContextPopup} from './contextpopup.js';
77
import {POST} from '../modules/fetch.js';
88

99
function initEditPreviewTab($form) {
1010
const $tabMenu = $form.find('.tabular.menu');
1111
$tabMenu.find('.item').tab();
12-
const $previewTab = $tabMenu.find(`.item[data-tab="${$tabMenu.data('preview')}"]`);
12+
const $previewTab = $tabMenu.find(
13+
`.item[data-tab="${$tabMenu.data('preview')}"]`,
14+
);
1315
if ($previewTab.length) {
1416
$previewTab.on('click', async function () {
1517
const $this = $(this);
@@ -24,12 +26,17 @@ function initEditPreviewTab($form) {
2426
const formData = new FormData();
2527
formData.append('mode', mode);
2628
formData.append('context', context);
27-
formData.append('text', $form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val());
29+
formData.append(
30+
'text',
31+
$form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val(),
32+
);
2833
formData.append('file_path', $treePathEl.val());
2934
try {
3035
const response = await POST($this.data('url'), {data: formData});
3136
const data = await response.text();
32-
const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`);
37+
const $previewPanel = $form.find(
38+
`.tab[data-tab="${$tabMenu.data('preview')}"]`,
39+
);
3340
renderPreviewPanelContent($previewPanel, data);
3441
} catch (error) {
3542
console.error('Error:', error);
@@ -96,8 +103,14 @@ export function initRepoEditor() {
96103
const value = parts[i];
97104
if (i < parts.length - 1) {
98105
if (value.length) {
99-
$(`<span class="section"><a href="#">${htmlEscape(value)}</a></span>`).insertBefore($(this));
100-
$('<div class="breadcrumb-divider">/</div>').insertBefore($(this));
106+
$editFilename[0].before(
107+
createElementFromHTML(
108+
`<span class="section"><a href="#">${htmlEscape(value)}</a></span>`,
109+
),
110+
);
111+
$editFilename[0].before(
112+
createElementFromHTML(`<div class="breadcrumb-divider">/</div>`),
113+
);
101114
}
102115
} else {
103116
$(this).val(value);
@@ -113,7 +126,11 @@ export function initRepoEditor() {
113126
const $section = $('.breadcrumb span.section');
114127

115128
// Jump back to last directory once the filename is empty
116-
if (e.code === 'Backspace' && getCursorPosition($(this)) === 0 && $section.length > 0) {
129+
if (
130+
e.code === 'Backspace' &&
131+
getCursorPosition($(this)) === 0 &&
132+
$section.length > 0
133+
) {
117134
e.preventDefault();
118135
const $divider = $('.breadcrumb .breadcrumb-divider');
119136
const value = $section.last().find('a').text();
@@ -164,11 +181,13 @@ export function initRepoEditor() {
164181
commitButton?.addEventListener('click', (e) => {
165182
// A modal which asks if an empty file should be committed
166183
if (!$editArea.val()) {
167-
$('#edit-empty-content-modal').modal({
168-
onApprove() {
169-
$('.edit.form').trigger('submit');
170-
},
171-
}).modal('show');
184+
$('#edit-empty-content-modal')
185+
.modal({
186+
onApprove() {
187+
$('.edit.form').trigger('submit');
188+
},
189+
})
190+
.modal('show');
172191
e.preventDefault();
173192
}
174193
});

web_src/js/utils/dom.js

+7
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,10 @@ export function replaceTextareaSelection(textarea, text) {
296296
textarea.dispatchEvent(new CustomEvent('change', {bubbles: true, cancelable: true}));
297297
}
298298
}
299+
300+
// Warning: Do not enter any unsanitized variables here
301+
export function createElementFromHTML(htmlString) {
302+
const div = document.createElement('div');
303+
div.innerHTML = htmlString.trim();
304+
return div.firstChild;
305+
}

web_src/js/utils/dom.test.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import {createElementFromHTML} from './dom.js';
2+
3+
test('createElementFromHTML', () => {
4+
expect(createElementFromHTML('<a>foo<span>bar</span></a>').outerHTML).toEqual('<a>foo<span>bar</span></a>');
5+
});

0 commit comments

Comments
 (0)