@jpeakai/mermaidjs-lint 0.2.0 → 0.3.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/README.md +7 -5
- package/dist/bin.js +174 -55
- package/dist/index.js +177 -55
- package/dist/testing.js +59 -23
- package/dist/types/bin.d.ts +2 -0
- package/dist/types/check.d.ts +10 -0
- package/dist/types/cli.d.ts +9 -0
- package/dist/types/config.d.ts +20 -0
- package/dist/types/errors.d.ts +88 -0
- package/dist/types/files.d.ts +8 -0
- package/dist/types/fix/engine.d.ts +10 -0
- package/dist/types/fix/verify.d.ts +12 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/model.d.ts +27 -0
- package/dist/types/parse/color.d.ts +28 -0
- package/dist/types/parse/contrast.d.ts +35 -0
- package/dist/types/parse/metrics.d.ts +48 -0
- package/dist/types/parse/stats.d.ts +24 -0
- package/dist/types/plugins/contract.d.ts +24 -0
- package/dist/types/plugins/discover.d.ts +20 -0
- package/dist/types/plugins/index.d.ts +19 -0
- package/dist/types/plugins/load.d.ts +14 -0
- package/dist/types/plugins/runtime.d.ts +6 -0
- package/dist/types/project.d.ts +18 -0
- package/dist/types/rules/complexity-node-count-acceptable-exceeded.d.ts +1 -0
- package/dist/types/rules/complexity-node-count-cognitive-limit.d.ts +1 -0
- package/dist/types/rules/complexity-node-count-hard-limit.d.ts +1 -0
- package/dist/types/rules/complexity-subgraph-nesting-too-deep.d.ts +2 -0
- package/dist/types/rules/complexity-visual-score-acceptable-exceeded.d.ts +1 -0
- package/dist/types/rules/complexity-visual-score-critical.d.ts +1 -0
- package/dist/types/rules/complexity.d.ts +12 -0
- package/dist/types/rules/contrast-border-below-ui-minimum.d.ts +2 -0
- package/dist/types/rules/contrast-directive-unauditable.d.ts +2 -0
- package/dist/types/rules/contrast-text-below-aa.d.ts +2 -0
- package/dist/types/rules/index.d.ts +3 -0
- package/dist/types/rules/parse-diagram-unparseable.d.ts +2 -0
- package/dist/types/rules/parse-fence-unterminated.d.ts +2 -0
- package/dist/types/rules/registry.d.ts +29 -0
- package/dist/types/rules/shared.d.ts +18 -0
- package/dist/types/rules/types.d.ts +67 -0
- package/dist/types/testing.d.ts +15 -0
- package/package.json +5 -4
- package/src/cli.ts +47 -15
- package/src/errors.ts +46 -0
- package/src/files.ts +21 -2
- package/src/fix/engine.ts +22 -10
- package/src/fix/verify.ts +6 -1
- package/src/index.ts +5 -3
- package/src/parse/stats.ts +39 -11
- package/src/plugins/contract.ts +4 -2
- package/src/plugins/discover.ts +38 -15
- package/src/plugins/index.ts +5 -3
- package/src/plugins/load.ts +32 -1
- package/src/project.ts +3 -1
package/dist/testing.js
CHANGED
|
@@ -547,12 +547,10 @@ function adaptMindmap(db) {
|
|
|
547
547
|
}
|
|
548
548
|
function adaptQuadrantChart(db) {
|
|
549
549
|
const data = callGetter(db, "getQuadrantData");
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
});
|
|
555
|
-
return { nodeIds: labels, edges: 0, subgraphNames: [], maxDepth: 0 };
|
|
550
|
+
const textOf = (t) => typeof t === "string" ? t : t?.text ?? "";
|
|
551
|
+
const quadrants = (data?.quadrants ?? []).map((q) => textOf(q.text)).filter((t) => t.trim() !== "");
|
|
552
|
+
const points = (data?.points ?? []).map((p, i) => textOf(p.text) || `point_${i}`);
|
|
553
|
+
return { nodeIds: [...quadrants, ...points], edges: 0, subgraphNames: [], maxDepth: 0 };
|
|
556
554
|
}
|
|
557
555
|
function adaptRequirement(db) {
|
|
558
556
|
const requirements = db.requirements instanceof Map ? db.requirements : new Map;
|
|
@@ -578,18 +576,30 @@ function adaptSankey(db) {
|
|
|
578
576
|
function adaptState(db) {
|
|
579
577
|
const nodes = db.nodes ?? [];
|
|
580
578
|
const edges = db.edges ?? [];
|
|
579
|
+
const groups = nodes.filter((n) => n.isGroup === true);
|
|
580
|
+
const parentOf = new Map(nodes.map((n) => [n.id ?? "", n.parentId]));
|
|
581
|
+
let maxDepth = 0;
|
|
582
|
+
for (const g of groups) {
|
|
583
|
+
let depth = 1;
|
|
584
|
+
const seen = new Set;
|
|
585
|
+
for (let cur = g.parentId;cur && !seen.has(cur); cur = parentOf.get(cur)) {
|
|
586
|
+
seen.add(cur);
|
|
587
|
+
depth++;
|
|
588
|
+
}
|
|
589
|
+
maxDepth = Math.max(maxDepth, depth);
|
|
590
|
+
}
|
|
581
591
|
return {
|
|
582
592
|
nodeIds: nodes.map((n) => n.id ?? ""),
|
|
583
593
|
edges: edges.length,
|
|
584
|
-
subgraphNames:
|
|
585
|
-
maxDepth
|
|
594
|
+
subgraphNames: groups.map((g) => g.id ?? ""),
|
|
595
|
+
maxDepth
|
|
586
596
|
};
|
|
587
597
|
}
|
|
588
598
|
function adaptTimeline(db) {
|
|
589
599
|
const tasks = callGetter(db, "getTasks") ?? [];
|
|
590
600
|
const sections = callGetter(db, "getSections") ?? [];
|
|
591
601
|
return {
|
|
592
|
-
nodeIds: tasks.
|
|
602
|
+
nodeIds: tasks.flatMap((t) => [t.task ?? "", ...(t.events ?? []).map((e) => `${t.task ?? ""}: ${e}`)]),
|
|
593
603
|
edges: 0,
|
|
594
604
|
subgraphNames: sections.map((s) => s.sectionName ?? s.section ?? ""),
|
|
595
605
|
maxDepth: sections.length > 0 ? 1 : 0
|
|
@@ -619,7 +629,10 @@ function adaptVenn(db) {
|
|
|
619
629
|
function adaptXychart(db) {
|
|
620
630
|
const data = callGetter(db, "getXYChartData");
|
|
621
631
|
const categories = data?.xAxis?.categories ?? [];
|
|
622
|
-
|
|
632
|
+
if (categories.length > 0)
|
|
633
|
+
return { nodeIds: categories, edges: 0, subgraphNames: [], maxDepth: 0 };
|
|
634
|
+
const longest = Math.max(0, ...(data?.plots ?? []).map((p) => p.data?.length ?? 0));
|
|
635
|
+
return { nodeIds: Array.from({ length: longest }, (_, i) => `x_${i}`), edges: 0, subgraphNames: [], maxDepth: 0 };
|
|
623
636
|
}
|
|
624
637
|
function subgraphNestingDepth(subGraphs) {
|
|
625
638
|
if (subGraphs.length === 0)
|
|
@@ -784,6 +797,15 @@ class RuleOptionError extends UsageError {
|
|
|
784
797
|
this.option = option;
|
|
785
798
|
}
|
|
786
799
|
}
|
|
800
|
+
class FixNotConvergingError extends MermaidLintError {
|
|
801
|
+
file;
|
|
802
|
+
rules;
|
|
803
|
+
constructor(file, passes, rules) {
|
|
804
|
+
super("fix-not-converging", `${file}: --fix did not converge after ${passes} passes; ${rules.join(", ")} kept proposing edits. A fixer must propose nothing once its edit is applied`);
|
|
805
|
+
this.file = file;
|
|
806
|
+
this.rules = rules;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
787
809
|
|
|
788
810
|
class PluginLoadError extends MermaidLintError {
|
|
789
811
|
source;
|
|
@@ -1663,13 +1685,17 @@ var sameDiagrams = async (before, after) => {
|
|
|
1663
1685
|
};
|
|
1664
1686
|
var verify = async (edit, before, after) => {
|
|
1665
1687
|
if (edit.expect.kind === "same-tree") {
|
|
1666
|
-
|
|
1688
|
+
if (!sameTree(before.tree, after.tree, {}))
|
|
1689
|
+
return "refuse";
|
|
1690
|
+
if (before.kind === "markdown" && after.kind === "markdown")
|
|
1691
|
+
return "accept";
|
|
1667
1692
|
}
|
|
1668
1693
|
return await sameDiagrams(before, after) ? "accept" : "refuse";
|
|
1669
1694
|
};
|
|
1670
1695
|
|
|
1671
1696
|
// src/fix/engine.ts
|
|
1672
1697
|
var MAX_PASSES = 1000;
|
|
1698
|
+
var RECENT_PASSES = 50;
|
|
1673
1699
|
var splice = (src, edits) => {
|
|
1674
1700
|
let out = src;
|
|
1675
1701
|
for (const e of [...edits].sort((a, b) => b.start - a.start))
|
|
@@ -1687,6 +1713,7 @@ var fixSourceReport = async (src, file, flags = {}, registry = BUILTIN) => {
|
|
|
1687
1713
|
const refused = [];
|
|
1688
1714
|
const refusedKeys = new Set;
|
|
1689
1715
|
let current = src;
|
|
1716
|
+
const keptBy = [];
|
|
1690
1717
|
for (let pass = 0;pass < MAX_PASSES; pass++) {
|
|
1691
1718
|
const doc = buildDocModel(current, kind);
|
|
1692
1719
|
const keyOf = (e) => `${e.rule}\x00${current.slice(e.start, e.end)}\x00${e.text}`;
|
|
@@ -1719,35 +1746,39 @@ var fixSourceReport = async (src, file, flags = {}, registry = BUILTIN) => {
|
|
|
1719
1746
|
continue;
|
|
1720
1747
|
if (edits.length > 1 && !overlaps(edits) && await attempt(edits)) {
|
|
1721
1748
|
progressed = true;
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1749
|
+
} else {
|
|
1750
|
+
for (const edit of edits) {
|
|
1751
|
+
if (await attempt([edit])) {
|
|
1752
|
+
progressed = true;
|
|
1753
|
+
break;
|
|
1754
|
+
}
|
|
1755
|
+
refusedKeys.add(keyOf(edit));
|
|
1756
|
+
refused.push(edit);
|
|
1728
1757
|
}
|
|
1729
|
-
refusedKeys.add(keyOf(edit));
|
|
1730
|
-
refused.push(edit);
|
|
1731
1758
|
}
|
|
1732
|
-
if (progressed)
|
|
1759
|
+
if (progressed) {
|
|
1760
|
+
keptBy.push(rule.id);
|
|
1733
1761
|
break;
|
|
1762
|
+
}
|
|
1734
1763
|
}
|
|
1735
1764
|
if (!progressed)
|
|
1736
1765
|
return { output: current, applied, refused };
|
|
1737
1766
|
}
|
|
1738
|
-
|
|
1767
|
+
const lingering = [...new Set(keptBy.slice(-RECENT_PASSES))].sort();
|
|
1768
|
+
throw new FixNotConvergingError(file, MAX_PASSES, lingering);
|
|
1739
1769
|
};
|
|
1740
1770
|
|
|
1741
1771
|
// src/plugins/contract.ts
|
|
1742
1772
|
var API_VERSION = 1;
|
|
1743
1773
|
var CATEGORY_WORD = /^[a-z]+$/;
|
|
1744
|
-
var NAMESPACE = /^[a-z][a-z0-9-]*$/;
|
|
1745
|
-
var RULE_KEY = /^[a-z][a-z0-9-]*$/;
|
|
1774
|
+
var NAMESPACE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
1775
|
+
var RULE_KEY = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
1746
1776
|
|
|
1747
1777
|
// src/plugins/load.ts
|
|
1748
1778
|
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1749
1779
|
var message2 = (err) => err instanceof Error ? err.message : String(err);
|
|
1750
1780
|
var OPTION_TYPES = new Set(["number", "string", "boolean", "string[]"]);
|
|
1781
|
+
var RESERVED_OPTIONS = ["preset", "profile"];
|
|
1751
1782
|
var checkRule = (spec, key, raw, own) => {
|
|
1752
1783
|
const where = `rule "${key}"`;
|
|
1753
1784
|
if (!isRecord(raw))
|
|
@@ -1777,6 +1808,11 @@ var checkRule = (spec, key, raw, own) => {
|
|
|
1777
1808
|
if (!valid) {
|
|
1778
1809
|
throw new PluginContractError(spec, `${where} options must map names to number, string, boolean or string[]`);
|
|
1779
1810
|
}
|
|
1811
|
+
for (const name of RESERVED_OPTIONS) {
|
|
1812
|
+
if (name in options && options[name] !== "string") {
|
|
1813
|
+
throw new PluginContractError(spec, `${where} declares option "${name}" as ${String(options[name])}, but "${name}" is reserved for the built-in ${name}, which is a string set by --${name}; declare it as "string" to follow the run's ${name}, or pick another name`);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1780
1816
|
}
|
|
1781
1817
|
return raw;
|
|
1782
1818
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type DocModel } from "./model.ts";
|
|
2
|
+
import { type Registry } from "./rules/registry.ts";
|
|
3
|
+
import type { Finding, Rule, RuleOptions } from "./rules/types.ts";
|
|
4
|
+
export interface RunFlags {
|
|
5
|
+
preset?: string;
|
|
6
|
+
profile?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const optionsFor: (rule: Rule, configured: RuleOptions | undefined, flags: RunFlags) => RuleOptions;
|
|
9
|
+
export declare const checkModel: (doc: DocModel, file: string, flags?: RunFlags, registry?: Registry) => Promise<Finding[]>;
|
|
10
|
+
export declare const checkMarkdown: (src: string, file: string, flags?: RunFlags, registry?: Registry) => Promise<Finding[]>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PluginFailure } from "./plugins/index.ts";
|
|
2
|
+
import type { LoadedSource, Registry } from "./rules/registry.ts";
|
|
3
|
+
import { type Finding } from "./rules/types.ts";
|
|
4
|
+
export declare const loadedLine: (sources: LoadedSource[], skipped: string[]) => string | null;
|
|
5
|
+
export declare const skippedLines: (failures: PluginFailure[], ignored: string[]) => string[];
|
|
6
|
+
export declare const listRules: (registry: Registry) => string;
|
|
7
|
+
export declare const reportLine: (f: Finding, file: string) => string;
|
|
8
|
+
export declare const describeError: (err: unknown) => string;
|
|
9
|
+
export declare const main: (argv?: string[], cwd?: string) => Promise<number>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { UsageError } from "./errors.ts";
|
|
2
|
+
import type { RuleOptions } from "./rules/types.ts";
|
|
3
|
+
export { UsageError };
|
|
4
|
+
export type Severity = "error" | "off";
|
|
5
|
+
export type PluginLoading = "strict" | "lenient";
|
|
6
|
+
export interface RuleSetting {
|
|
7
|
+
severity: Severity;
|
|
8
|
+
options: RuleOptions;
|
|
9
|
+
}
|
|
10
|
+
export interface Config {
|
|
11
|
+
plugins: string[] | false;
|
|
12
|
+
pluginLoading: PluginLoading;
|
|
13
|
+
rules: Map<string, RuleSetting>;
|
|
14
|
+
file: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare const NO_CONFIG: Config;
|
|
17
|
+
export declare const CONFIG_FILES: readonly ["mermaidjs-lint.config.json", "mermaidjs-lint.config.mjs"];
|
|
18
|
+
export declare const parseConfig: (file: string, raw: unknown) => Config;
|
|
19
|
+
export declare const findConfig: (root: string) => Promise<string | null>;
|
|
20
|
+
export declare const loadConfig: (file: string) => Promise<Config>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export declare class MermaidLintError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
constructor(code: string, message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class UsageError extends MermaidLintError {
|
|
6
|
+
constructor(message: string, code?: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class FlagError extends UsageError {
|
|
9
|
+
readonly flag: string;
|
|
10
|
+
constructor(flag: string, message: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class ConfigFileError extends UsageError {
|
|
13
|
+
readonly file: string;
|
|
14
|
+
constructor(file: string, message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class ConfigNotFoundError extends UsageError {
|
|
17
|
+
readonly path: string;
|
|
18
|
+
constructor(path: string);
|
|
19
|
+
}
|
|
20
|
+
export declare class ConfigCodeError extends UsageError {
|
|
21
|
+
readonly file: string;
|
|
22
|
+
constructor(file: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class AmbiguousConfigError extends UsageError {
|
|
25
|
+
readonly files: string[];
|
|
26
|
+
constructor(root: string, files: string[]);
|
|
27
|
+
}
|
|
28
|
+
export declare class ConfigShapeError extends UsageError {
|
|
29
|
+
readonly file: string;
|
|
30
|
+
readonly key: string | null;
|
|
31
|
+
constructor(file: string, message: string, key?: string | null);
|
|
32
|
+
}
|
|
33
|
+
export declare class RuleSettingError extends UsageError {
|
|
34
|
+
readonly file: string;
|
|
35
|
+
readonly rule: string;
|
|
36
|
+
constructor(file: string, rule: string, message: string);
|
|
37
|
+
}
|
|
38
|
+
export declare class UnknownRuleError extends UsageError {
|
|
39
|
+
readonly file: string;
|
|
40
|
+
readonly rule: string;
|
|
41
|
+
readonly known: string[];
|
|
42
|
+
constructor(file: string, rule: string, known: string[]);
|
|
43
|
+
}
|
|
44
|
+
export declare class RuleOptionError extends UsageError {
|
|
45
|
+
readonly file: string;
|
|
46
|
+
readonly rule: string;
|
|
47
|
+
readonly option: string;
|
|
48
|
+
constructor(file: string, rule: string, option: string, message: string);
|
|
49
|
+
}
|
|
50
|
+
export declare class FixOutsideRootError extends UsageError {
|
|
51
|
+
readonly file: string;
|
|
52
|
+
readonly target: string;
|
|
53
|
+
constructor(file: string, target: string, root: string);
|
|
54
|
+
}
|
|
55
|
+
export declare class PackageJsonError extends MermaidLintError {
|
|
56
|
+
readonly file: string;
|
|
57
|
+
constructor(file: string);
|
|
58
|
+
}
|
|
59
|
+
export declare class FixNotConvergingError extends MermaidLintError {
|
|
60
|
+
readonly file: string;
|
|
61
|
+
readonly rules: string[];
|
|
62
|
+
constructor(file: string, passes: number, rules: string[]);
|
|
63
|
+
}
|
|
64
|
+
export declare class PluginLoadError extends MermaidLintError {
|
|
65
|
+
readonly source: string;
|
|
66
|
+
constructor(source: string, reason: string, code?: string);
|
|
67
|
+
}
|
|
68
|
+
export declare class PluginImportError extends PluginLoadError {
|
|
69
|
+
constructor(source: string, reason: string);
|
|
70
|
+
}
|
|
71
|
+
export declare class PluginContractError extends PluginLoadError {
|
|
72
|
+
constructor(source: string, reason: string);
|
|
73
|
+
}
|
|
74
|
+
export declare class PluginConflictError extends PluginLoadError {
|
|
75
|
+
readonly other: string;
|
|
76
|
+
constructor(source: string, other: string, reason: string);
|
|
77
|
+
}
|
|
78
|
+
export declare class PluginNotInstalledError extends PluginLoadError {
|
|
79
|
+
readonly root: string;
|
|
80
|
+
constructor(source: string, root: string);
|
|
81
|
+
}
|
|
82
|
+
export declare class PluginSourceError extends PluginLoadError {
|
|
83
|
+
constructor(source: string, reason: string);
|
|
84
|
+
}
|
|
85
|
+
export declare class PluginFixerError extends MermaidLintError {
|
|
86
|
+
readonly rule: string;
|
|
87
|
+
constructor(rule: string, reason: string);
|
|
88
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const DIAGRAM_FILE_EXTS: Set<string>;
|
|
2
|
+
export declare const SKIP_DIRS: Set<string>;
|
|
3
|
+
export interface Collected {
|
|
4
|
+
files: string[];
|
|
5
|
+
unreadable: string[];
|
|
6
|
+
symlinks: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare const collectFiles: (paths: string[]) => Collected;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type RunFlags } from "../check.ts";
|
|
2
|
+
import { type Registry } from "../rules/registry.ts";
|
|
3
|
+
import type { Edit } from "../rules/types.ts";
|
|
4
|
+
export interface FixReport {
|
|
5
|
+
output: string;
|
|
6
|
+
applied: Edit[];
|
|
7
|
+
refused: Edit[];
|
|
8
|
+
}
|
|
9
|
+
export declare const fixSourceReport: (src: string, file: string, flags?: RunFlags, registry?: Registry) => Promise<FixReport>;
|
|
10
|
+
export declare const fixSource: (src: string, file: string, flags?: RunFlags, registry?: Registry) => Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Node } from "mdast";
|
|
2
|
+
import type { DocModel } from "../model.ts";
|
|
3
|
+
import type { Edit } from "../rules/types.ts";
|
|
4
|
+
type Plain = {
|
|
5
|
+
[k: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
export declare const normalise: (node: Node, opts?: {
|
|
8
|
+
blankDiagrams?: boolean;
|
|
9
|
+
}) => Plain;
|
|
10
|
+
export type Verdict = "accept" | "refuse";
|
|
11
|
+
export declare const verify: (edit: Edit, before: DocModel, after: DocModel) => Promise<Verdict>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { checkMarkdown, checkModel, type RunFlags } from "./check.ts";
|
|
2
|
+
export { main } from "./cli.ts";
|
|
3
|
+
export { type Config, loadConfig, type PluginLoading, parseConfig, type RuleSetting, type Severity } from "./config.ts";
|
|
4
|
+
export * from "./errors.ts";
|
|
5
|
+
export { type Collected, collectFiles } from "./files.ts";
|
|
6
|
+
export { type FixReport, fixSource, fixSourceReport } from "./fix/engine.ts";
|
|
7
|
+
export { buildDocModel, DIAGRAM_EXTS, type Diagram, type DocModel, documentKind } from "./model.ts";
|
|
8
|
+
export type { ContrastAssessment, StyleDirective, ValueSpan } from "./parse/color.ts";
|
|
9
|
+
export { PRESETS, type Preset, type ThresholdConfig, thresholdsFrom } from "./parse/metrics.ts";
|
|
10
|
+
export { type DiagramStats, detectKeyword, extractStats } from "./parse/stats.ts";
|
|
11
|
+
export type { Plugin, PluginEdit, PluginFinding, PluginMeta, PluginRule } from "./plugins/contract.ts";
|
|
12
|
+
export type { SourceKind } from "./plugins/discover.ts";
|
|
13
|
+
export type { PluginFailure } from "./plugins/index.ts";
|
|
14
|
+
export { findProjectRoot, type Setup, type SetupOptions, setUp } from "./project.ts";
|
|
15
|
+
export { FIX_ORDER, RULES } from "./rules/index.ts";
|
|
16
|
+
export { BUILTIN, BUILTIN_CATEGORIES, buildRegistry, type LoadedSource, type Registry, type RegistryInput, } from "./rules/registry.ts";
|
|
17
|
+
export type { Category, CheckContext, CoreRuleId, Edit, Expectation, Finding, FixContext, Helpers, OptionSpec, OptionType, PluginRuleId, Rule, RuleContext, RuleId, RuleOptions, } from "./rules/types.ts";
|
|
18
|
+
export { CATEGORIES, RULE } from "./rules/types.ts";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Root } from "mdast";
|
|
2
|
+
import { type StyleDirective, type ValueSpan } from "./parse/color.ts";
|
|
3
|
+
import { type DiagramStats } from "./parse/stats.ts";
|
|
4
|
+
export interface Diagram {
|
|
5
|
+
index: number;
|
|
6
|
+
source: string;
|
|
7
|
+
keyword: string | null;
|
|
8
|
+
startLine: number;
|
|
9
|
+
endLine: number;
|
|
10
|
+
firstLine: number;
|
|
11
|
+
terminated: boolean;
|
|
12
|
+
endOffset: number;
|
|
13
|
+
directives: StyleDirective[];
|
|
14
|
+
offsetOf: (span: ValueSpan) => number | null;
|
|
15
|
+
stats: () => Promise<DiagramStats>;
|
|
16
|
+
}
|
|
17
|
+
export interface DocModel {
|
|
18
|
+
src: string;
|
|
19
|
+
kind: "markdown" | "diagram";
|
|
20
|
+
tree: Root;
|
|
21
|
+
diagrams: Diagram[];
|
|
22
|
+
}
|
|
23
|
+
export declare const parse: (src: string) => Root;
|
|
24
|
+
export declare const DIAGRAM_EXTS: readonly [".mmd", ".mermaid"];
|
|
25
|
+
export declare const documentKind: (file: string) => "markdown" | "diagram";
|
|
26
|
+
export declare const buildDocModel: (src: string, kind?: "markdown" | "diagram") => DocModel;
|
|
27
|
+
export declare const isMarkdownFile: (file: string) => boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type WcagRating = "AAA" | "AA" | "AA Large" | "Fail";
|
|
2
|
+
export interface ContrastAssessment {
|
|
3
|
+
foreground: string;
|
|
4
|
+
background: string;
|
|
5
|
+
ratio: number;
|
|
6
|
+
rating: WcagRating;
|
|
7
|
+
apca_lc: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const wcagRatio: (fg: string, bg: string) => number;
|
|
10
|
+
export declare const apcaLc: (fg: string, bg: string) => number;
|
|
11
|
+
export declare const alphaOf: (color: string) => number;
|
|
12
|
+
export declare const compositeOver: (fg: string, bg: string) => string;
|
|
13
|
+
export declare const wcagRating: (ratio: number) => WcagRating;
|
|
14
|
+
export declare const wcagAssess: (fg: string, bg: string) => ContrastAssessment;
|
|
15
|
+
export interface ValueSpan {
|
|
16
|
+
line: number;
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
}
|
|
20
|
+
export interface StyleDirective {
|
|
21
|
+
kind: "classDef" | "style" | "linkStyle" | "inlineClass";
|
|
22
|
+
selector: string;
|
|
23
|
+
class_name?: string;
|
|
24
|
+
properties: Record<string, string>;
|
|
25
|
+
spans: Record<string, ValueSpan>;
|
|
26
|
+
line: number;
|
|
27
|
+
}
|
|
28
|
+
export declare const extractStyleDirectives: (source: string) => StyleDirective[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ContrastAssessment, type StyleDirective } from "./color.ts";
|
|
2
|
+
export type Profile = "github" | "mkdocs-material";
|
|
3
|
+
export type Theme = "light" | "dark";
|
|
4
|
+
export type PairKind = "text" | "border";
|
|
5
|
+
export type ErRow = "odd" | "even";
|
|
6
|
+
export declare const PROFILES: readonly ["auto", "github", "mkdocs-material"];
|
|
7
|
+
export declare const edgeLabelBackground: (theme: Theme) => string;
|
|
8
|
+
export interface ContrastPair {
|
|
9
|
+
kind: PairKind;
|
|
10
|
+
selector: string;
|
|
11
|
+
directive: StyleDirective;
|
|
12
|
+
foreground: string;
|
|
13
|
+
background: string;
|
|
14
|
+
line: number;
|
|
15
|
+
assessment: ContrastAssessment;
|
|
16
|
+
passes: boolean;
|
|
17
|
+
theme?: Theme;
|
|
18
|
+
row?: ErRow;
|
|
19
|
+
advisory?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface SkippedDirective {
|
|
22
|
+
selector: string;
|
|
23
|
+
line: number;
|
|
24
|
+
reason: string;
|
|
25
|
+
blocking?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface ContrastResult {
|
|
28
|
+
pairs: ContrastPair[];
|
|
29
|
+
skipped: SkippedDirective[];
|
|
30
|
+
}
|
|
31
|
+
export declare const scoreGithub: (directives: StyleDirective[]) => ContrastResult;
|
|
32
|
+
export declare const scoreMkdocs: (directives: StyleDirective[]) => ContrastResult;
|
|
33
|
+
export declare const scoreEr: (directives: StyleDirective[]) => ContrastResult;
|
|
34
|
+
export declare const scoreForProfile: (directives: StyleDirective[], profile: Profile, keyword: string | null) => ContrastResult;
|
|
35
|
+
export declare const detectProfile: (filePath: string) => Profile;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DiagramStats } from "./stats.ts";
|
|
2
|
+
export interface Preset {
|
|
3
|
+
node_ideal: number;
|
|
4
|
+
node_acceptable: number;
|
|
5
|
+
node_complex: number;
|
|
6
|
+
node_hard_limit: number;
|
|
7
|
+
vcs_ideal: number;
|
|
8
|
+
vcs_acceptable: number;
|
|
9
|
+
vcs_complex: number;
|
|
10
|
+
vcs_critical: number;
|
|
11
|
+
node_target: number;
|
|
12
|
+
vcs_target: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const PRESETS: Record<string, Preset>;
|
|
15
|
+
export declare const DEFAULT_PRESET = "high-density";
|
|
16
|
+
export interface ThresholdConfig extends Preset {
|
|
17
|
+
edge_weight: number;
|
|
18
|
+
subgraph_weight: number;
|
|
19
|
+
depth_weight: number;
|
|
20
|
+
preset_name: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const THRESHOLD_OPTIONS: {
|
|
23
|
+
readonly nodeIdeal: "node_ideal";
|
|
24
|
+
readonly nodeAcceptable: "node_acceptable";
|
|
25
|
+
readonly nodeComplex: "node_complex";
|
|
26
|
+
readonly nodeHardLimit: "node_hard_limit";
|
|
27
|
+
readonly vcsIdeal: "vcs_ideal";
|
|
28
|
+
readonly vcsAcceptable: "vcs_acceptable";
|
|
29
|
+
readonly vcsComplex: "vcs_complex";
|
|
30
|
+
readonly vcsCritical: "vcs_critical";
|
|
31
|
+
readonly nodeTarget: "node_target";
|
|
32
|
+
readonly vcsTarget: "vcs_target";
|
|
33
|
+
readonly edgeWeight: "edge_weight";
|
|
34
|
+
readonly subgraphWeight: "subgraph_weight";
|
|
35
|
+
readonly depthWeight: "depth_weight";
|
|
36
|
+
};
|
|
37
|
+
export declare const PRESET_NAMES: string[];
|
|
38
|
+
export declare const canonicalPreset: (name: string) => string | null;
|
|
39
|
+
export declare const configFromPreset: (name: string) => ThresholdConfig;
|
|
40
|
+
export declare const thresholdsFrom: (options: Readonly<Record<string, unknown>>) => ThresholdConfig;
|
|
41
|
+
export interface ComplexityMetrics {
|
|
42
|
+
visual_complexity_score: number;
|
|
43
|
+
edge_density: number;
|
|
44
|
+
cyclomatic_complexity: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const calculateComplexity: (stats: DiagramStats, config: ThresholdConfig) => ComplexityMetrics;
|
|
47
|
+
export declare const parseFailed: (content: string, stats: DiagramStats) => boolean;
|
|
48
|
+
export declare const sourceLines: (content: string) => number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface DiagramStats {
|
|
2
|
+
nodes: number;
|
|
3
|
+
edges: number;
|
|
4
|
+
subgraphs: number;
|
|
5
|
+
max_subgraph_depth: number;
|
|
6
|
+
node_ids: string[];
|
|
7
|
+
subgraph_names: string[];
|
|
8
|
+
parser_used: "langium" | "mermaid-core";
|
|
9
|
+
diagram_type: string;
|
|
10
|
+
error: string | null;
|
|
11
|
+
}
|
|
12
|
+
type MermaidStats = DiagramStats;
|
|
13
|
+
export declare function detectKeyword(content: string): string | null;
|
|
14
|
+
export declare function extractStats(content: string): Promise<MermaidStats>;
|
|
15
|
+
export declare const parserReason: (err: unknown) => string;
|
|
16
|
+
export declare function indentTreeStats(items: Array<{
|
|
17
|
+
label: string;
|
|
18
|
+
indent: number;
|
|
19
|
+
}>): {
|
|
20
|
+
labels: string[];
|
|
21
|
+
edges: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Awaitable, CheckContext, Edit, Finding, FixContext, OptionSpec } from "../rules/types.ts";
|
|
2
|
+
export declare const API_VERSION = 1;
|
|
3
|
+
export type PluginFinding = Pick<Finding, "line" | "message"> & Partial<Pick<Finding, "endLine" | "remediation">>;
|
|
4
|
+
export type PluginEdit = Omit<Edit, "rule">;
|
|
5
|
+
export interface PluginRule {
|
|
6
|
+
category: string;
|
|
7
|
+
summary: string;
|
|
8
|
+
options?: OptionSpec;
|
|
9
|
+
check: (ctx: CheckContext) => Awaitable<PluginFinding[]>;
|
|
10
|
+
fix?: (ctx: FixContext) => Awaitable<PluginEdit[]>;
|
|
11
|
+
}
|
|
12
|
+
export interface PluginMeta {
|
|
13
|
+
name: string;
|
|
14
|
+
namespace: string;
|
|
15
|
+
apiVersion: number;
|
|
16
|
+
categories?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export interface Plugin {
|
|
19
|
+
meta: PluginMeta;
|
|
20
|
+
rules: Record<string, PluginRule>;
|
|
21
|
+
}
|
|
22
|
+
export declare const CATEGORY_WORD: RegExp;
|
|
23
|
+
export declare const NAMESPACE: RegExp;
|
|
24
|
+
export declare const RULE_KEY: RegExp;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Config } from "../config.ts";
|
|
2
|
+
import { PluginLoadError } from "../errors.ts";
|
|
3
|
+
export type SourceKind = "local" | "package" | "config";
|
|
4
|
+
export interface PluginSource {
|
|
5
|
+
kind: SourceKind;
|
|
6
|
+
spec: string;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
export interface UnresolvedSource {
|
|
10
|
+
kind: SourceKind;
|
|
11
|
+
error: PluginLoadError;
|
|
12
|
+
}
|
|
13
|
+
export interface Discovery {
|
|
14
|
+
sources: PluginSource[];
|
|
15
|
+
failures: UnresolvedSource[];
|
|
16
|
+
}
|
|
17
|
+
export declare const LOCAL_RULES: string;
|
|
18
|
+
export declare const PACKAGE_PATTERN: RegExp;
|
|
19
|
+
export declare const resolvePackage: (root: string, name: string) => Promise<string>;
|
|
20
|
+
export declare const discoverSources: (root: string, config: Config, pluginsOff?: boolean) => Promise<Discovery>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config } from "../config.ts";
|
|
2
|
+
import { PluginLoadError } from "../errors.ts";
|
|
3
|
+
import { type LoadedSource } from "../rules/registry.ts";
|
|
4
|
+
import type { Rule } from "../rules/types.ts";
|
|
5
|
+
import { type SourceKind } from "./discover.ts";
|
|
6
|
+
export type PluginMode = "off" | "strict" | "lenient" | "collect";
|
|
7
|
+
export interface PluginFailure {
|
|
8
|
+
source: string;
|
|
9
|
+
kind: SourceKind;
|
|
10
|
+
error: PluginLoadError;
|
|
11
|
+
}
|
|
12
|
+
export interface PluginSet {
|
|
13
|
+
rules: Rule[];
|
|
14
|
+
categories: Map<string, string>;
|
|
15
|
+
sources: LoadedSource[];
|
|
16
|
+
skipped: string[];
|
|
17
|
+
failures: PluginFailure[];
|
|
18
|
+
}
|
|
19
|
+
export declare const loadPlugins: (root: string, config: Config, mode: PluginMode) => Promise<PluginSet>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PluginLoadError } from "../errors.ts";
|
|
2
|
+
import type { Rule } from "../rules/types.ts";
|
|
3
|
+
import { type Plugin, type PluginRule } from "./contract.ts";
|
|
4
|
+
import type { PluginSource } from "./discover.ts";
|
|
5
|
+
import { type RuntimeInfo } from "./runtime.ts";
|
|
6
|
+
export { PluginLoadError };
|
|
7
|
+
export declare const parsePlugin: (spec: string, raw: unknown, reserved: ReadonlySet<string>) => Plugin;
|
|
8
|
+
export declare const loadPackage: (source: PluginSource, reserved: ReadonlySet<string>) => Promise<Plugin>;
|
|
9
|
+
export interface LocalLoad {
|
|
10
|
+
plugin: Plugin | null;
|
|
11
|
+
failures: PluginLoadError[];
|
|
12
|
+
}
|
|
13
|
+
export declare const loadLocal: (sources: PluginSource[], runtime?: RuntimeInfo) => Promise<LocalLoad>;
|
|
14
|
+
export declare const toRule: (namespace: string, key: string, rule: PluginRule) => Rule;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface RuntimeInfo {
|
|
2
|
+
versions: Record<string, string | undefined>;
|
|
3
|
+
features: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
export declare const canImportTypeScript: (runtime?: RuntimeInfo) => boolean;
|
|
6
|
+
export declare const TYPESCRIPT_HELP = "TypeScript cannot be imported by this runtime. Run with Bun (bunx --bun @jpeakai/mermaidjs-lint), use Node 22.18 or newer, or write a .js or .mjs file";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type PluginFailure } from "./plugins/index.ts";
|
|
2
|
+
import { type Registry } from "./rules/registry.ts";
|
|
3
|
+
export declare const LOCAL_DIR = ".mermaidjs-lint";
|
|
4
|
+
export declare const findProjectRoot: (cwd: string) => Promise<string>;
|
|
5
|
+
export interface SetupOptions {
|
|
6
|
+
cwd: string;
|
|
7
|
+
configPath?: string;
|
|
8
|
+
noPlugins?: boolean;
|
|
9
|
+
lenient?: boolean;
|
|
10
|
+
collect?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface Setup {
|
|
13
|
+
root: string;
|
|
14
|
+
registry: Registry;
|
|
15
|
+
skipped: string[];
|
|
16
|
+
failures: PluginFailure[];
|
|
17
|
+
}
|
|
18
|
+
export declare const setUp: ({ cwd, configPath, noPlugins, lenient, collect, }: SetupOptions) => Promise<Setup>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const complexityNodeCountAcceptableExceeded: import("./types.ts").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const complexityNodeCountCognitiveLimit: import("./types.ts").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const complexityNodeCountHardLimit: import("./types.ts").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const complexityVisualScoreAcceptableExceeded: import("./types.ts").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const complexityVisualScoreCritical: import("./types.ts").Rule;
|