1
1
mirror of https://github.com/theoludwig/html-w3c-validator.git synced 2025-05-21 23:21:29 +02:00

feat: support plain HTML files (not served)

fixes #2
This commit is contained in:
Divlo
2022-02-24 11:55:32 +01:00
parent d92235d79d
commit e032bbe637
9 changed files with 431 additions and 478 deletions

View File

@ -4,7 +4,10 @@ import fs from 'node:fs'
import { Command } from 'clipanion'
import chalk from 'chalk'
import ora from 'ora'
import validateHTML, { ValidationMessageLocationObject } from 'html-validator'
import validateHTML, {
ValidationMessageLocationObject,
ParsedJsonAsValidationResults
} from 'html-validator'
import { table } from 'table'
import { isExistingPath } from './utils/isExistingPath.js'
@ -13,11 +16,12 @@ const CURRENT_DIRECTORY = process.cwd()
const CONFIG_FILE_NAME = '.html-w3c-validatorrc.json'
interface Config {
urls: string[]
urls?: string[]
files?: string[]
}
interface Error {
url: string
data: string
messagesTable: string[][]
}
@ -39,59 +43,104 @@ export class HTMLValidatorCommand extends Command {
const configData = await fs.promises.readFile(configPath, {
encoding: 'utf-8'
})
let config: Config = { urls: [] }
let config: Config = { urls: [], files: [] }
let isValidConfig = true
try {
config = JSON.parse(configData)
} catch {
isValidConfig = false
}
isValidConfig = isValidConfig && Array.isArray(config.urls)
isValidConfig =
isValidConfig &&
(Array.isArray(config.urls) || Array.isArray(config.urls))
if (!isValidConfig) {
throw new Error(
`Invalid config file at ${configPath}. Please check the syntax.`
)
}
const urls =
config.urls == null
? []
: config.urls.map((url) => {
return { type: 'url', data: url }
})
const files =
config.files == null
? []
: config.files.map((file) => {
return { type: 'file', data: file }
})
const dataToValidate = [...urls, ...files]
const errors: Error[] = []
let isValid = true
for (const url of config.urls) {
const loader = ora(`Validating ${url}`).start()
const result = await validateHTML({
url,
format: 'json',
isLocal: true
})
const isValidHTML = result.messages.length === 0
if (isValidHTML) {
loader.succeed()
} else {
loader.fail()
const messagesTable: string[][] = []
for (const message of result.messages) {
const row: string[] = []
if (message.type === 'error') {
row.push(chalk.red(message.type))
} else {
row.push(chalk.yellow(message.type))
}
row.push(message.message)
const violation = message as ValidationMessageLocationObject
if (violation.extract != null) {
row.push(
`line: ${violation.lastLine}, column: ${violation.firstColumn}-${violation.lastColumn}`
for (const { data, type } of dataToValidate) {
const loader = ora(`Validating ${data}`).start()
try {
const options = {
format: 'json' as 'json' | undefined
}
let result: ParsedJsonAsValidationResults | undefined
if (type === 'url') {
result = await validateHTML({
url: data,
isLocal: true,
...options
})
} else if (type === 'file') {
const htmlPath = path.resolve(CURRENT_DIRECTORY, data)
if (!(await isExistingPath(htmlPath))) {
throw new Error(
`No file found at ${htmlPath}. Please check the path.`
)
}
messagesTable.push(row)
const html = await fs.promises.readFile(htmlPath, {
encoding: 'utf-8'
})
result = await validateHTML({
data: html,
...options
})
} else {
throw new Error('Invalid type')
}
errors.push({ url, messagesTable })
const isValidHTML = result.messages.length === 0
if (isValidHTML) {
loader.succeed()
} else {
loader.fail()
const messagesTable: string[][] = []
for (const message of result.messages) {
const row: string[] = []
if (message.type === 'error') {
row.push(chalk.red(message.type))
} else {
row.push(chalk.yellow(message.type))
}
row.push(message.message)
const violation = message as ValidationMessageLocationObject
if (violation.extract != null) {
row.push(
`line: ${violation.lastLine}, column: ${violation.firstColumn}-${violation.lastColumn}`
)
}
messagesTable.push(row)
}
errors.push({ data, messagesTable })
isValid = false
}
} catch (error) {
loader.fail()
isValid = false
if (error instanceof Error) {
const messagesTable: string[][] = [[error.message]]
errors.push({ data, messagesTable })
}
}
}
if (!isValid) {
for (const error of errors) {
console.error(`\n${error.url}`)
console.error(`\n${error.data}`)
console.error(table(error.messagesTable))
console.error('------------------------------')
}