31 lines
1.2 KiB
JavaScript
31 lines
1.2 KiB
JavaScript
/**
|
|
* Insert markup before the document's closing </body> or </head>, ignoring
|
|
* occurrences inside inline scripts, styles, or string literals.
|
|
*/
|
|
|
|
function maskHtmlLiteralRegions(html) {
|
|
return String(html ?? '').replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, (match) =>
|
|
' '.repeat(match.length),
|
|
).replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, (match) => ' '.repeat(match.length));
|
|
}
|
|
|
|
export function injectBeforeDocumentClosingBody(html, markup) {
|
|
const source = String(html ?? '');
|
|
const injection = String(markup ?? '');
|
|
if (!injection) return source;
|
|
const masked = maskHtmlLiteralRegions(source).toLowerCase();
|
|
const lastIndex = masked.lastIndexOf('</body>');
|
|
if (lastIndex < 0) return `${source}${injection}`;
|
|
return `${source.slice(0, lastIndex)}${injection}${source.slice(lastIndex)}`;
|
|
}
|
|
|
|
export function injectBeforeDocumentClosingHead(html, markup) {
|
|
const source = String(html ?? '');
|
|
const injection = String(markup ?? '');
|
|
if (!injection) return source;
|
|
const masked = maskHtmlLiteralRegions(source).toLowerCase();
|
|
const index = masked.indexOf('</head>');
|
|
if (index < 0) return `${injection}${source}`;
|
|
return `${source.slice(0, index)}${injection}${source.slice(index)}`;
|
|
}
|