1import decorateDisclaimerBlock, { 2 getDisclaimerBlockData, 3} from '../blocks/disclaimer/disclaimer.js'; 4import { 5 collectDisclaimerQueryEntries, 6 fetchQueryDisclaimers, 7 normalizeDisclaimerPath, 8} from './disclaimer-query-utils.js'; 9import { resolveDisclaimerConfig } from './disclaimer-config.js'; 10import { isUniversalEditorMode } from './utility/shared.js'; 11 12async function fetchCurrentPageQueryDisclaimers(entries, config, host = config.assetsHost) { 13 return fetchQueryDisclaimers(entries, { 14 host, 15 disclaimerRoot: config.disclaimerRoot, 16 }); 17} 18 19function getAuthoredDisclaimerLinks(main, disclaimerRoot) { 20 return [...main.querySelectorAll(`a[href^="${disclaimerRoot}/"]`)].filter( 21 (link) => !link.closest('.disclaimer') && link.textContent.trim() === '[#]', 22 ); 23} 24 25function reconcileDisclaimerLinks(main, response, disclaimerRoot) { 26 const pathToNumber = new Map( 27 response.disclaimers.map(({ path, number }) => [ 28 normalizeDisclaimerPath(path, disclaimerRoot), 29 number, 30 ]), 31 ); 32 33 getAuthoredDisclaimerLinks(main, disclaimerRoot).forEach((link) => { 34 const normalizedPath = normalizeDisclaimerPath(link.getAttribute('href'), disclaimerRoot); 35 const number = pathToNumber.get(normalizedPath); 36 if (number === undefined) { 37 link.replaceWith(document.createTextNode('[#]')); 38 return; 39 } 40 41 const targetId = `disclaimer-${number}`; 42 link.setAttribute('href', `#${targetId}`); 43 link.setAttribute('aria-label', `Footnote ${number}`); 44 link.dataset.target = targetId; 45 link.innerHTML = `<sup aria-hidden="true">[${number}]</sup>`; 46 link.classList.add('disclaimer-link', 'disclaimer-superscript-target'); 47 }); 48} 49 50export async function decorateDisclaimerPage(main, implementations = {}) { 51 const universalEditorMode = isUniversalEditorMode(); 52 const block = main.querySelector('.disclaimer'); 53 const blockData = block ? getDisclaimerBlockData(block) : null; 54 if (!block || !blockData) return; 55 56 const configResolver = implementations.configResolver || resolveDisclaimerConfig; 57 const config = await configResolver(); 58 const queryHost = universalEditorMode ? window.location.origin : config.assetsHost; 59 const { queryFetcher: providedQueryFetcher } = implementations; 60 let queryFetcher = providedQueryFetcher; 61 if (!queryFetcher) { 62 queryFetcher = (entries) => fetchCurrentPageQueryDisclaimers(entries, config, queryHost); 63 } 64 const entries = collectDisclaimerQueryEntries(main, blockData, config); 65 const response = await queryFetcher(entries, { host: queryHost }); 66 67 if (!response.requestSucceeded) return; 68 69 await decorateDisclaimerBlock(block, response, config); 70 if (!universalEditorMode) { 71 reconcileDisclaimerLinks(main, response, config.disclaimerRoot); 72 } 73} 74 75export default decorateDisclaimerPage;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.