Comparing version 0.2.2 to 0.3.0
@@ -7,3 +7,3 @@ import process from 'node:process'; | ||
import { getPackageJson } from './util.js'; | ||
import { reportOutputFile } from './constants.js'; | ||
import { reportOutputFilename } from './constants.js'; | ||
const help = `Usage: a11y <files> [options] | ||
@@ -18,2 +18,3 @@ | ||
-r, --report Generate a report instead of fixing files | ||
-o, --format <format> Report format [html, md] (default: html) | ||
--verbose Show detailed logs | ||
@@ -24,2 +25,3 @@ --help Show this help | ||
const options = minimist(args, { | ||
string: ['format'], | ||
boolean: ['fix', 'verbose', 'version', 'help', 'patch-diff', 'report'], | ||
@@ -30,2 +32,3 @@ alias: { | ||
r: 'report', | ||
o: 'format', | ||
v: 'version' | ||
@@ -49,3 +52,3 @@ } | ||
dot: true, | ||
ignore: ['**/node_modules/**', reportOutputFile] | ||
ignore: ['**/node_modules/**', `${reportOutputFilename}.*`] | ||
}); | ||
@@ -58,3 +61,5 @@ if (files.length === 0) { | ||
if (options.report) { | ||
await report(files); | ||
await report(files, { | ||
format: options.format | ||
}); | ||
} | ||
@@ -61,0 +66,0 @@ else { |
@@ -1,2 +0,4 @@ | ||
export type ReportOptions = Record<string, unknown>; | ||
export type ReportOptions = { | ||
format?: 'html' | 'md'; | ||
}; | ||
export type FileReport = { | ||
@@ -6,5 +8,12 @@ file: string; | ||
patch?: string; | ||
rawPatch?: string; | ||
}; | ||
export declare function report(files: string[], options?: ReportOptions): Promise<void>; | ||
export declare function generateHtmlReport(outputFile: string, reports: FileReport[]): Promise<void>; | ||
export type ReportResult = { | ||
reports: FileReport[]; | ||
outputFile: string; | ||
contents: string; | ||
}; | ||
export declare function report(files: string[], options?: ReportOptions): Promise<ReportResult | undefined>; | ||
export declare function generateHtmlReport(reports: FileReport[]): Promise<string>; | ||
export declare function generateMarkdownReport(reports: FileReport[]): Promise<string>; | ||
export declare function reportFile(file: string, options?: ReportOptions): Promise<FileReport>; |
@@ -11,5 +11,6 @@ import path from 'node:path'; | ||
import { getPackageJson, escapeForHtml } from '../util.js'; | ||
import { reportOutputFile } from '../constants.js'; | ||
import { reportOutputFilename } from '../constants.js'; | ||
const debug = createDebug('report'); | ||
export async function report(files, options = {}) { | ||
const format = options.format === 'md' ? 'md' : 'html'; | ||
let spinner; | ||
@@ -22,6 +23,14 @@ try { | ||
const promises = files.map(async (file) => reportFile(file, options)); | ||
const results = await Promise.all(promises); | ||
await generateHtmlReport(reportOutputFile, results); | ||
const reports = await Promise.all(promises); | ||
const contents = format === 'md' ? await generateMarkdownReport(reports) : await generateHtmlReport(reports); | ||
const outputFile = reportOutputFilename + `.${format}`; | ||
await fs.mkdir(path.dirname(outputFile), { recursive: true }); | ||
await fs.writeFile(outputFile, contents); | ||
chalk.level = oldLevel; | ||
spinner.succeed(`Generated report to ${chalk.cyan(reportOutputFile)}`); | ||
spinner.succeed(`Generated report to ${chalk.cyan(outputFile)}`); | ||
return { | ||
reports, | ||
outputFile, | ||
contents | ||
}; | ||
} | ||
@@ -35,3 +44,3 @@ catch (error) { | ||
} | ||
export async function generateHtmlReport(outputFile, reports) { | ||
export async function generateHtmlReport(reports) { | ||
const ansiToHtml = new AnsiToHtml({ | ||
@@ -60,5 +69,20 @@ fg: '#000', | ||
} | ||
await fs.mkdir(path.dirname(outputFile), { recursive: true }); | ||
await fs.writeFile(outputFile, html); | ||
return html; | ||
} | ||
export async function generateMarkdownReport(reports) { | ||
const pkg = await getPackageJson(); | ||
const repoUrl = pkg.repository.url; | ||
let md = '# Accessibility Suggestions Report\n'; | ||
md += `_Generated by [a11y-ai](${repoUrl}) on ${new Date().toLocaleString()}_\n\n`; | ||
for (const report of reports) { | ||
if (report.suggestion !== undefined && report.patch !== undefined) { | ||
md += `---\n\n`; | ||
md += `### Suggested fixes for \`${report.file}\`\n\n`; | ||
md += '<details><summary>Raw suggestion</summary>'; | ||
md += `<pre><textarea rows="5" style="width:100%">${escapeForHtml(report.suggestion)}</textarea></pre></details>\n\n`; | ||
md += `\`\`\`diff\n${report.rawPatch}\n\`\`\`\n\n`; | ||
} | ||
} | ||
return md; | ||
} | ||
export async function reportFile(file, options = {}) { | ||
@@ -75,4 +99,5 @@ try { | ||
const patch = generatePatchDiff(file, content, suggestion); | ||
const rawPatch = generatePatchDiff(file, content, suggestion, false); | ||
debug(patch); | ||
return { file, suggestion, patch }; | ||
return { file, suggestion, patch, rawPatch }; | ||
} | ||
@@ -79,0 +104,0 @@ catch (error) { |
@@ -1,2 +0,2 @@ | ||
export declare const reportOutputFile = "report/a11y-report.html"; | ||
export declare const reportOutputFilename = "report/a11y-report"; | ||
export declare const apiUrl = "https://a11y.nubesgen.com"; |
@@ -1,2 +0,2 @@ | ||
export const reportOutputFile = 'report/a11y-report.html'; | ||
export const reportOutputFilename = 'report/a11y-report'; | ||
export const apiUrl = 'https://a11y.nubesgen.com'; |
export declare function generateColoredDiff(content: string, suggestion: string): string; | ||
export declare function generatePatchDiff(file: string, content: string, suggestion: string): string; | ||
export declare function generatePatchDiff(file: string, content: string, suggestion: string, colors?: boolean): string; |
@@ -19,31 +19,36 @@ import chalk from 'chalk'; | ||
} | ||
export function generatePatchDiff(file, content, suggestion) { | ||
const diff = createPatch(file, content, suggestion); | ||
return (diff | ||
// Remove header | ||
export function generatePatchDiff(file, content, suggestion, colors = true) { | ||
let diff = createPatch(file, content, suggestion); | ||
// Remove header | ||
diff = diff | ||
.split(/={10,}/) | ||
.slice(1) | ||
.join('') | ||
.split('\n') | ||
.map((line) => { | ||
switch (line[0]) { | ||
case '+': { | ||
return line.startsWith('+++') ? line : chalk.green(line); | ||
.trim(); | ||
if (colors) { | ||
diff = diff | ||
.split('\n') | ||
.map((line) => { | ||
switch (line[0]) { | ||
case '+': { | ||
return line.startsWith('+++') ? line : chalk.green(line); | ||
} | ||
case '-': { | ||
return line.startsWith('---') ? line : chalk.red(line); | ||
} | ||
case '@': { | ||
return chalk.cyan(line); | ||
} | ||
case '\\': { | ||
return chalk.dim(line); | ||
} | ||
default: { | ||
return line; | ||
} | ||
} | ||
case '-': { | ||
return line.startsWith('---') ? line : chalk.red(line); | ||
} | ||
case '@': { | ||
return chalk.cyan(line); | ||
} | ||
case '\\': { | ||
return chalk.dim(line); | ||
} | ||
default: { | ||
return line; | ||
} | ||
} | ||
}) | ||
.join('\n') | ||
.trim()); | ||
}) | ||
.join('\n') | ||
.trim(); | ||
} | ||
return diff; | ||
} |
{ | ||
"name": "a11y-ai", | ||
"version": "0.2.2", | ||
"description": "Experimental tool to automatically detect accessibility issues in web pages and provide suggestions for fixing them", | ||
"version": "0.3.0", | ||
"description": "Experimental tool to automatically detect accessibility issues in web pages using OpenAI and provide suggestions for fixing them", | ||
"type": "module", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -9,3 +9,3 @@ # :robot: a11y-ai | ||
> Experimental tool to automatically detect accessibility issues in web pages and provide suggestions for fixing them. | ||
> Experimental tool to automatically detect accessibility issues in web pages using OpenAI and provide suggestions for fixing them. | ||
@@ -44,4 +44,5 @@ ![a11y-ai portrait by another AI](https://user-images.githubusercontent.com/593151/221144683-af658535-500b-4024-afe9-032526b3eec9.png) | ||
-r, --report Generate a report instead of fixing files | ||
-o, --format <format> Report format [html, md] (default: html) | ||
--verbose Show detailed logs | ||
--help Show this help | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19585
408
47