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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # html-validate changelog
2
2
 
3
+ ## [6.1.0](https://gitlab.com/html-validate/html-validate/compare/v6.0.2...v6.1.0) (2021-10-02)
4
+
5
+ ### Features
6
+
7
+ - **rules:** `allowed-links` support `include` and `exclude` ([a3f7b6a](https://gitlab.com/html-validate/html-validate/commit/a3f7b6aa2414ab41239ec1aed6d463502575bb13))
8
+
9
+ ### Bug Fixes
10
+
11
+ - handle multiline templating strings ([cddf7d5](https://gitlab.com/html-validate/html-validate/commit/cddf7d5e66ad3ce3f49b32b5dea873b04f9b6f7d)), closes [#134](https://gitlab.com/html-validate/html-validate/issues/134)
12
+
3
13
  ### [6.0.2](https://gitlab.com/html-validate/html-validate/compare/v6.0.1...v6.0.2) (2021-09-27)
4
14
 
5
15
  ### Bug Fixes
package/dist/cjs/core.js CHANGED
@@ -2864,7 +2864,7 @@ var TRANSFORMER_API;
2864
2864
  })(TRANSFORMER_API || (TRANSFORMER_API = {}));
2865
2865
 
2866
2866
  const name = "html-validate";
2867
- const version = "6.0.2";
2867
+ const version = "6.1.0";
2868
2868
  const homepage = "https://html-validate.org";
2869
2869
  const bugs = {
2870
2870
  url: "https://gitlab.com/html-validate/html-validate/issues/new"
@@ -3154,24 +3154,60 @@ const description = {
3154
3154
  ["absolute" /* ABSOLUTE */]: "Absolute links are not allowed by current configuration.",
3155
3155
  ["anchor" /* ANCHOR */]: null,
3156
3156
  };
3157
+ function parseAllow(value) {
3158
+ if (typeof value === "boolean") {
3159
+ return value;
3160
+ }
3161
+ return {
3162
+ /* eslint-disable security/detect-non-literal-regexp */
3163
+ include: value.include ? value.include.map((it) => new RegExp(it)) : null,
3164
+ exclude: value.exclude ? value.exclude.map((it) => new RegExp(it)) : null,
3165
+ /* eslint-enable security/detect-non-literal-regexp */
3166
+ };
3167
+ }
3168
+ /**
3169
+ * @internal
3170
+ */
3171
+ function matchList(value, list) {
3172
+ if (list.include && !list.include.some((it) => it.test(value))) {
3173
+ return false;
3174
+ }
3175
+ if (list.exclude && list.exclude.some((it) => it.test(value))) {
3176
+ return false;
3177
+ }
3178
+ return true;
3179
+ }
3157
3180
  class AllowedLinks extends Rule {
3158
3181
  constructor(options) {
3159
3182
  super({ ...defaults$p, ...options });
3183
+ this.allowExternal = parseAllow(this.options.allowExternal);
3184
+ this.allowRelative = parseAllow(this.options.allowRelative);
3185
+ this.allowAbsolute = parseAllow(this.options.allowAbsolute);
3160
3186
  }
3161
3187
  static schema() {
3188
+ const booleanOrObject = {
3189
+ anyOf: [
3190
+ { type: "boolean" },
3191
+ {
3192
+ type: "object",
3193
+ properties: {
3194
+ include: {
3195
+ type: "array",
3196
+ items: { type: "string" },
3197
+ },
3198
+ exclude: {
3199
+ type: "array",
3200
+ items: { type: "string" },
3201
+ },
3202
+ },
3203
+ },
3204
+ ],
3205
+ };
3162
3206
  return {
3163
- allowAbsolute: {
3164
- type: "boolean",
3165
- },
3166
- allowBase: {
3167
- type: "boolean",
3168
- },
3169
- allowExternal: {
3170
- type: "boolean",
3171
- },
3172
- allowRelative: {
3173
- type: "boolean",
3174
- },
3207
+ allowExternal: { ...booleanOrObject },
3208
+ allowRelative: { ...booleanOrObject },
3209
+ allowAbsolute: { ...booleanOrObject },
3210
+ allowBase: { type: "boolean" },
3175
3211
  };
3176
3212
  }
3177
3213
  documentation(context) {
@@ -3193,16 +3229,16 @@ class AllowedLinks extends Rule {
3193
3229
  /* anchor links are always allowed by this rule */
3194
3230
  break;
3195
3231
  case "absolute" /* ABSOLUTE */:
3196
- this.handleAbsolute(event, style);
3232
+ this.handleAbsolute(link, event, style);
3197
3233
  break;
3198
3234
  case "external" /* EXTERNAL */:
3199
- this.handleExternal(event, style);
3235
+ this.handleExternal(link, event, style);
3200
3236
  break;
3201
3237
  case "relative-base" /* RELATIVE_BASE */:
3202
- this.handleRelativeBase(event, style);
3238
+ this.handleRelativeBase(link, event, style);
3203
3239
  break;
3204
3240
  case "relative-path" /* RELATIVE_PATH */:
3205
- this.handleRelativePath(event, style);
3241
+ this.handleRelativePath(link, event, style);
3206
3242
  break;
3207
3243
  }
3208
3244
  });
@@ -3236,28 +3272,49 @@ class AllowedLinks extends Rule {
3236
3272
  return "relative-base" /* RELATIVE_BASE */;
3237
3273
  }
3238
3274
  }
3239
- handleAbsolute(event, style) {
3240
- const { allowAbsolute } = this.options;
3241
- if (!allowAbsolute) {
3275
+ handleAbsolute(target, event, style) {
3276
+ const { allowAbsolute } = this;
3277
+ if (allowAbsolute === true) {
3278
+ return;
3279
+ }
3280
+ else if (allowAbsolute === false) {
3242
3281
  this.report(event.target, "Link destination must not be absolute url", event.valueLocation, style);
3243
3282
  }
3283
+ else if (!matchList(target, allowAbsolute)) {
3284
+ this.report(event.target, "Absolute link to this destination is not allowed by current configuration", event.valueLocation, style);
3285
+ }
3244
3286
  }
3245
- handleExternal(event, style) {
3246
- const { allowExternal } = this.options;
3247
- if (!allowExternal) {
3287
+ handleExternal(target, event, style) {
3288
+ const { allowExternal } = this;
3289
+ if (allowExternal === true) {
3290
+ return;
3291
+ }
3292
+ else if (allowExternal === false) {
3248
3293
  this.report(event.target, "Link destination must not be external url", event.valueLocation, style);
3249
3294
  }
3295
+ else if (!matchList(target, allowExternal)) {
3296
+ this.report(event.target, "External link to this destination is not allowed by current configuration", event.valueLocation, style);
3297
+ }
3250
3298
  }
3251
- handleRelativePath(event, style) {
3252
- const { allowRelative } = this.options;
3253
- if (!allowRelative) {
3299
+ handleRelativePath(target, event, style) {
3300
+ const { allowRelative } = this;
3301
+ if (allowRelative === true) {
3302
+ return false;
3303
+ }
3304
+ else if (allowRelative === false) {
3254
3305
  this.report(event.target, "Link destination must not be relative url", event.valueLocation, style);
3306
+ return true;
3255
3307
  }
3308
+ else if (!matchList(target, allowRelative)) {
3309
+ this.report(event.target, "Relative link to this destination is not allowed by current configuration", event.valueLocation, style);
3310
+ return true;
3311
+ }
3312
+ return false;
3256
3313
  }
3257
- handleRelativeBase(event, style) {
3258
- const { allowRelative, allowBase } = this.options;
3259
- if (!allowRelative) {
3260
- this.report(event.target, "Link destination must not be relative url", event.valueLocation, style);
3314
+ handleRelativeBase(target, event, style) {
3315
+ const { allowBase } = this.options;
3316
+ if (this.handleRelativePath(target, event, style)) {
3317
+ return;
3261
3318
  }
3262
3319
  else if (!allowBase) {
3263
3320
  this.report(event.target, "Relative links must be relative to current folder", event.valueLocation, style);
@@ -3494,7 +3551,7 @@ const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
3494
3551
  const MATCH_TAG_OPEN = /^<(\/?)([a-zA-Z0-9\-:]+)/; // https://www.w3.org/TR/html/syntax.html#start-tags
3495
3552
  const MATCH_TAG_CLOSE = /^\/?>/;
3496
3553
  const MATCH_TEXT = /^[^]*?(?=(?:[ \t]*(?:\r\n|\r|\n)|<[^ ]|$))/;
3497
- const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/;
3554
+ const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
3498
3555
  const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
3499
3556
  const MATCH_ATTR_START = /^([^\t\r\n\f \/><"'=]+)/; // https://www.w3.org/TR/html/syntax.html#elements-attributes
3500
3557
  const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
@@ -6159,7 +6216,7 @@ const defaults$9 = {
6159
6216
  };
6160
6217
  const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
6161
6218
  const unquotedAttrRegexp = /([<>"'=`]|&(?![a-zA-Z0-9#]+;))/g;
6162
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/;
6219
+ const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
6163
6220
  const replacementTable = new Map([
6164
6221
  ['"', "&quot;"],
6165
6222
  ["&", "&amp;"],