html-validate 6.0.2 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/core.js CHANGED
@@ -2852,7 +2852,7 @@ var TRANSFORMER_API;
2852
2852
  })(TRANSFORMER_API || (TRANSFORMER_API = {}));
2853
2853
 
2854
2854
  const name = "html-validate";
2855
- const version = "6.0.2";
2855
+ const version = "6.1.0";
2856
2856
  const homepage = "https://html-validate.org";
2857
2857
  const bugs = {
2858
2858
  url: "https://gitlab.com/html-validate/html-validate/issues/new"
@@ -3142,24 +3142,60 @@ const description = {
3142
3142
  ["absolute" /* ABSOLUTE */]: "Absolute links are not allowed by current configuration.",
3143
3143
  ["anchor" /* ANCHOR */]: null,
3144
3144
  };
3145
+ function parseAllow(value) {
3146
+ if (typeof value === "boolean") {
3147
+ return value;
3148
+ }
3149
+ return {
3150
+ /* eslint-disable security/detect-non-literal-regexp */
3151
+ include: value.include ? value.include.map((it) => new RegExp(it)) : null,
3152
+ exclude: value.exclude ? value.exclude.map((it) => new RegExp(it)) : null,
3153
+ /* eslint-enable security/detect-non-literal-regexp */
3154
+ };
3155
+ }
3156
+ /**
3157
+ * @internal
3158
+ */
3159
+ function matchList(value, list) {
3160
+ if (list.include && !list.include.some((it) => it.test(value))) {
3161
+ return false;
3162
+ }
3163
+ if (list.exclude && list.exclude.some((it) => it.test(value))) {
3164
+ return false;
3165
+ }
3166
+ return true;
3167
+ }
3145
3168
  class AllowedLinks extends Rule {
3146
3169
  constructor(options) {
3147
3170
  super({ ...defaults$p, ...options });
3171
+ this.allowExternal = parseAllow(this.options.allowExternal);
3172
+ this.allowRelative = parseAllow(this.options.allowRelative);
3173
+ this.allowAbsolute = parseAllow(this.options.allowAbsolute);
3148
3174
  }
3149
3175
  static schema() {
3176
+ const booleanOrObject = {
3177
+ anyOf: [
3178
+ { type: "boolean" },
3179
+ {
3180
+ type: "object",
3181
+ properties: {
3182
+ include: {
3183
+ type: "array",
3184
+ items: { type: "string" },
3185
+ },
3186
+ exclude: {
3187
+ type: "array",
3188
+ items: { type: "string" },
3189
+ },
3190
+ },
3191
+ },
3192
+ ],
3193
+ };
3150
3194
  return {
3151
- allowAbsolute: {
3152
- type: "boolean",
3153
- },
3154
- allowBase: {
3155
- type: "boolean",
3156
- },
3157
- allowExternal: {
3158
- type: "boolean",
3159
- },
3160
- allowRelative: {
3161
- type: "boolean",
3162
- },
3195
+ allowExternal: { ...booleanOrObject },
3196
+ allowRelative: { ...booleanOrObject },
3197
+ allowAbsolute: { ...booleanOrObject },
3198
+ allowBase: { type: "boolean" },
3163
3199
  };
3164
3200
  }
3165
3201
  documentation(context) {
@@ -3181,16 +3217,16 @@ class AllowedLinks extends Rule {
3181
3217
  /* anchor links are always allowed by this rule */
3182
3218
  break;
3183
3219
  case "absolute" /* ABSOLUTE */:
3184
- this.handleAbsolute(event, style);
3220
+ this.handleAbsolute(link, event, style);
3185
3221
  break;
3186
3222
  case "external" /* EXTERNAL */:
3187
- this.handleExternal(event, style);
3223
+ this.handleExternal(link, event, style);
3188
3224
  break;
3189
3225
  case "relative-base" /* RELATIVE_BASE */:
3190
- this.handleRelativeBase(event, style);
3226
+ this.handleRelativeBase(link, event, style);
3191
3227
  break;
3192
3228
  case "relative-path" /* RELATIVE_PATH */:
3193
- this.handleRelativePath(event, style);
3229
+ this.handleRelativePath(link, event, style);
3194
3230
  break;
3195
3231
  }
3196
3232
  });
@@ -3224,28 +3260,49 @@ class AllowedLinks extends Rule {
3224
3260
  return "relative-base" /* RELATIVE_BASE */;
3225
3261
  }
3226
3262
  }
3227
- handleAbsolute(event, style) {
3228
- const { allowAbsolute } = this.options;
3229
- if (!allowAbsolute) {
3263
+ handleAbsolute(target, event, style) {
3264
+ const { allowAbsolute } = this;
3265
+ if (allowAbsolute === true) {
3266
+ return;
3267
+ }
3268
+ else if (allowAbsolute === false) {
3230
3269
  this.report(event.target, "Link destination must not be absolute url", event.valueLocation, style);
3231
3270
  }
3271
+ else if (!matchList(target, allowAbsolute)) {
3272
+ this.report(event.target, "Absolute link to this destination is not allowed by current configuration", event.valueLocation, style);
3273
+ }
3232
3274
  }
3233
- handleExternal(event, style) {
3234
- const { allowExternal } = this.options;
3235
- if (!allowExternal) {
3275
+ handleExternal(target, event, style) {
3276
+ const { allowExternal } = this;
3277
+ if (allowExternal === true) {
3278
+ return;
3279
+ }
3280
+ else if (allowExternal === false) {
3236
3281
  this.report(event.target, "Link destination must not be external url", event.valueLocation, style);
3237
3282
  }
3283
+ else if (!matchList(target, allowExternal)) {
3284
+ this.report(event.target, "External link to this destination is not allowed by current configuration", event.valueLocation, style);
3285
+ }
3238
3286
  }
3239
- handleRelativePath(event, style) {
3240
- const { allowRelative } = this.options;
3241
- if (!allowRelative) {
3287
+ handleRelativePath(target, event, style) {
3288
+ const { allowRelative } = this;
3289
+ if (allowRelative === true) {
3290
+ return false;
3291
+ }
3292
+ else if (allowRelative === false) {
3242
3293
  this.report(event.target, "Link destination must not be relative url", event.valueLocation, style);
3294
+ return true;
3243
3295
  }
3296
+ else if (!matchList(target, allowRelative)) {
3297
+ this.report(event.target, "Relative link to this destination is not allowed by current configuration", event.valueLocation, style);
3298
+ return true;
3299
+ }
3300
+ return false;
3244
3301
  }
3245
- handleRelativeBase(event, style) {
3246
- const { allowRelative, allowBase } = this.options;
3247
- if (!allowRelative) {
3248
- this.report(event.target, "Link destination must not be relative url", event.valueLocation, style);
3302
+ handleRelativeBase(target, event, style) {
3303
+ const { allowBase } = this.options;
3304
+ if (this.handleRelativePath(target, event, style)) {
3305
+ return;
3249
3306
  }
3250
3307
  else if (!allowBase) {
3251
3308
  this.report(event.target, "Relative links must be relative to current folder", event.valueLocation, style);
@@ -3482,7 +3539,7 @@ const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
3482
3539
  const MATCH_TAG_OPEN = /^<(\/?)([a-zA-Z0-9\-:]+)/; // https://www.w3.org/TR/html/syntax.html#start-tags
3483
3540
  const MATCH_TAG_CLOSE = /^\/?>/;
3484
3541
  const MATCH_TEXT = /^[^]*?(?=(?:[ \t]*(?:\r\n|\r|\n)|<[^ ]|$))/;
3485
- const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/;
3542
+ const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
3486
3543
  const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
3487
3544
  const MATCH_ATTR_START = /^([^\t\r\n\f \/><"'=]+)/; // https://www.w3.org/TR/html/syntax.html#elements-attributes
3488
3545
  const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
@@ -6147,7 +6204,7 @@ const defaults$9 = {
6147
6204
  };
6148
6205
  const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
6149
6206
  const unquotedAttrRegexp = /([<>"'=`]|&(?![a-zA-Z0-9#]+;))/g;
6150
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/;
6207
+ const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
6151
6208
  const replacementTable = new Map([
6152
6209
  ['"', "&quot;"],
6153
6210
  ["&", "&amp;"],