@geoql/doctor-core 1.5.0 → 1.6.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/index.d.ts CHANGED
@@ -66,7 +66,8 @@ declare function scoreDiagnostics(diagnostics: Diagnostic[], config?: ScoreConfi
66
66
  //#endregion
67
67
  //#region src/types/project-info.d.ts
68
68
  type Framework = 'vue' | 'nuxt' | 'unknown';
69
- type Capability = string;
69
+ declare const CAPABILITIES: readonly ["vue:3", "vue:3.4", "vue:3.5", "vue:vapor", "nuxt:4", "nuxt:4.4", "nuxt4", "nuxt-config", "app-dir", "server-dir", "pages-dir", "wrangler", "auto-imports:vue", "components:auto", "pinia", "vue-router", "typescript", "typescript:6", "monorepo:pnpm", "monorepo:yarn", "monorepo:npm", "cf-pages:enabled", "nitro:node-server"];
70
+ type Capability = (typeof CAPABILITIES)[number];
70
71
  type MonorepoKind = 'pnpm' | 'yarn' | 'npm' | 'turbo' | null;
71
72
  interface ProjectInfo {
72
73
  readonly framework: Framework;
@@ -464,10 +465,12 @@ interface DirectiveSet {
464
465
  declare function parseDirectives(text: string): DirectiveSet;
465
466
  //#endregion
466
467
  //#region src/git-scope.d.ts
467
- type GitScopeMode = 'diff' | 'staged';
468
+ type GitScopeMode = 'diff' | 'staged' | 'changed-from';
468
469
  interface GitScopeOptions {
469
470
  rootDir: string;
470
471
  mode: GitScopeMode;
472
+ ref?: string;
473
+ includeUntracked?: boolean;
471
474
  }
472
475
  declare function listChangedFiles(options: GitScopeOptions): Promise<string[]>;
473
476
  //#endregion
package/dist/index.js CHANGED
@@ -1582,7 +1582,8 @@ const VUE_DEFAULT_RULES = {
1582
1582
  "vue-doctor/security/no-inner-html": "error",
1583
1583
  "vue-doctor/security/no-eval-like": "error",
1584
1584
  "vue-doctor/security/no-auth-token-in-web-storage": "warn",
1585
- "vue-doctor/security/no-secrets-in-source": "warn"
1585
+ "vue-doctor/security/no-secrets-in-source": "warn",
1586
+ "vue-doctor/security/markdown-it-unsanitized-html": "warn"
1586
1587
  };
1587
1588
  const NUXT_PLUGIN_RULES = {
1588
1589
  "nuxt-doctor/ai-slop/no-process-client-server": "error",
@@ -1644,7 +1645,8 @@ const VUE_OXLINT_RULE_IDS = /* @__PURE__ */ new Set([
1644
1645
  "vue-doctor/security/no-inner-html",
1645
1646
  "vue-doctor/security/no-eval-like",
1646
1647
  "vue-doctor/security/no-auth-token-in-web-storage",
1647
- "vue-doctor/security/no-secrets-in-source"
1648
+ "vue-doctor/security/no-secrets-in-source",
1649
+ "vue-doctor/security/markdown-it-unsanitized-html"
1648
1650
  ]);
1649
1651
  const NUXT_OXLINT_RULE_IDS = new Set(Object.keys(NUXT_PLUGIN_RULES));
1650
1652
  function oxlintRuleAllowlist(framework) {
@@ -2614,6 +2616,13 @@ const RULE_REGISTRY = [
2614
2616
  source: "doctor",
2615
2617
  recommended: true
2616
2618
  },
2619
+ {
2620
+ id: "vue-doctor/security/markdown-it-unsanitized-html",
2621
+ severity: "warn",
2622
+ category: "security",
2623
+ source: "doctor",
2624
+ recommended: true
2625
+ },
2617
2626
  {
2618
2627
  id: "vue-doctor/security/no-target-blank-without-rel",
2619
2628
  severity: "warn",
@@ -4958,34 +4967,68 @@ const SOURCE_EXTENSIONS = [
4958
4967
  function isSourceFile(path) {
4959
4968
  return SOURCE_EXTENSIONS.some((ext) => path.endsWith(ext));
4960
4969
  }
4970
+ var GitRefError = class extends Error {
4971
+ ref;
4972
+ constructor(ref) {
4973
+ super(`Cannot resolve git ref "${ref}" for --changed-files-from`);
4974
+ this.ref = ref;
4975
+ this.name = "GitRefError";
4976
+ }
4977
+ };
4961
4978
  async function gitLines(rootDir, args) {
4962
4979
  const { stdout } = await execFileAsync("git", args, { cwd: rootDir });
4963
4980
  return stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
4964
4981
  }
4965
- async function listChangedFiles(options) {
4966
- const { rootDir, mode } = options;
4967
- let relPaths;
4968
- if (mode === "staged") relPaths = await gitLines(rootDir, [
4969
- "diff",
4970
- "--name-only",
4971
- "--cached",
4972
- "--relative",
4973
- "--diff-filter=ACMR"
4982
+ async function untrackedLines(rootDir) {
4983
+ return gitLines(rootDir, [
4984
+ "ls-files",
4985
+ "--others",
4986
+ "--exclude-standard"
4974
4987
  ]);
4975
- else {
4976
- const tracked = await gitLines(rootDir, [
4988
+ }
4989
+ async function resolveRef(rootDir, ref) {
4990
+ try {
4991
+ await execFileAsync("git", [
4992
+ "rev-parse",
4993
+ "--verify",
4994
+ `${ref}^{commit}`
4995
+ ], { cwd: rootDir });
4996
+ } catch {
4997
+ throw new GitRefError(ref);
4998
+ }
4999
+ }
5000
+ async function listChangedFiles(options) {
5001
+ const { rootDir, mode, ref, includeUntracked } = options;
5002
+ const relPaths = [];
5003
+ if (mode === "staged") {
5004
+ relPaths.push(...await gitLines(rootDir, [
5005
+ "diff",
5006
+ "--name-only",
5007
+ "--cached",
5008
+ "--relative",
5009
+ "--diff-filter=ACMR"
5010
+ ]));
5011
+ if (includeUntracked) relPaths.push(...await untrackedLines(rootDir));
5012
+ } else if (mode === "changed-from") {
5013
+ const base = ref ?? "HEAD";
5014
+ await resolveRef(rootDir, base);
5015
+ relPaths.push(...await gitLines(rootDir, [
5016
+ "diff",
5017
+ "--name-only",
5018
+ base,
5019
+ "--relative",
5020
+ "--diff-filter=ACMR"
5021
+ ]));
5022
+ if (includeUntracked) relPaths.push(...await untrackedLines(rootDir));
5023
+ } else {
5024
+ relPaths.push(...await gitLines(rootDir, [
4977
5025
  "diff",
4978
5026
  "--name-only",
4979
5027
  "HEAD",
4980
5028
  "--relative",
4981
5029
  "--diff-filter=ACMR"
4982
- ]);
4983
- const untracked = await gitLines(rootDir, [
4984
- "ls-files",
4985
- "--others",
4986
- "--exclude-standard"
4987
- ]);
4988
- relPaths = [...tracked, ...untracked];
5030
+ ]));
5031
+ relPaths.push(...await untrackedLines(rootDir));
4989
5032
  }
4990
5033
  const absolute = relPaths.filter(isSourceFile).map((rel) => resolve(rootDir, rel));
4991
5034
  return [...new Set(absolute)].sort();