|
| 1 | +// Imports |
| 2 | +import retrieveValidation from './retrieve-validation'; |
| 3 | + |
| 4 | +// Define types |
| 5 | +interface ValidateTextOptionsBase { |
| 6 | + medium?: 'all' | 'braille' | 'embossed' | 'handheld' | 'print' | 'projection' | 'screen' | 'speech' | 'tty' | 'tv'; |
| 7 | +} |
| 8 | + |
| 9 | +interface ValidateTextOptionsWithoutWarnings extends ValidateTextOptionsBase { |
| 10 | + warningLevel?: 0; |
| 11 | +} |
| 12 | + |
| 13 | +interface ValidateTextOptionsWithWarnings extends ValidateTextOptionsBase { |
| 14 | + warningLevel: 1 | 2 | 3; |
| 15 | +} |
| 16 | + |
| 17 | +type ValidateTextOptions = ValidateTextOptionsWithWarnings | ValidateTextOptionsWithoutWarnings; |
| 18 | + |
| 19 | +interface ValidateTextResultBase { |
| 20 | + valid: boolean; |
| 21 | + errors: { |
| 22 | + line: number; |
| 23 | + message: string; |
| 24 | + }[]; |
| 25 | +} |
| 26 | + |
| 27 | +interface ValidateTextResultWithWarnings extends ValidateTextResultBase { |
| 28 | + warnings: { |
| 29 | + line: number; |
| 30 | + level: 1 | 2 | 3; |
| 31 | + message: string; |
| 32 | + }[]; |
| 33 | +} |
| 34 | + |
| 35 | +interface ValidateTextResultWithoutWarnings extends ValidateTextResultBase { |
| 36 | + warnings?: never; |
| 37 | +} |
| 38 | + |
| 39 | +type ValidateTextResult = ValidateTextResultWithWarnings | ValidateTextResultWithoutWarnings; |
| 40 | + |
| 41 | +// Validates a string of CSS |
| 42 | +async function validateText( |
| 43 | + textToValidate: string, |
| 44 | + options?: ValidateTextOptionsWithoutWarnings |
| 45 | +): Promise<ValidateTextResultWithoutWarnings>; |
| 46 | +async function validateText( |
| 47 | + textToValidate: string, |
| 48 | + options: ValidateTextOptionsWithWarnings |
| 49 | +): Promise<ValidateTextResultWithWarnings>; |
| 50 | +async function validateText(textToBeValidated: string, options?: ValidateTextOptions): Promise<ValidateTextResult> { |
| 51 | + // Build URL for fetching |
| 52 | + const params = { |
| 53 | + text: encodeURIComponent(textToBeValidated), |
| 54 | + usermedium: options?.medium ?? 'all', |
| 55 | + warning: options?.warningLevel ? options.warningLevel - 1 : 'no', |
| 56 | + output: 'application/json', |
| 57 | + }; |
| 58 | + |
| 59 | + const url = `https://jigsaw.w3.org/css-validator/validator?${Object.entries(params) |
| 60 | + .map(([key, val]) => `${key}=${val}`) |
| 61 | + .join('&')}`; |
| 62 | + |
| 63 | + // Call W3C CSS Validator API and store response |
| 64 | + const cssValidationResponse = await retrieveValidation(url); |
| 65 | + |
| 66 | + // Build result |
| 67 | + const base: ValidateTextResultBase = { |
| 68 | + valid: false, |
| 69 | + errors: [], |
| 70 | + }; |
| 71 | + const result: ValidateTextResultWithWarnings | ValidateTextResultBase = options?.warningLevel |
| 72 | + ? { |
| 73 | + ...base, |
| 74 | + warnings: [], |
| 75 | + } |
| 76 | + : base; |
| 77 | + |
| 78 | + result.valid = cssValidationResponse.validity; |
| 79 | + |
| 80 | + cssValidationResponse.errors?.forEach((error) => { |
| 81 | + result.errors.push({ |
| 82 | + line: error.line, |
| 83 | + message: error.message, |
| 84 | + }); |
| 85 | + }); |
| 86 | + |
| 87 | + if ('warnings' in result) { |
| 88 | + cssValidationResponse.warnings?.forEach((warning) => { |
| 89 | + result.warnings.push({ |
| 90 | + line: warning.line, |
| 91 | + message: warning.message, |
| 92 | + level: (warning.level + 1) as 1 | 2 | 3, |
| 93 | + }); |
| 94 | + }); |
| 95 | + } |
| 96 | + |
| 97 | + // Return |
| 98 | + return result; |
| 99 | +} |
| 100 | + |
| 101 | +export default validateText; |
0 commit comments