Better errors when an image is missing
This commit is contained in:
parent
494bc28ddf
commit
f27b60f80d
3 changed files with 65 additions and 23 deletions
|
@ -39,6 +39,14 @@ export abstract class Conversion<TIn, TOut> {
|
|||
return DesugaringStep.strict(fixed)
|
||||
}
|
||||
|
||||
public convertJoin(json: TIn, context: string, errors: string[], warnings?: string[], information?: string[]): TOut {
|
||||
const fixed = this.convert(json, context)
|
||||
errors?.push(...(fixed.errors ?? []))
|
||||
warnings?.push(...(fixed.warnings ?? []))
|
||||
information?.push(...(fixed.information ?? []))
|
||||
return fixed.result
|
||||
}
|
||||
|
||||
public andThenF<X>(f: (tout:TOut) => X ): Conversion<TIn, X>{
|
||||
return new Pipe(
|
||||
this,
|
||||
|
|
|
@ -45,6 +45,53 @@ class ValidateLanguageCompleteness extends DesugaringStep<any> {
|
|||
}
|
||||
}
|
||||
|
||||
export class DoesImageExist extends DesugaringStep<string>{
|
||||
|
||||
private readonly _knownImagePaths: Set<string>;
|
||||
public static doesPathExist : (path: string) => boolean = undefined;
|
||||
|
||||
constructor(knownImagePaths: Set<string>) {
|
||||
super("Checks if an image exists", [], "DoesImageExist");
|
||||
this._knownImagePaths = knownImagePaths;
|
||||
}
|
||||
|
||||
convert(image: string, context: string): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } {
|
||||
const errors = []
|
||||
const warnings = []
|
||||
const information = []
|
||||
if (image.indexOf("{") >= 0) {
|
||||
information.push("Ignoring image with { in the path: " + image)
|
||||
return {result: image}
|
||||
}
|
||||
|
||||
if (image === "assets/SocialImage.png") {
|
||||
return {result: image}
|
||||
}
|
||||
if (image.match(/[a-z]*/)) {
|
||||
|
||||
if (Svg.All[image + ".svg"] !== undefined) {
|
||||
// This is a builtin img, e.g. 'checkmark' or 'crosshair'
|
||||
return {result: image};
|
||||
}
|
||||
}
|
||||
|
||||
if (this._knownImagePaths !== undefined && !this._knownImagePaths.has(image)) {
|
||||
if(DoesImageExist.doesPathExist === undefined){
|
||||
errors.push(`Image with path ${image} not found or not attributed; it is used in ${context}`)
|
||||
}else if(!DoesImageExist.doesPathExist(image)){
|
||||
errors.push(`Image with path ${image} does not exist; it is used in ${context}.\n Check for typo's and missing directories in the path.`)
|
||||
}else{
|
||||
errors.push(`Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info`)
|
||||
}
|
||||
}
|
||||
return {
|
||||
result: image,
|
||||
errors, warnings, information
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
||||
/**
|
||||
* The paths where this layer is originally saved. Triggers some extra checks
|
||||
|
@ -54,13 +101,14 @@ class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
|||
private readonly knownImagePaths: Set<string>;
|
||||
private readonly _isBuiltin: boolean;
|
||||
private _sharedTagRenderings: Map<string, any>;
|
||||
|
||||
private readonly _validateImage : DesugaringStep<string>;
|
||||
constructor(knownImagePaths: Set<string>, path: string, isBuiltin: boolean, sharedTagRenderings: Map<string, any>) {
|
||||
super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme");
|
||||
this.knownImagePaths = knownImagePaths;
|
||||
this._path = path;
|
||||
this._isBuiltin = isBuiltin;
|
||||
this._sharedTagRenderings = sharedTagRenderings;
|
||||
this._validateImage = new DoesImageExist(this.knownImagePaths);
|
||||
}
|
||||
|
||||
convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[], warnings: string[], information: string[] } {
|
||||
|
@ -89,26 +137,7 @@ class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
|||
errors.push("Found a remote image: " + remoteImage + " in theme " + json.id + ", please download it.")
|
||||
}
|
||||
for (const image of images) {
|
||||
if (image.indexOf("{") >= 0) {
|
||||
information.push("Ignoring image with { in the path: " + image)
|
||||
continue
|
||||
}
|
||||
|
||||
if (image === "assets/SocialImage.png") {
|
||||
continue
|
||||
}
|
||||
if (image.match(/[a-z]*/)) {
|
||||
|
||||
if (Svg.All[image + ".svg"] !== undefined) {
|
||||
// This is a builtin img, e.g. 'checkmark' or 'crosshair'
|
||||
continue;// =>
|
||||
}
|
||||
}
|
||||
|
||||
if (this.knownImagePaths !== undefined && !this.knownImagePaths.has(image)) {
|
||||
const ctx = context === undefined ? "" : ` in a layer defined in the theme ${context}`
|
||||
errors.push(`Image with path ${image} not found or not attributed; it is used in ${json.id}${ctx}`)
|
||||
}
|
||||
this._validateImage.convertJoin(image, context === undefined ? "" : ` in a layer defined in the theme ${context}`, errors, warnings, information)
|
||||
}
|
||||
|
||||
if (json.icon.endsWith(".svg")) {
|
||||
|
@ -433,8 +462,11 @@ export class DetectMappingsWithImages extends DesugaringStep<TagRenderingConfigJ
|
|||
|
||||
for (const image of images) {
|
||||
if (this.knownImagePaths !== undefined && !this.knownImagePaths.has(image)) {
|
||||
|
||||
const closeNames = Utils.sortedByLevenshteinDistance(image, Array.from(this.knownImagePaths), i => i);
|
||||
|
||||
const ctx = context === undefined ? "" : ` in a layer defined in the theme ${context}`
|
||||
errors.push(`Image with path ${image} not found or not attributed; it is used in ${json.id}${ctx}`)
|
||||
errors.push(`Image with path ${image} not found or not attributed; it is used in ${json.id}${ctx}.\n Did you mean one of ${closeNames.slice(0, 3).join(", ")}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson";
|
|||
import {LayerConfigJson} from "../Models/ThemeConfig/Json/LayerConfigJson";
|
||||
import Constants from "../Models/Constants";
|
||||
import {
|
||||
DoesImageExist,
|
||||
PrevalidateTheme,
|
||||
ValidateLayer,
|
||||
ValidateTagRenderings,
|
||||
|
@ -152,6 +153,8 @@ class LayerOverviewUtils {
|
|||
|
||||
main(_: string[]) {
|
||||
|
||||
DoesImageExist.doesPathExist = (path) => existsSync(path)
|
||||
|
||||
const licensePaths = new Set<string>()
|
||||
for (const i in licenses) {
|
||||
licensePaths.add(licenses[i].path)
|
||||
|
@ -261,7 +264,6 @@ class LayerOverviewUtils {
|
|||
tagRenderings: this.getSharedTagRenderings(knownImagePaths),
|
||||
publicLayers
|
||||
}
|
||||
const nonDefaultLanguages : {theme: string, language: string}[] = []
|
||||
for (const themeInfo of themeFiles) {
|
||||
let themeFile = themeInfo.parsed
|
||||
const themePath = themeInfo.path
|
||||
|
|
Loading…
Reference in a new issue