87 lines
2.1 KiB
JavaScript
Raw Normal View History

2023-01-02 15:23:16 +01:00
'use strict'
2023-01-02 15:23:47 +01:00
const { pathToFileURL } = require('node:url')
const fs = require('node:fs')
/**
* Calls the provided function for each matching token.
*
* @param {Object} params RuleParams instance.
* @param {string} type Token type identifier.
* @param {Function} handler Callback function.
* @returns {void}
*/
const filterTokens = (params, type, handler) => {
for (const token of params.tokens) {
if (token.type === type) {
handler(token)
}
}
}
/**
* Adds a generic error object via the onError callback.
*
* @param {Object} onError RuleOnError instance.
* @param {number} lineNumber Line number.
* @param {string} [detail] Error details.
* @param {string} [context] Error context.
* @param {number[]} [range] Column and length of error.
* @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
* @returns {void}
*/
const addError = (onError, lineNumber, detail, context, range, fixInfo) => {
onError({
lineNumber,
detail,
context,
range,
fixInfo
})
}
2023-01-02 15:23:16 +01:00
const customRule = {
names: ['relative-links'],
description: 'Relative links should be valid',
tags: ['links'],
2023-01-02 15:23:47 +01:00
function: (params, onError) => {
filterTokens(params, 'inline', (token) => {
token.children.forEach((child) => {
const { lineNumber, type, attrs } = child
2023-01-02 19:45:46 +01:00
/** @type {string | null} */
let hrefSrc = null
2023-01-02 15:23:47 +01:00
if (type === 'link_open') {
attrs.forEach((attr) => {
if (attr[0] === 'href') {
2023-01-02 19:45:46 +01:00
hrefSrc = attr[1]
2023-01-02 15:23:47 +01:00
}
})
}
2023-01-02 19:45:46 +01:00
if (type === 'image') {
attrs.forEach((attr) => {
if (attr[0] === 'src') {
hrefSrc = attr[1]
}
})
}
if (hrefSrc != null) {
const url = new URL(hrefSrc, pathToFileURL(params.name))
url.hash = ''
const isRelative =
url.protocol === 'file:' && !hrefSrc.startsWith('/')
if (isRelative && !fs.existsSync(url)) {
2023-01-02 19:45:46 +01:00
const detail = `Link "${hrefSrc}" is dead`
addError(onError, lineNumber, detail)
}
}
2023-01-02 15:23:47 +01:00
})
})
}
2023-01-02 15:23:16 +01:00
}
module.exports = customRule