// @ts-check "use strict"; const { addErrorContext, bareUrlRe, filterTokens } = require("../helpers"); const htmlLinkOpenRe = /^]/i; const htmlLinkCloseRe = /^<\/a[\s>]/i; module.exports = { "names": [ "MD034", "no-bare-urls" ], "description": "Bare URL used", "tags": [ "links", "url" ], "function": function MD034(params, onError) { filterTokens(params, "inline", (token) => { let inLink = false; let inInline = false; for (const child of token.children) { const { content, line, lineNumber, type } = child; let match = null; if (type === "link_open") { inLink = true; } else if (type === "link_close") { inLink = false; } else if ((type === "html_inline") && htmlLinkOpenRe.test(content)) { inInline = true; } else if ((type === "html_inline") && htmlLinkCloseRe.test(content)) { inInline = false; } else if ((type === "text") && !inLink && !inInline) { while ((match = bareUrlRe.exec(content)) !== null) { const [ bareUrl ] = match; const matchIndex = match.index; const bareUrlLength = bareUrl.length; // Allow "[LINK]" to avoid conflicts with MD011/no-reversed-links // Allow quoting as a way of deliberately including a bare URL const leftChar = content[matchIndex - 1]; const rightChar = content[matchIndex + bareUrlLength]; if ( !((leftChar === "[") && (rightChar === "]")) && !((leftChar === "\"") && (rightChar === "\"")) && !((leftChar === "'") && (rightChar === "'")) ) { const index = line.indexOf(content); const range = (index === -1) ? null : [ index + matchIndex + 1, bareUrlLength ]; const fixInfo = range ? { "editColumn": range[0], "deleteCount": range[1], "insertText": `<${bareUrl}>` } : null; addErrorContext( onError, lineNumber, bareUrl, null, null, range, fixInfo ); } } } } }); } };