@jpeakai/mermaidjs-lint 0.5.0 → 0.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/bin.js CHANGED
@@ -9,7 +9,7 @@ import { parseArgs } from "node:util";
9
9
  // package.json
10
10
  var package_default = {
11
11
  name: "@jpeakai/mermaidjs-lint",
12
- version: "0.5.0",
12
+ version: "0.6.0",
13
13
  type: "module",
14
14
  description: "Deterministic lint gates and verified fixers for Mermaid diagrams in markdown",
15
15
  license: "MIT",
@@ -179,6 +179,14 @@ class RuleOptionError extends UsageError {
179
179
  }
180
180
  }
181
181
 
182
+ class CanvasProfileError extends UsageError {
183
+ file;
184
+ constructor(file) {
185
+ super(`${file}: a canvas applies under the github profile only, and this file is scored under mkdocs-material, whose page is Material's own; drop the canvas for it, or pass --profile github`, "canvas-profile");
186
+ this.file = file;
187
+ }
188
+ }
189
+
182
190
  class FixOutsideRootError extends UsageError {
183
191
  file;
184
192
  target;
@@ -1041,15 +1049,27 @@ var MKDOCS_MATERIAL = {
1041
1049
  light: { bg: "#ffffff", text: "#36464e" },
1042
1050
  dark: { bg: "#1e2129", text: "hsl(225 18% 86% / 0.82)" }
1043
1051
  };
1044
- var GITHUB = { light: { bg: "#ffffff" }, dark: { bg: "#0d1117" } };
1052
+ var GITHUB_CANVAS = { light: "#ffffff", dark: "#0d1117" };
1045
1053
  var THEMES = ["light", "dark"];
1054
+ var canvasColourProblem = (value) => {
1055
+ if (typeof value !== "string")
1056
+ return "is not a colour string";
1057
+ let alpha;
1058
+ try {
1059
+ alpha = alphaOf(value);
1060
+ } catch {
1061
+ return "is not a CSS colour";
1062
+ }
1063
+ return alpha < 1 ? "is translucent, and a page canvas must be opaque" : null;
1064
+ };
1065
+ var resolveCanvas = (setting) => ({ ...GITHUB_CANVAS, ...setting });
1046
1066
  var MERMAID_EDGE_LABEL = {
1047
1067
  light: { box: "rgba(232,232,232,0.8)", backing: "rgba(232,232,232,0.5)" },
1048
1068
  dark: { box: "#585858", backing: "rgba(88,88,88,0.5)" }
1049
1069
  };
1050
- var edgeLabelBackground = (theme) => {
1070
+ var edgeLabelBackground = (theme, canvas = GITHUB_CANVAS) => {
1051
1071
  const { box, backing } = MERMAID_EDGE_LABEL[theme];
1052
- return compositeOver(box, compositeOver(box, compositeOver(backing, GITHUB[theme].bg)));
1072
+ return compositeOver(box, compositeOver(box, compositeOver(backing, canvas[theme])));
1053
1073
  };
1054
1074
  var MERMAID_ER = {
1055
1075
  light: { odd: "#ffffff", even: "#f1f1ff", label: "#333333" },
@@ -1071,12 +1091,12 @@ var scorePair = (kind, d, fg, bg) => {
1071
1091
  };
1072
1092
  };
1073
1093
  var message = (err) => err instanceof Error ? err.message : String(err);
1074
- var scoreEdgeLabel = (d, pairs, skipped) => {
1094
+ var scoreEdgeLabel = (d, canvas, pairs, skipped) => {
1075
1095
  const { color } = d.properties;
1076
1096
  if (!color)
1077
1097
  return;
1078
1098
  try {
1079
- pairs.push(...THEMES.map((t) => scoreHostPair("text", d, t, color, edgeLabelBackground(t))));
1099
+ pairs.push(...THEMES.map((t) => scoreHostPair("text", d, t, color, edgeLabelBackground(t, canvas))));
1080
1100
  } catch (err) {
1081
1101
  skipped.push({
1082
1102
  selector: d.selector,
@@ -1086,12 +1106,12 @@ var scoreEdgeLabel = (d, pairs, skipped) => {
1086
1106
  });
1087
1107
  }
1088
1108
  };
1089
- var scoreGithub = (directives) => {
1109
+ var scoreGithub = (directives, canvas = GITHUB_CANVAS) => {
1090
1110
  const pairs = [];
1091
1111
  const skipped = [];
1092
1112
  for (const d of directives) {
1093
1113
  if (d.kind === "linkStyle")
1094
- scoreEdgeLabel(d, pairs, skipped);
1114
+ scoreEdgeLabel(d, canvas, pairs, skipped);
1095
1115
  if (d.kind !== "classDef" && d.kind !== "style")
1096
1116
  continue;
1097
1117
  const { fill, color, stroke } = d.properties;
@@ -1113,7 +1133,7 @@ var scoreGithub = (directives) => {
1113
1133
  note("fill is fully transparent, so there is no box to anchor contrast");
1114
1134
  continue;
1115
1135
  }
1116
- const boxes = alpha < 1 ? THEMES.map((t) => [compositeOver(fill, GITHUB[t].bg), t]) : [[fill, undefined]];
1136
+ const boxes = alpha < 1 ? THEMES.map((t) => [compositeOver(fill, canvas[t]), t]) : [[fill, undefined]];
1117
1137
  if (!color) {
1118
1138
  note("no color: declared beside fill:, and the github profile requires one " + "(if the host forces label text, use the mkdocs-material profile)", true);
1119
1139
  }
@@ -1246,10 +1266,10 @@ var scoreEr = (directives) => {
1246
1266
  }
1247
1267
  return { pairs, skipped };
1248
1268
  };
1249
- var scoreForProfile = (directives, profile, keyword) => {
1269
+ var scoreForProfile = (directives, profile, keyword, canvas = GITHUB_CANVAS) => {
1250
1270
  if (profile === "mkdocs-material")
1251
1271
  return scoreMkdocs(directives);
1252
- return keyword === "erDiagram" ? scoreEr(directives) : scoreGithub(directives);
1272
+ return keyword === "erDiagram" ? scoreEr(directives) : scoreGithub(directives, canvas);
1253
1273
  };
1254
1274
  var SEQUENCE_THEMES = ["base", "default", "dark", "forest", "neutral"];
1255
1275
  var LINE = { NOTE: 2, ACTIVE_START: 17, RECT_START: 22, AUTONUMBER: 26 };
@@ -1286,7 +1306,7 @@ var themeVariable = (selector, line) => ({
1286
1306
  spans: {},
1287
1307
  line
1288
1308
  });
1289
- var scoreSequence = async (source, profile) => {
1309
+ var scoreSequence = async (source, profile, canvas = GITHUB_CANVAS) => {
1290
1310
  const pairs = [];
1291
1311
  const skipped = [];
1292
1312
  const lines = source.split(`
@@ -1326,7 +1346,7 @@ var scoreSequence = async (source, profile) => {
1326
1346
  return block("themeVariables", `Mermaid could not resolve the theme: ${message(err)}`);
1327
1347
  }
1328
1348
  for (const t of THEMES) {
1329
- const page = (host ? MKDOCS_MATERIAL : GITHUB)[t].bg;
1349
+ const page = host ? MKDOCS_MATERIAL[t].bg : canvas[t];
1330
1350
  const vars = variables[t];
1331
1351
  const color = (key) => {
1332
1352
  const value = vars[key];
@@ -1383,7 +1403,7 @@ var scoreSequence = async (source, profile) => {
1383
1403
  }
1384
1404
  return { pairs, skipped };
1385
1405
  };
1386
- var scoreDiagram = (source, directives, profile, keyword) => keyword === "sequenceDiagram" ? scoreSequence(source, profile) : Promise.resolve(scoreForProfile(directives, profile, keyword));
1406
+ var scoreDiagram = (source, directives, profile, keyword, canvas = GITHUB_CANVAS) => keyword === "sequenceDiagram" ? scoreSequence(source, profile, canvas) : Promise.resolve(scoreForProfile(directives, profile, keyword, canvas));
1387
1407
  var detectProfile = (filePath) => {
1388
1408
  let dir = dirname(resolve(filePath));
1389
1409
  for (let i = 0;i < 20; i++) {
@@ -1547,7 +1567,7 @@ var COMPLEXITY_OPTIONS = {
1547
1567
  subgraphWeight: "number",
1548
1568
  depthWeight: "number"
1549
1569
  };
1550
- var CONTRAST_OPTIONS = { profile: "string" };
1570
+ var CONTRAST_OPTIONS = { profile: "string", canvas: "canvas" };
1551
1571
  var measure = async (diagram, config) => {
1552
1572
  const stats = await diagram.stats();
1553
1573
  if (parseFailed(diagram.source, stats))
@@ -1577,17 +1597,35 @@ var profileOf = (ctx) => {
1577
1597
  }
1578
1598
  return wanted === "auto" ? detectProfile(ctx.file) : wanted;
1579
1599
  };
1580
- var scored = new WeakMap;
1581
- var contrastOf = (diagram, profile) => {
1582
- let byProfile = scored.get(diagram);
1583
- if (!byProfile) {
1584
- byProfile = new Map;
1585
- scored.set(diagram, byProfile);
1600
+ var settingsOf = (ctx) => {
1601
+ const profile = profileOf(ctx);
1602
+ const setting = ctx.options.canvas;
1603
+ if (setting === undefined)
1604
+ return { profile, canvas: GITHUB_CANVAS };
1605
+ for (const side of THEMES) {
1606
+ if (!(side in setting))
1607
+ continue;
1608
+ const problem = canvasColourProblem(setting[side]);
1609
+ if (problem)
1610
+ throw new Error(`canvas.${side} ${problem}: ${JSON.stringify(setting[side])}`);
1586
1611
  }
1587
- let result = byProfile.get(profile);
1612
+ if (profile === "mkdocs-material")
1613
+ throw new CanvasProfileError(ctx.file);
1614
+ return { profile, canvas: resolveCanvas(setting) };
1615
+ };
1616
+ var scored = new WeakMap;
1617
+ var contrastOf = (diagram, settings) => {
1618
+ const { profile, canvas } = settings;
1619
+ const key = `${profile}\x00${canvas.light}\x00${canvas.dark}`;
1620
+ let bySettings = scored.get(diagram);
1621
+ if (!bySettings) {
1622
+ bySettings = new Map;
1623
+ scored.set(diagram, bySettings);
1624
+ }
1625
+ let result = bySettings.get(key);
1588
1626
  if (!result) {
1589
- result = scoreDiagram(diagram.source, diagram.directives, profile, diagram.keyword);
1590
- byProfile.set(profile, result);
1627
+ result = scoreDiagram(diagram.source, diagram.directives, profile, diagram.keyword, canvas);
1628
+ bySettings.set(key, result);
1591
1629
  }
1592
1630
  return result;
1593
1631
  };
@@ -1700,10 +1738,10 @@ var contrastBorderBelowUiMinimum = {
1700
1738
  summary: "a border below 3:1 against its fill",
1701
1739
  options: CONTRAST_OPTIONS,
1702
1740
  check: async (ctx) => {
1703
- const profile = profileOf(ctx);
1741
+ const settings = settingsOf(ctx);
1704
1742
  const found = [];
1705
1743
  for (const diagram of ctx.doc.diagrams) {
1706
- for (const p of (await contrastOf(diagram, profile)).pairs) {
1744
+ for (const p of (await contrastOf(diagram, settings)).pairs) {
1707
1745
  if (p.kind !== "border" || p.passes || p.advisory)
1708
1746
  continue;
1709
1747
  const line = fileLine(diagram, p.line);
@@ -1728,10 +1766,10 @@ var contrastDirectiveUnauditable = {
1728
1766
  summary: "a style directive whose contrast cannot be audited",
1729
1767
  options: CONTRAST_OPTIONS,
1730
1768
  check: async (ctx) => {
1731
- const profile = profileOf(ctx);
1769
+ const settings = settingsOf(ctx);
1732
1770
  const found = [];
1733
1771
  for (const diagram of ctx.doc.diagrams) {
1734
- for (const s of (await contrastOf(diagram, profile)).skipped) {
1772
+ for (const s of (await contrastOf(diagram, settings)).skipped) {
1735
1773
  if (!s.blocking)
1736
1774
  continue;
1737
1775
  const line = fileLine(diagram, s.line);
@@ -1759,10 +1797,10 @@ var contrastTextBelowAa = {
1759
1797
  summary: "label text below 4.5:1 against its fill",
1760
1798
  options: CONTRAST_OPTIONS,
1761
1799
  check: async (ctx) => {
1762
- const profile = profileOf(ctx);
1800
+ const settings = settingsOf(ctx);
1763
1801
  const found = [];
1764
1802
  for (const diagram of ctx.doc.diagrams) {
1765
- for (const p of (await contrastOf(diagram, profile)).pairs) {
1803
+ for (const p of (await contrastOf(diagram, settings)).pairs) {
1766
1804
  if (p.kind !== "text" || p.passes)
1767
1805
  continue;
1768
1806
  const where = [p.theme, p.row].filter(Boolean).join("/");
@@ -1773,19 +1811,19 @@ var contrastTextBelowAa = {
1773
1811
  endLine: line,
1774
1812
  rule: RULE.TEXT,
1775
1813
  message: `${p.directive.kind} ${p.selector}: text ${p.assessment.ratio.toFixed(2)}:1 < ${AA_NORMAL2} ` + `(${p.foreground} on ${p.background}${where ? `, ${where}` : ""})`,
1776
- remediation: profile === "mkdocs-material" ? "The host theme forces the label text, so change the fill until the host text reads on it in both themes." : p.directive.kind === "themeVariables" ? "A sequence diagram colour is a theme variable, and text with no box of its own sits on the page, so set the variable to a colour that reads on its background in both themes, or remove it and let the theme set it." : p.directive.kind === "linkStyle" ? "An edge label sits on Mermaid's own label box, light in one theme and grey in the other, and no one colour reads on both, so drop color: from the linkStyle and let the theme set the label text." : "Darken or lighten the fill, or change color:, until the ratio reaches 4.5:1 in every theme."
1814
+ remediation: settings.profile === "mkdocs-material" ? "The host theme forces the label text, so change the fill until the host text reads on it in both themes." : p.directive.kind === "themeVariables" ? "A sequence diagram colour is a theme variable, and text with no box of its own sits on the page, so set the variable to a colour that reads on its background in both themes, or remove it and let the theme set it." : p.directive.kind === "linkStyle" ? "An edge label sits on Mermaid's own label box, light in one theme and grey in the other, and no one colour reads on both, so drop color: from the linkStyle and let the theme set the label text." : "Darken or lighten the fill, or change color:, until the ratio reaches 4.5:1 in every theme."
1777
1815
  });
1778
1816
  }
1779
1817
  }
1780
1818
  return found;
1781
1819
  },
1782
1820
  fix: async (ctx) => {
1783
- const profile = profileOf(ctx);
1784
- if (profile === "mkdocs-material")
1821
+ const settings = settingsOf(ctx);
1822
+ if (settings.profile === "mkdocs-material")
1785
1823
  return [];
1786
1824
  const edits = [];
1787
1825
  for (const diagram of ctx.doc.diagrams) {
1788
- const { pairs } = await contrastOf(diagram, profile);
1826
+ const { pairs } = await contrastOf(diagram, settings);
1789
1827
  const failing = new Set(pairs.filter((p) => p.kind === "text" && !p.passes).map((p) => p.directive));
1790
1828
  for (const directive of failing) {
1791
1829
  const span = directive.spans.color;
@@ -1905,8 +1943,27 @@ var typeOf = (value) => {
1905
1943
  return "boolean";
1906
1944
  if (Array.isArray(value) && value.every((v) => typeof v === "string"))
1907
1945
  return "string[]";
1946
+ if (isCanvasShape(value))
1947
+ return "canvas";
1908
1948
  return null;
1909
1949
  };
1950
+ var isCanvasShape = (value) => {
1951
+ if (typeof value !== "object" || value === null || Array.isArray(value))
1952
+ return false;
1953
+ const keys = Object.keys(value);
1954
+ return keys.length > 0 && keys.every((k) => THEMES.includes(k));
1955
+ };
1956
+ var describeType = (want) => want === "canvas" ? 'an object such as { "light": "#ffffff", "dark": "#0d1117" }' : `a ${want}`;
1957
+ var checkCanvas = (where, rule, name, value) => {
1958
+ for (const side of THEMES) {
1959
+ if (!(side in value))
1960
+ continue;
1961
+ const problem = canvasColourProblem(value[side]);
1962
+ if (problem) {
1963
+ throw new RuleOptionError(where, rule.id, name, `option "${name}.${side}" of "${rule.id}" ${problem}: ${JSON.stringify(value[side])}`);
1964
+ }
1965
+ }
1966
+ };
1910
1967
  var checkOptions = (where, rule, options) => {
1911
1968
  const accepted = Object.keys(rule.options ?? {});
1912
1969
  for (const [name, value] of Object.entries(options)) {
@@ -1916,8 +1973,13 @@ var checkOptions = (where, rule, options) => {
1916
1973
  throw new RuleOptionError(where, rule.id, name, `rule "${rule.id}" has no option "${name}"; ${list}`);
1917
1974
  }
1918
1975
  if (typeOf(value) !== want) {
1919
- throw new RuleOptionError(where, rule.id, name, `option "${name}" of "${rule.id}" must be a ${want}`);
1976
+ throw new RuleOptionError(where, rule.id, name, `option "${name}" of "${rule.id}" must be ${describeType(want)}`);
1920
1977
  }
1978
+ if (want === "canvas")
1979
+ checkCanvas(where, rule, name, value);
1980
+ }
1981
+ if (options.profile === "mkdocs-material" && options.canvas !== undefined && rule.options?.canvas === "canvas") {
1982
+ throw new RuleOptionError(where, rule.id, "canvas", `option "canvas" of "${rule.id}" applies under the github profile only, and this rule sets profile mkdocs-material, whose page is Material's own`);
1921
1983
  }
1922
1984
  if (typeof options.preset === "string" && canonicalPreset(options.preset) === null) {
1923
1985
  throw new RuleOptionError(where, rule.id, "preset", `option "preset" of "${rule.id}" is not a known preset`);
@@ -1961,8 +2023,24 @@ var buildRegistry = (input) => {
1961
2023
  var BUILTIN = buildRegistry({ rules: RULES, fixOrder: FIX_ORDER, categories: BUILTIN_CATEGORIES });
1962
2024
 
1963
2025
  // src/check.ts
2026
+ var canvasName = (side, prefix) => prefix ? `${prefix}canvas-${side}` : `canvas.${side}`;
1964
2027
  var checkRunFlags = (flags, prefix = "") => {
1965
- const { preset, profile } = flags;
2028
+ const { preset, profile, canvas } = flags;
2029
+ for (const side of THEMES) {
2030
+ if (canvas?.[side] === undefined)
2031
+ continue;
2032
+ const problem = canvasColourProblem(canvas[side]);
2033
+ if (problem) {
2034
+ const name = canvasName(side, prefix);
2035
+ throw new FlagError(name, `${name} ${problem}: "${canvas[side]}"; give an opaque CSS colour, such as #ffffff`);
2036
+ }
2037
+ }
2038
+ const sides = THEMES.filter((side) => canvas?.[side] !== undefined);
2039
+ const first = sides[0];
2040
+ if (profile === "mkdocs-material" && first !== undefined) {
2041
+ const name = canvasName(first, prefix);
2042
+ throw new FlagError(name, `${name} applies under the github profile only; mkdocs-material scores Material's own page colours`);
2043
+ }
1966
2044
  if (preset !== undefined && canonicalPreset(preset) === null) {
1967
2045
  throw new FlagError(`${prefix}preset`, `${prefix}preset must be one of ${PRESET_NAMES.join(", ")}, not "${preset}"`);
1968
2046
  }
@@ -1979,6 +2057,17 @@ var optionsFor = (rule, configured, flags) => {
1979
2057
  }
1980
2058
  if (typeof options.preset === "string")
1981
2059
  options.preset = canonicalPreset(options.preset) ?? options.preset;
2060
+ const canvas = flags.canvas;
2061
+ if (canvas && THEMES.some((side) => canvas[side] !== undefined) && rule.options?.canvas === "canvas") {
2062
+ const configured2 = typeof options.canvas === "object" && options.canvas !== null ? options.canvas : {};
2063
+ const merged = { ...configured2 };
2064
+ for (const side of THEMES) {
2065
+ const value = canvas[side];
2066
+ if (value !== undefined)
2067
+ merged[side] = value;
2068
+ }
2069
+ options.canvas = merged;
2070
+ }
1982
2071
  return options;
1983
2072
  };
1984
2073
  var checkModel = async (doc, file, flags = {}, registry = BUILTIN) => {
@@ -2425,7 +2514,7 @@ var importModule = async (source, runtime) => {
2425
2514
  throw new PluginImportError(source.spec, message2(err));
2426
2515
  }
2427
2516
  };
2428
- var OPTION_TYPES = new Set(["number", "string", "boolean", "string[]"]);
2517
+ var OPTION_TYPES = new Set(["number", "string", "boolean", "string[]", "canvas"]);
2429
2518
  var RESERVED_OPTIONS = ["preset", "profile"];
2430
2519
  var checkRule = (spec, key, raw, own) => {
2431
2520
  const where = `rule "${key}"`;
@@ -2454,7 +2543,7 @@ var checkRule = (spec, key, raw, own) => {
2454
2543
  if (options !== undefined) {
2455
2544
  const valid = isRecord3(options) && Object.values(options).every((t) => OPTION_TYPES.has(t));
2456
2545
  if (!valid) {
2457
- throw new PluginContractError(spec, `${where} options must map names to number, string, boolean or string[]`);
2546
+ throw new PluginContractError(spec, `${where} options must map names to number, string, boolean, string[] or canvas`);
2458
2547
  }
2459
2548
  for (const name of RESERVED_OPTIONS) {
2460
2549
  if (name in options && options[name] !== "string") {
@@ -2721,7 +2810,7 @@ var setUp = async ({
2721
2810
 
2722
2811
  // src/cli.ts
2723
2812
  var SYNOPSIS = `usage: mermaidjs-lint <path...> [--fix] [--json] [--preset NAME] [--profile NAME] [--config FILE]
2724
- [--no-plugins | --lenient-plugins]
2813
+ [--canvas-light COLOUR] [--canvas-dark COLOUR] [--no-plugins | --lenient-plugins]
2725
2814
  mermaidjs-lint --list-rules
2726
2815
  mermaidjs-lint --validate-plugins [--json] [--config FILE]
2727
2816
  mermaidjs-lint --version | -h, --help`;
@@ -2747,6 +2836,10 @@ Examples of every rule, with fixes: https://jpeakai.github.io/jpai-mermaidjs-lin
2747
2836
  numeric threshold set in the config overrides both.
2748
2837
  --profile NAME sets how contrast is read: ${PROFILES.join(", ")}. It overrides a profile set in the config.
2749
2838
  auto reads mkdocs-material when any parent folder holds mkdocs.yml or mkdocs.yaml, else github.
2839
+ --canvas-light COLOUR and --canvas-dark COLOUR set the page a host draws in each theme, under the github
2840
+ profile only. A translucent fill, an edge label box and a sequence diagram's page-backed text are scored
2841
+ on it. Each is an opaque CSS colour such as #faf8f9, and a side not given keeps the config's, or GitHub's
2842
+ (#ffffff light, #0d1117 dark). A file scored under mkdocs-material refuses a canvas with a usage error.
2750
2843
  --json prints one JSON object instead of text lines.
2751
2844
  --fix applies every fix it can prove safe, then reports what remains.
2752
2845
  A fixer that is unsure leaves the text alone and the finding stays.
@@ -2770,6 +2863,8 @@ var parse2 = (argv) => parseArgs({
2770
2863
  help: { type: "boolean", short: "h", default: false },
2771
2864
  preset: { type: "string", short: "p" },
2772
2865
  profile: { type: "string" },
2866
+ "canvas-light": { type: "string" },
2867
+ "canvas-dark": { type: "string" },
2773
2868
  config: { type: "string" },
2774
2869
  "no-plugins": { type: "boolean", default: false },
2775
2870
  "lenient-plugins": { type: "boolean", default: false },
@@ -2875,7 +2970,16 @@ var run = async (argv, cwd) => {
2875
2970
  }
2876
2971
  const listing = values["list-rules"];
2877
2972
  const validating = values["validate-plugins"];
2878
- checkRunFlags({ preset: values.preset, profile: values.profile }, "--");
2973
+ const canvas = {
2974
+ ...values["canvas-light"] !== undefined && { light: values["canvas-light"] },
2975
+ ...values["canvas-dark"] !== undefined && { dark: values["canvas-dark"] }
2976
+ };
2977
+ const flags = {
2978
+ preset: values.preset,
2979
+ profile: values.profile,
2980
+ ...Object.keys(canvas).length > 0 && { canvas }
2981
+ };
2982
+ checkRunFlags(flags, "--");
2879
2983
  if (values["no-plugins"] && values["lenient-plugins"]) {
2880
2984
  throw new FlagError("--lenient-plugins", "--no-plugins and --lenient-plugins contradict each other");
2881
2985
  }
@@ -2921,7 +3025,6 @@ var run = async (argv, cwd) => {
2921
3025
  throw new FlagError("files", "no matching files");
2922
3026
  if (values.fix)
2923
3027
  await refuseOutsideLinks(files, root, cwd);
2924
- const flags = { preset: values.preset, profile: values.profile };
2925
3028
  const perFile = await Promise.all(files.map(async (file) => {
2926
3029
  let src = await readFile3(file, "utf8");
2927
3030
  if (values.fix) {