html-validate 11.4.0 → 11.5.1

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.
Files changed (50) hide show
  1. package/dist/cjs/browser.js +1 -1
  2. package/dist/cjs/cli.js +7 -0
  3. package/dist/cjs/cli.js.map +1 -1
  4. package/dist/cjs/core-nodejs.js +212 -2
  5. package/dist/cjs/core-nodejs.js.map +1 -1
  6. package/dist/cjs/core.js +85 -30
  7. package/dist/cjs/core.js.map +1 -1
  8. package/dist/cjs/elements.js +429 -58
  9. package/dist/cjs/elements.js.map +1 -1
  10. package/dist/cjs/html-validate.js +1 -1
  11. package/dist/cjs/index.js +3 -1
  12. package/dist/cjs/index.js.map +1 -1
  13. package/dist/cjs/jest-worker.js +1 -1
  14. package/dist/cjs/jest.js +1 -1
  15. package/dist/cjs/presets.d.ts +1 -0
  16. package/dist/cjs/presets.js +22 -0
  17. package/dist/cjs/presets.js.map +1 -0
  18. package/dist/cjs/vitest-matchers.js +20 -4
  19. package/dist/cjs/vitest-matchers.js.map +1 -1
  20. package/dist/cjs/vitest-worker.js +1 -1
  21. package/dist/cjs/vitest.js +1 -1
  22. package/dist/esm/browser.js +2 -2
  23. package/dist/esm/cli.js +10 -3
  24. package/dist/esm/cli.js.map +1 -1
  25. package/dist/esm/core-browser.js +1 -1
  26. package/dist/esm/core-nodejs.js +212 -4
  27. package/dist/esm/core-nodejs.js.map +1 -1
  28. package/dist/esm/core.js +78 -30
  29. package/dist/esm/core.js.map +1 -1
  30. package/dist/esm/elements.js +429 -58
  31. package/dist/esm/elements.js.map +1 -1
  32. package/dist/esm/html-validate.js +3 -3
  33. package/dist/esm/index.js +3 -3
  34. package/dist/esm/jest-matchers.js +2 -2
  35. package/dist/esm/jest-utils.js +2 -2
  36. package/dist/esm/jest-worker.js +2 -2
  37. package/dist/esm/jest.js +1 -1
  38. package/dist/esm/presets.d.ts +1 -0
  39. package/dist/esm/presets.js +11 -0
  40. package/dist/esm/presets.js.map +1 -0
  41. package/dist/esm/vitest-matchers.js +23 -7
  42. package/dist/esm/vitest-matchers.js.map +1 -1
  43. package/dist/esm/vitest-utils.js +2 -2
  44. package/dist/esm/vitest-worker.js +2 -2
  45. package/dist/esm/vitest.js +1 -1
  46. package/dist/schema/elements.json +14 -1
  47. package/dist/types/browser.d.ts +88 -4
  48. package/dist/types/index.d.ts +154 -4
  49. package/dist/types/presets.d.ts +8 -0
  50. package/package.json +7 -2
@@ -1,5 +1,5 @@
1
1
  import fs, { existsSync } from 'node:fs';
2
- import { m as StaticConfigLoader, i as PerformanceTracker, a1 as transformSource, E as Engine, P as Parser, a2 as transformSourceSync, $ as transformFilename, a0 as transformFilenameSync, R as Reporter, u as configurationSchema, J as isThenable, U as UserError, b as ConfigLoader, V as normalizeSource, a as ConfigError, C as Config, t as compatibilityCheckImpl, a3 as version } from './core.js';
2
+ import { S as StaticConfigLoader, P as PerformanceTracker, t as transformSource, E as Engine, a as Parser, b as transformSourceSync, c as transformFilename, d as transformFilenameSync, R as Reporter, e as configurationSchema, i as isThenable, U as UserError, C as ConfigLoader, n as normalizeSource, g as ConfigError, h as Config, M as MetaTable, p as parseSeverity, j as ResolvedConfig, f as compatibilityCheckImpl, v as version } from './core.js';
3
3
  import path from 'node:path';
4
4
  import fs$1 from 'node:fs/promises';
5
5
  import { pathToFileURL } from 'node:url';
@@ -690,7 +690,7 @@ function findConfigurationFiles(fs2, directory) {
690
690
  function normalizeFilename(filename) {
691
691
  return filename === "/dev/stdin" ? path.join(process.cwd(), "noop.html") : filename;
692
692
  }
693
- const defaultResolvers = [esmResolver()];
693
+ const defaultResolvers$1 = [esmResolver()];
694
694
  function hasResolver(value) {
695
695
  return Array.isArray(value[0]);
696
696
  }
@@ -705,7 +705,7 @@ class FileSystemConfigLoader extends ConfigLoader {
705
705
  options.fs ?? fs;
706
706
  } else {
707
707
  const [config, options = {}] = args;
708
- super(defaultResolvers, config);
708
+ super(defaultResolvers$1, config);
709
709
  this.fs = /* istanbul ignore next */
710
710
  options.fs ?? fs;
711
711
  }
@@ -897,6 +897,214 @@ class FileSystemConfigLoader extends ConfigLoader {
897
897
  }
898
898
  }
899
899
 
900
+ function defineFlatConfig(config) {
901
+ return config;
902
+ }
903
+
904
+ const FLAT_CONFIG_FILES = [
905
+ "html-validate.config.mjs",
906
+ "html-validate.config.cjs",
907
+ "html-validate.config.js",
908
+ "html-validate.config.mts",
909
+ "html-validate.config.cts",
910
+ "html-validate.config.ts"
911
+ ];
912
+ function findFlatConfigFile(startDir) {
913
+ let current = path.resolve(startDir);
914
+ const root = path.parse(current).root;
915
+ for (; ; ) {
916
+ for (const filename of FLAT_CONFIG_FILES) {
917
+ const candidate = path.join(current, filename);
918
+ if (fs.existsSync(candidate)) {
919
+ return candidate;
920
+ }
921
+ }
922
+ const parent = path.dirname(current);
923
+ if (current === root || parent === current) {
924
+ return null;
925
+ }
926
+ current = parent;
927
+ }
928
+ }
929
+
930
+ async function loadFlatConfigFile(filePath) {
931
+ const url = pathToFileURL(filePath);
932
+ const stat = await fs$1.stat(url);
933
+ url.searchParams.append("mtime", String(stat.mtime.getTime()));
934
+ const module = await import(url.href);
935
+ const value = module.default;
936
+ if (!Array.isArray(value)) {
937
+ throw new TypeError(
938
+ `Flat config file "${filePath}" must have a default export that is an array`
939
+ );
940
+ }
941
+ return value;
942
+ }
943
+
944
+ function mergeFlatConfig(blocks) {
945
+ const merged = {
946
+ elements: [],
947
+ plugins: [],
948
+ transform: {},
949
+ rules: {}
950
+ };
951
+ for (const block of blocks) {
952
+ if (block.elements) {
953
+ merged.elements = [...merged.elements, ...block.elements];
954
+ }
955
+ if (block.plugins) {
956
+ merged.plugins = [...merged.plugins, ...block.plugins];
957
+ }
958
+ if (block.transform) {
959
+ merged.transform = { ...merged.transform, ...block.transform };
960
+ }
961
+ if (block.rules) {
962
+ merged.rules = { ...merged.rules, ...block.rules };
963
+ }
964
+ }
965
+ return merged;
966
+ }
967
+
968
+ function isGlobalIgnore(block) {
969
+ return block.ignores !== void 0 && block.files === void 0 && block.elements === void 0 && block.plugins === void 0 && block.transform === void 0 && block.rules === void 0;
970
+ }
971
+ function matchesFile(block, rel) {
972
+ if (block.ignores?.some((it) => path.matchesGlob(rel, it))) {
973
+ return false;
974
+ }
975
+ if (!block.files) {
976
+ return true;
977
+ }
978
+ return block.files.some((it) => path.matchesGlob(rel, it.includes("/") ? it : `**/${it}`));
979
+ }
980
+ function configDataToFlatConfigObject(data) {
981
+ if (!data) {
982
+ return {};
983
+ }
984
+ const elements = data.elements?.filter((it) => typeof it !== "string");
985
+ const plugins = data.plugins?.filter((it) => typeof it !== "string");
986
+ const rules = data.rules;
987
+ return {
988
+ elements,
989
+ plugins,
990
+ rules
991
+ };
992
+ }
993
+ function buildResolvedConfig(merged, original) {
994
+ const metaTable = new MetaTable();
995
+ for (const element of merged.elements) {
996
+ metaTable.loadFromObject(element);
997
+ }
998
+ metaTable.init();
999
+ const plugins = merged.plugins;
1000
+ const rules = /* @__PURE__ */ new Map();
1001
+ for (const [ruleId, data] of Object.entries(merged.rules)) {
1002
+ let rawSeverity;
1003
+ let options;
1004
+ if (!Array.isArray(data)) {
1005
+ rawSeverity = data;
1006
+ options = {};
1007
+ } else if (data.length === 1) {
1008
+ rawSeverity = data[0];
1009
+ options = {};
1010
+ } else {
1011
+ rawSeverity = data[0];
1012
+ options = data[1];
1013
+ }
1014
+ rules.set(ruleId, [parseSeverity(rawSeverity), options]);
1015
+ }
1016
+ const transformers = Object.entries(merged.transform).map(
1017
+ /* eslint-disable-next-line security/detect-non-literal-regexp -- transform patterns are user-provided regexp strings */
1018
+ ([pattern, fn]) => ({ kind: "function", pattern: new RegExp(pattern), function: fn })
1019
+ );
1020
+ const resolvedData = { metaTable, plugins, rules, transformers };
1021
+ return new ResolvedConfig(resolvedData, original);
1022
+ }
1023
+ const defaultResolvers = [esmResolver()];
1024
+ class FlatConfigLoader extends ConfigLoader {
1025
+ configFilePath;
1026
+ configCache;
1027
+ fileCache;
1028
+ /**
1029
+ * @param configFilePath - Absolute path to the flat config file.
1030
+ * @param resolvers - Resolvers to use.
1031
+ */
1032
+ constructor(configFilePath, resolvers = defaultResolvers) {
1033
+ super(resolvers);
1034
+ this.configFilePath = configFilePath;
1035
+ this.configCache = null;
1036
+ this.fileCache = /* @__PURE__ */ new Map();
1037
+ }
1038
+ /**
1039
+ * Search `dir` and its ancestors for a flat config file and, if found,
1040
+ * return a new `FlatConfigLoader` pointed at it. Returns `null` when no
1041
+ * config file can be found.
1042
+ *
1043
+ * @param dir - Directory to start searching from.
1044
+ * @param resolvers - Resolvers to use.
1045
+ */
1046
+ static fromDirectory(dir, resolvers) {
1047
+ const configFilePath = findFlatConfigFile(dir);
1048
+ if (!configFilePath) {
1049
+ return null;
1050
+ }
1051
+ return new FlatConfigLoader(configFilePath, resolvers);
1052
+ }
1053
+ /**
1054
+ * Get configuration for the given filename.
1055
+ *
1056
+ * Do note that if `configOverride` is changed between calls the cache must be
1057
+ * flushed in-between. This loader caches the final merged result.
1058
+ *
1059
+ * @param filename - Absolute or relative path to the file being validated.
1060
+ * @param configOverride - Optional configuration to merge into the result.
1061
+ */
1062
+ async getConfigFor(filename, configOverride) {
1063
+ const cached = this.fileCache.get(filename);
1064
+ if (cached) {
1065
+ return cached;
1066
+ }
1067
+ const { flatConfig, globalIgnores } = await this.loadConfig();
1068
+ const configDir = path.dirname(this.configFilePath);
1069
+ const rel = path.relative(configDir, path.resolve(filename));
1070
+ if (globalIgnores.some((p) => path.matchesGlob(rel, p))) {
1071
+ return buildResolvedConfig({ elements: [], plugins: [], transform: {}, rules: {} }, []);
1072
+ }
1073
+ const overrideBlock = configDataToFlatConfigObject(configOverride);
1074
+ const matchingBlocks = flatConfig.filter((block) => matchesFile(block, rel));
1075
+ const blocks = [...matchingBlocks, overrideBlock];
1076
+ const merged = mergeFlatConfig(blocks);
1077
+ const resolved = buildResolvedConfig(merged, blocks);
1078
+ this.fileCache.set(filename, resolved);
1079
+ return resolved;
1080
+ }
1081
+ /**
1082
+ * Flush the cached flat config, forcing a reload on the next call.
1083
+ */
1084
+ flushCache(handle) {
1085
+ if (handle) {
1086
+ this.fileCache.delete(handle);
1087
+ } else {
1088
+ this.configCache = null;
1089
+ this.fileCache = /* @__PURE__ */ new Map();
1090
+ }
1091
+ }
1092
+ /* istanbul ignore next */
1093
+ defaultConfig() {
1094
+ return this.empty();
1095
+ }
1096
+ async loadConfig() {
1097
+ if (this.configCache) {
1098
+ return this.configCache;
1099
+ }
1100
+ const raw = await loadFlatConfigFile(this.configFilePath);
1101
+ const flatConfig = raw.filter((block) => !isGlobalIgnore(block));
1102
+ const globalIgnores = raw.filter(isGlobalIgnore).flatMap((block) => block.ignores);
1103
+ this.configCache = { flatConfig, globalIgnores };
1104
+ return this.configCache;
1105
+ }
1106
+ }
1107
+
900
1108
  const defaults = {
901
1109
  silent: false,
902
1110
  version,
@@ -911,5 +1119,5 @@ function compatibilityCheck(name, declared, options) {
911
1119
  });
912
1120
  }
913
1121
 
914
- export { FileSystemConfigLoader as F, HtmlValidate as H, compatibilityCheck as a, cjsResolver as c, esmResolver as e, legacyRequire as l };
1122
+ export { FlatConfigLoader as F, HtmlValidate as H, FileSystemConfigLoader as a, compatibilityCheck as b, cjsResolver as c, defineFlatConfig as d, esmResolver as e, legacyRequire as l };
915
1123
  //# sourceMappingURL=core-nodejs.js.map