structured-data-testing-tool
Version:
A library and command line tool to help test for Structured Data.
206 lines (189 loc) • 7.67 kB
JavaScript
const yargs = require(`yargs`)
const chalk = require('chalk')
const fs = require('fs')
const { structuredDataTest } = require('../index')
const presets = require('../presets')
const { schemas } = require('../lib/schemas')
const Package = require('../package')
const { error, printTestResults, printSupportedPresets, printListSchemas } = require('../lib/cli')
;(async () => {
let showHelp = false
let showInfo = false
let testInput = null
let testOutput = null
let testOptions = {
presets: [],
schemas: [],
}
if (yargs.argv.help || yargs.argv.h) {
showHelp = true
}
if (yargs.argv.info || yargs.argv.i) {
showInfo = true
}
if (yargs.argv.output || yargs.argv.o) {
if ((yargs.argv.output && yargs.argv.output !== true) || (yargs.argv.o && yargs.argv.o !== true)) {
testOutput = yargs.argv.output || yargs.argv.o
} else {
console.error(error(`Error: Must specify a file to output to when using -o/--output`))
return process.exit(1)
}
}
// Get input arguments
if ((yargs.argv.file && yargs.argv.file !== true) || (yargs.argv.f && yargs.argv.f !== true)) {
if (yargs.argv.url || yargs.argv.u) {
console.error(error(`Error: Must provide either URL (-u/--url) *or* file (-f/--file) to test, not both`))
return process.exit(1)
}
// Get path to file input
try {
testInput = fs.readFileSync(yargs.argv.file || yargs.argv.f)
} catch (e) {
console.error(error(`Error: Unable to open file '${yargs.argv.file || yargs.argv.f}'`))
return process.exit(1)
}
} else if ((yargs.argv.url && yargs.argv.url !== true) || (yargs.argv.u && yargs.argv.u !== true)) {
// Get URL argument
testInput = yargs.argv.url || yargs.argv.u
}
// If --schemas or -s is passed display supported schemas
if (yargs.argv.schemas || yargs.argv.s) {
if ((yargs.argv.schemas && yargs.argv.schemas === true) || (yargs.argv.s && yargs.argv.s === true)) {
printListSchemas()
return process.exit()
}
let schemaErrors = []
let schemaArgs = yargs.argv.schemas || yargs.argv.s
if (!Array.isArray(schemaArgs))
schemaArgs = schemaArgs.split(',')
schemaArgs.map(schema => {
let [ structuredDataType, schemaName ] = schema.trim().split(':')
if (!schemaName) {
schemaName = structuredDataType
structuredDataType = null
}
testOptions.schemas.push(schema)
if (!schemas[schemaName]) {
schemaErrors.push(`Warning: "${schemaName}" is not a valid schema.`)
}
})
}
// Parse presets of provided, and halt on error when parsing them
if (yargs.argv.presets || yargs.argv.p) {
// If --presets or -p is passed with no arguments, display supported presets
if ((yargs.argv.presets && yargs.argv.presets === true) || (yargs.argv.p && yargs.argv.p === true)) {
printSupportedPresets()
return process.exit()
}
let presetErrors = []
let presetArgs = yargs.argv.presets || yargs.argv.p
if (!Array.isArray(presetArgs))
presetArgs = presetArgs.split(',')
presetArgs.map(preset => {
if (presets[preset.trim()]) {
testOptions.presets.push(presets[preset.trim()])
} else {
presetErrors.push(`Error: "${preset.trim()}" is not a valid preset.`)
}
})
// If errors, display them and exit
if (presetErrors.length > 0) {
printSupportedPresets()
presetErrors.map(err => console.error(error(err)))
return process.exit(1)
}
}
if (testInput && !showHelp) {
// Run test
await structuredDataTest(testInput, testOptions)
.then(res => {
printTestResults(res, { showInfo })
if (testOutput)
fs.writeFileSync(testOutput, JSON.stringify(err.res, null, 2))
return process.exit()
})
.catch(err => {
if (err.type === 'VALIDATION_FAILED') {
printTestResults(err.res, { showInfo })
if (testOutput)
fs.writeFileSync(testOutput, JSON.stringify(err.res, null, 2))
} else {
// Handle other errors (e.g. fetching URL)
if (yargs.argv.file || yargs.argv.f) {
console.error(error(`Unable to open file "${yargs.argv.file || yargs.argv.f}"`))
} else if (yargs.argv.url || yargs.argv.u) {
console.error(error(`Unable to fetch content from "${yargs.argv.url || yargs.argv.u}"`))
} else {
throw err
}
}
return process.exit(1)
})
}
// if (yargs.argv.config && yargs.argv.config !== true) { }
yargs
.usage(`Usage: ${ chalk.yellowBright('$0 --url <url> [--presets <presets>] [--schemas <schemas]')}`)
// .option('c', {
// alias: 'config',
// description: 'Use configuration file'
// })
.option('u', {
alias: 'url',
type: 'string',
description: 'Inspect a URL'
})
.implies('--url', '--presets')
.option('f', {
alias: 'file',
type: 'string',
description: 'Inspect a file'
})
.implies('--file', '--presets')
.option('p', {
alias: 'presets',
type: 'string',
description: 'Test for specific markup from a list of presets'
})
.option('s', {
alias: 'schemas',
type: 'string',
description: 'Test for a specific schema from a list of schemas'
})
.option('i', {
alias: 'info',
type: 'boolean',
description: 'Show more detailed information about structured data found'
})
.option('o', {
alias: 'output',
type: 'string',
description: 'Output test results to a file'
})
.help('h')
.alias('h', 'help')
.version(Package.version)
.alias('v', 'version')
.showHelpOnFail(true)
.demandOption('--url or --file')
.hide('--url or --file')
//.example(chalk.cyan(`$0 --config path/to/config.js`), chalk.grey('Load URL(s) and tests from a configuration file'))
.example(chalk.cyan(`$0 --url "https://example.com/article"`), chalk.grey('Inspect a URL'))
.example(chalk.cyan(`$0 --url <url> --presets SocialMedia`), chalk.grey('Test a URL for social media metatags'))
.example(chalk.cyan(`$0 --url <url> --presets Google`), chalk.grey('Test a URL for markup inspected by Google'))
.example(chalk.cyan(`$0 --url <url> --presets "Twitter,Facebook"`), chalk.grey('Test a URL with multiple presets'))
.example(chalk.cyan(`$0 --url <url> -p Twitter -p Facebook`), chalk.grey('Test a URL with multiple presets (alternative)'))
.example(chalk.cyan(`$0 --url <url> --schemas Article`), chalk.grey('Test a URL for the Article schema'))
.example(chalk.cyan(`$0 --url <url> --schemas "jsonld:Article"`), chalk.grey('Test a URL for the Article schema in JSON-LD'))
.example(chalk.cyan(`$0 --url <url> --schemas "microdata:Article"`), chalk.grey('Test a URL for the Article schema in microdata/HTML'))
.example(chalk.cyan(`$0 --url <url> --schemas "rdfa:Article"`), chalk.grey('Test a URL for the Article schema in RDFa'))
.example(chalk.cyan(`$0 --url <url> --schemas "Article,WPHeader,WPFooter"`), chalk.grey('Test a URL for multiple schemas'))
.example(chalk.cyan(`$0 --url <url> -s Article -s WPHeader -s WPFooter`), chalk.grey('Test a URL for multiple schemas (alternative)'))
.example(chalk.cyan(`$0 --url <url> --output results.json`), chalk.grey('Output test results to a JSON file'))
.example(chalk.cyan(`$0 --file <path-to-file>.html`), chalk.grey('Test file containing HTML'))
.example(chalk.cyan(`$0 --file <path-to-file>.json`), chalk.grey('Test file containing JSON-LD'))
.example(chalk.cyan(`$0 --presets`), chalk.grey('List all built-in presets'))
.example(chalk.cyan(`$0 --schemas`), chalk.grey('List all supported schemas'))
.wrap(120)
.argv
})()