mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	JS refactors (#22227)
- Replace all default exports with named exports, except for Vue SFCs - Remove names from Vue SFCs, they are automatically inferred from the filename - Misc whitespace-related tweaks
This commit is contained in:
		| @@ -18,7 +18,6 @@ | ||||
| import {CalendarHeatmap} from 'vue3-calendar-heatmap'; | ||||
|  | ||||
| export default { | ||||
|   name: 'ActivityHeatmap', | ||||
|   components: {CalendarHeatmap}, | ||||
|   props: { | ||||
|     values: { | ||||
|   | ||||
| @@ -46,19 +46,13 @@ const luminance = (colorString) => { | ||||
| const luminanceThreshold = 0.179; | ||||
|  | ||||
| export default { | ||||
|   name: 'ContextPopup', | ||||
|  | ||||
|   components: { | ||||
|     SvgIcon, | ||||
|   }, | ||||
|  | ||||
|   components: {SvgIcon}, | ||||
|   data: () => ({ | ||||
|     loading: false, | ||||
|     issue: null, | ||||
|     i18nErrorOccurred: i18n.error_occurred, | ||||
|     i18nErrorMessage: null, | ||||
|   }), | ||||
|  | ||||
|   computed: { | ||||
|     createdAt() { | ||||
|       return new Date(this.issue.created_at).toLocaleDateString(undefined, {year: 'numeric', month: 'short', day: 'numeric'}); | ||||
| @@ -107,7 +101,6 @@ export default { | ||||
|       }); | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.$refs.root.addEventListener('us-load-context-popup', (e) => { | ||||
|       const data = e.detail; | ||||
| @@ -116,7 +109,6 @@ export default { | ||||
|       } | ||||
|     }); | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     load(data) { | ||||
|       this.loading = true; | ||||
|   | ||||
| @@ -27,12 +27,9 @@ import {doLoadMoreFiles} from '../features/repo-diff.js'; | ||||
| const {pageData} = window.config; | ||||
|  | ||||
| export default { | ||||
|   name: 'DiffFileList', | ||||
|  | ||||
|   data: () => { | ||||
|     return pageData.diffFileInfo; | ||||
|   }, | ||||
|  | ||||
|   watch: { | ||||
|     fileListIsVisible(newValue) { | ||||
|       if (newValue === true) { | ||||
| @@ -44,15 +41,12 @@ export default { | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     document.getElementById('show-file-list-btn').addEventListener('click', this.toggleFileList); | ||||
|   }, | ||||
|  | ||||
|   unmounted() { | ||||
|     document.getElementById('show-file-list-btn').removeEventListener('click', this.toggleFileList); | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     toggleFileList() { | ||||
|       this.fileListIsVisible = !this.fileListIsVisible; | ||||
|   | ||||
| @@ -21,15 +21,12 @@ const {pageData} = window.config; | ||||
| const LOCAL_STORAGE_KEY = 'diff_file_tree_visible'; | ||||
|  | ||||
| export default { | ||||
|   name: 'DiffFileTree', | ||||
|   components: {DiffFileTreeItem}, | ||||
|  | ||||
|   data: () => { | ||||
|     const fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) === 'true'; | ||||
|     pageData.diffFileInfo.fileTreeIsVisible = fileTreeIsVisible; | ||||
|     return pageData.diffFileInfo; | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     fileTree() { | ||||
|       const result = []; | ||||
| @@ -94,7 +91,6 @@ export default { | ||||
|       return result; | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     // ensure correct buttons when we are mounted to the dom | ||||
|     this.adjustToggleButton(this.fileTreeIsVisible); | ||||
| @@ -125,7 +121,7 @@ export default { | ||||
|       doLoadMoreFiles(this.link, this.diffEnd, () => { | ||||
|         this.isLoadingNewData = false; | ||||
|       }); | ||||
|     } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -43,11 +43,7 @@ | ||||
| import {SvgIcon} from '../svg.js'; | ||||
|  | ||||
| export default { | ||||
|   name: 'DiffFileTreeItem', | ||||
|   components: { | ||||
|     SvgIcon, | ||||
|   }, | ||||
|  | ||||
|   components: {SvgIcon}, | ||||
|   props: { | ||||
|     item: { | ||||
|       type: Object, | ||||
| @@ -59,7 +55,6 @@ export default { | ||||
|       default: true | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   data: () => ({ | ||||
|     collapsed: false, | ||||
|   }), | ||||
|   | ||||
| @@ -111,11 +111,7 @@ import {SvgIcon} from '../svg.js'; | ||||
| const {csrfToken, pageData} = window.config; | ||||
|  | ||||
| export default { | ||||
|   name: 'PullRequestMergeForm', | ||||
|   components: { | ||||
|     SvgIcon, | ||||
|   }, | ||||
|  | ||||
|   components: {SvgIcon}, | ||||
|   data: () => ({ | ||||
|     csrfToken, | ||||
|     mergeForm: pageData.pullRequestMergeForm, | ||||
| @@ -137,20 +133,17 @@ export default { | ||||
|     showMergeStyleMenu: false, | ||||
|     showActionForm: false, | ||||
|   }), | ||||
|  | ||||
|   computed: { | ||||
|     mergeButtonStyleClass() { | ||||
|       if (this.mergeForm.allOverridableChecksOk) return 'green'; | ||||
|       return this.autoMergeWhenSucceed ? 'blue' : 'red'; | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   watch: { | ||||
|     mergeStyle(val) { | ||||
|       this.mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val); | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.mergeStyleAllowedCount = this.mergeForm.mergeStyles.reduce((v, msd) => v + (msd.allowed ? 1 : 0), 0); | ||||
|  | ||||
| @@ -158,15 +151,12 @@ export default { | ||||
|     if (!mergeStyle) mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed)?.name; | ||||
|     this.switchMergeStyle(mergeStyle, !this.mergeForm.canMergeNow); | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     document.addEventListener('mouseup', this.hideMergeStyleMenu); | ||||
|   }, | ||||
|  | ||||
|   unmounted() { | ||||
|     document.removeEventListener('mouseup', this.hideMergeStyleMenu); | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     hideMergeStyleMenu() { | ||||
|       this.showMergeStyleMenu = false; | ||||
|   | ||||
| @@ -44,7 +44,7 @@ function fallbackCopyToClipboard(text) { | ||||
|  | ||||
| // For all DOM elements with [data-clipboard-target] or [data-clipboard-text], | ||||
| // this copy-to-clipboard will work for them | ||||
| export default function initGlobalCopyToClipboardListener() { | ||||
| export function initGlobalCopyToClipboardListener() { | ||||
|   document.addEventListener('click', (e) => { | ||||
|     let target = e.target; | ||||
|     // in case <button data-clipboard-text><svg></button>, so we just search | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| export default async function createColorPicker($els) { | ||||
| export async function createColorPicker($els) { | ||||
|   if (!$els || !$els.length) return; | ||||
|  | ||||
|   await Promise.all([ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import $ from 'jquery'; | ||||
| import 'jquery.are-you-sure'; | ||||
| import {mqBinarySearch} from '../utils.js'; | ||||
| import createDropzone from './dropzone.js'; | ||||
| import {createDropzone} from './dropzone.js'; | ||||
| import {initCompColorPicker} from './comp/ColorPicker.js'; | ||||
| import {showGlobalErrorMessage} from '../bootstrap.js'; | ||||
| import {attachDropdownAria} from './aria.js'; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import $ from 'jquery'; | ||||
| import createColorPicker from '../colorpicker.js'; | ||||
| import {createColorPicker} from '../colorpicker.js'; | ||||
|  | ||||
| export function initCompColorPicker() { | ||||
|   createColorPicker($('.color-picker')); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import $ from 'jquery'; | ||||
| import attachTribute from '../tribute.js'; | ||||
| import {attachTribute} from '../tribute.js'; | ||||
| import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js'; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import $ from 'jquery'; | ||||
| import {htmlEscape} from 'escape-goat'; | ||||
|  | ||||
| const {appSubUrl} = window.config; | ||||
|  | ||||
| const looksLikeEmailAddressCheck = /^\S+@\S+$/; | ||||
|  | ||||
| export function initCompSearchUserBox() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import $ from 'jquery'; | ||||
|  | ||||
| const {csrfToken} = window.config; | ||||
|  | ||||
| export function initCompWebHookEditor() { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ContextPopup from '../components/ContextPopup.vue'; | ||||
| import {parseIssueHref} from '../utils.js'; | ||||
| import {createTippy} from '../modules/tippy.js'; | ||||
|  | ||||
| export default function initContextPopups() { | ||||
| export function initContextPopups() { | ||||
|   const refIssues = $('.ref-issue'); | ||||
|   if (!refIssues.length) return; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import {copyToClipboard} from './clipboard.js'; | ||||
| import {showTemporaryTooltip} from '../modules/tippy.js'; | ||||
| import {convertImage} from '../utils.js'; | ||||
|  | ||||
| const {i18n} = window.config; | ||||
|  | ||||
| async function doCopy(content, btn) { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| export default async function createDropzone(el, opts) { | ||||
| export async function createDropzone(el, opts) { | ||||
|   const [{Dropzone}] = await Promise.all([ | ||||
|     import(/* webpackChunkName: "dropzone" */'dropzone'), | ||||
|     import(/* webpackChunkName: "dropzone" */'dropzone/dist/dropzone.css'), | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import emojis from '../../../assets/emoji.json'; | ||||
|  | ||||
| const {assetUrlPrefix} = window.config; | ||||
| const {customEmojis} = window.config; | ||||
| const {assetUrlPrefix, customEmojis} = window.config; | ||||
|  | ||||
| const tempMap = {...customEmojis}; | ||||
| for (const {emoji, aliases} of emojis) { | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import {svg} from '../svg.js'; | ||||
|  | ||||
|  | ||||
| // Hides the file if newFold is true, and shows it otherwise. The actual hiding is performed using CSS. | ||||
| // | ||||
| // The fold arrow is the icon displayed on the upper left of the file box, especially intended for components having the 'fold-file' class. | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import {prettyNumber} from '../utils.js'; | ||||
|  | ||||
| const {lang} = document.documentElement; | ||||
|  | ||||
| const dateFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'long', day: 'numeric'}); | ||||
| const shortDateFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'short', day: 'numeric'}); | ||||
| const dateTimeFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'}); | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import {createApp} from 'vue'; | ||||
| import ActivityHeatmap from '../components/ActivityHeatmap.vue'; | ||||
| import {translateMonth, translateDay} from '../utils.js'; | ||||
| export default function initHeatmap() { | ||||
|  | ||||
| export function initHeatmap() { | ||||
|   const el = document.getElementById('user-heatmap'); | ||||
|   if (!el) return; | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,7 @@ function getDefaultSvgBoundsIfUndefined(svgXml, src) { | ||||
|   return null; | ||||
| } | ||||
|  | ||||
| export default function initImageDiff() { | ||||
| export function initImageDiff() { | ||||
|   function createContext(image1, image2) { | ||||
|     const size1 = { | ||||
|       width: image1 && image1.width || 0, | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import {createApp} from 'vue'; | ||||
| import DiffFileTree from '../components/DiffFileTree.vue'; | ||||
| import DiffFileList from '../components/DiffFileList.vue'; | ||||
|  | ||||
| export default function initDiffFileTree() { | ||||
| export function initDiffFileTree() { | ||||
|   const el = document.getElementById('diff-file-tree'); | ||||
|   if (!el) return; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import $ from 'jquery'; | ||||
|  | ||||
| import {svg} from '../svg.js'; | ||||
|  | ||||
| const {csrf} = window.config; | ||||
|  | ||||
| const threshold = 50; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import $ from 'jquery'; | ||||
|  | ||||
| export default function initRepoGraphGit() { | ||||
| export function initRepoGraphGit() { | ||||
|   const graphContainer = document.getElementById('git-graph-container'); | ||||
|   if (!graphContainer) return; | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {createApp} from 'vue'; | ||||
| import PullRequestMergeForm from '../components/PullRequestMergeForm.vue'; | ||||
|  | ||||
| export default function initPullRequestMergeForm() { | ||||
| export function initRepoPullRequestMergeForm() { | ||||
|   const el = document.getElementById('pull-request-merge-form'); | ||||
|   if (!el) return; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import $ from 'jquery'; | ||||
| import {htmlEscape} from 'escape-goat'; | ||||
| import attachTribute from './tribute.js'; | ||||
| import {attachTribute} from './tribute.js'; | ||||
| import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js'; | ||||
| import {initEasyMDEImagePaste} from './comp/ImagePaste.js'; | ||||
| import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js'; | ||||
|   | ||||
| @@ -3,33 +3,28 @@ import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js'; | ||||
| import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js'; | ||||
| import {initEasyMDEImagePaste} from './comp/ImagePaste.js'; | ||||
| import { | ||||
|   initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, | ||||
|   initRepoIssueCommentDelete, | ||||
|   initRepoIssueComments, initRepoIssueDependencyDelete, | ||||
|   initRepoIssueReferenceIssue, initRepoIssueStatusButton, | ||||
|   initRepoIssueTitleEdit, | ||||
|   initRepoIssueWipToggle, initRepoPullRequestUpdate, | ||||
|   updateIssuesMeta, | ||||
|   initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete, | ||||
|   initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue, | ||||
|   initRepoIssueStatusButton, initRepoIssueTitleEdit, initRepoIssueWipToggle, | ||||
|   initRepoPullRequestUpdate, updateIssuesMeta, | ||||
| } from './repo-issue.js'; | ||||
| import {initUnicodeEscapeButton} from './repo-unicode-escape.js'; | ||||
| import {svg} from '../svg.js'; | ||||
| import {htmlEscape} from 'escape-goat'; | ||||
| import {initRepoBranchTagDropdown} from '../components/RepoBranchTagDropdown.js'; | ||||
| import { | ||||
|   initRepoCloneLink, | ||||
|   initRepoCommonBranchOrTagDropdown, | ||||
|   initRepoCommonFilterSearchDropdown, | ||||
|   initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown, | ||||
|   initRepoCommonLanguageStats, | ||||
| } from './repo-common.js'; | ||||
| import {initCitationFileCopyContent} from './citation.js'; | ||||
| import {initCompLabelEdit} from './comp/LabelEdit.js'; | ||||
| import {initRepoDiffConversationNav} from './repo-diff.js'; | ||||
| import attachTribute from './tribute.js'; | ||||
| import createDropzone from './dropzone.js'; | ||||
| import {attachTribute} from './tribute.js'; | ||||
| import {createDropzone} from './dropzone.js'; | ||||
| import {initCommentContent, initMarkupContent} from '../markup/content.js'; | ||||
| import {initCompReactionSelector} from './comp/ReactionSelector.js'; | ||||
| import {initRepoSettingBranches} from './repo-settings.js'; | ||||
| import initRepoPullRequestMergeForm from './repo-issue-pr-form.js'; | ||||
| import {initRepoPullRequestMergeForm} from './repo-issue-pr-form.js'; | ||||
|  | ||||
| const {csrfToken} = window.config; | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ const $lfsSettings = $('#lfs_settings'); | ||||
| const $lfsEndpoint = $('#lfs_endpoint'); | ||||
| const $items = $('#migrate_items').find('input[type=checkbox]'); | ||||
|  | ||||
| export default function initRepoMigration() { | ||||
| export function initRepoMigration() { | ||||
|   checkAuth(); | ||||
|   setLFSSettingsVisibility(); | ||||
|  | ||||
|   | ||||
| @@ -84,7 +84,7 @@ async function initRepoProjectSortable() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| export default function initRepoProject() { | ||||
| export function initRepoProject() { | ||||
|   if (!$('.repository.projects').length) { | ||||
|     return; | ||||
|   } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import $ from 'jquery'; | ||||
| import attachTribute from './tribute.js'; | ||||
| import {attachTribute} from './tribute.js'; | ||||
| import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js'; | ||||
| import {initEasyMDEImagePaste} from './comp/ImagePaste.js'; | ||||
| import {createCommentEasyMDE} from './comp/EasyMDE.js'; | ||||
|   | ||||
| @@ -35,7 +35,7 @@ async function checkCacheValidity() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| export default async function initServiceWorker() { | ||||
| export async function initServiceWorker() { | ||||
|   if (!('serviceWorker' in navigator)) return; | ||||
|  | ||||
|   if (useServiceWorker) { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| export default function initTableSort() { | ||||
| export function initTableSort() { | ||||
|   for (const header of document.querySelectorAll('th[data-sortt-asc]') || []) { | ||||
|     const sorttAsc = header.getAttribute('data-sortt-asc'); | ||||
|     const sorttDesc = header.getAttribute('data-sortt-desc'); | ||||
|   | ||||
| @@ -49,7 +49,7 @@ function makeCollections({mentions, emoji}) { | ||||
|   return collections; | ||||
| } | ||||
|  | ||||
| export default async function attachTribute(elementOrNodeList, {mentions, emoji} = {}) { | ||||
| export async function attachTribute(elementOrNodeList, {mentions, emoji} = {}) { | ||||
|   if (!window.config.requireTribute || !elementOrNodeList) return; | ||||
|   const nodes = Array.from('length' in elementOrNodeList ? elementOrNodeList : [elementOrNodeList]); | ||||
|   if (!nodes.length) return; | ||||
|   | ||||
| @@ -6,16 +6,16 @@ import {initVueEnv} from './components/VueComponentLoader.js'; | ||||
| import {initRepoActivityTopAuthorsChart} from './components/RepoActivityTopAuthors.vue'; | ||||
| import {initDashboardRepoList} from './components/DashboardRepoList.js'; | ||||
|  | ||||
| import attachTribute from './features/tribute.js'; | ||||
| import initGlobalCopyToClipboardListener from './features/clipboard.js'; | ||||
| import initContextPopups from './features/contextpopup.js'; | ||||
| import initRepoGraphGit from './features/repo-graph.js'; | ||||
| import initHeatmap from './features/heatmap.js'; | ||||
| import initImageDiff from './features/imagediff.js'; | ||||
| import initRepoMigration from './features/repo-migration.js'; | ||||
| import initRepoProject from './features/repo-projects.js'; | ||||
| import initServiceWorker from './features/serviceworker.js'; | ||||
| import initTableSort from './features/tablesort.js'; | ||||
| import {attachTribute} from './features/tribute.js'; | ||||
| import {initGlobalCopyToClipboardListener} from './features/clipboard.js'; | ||||
| import {initContextPopups} from './features/contextpopup.js'; | ||||
| import {initRepoGraphGit} from './features/repo-graph.js'; | ||||
| import {initHeatmap} from './features/heatmap.js'; | ||||
| import {initImageDiff} from './features/imagediff.js'; | ||||
| import {initRepoMigration} from './features/repo-migration.js'; | ||||
| import {initRepoProject} from './features/repo-projects.js'; | ||||
| import {initServiceWorker} from './features/serviceworker.js'; | ||||
| import {initTableSort} from './features/tablesort.js'; | ||||
| import {initAdminUserListSearchForm} from './features/admin/users.js'; | ||||
| import {initAdminConfigs} from './features/admin/config.js'; | ||||
| import {initMarkupAnchors} from './markup/anchors.js'; | ||||
| @@ -24,7 +24,7 @@ import {initRepoIssueContentHistory} from './features/repo-issue-content.js'; | ||||
| import {initStopwatch} from './features/stopwatch.js'; | ||||
| import {initFindFileInRepo} from './features/repo-findfile.js'; | ||||
| import {initCommentContent, initMarkupContent} from './markup/content.js'; | ||||
| import initDiffFileTree from './features/repo-diff-filetree.js'; | ||||
| import {initDiffFileTree} from './features/repo-diff-filetree.js'; | ||||
|  | ||||
| import {initUserAuthLinkAccountView, initUserAuthOauth2} from './features/user-auth.js'; | ||||
| import { | ||||
|   | ||||
| @@ -26,7 +26,6 @@ import octiconSidebarExpand from '../../public/img/svg/octicon-sidebar-expand.sv | ||||
| import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg'; | ||||
| import octiconX from '../../public/img/svg/octicon-x.svg'; | ||||
|  | ||||
|  | ||||
| export const svgs = { | ||||
|   'octicon-chevron-down': octiconChevronDown, | ||||
|   'octicon-chevron-right': octiconChevronRight, | ||||
| @@ -57,7 +56,6 @@ export const svgs = { | ||||
|   'octicon-x': octiconX, | ||||
| }; | ||||
|  | ||||
|  | ||||
| const parser = new DOMParser(); | ||||
| const serializer = new XMLSerializer(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user