@amritk/lint 0.0.0 → 0.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.
Files changed (75) hide show
  1. package/dist/core/document.d.ts +19 -0
  2. package/dist/core/document.js +11 -0
  3. package/dist/core/formats.d.ts +9 -0
  4. package/dist/core/formats.js +14 -0
  5. package/dist/core/glob.d.ts +4 -0
  6. package/dist/core/glob.js +48 -0
  7. package/dist/core/index.d.ts +11 -0
  8. package/dist/core/index.js +11 -0
  9. package/dist/core/jsonpath.d.ts +59 -0
  10. package/dist/core/jsonpath.js +415 -0
  11. package/dist/core/lint.d.ts +57 -0
  12. package/dist/core/lint.js +82 -0
  13. package/dist/core/plugin.d.ts +59 -0
  14. package/dist/core/plugin.js +25 -0
  15. package/dist/core/pointers.d.ts +35 -0
  16. package/dist/core/pointers.js +169 -0
  17. package/dist/core/ruleset.d.ts +52 -0
  18. package/dist/core/ruleset.js +170 -0
  19. package/dist/core/runner.d.ts +21 -0
  20. package/dist/core/runner.js +222 -0
  21. package/dist/core/types.d.ts +170 -0
  22. package/dist/core/types.js +1 -0
  23. package/dist/core/validate-ruleset.d.ts +14 -0
  24. package/dist/core/validate-ruleset.js +105 -0
  25. package/dist/fix/apply.d.ts +21 -0
  26. package/dist/fix/apply.js +51 -0
  27. package/dist/fix/index.d.ts +3 -0
  28. package/dist/fix/index.js +2 -0
  29. package/dist/fix/plugin.d.ts +18 -0
  30. package/dist/fix/plugin.js +21 -0
  31. package/dist/fix/types.d.ts +39 -0
  32. package/dist/fix/types.js +0 -0
  33. package/dist/functions/alphabetical.d.ts +8 -0
  34. package/dist/functions/alphabetical.js +28 -0
  35. package/dist/functions/casing.d.ts +14 -0
  36. package/dist/functions/casing.js +30 -0
  37. package/dist/functions/defined.d.ts +3 -0
  38. package/dist/functions/defined.js +6 -0
  39. package/dist/functions/enumeration.d.ts +5 -0
  40. package/dist/functions/enumeration.js +10 -0
  41. package/dist/functions/falsy.d.ts +3 -0
  42. package/dist/functions/falsy.js +6 -0
  43. package/dist/functions/index.d.ts +16 -0
  44. package/dist/functions/index.js +42 -0
  45. package/dist/functions/length.d.ts +6 -0
  46. package/dist/functions/length.js +27 -0
  47. package/dist/functions/pattern.d.ts +6 -0
  48. package/dist/functions/pattern.js +20 -0
  49. package/dist/functions/schema.d.ts +8 -0
  50. package/dist/functions/schema.js +36 -0
  51. package/dist/functions/truthy.d.ts +3 -0
  52. package/dist/functions/truthy.js +6 -0
  53. package/dist/functions/typed-enum.d.ts +3 -0
  54. package/dist/functions/typed-enum.js +34 -0
  55. package/dist/functions/undefined.d.ts +6 -0
  56. package/dist/functions/undefined.js +9 -0
  57. package/dist/functions/unreferenced-reusable-object.d.ts +8 -0
  58. package/dist/functions/unreferenced-reusable-object.js +37 -0
  59. package/dist/functions/xor.d.ts +7 -0
  60. package/dist/functions/xor.js +11 -0
  61. package/dist/index.d.ts +89 -0
  62. package/dist/index.js +168 -0
  63. package/dist/parsers/edit-model.d.ts +69 -0
  64. package/dist/parsers/edit-model.js +326 -0
  65. package/dist/parsers/index.d.ts +18 -0
  66. package/dist/parsers/index.js +21 -0
  67. package/dist/parsers/json.d.ts +3 -0
  68. package/dist/parsers/json.js +38 -0
  69. package/dist/parsers/lines.d.ts +13 -0
  70. package/dist/parsers/lines.js +28 -0
  71. package/dist/parsers/types.d.ts +50 -0
  72. package/dist/parsers/types.js +8 -0
  73. package/dist/parsers/yaml.d.ts +6 -0
  74. package/dist/parsers/yaml.js +65 -0
  75. package/package.json +3 -4
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Builds a {@link LineMap} for `source`. The line-start offsets are precomputed
3
+ * once so each `positionAt` lookup is a binary search rather than a re-scan.
4
+ */
5
+ export const createLineMap = (source) => {
6
+ const length = source.length;
7
+ // Offset at which each line starts. lineStarts[0] === 0.
8
+ const lineStarts = [0];
9
+ for (let i = 0; i < source.length; i++) {
10
+ if (source.charCodeAt(i) === 10 /* \n */)
11
+ lineStarts.push(i + 1);
12
+ }
13
+ const positionAt = (offset) => {
14
+ const clamped = Math.max(0, Math.min(offset, length));
15
+ // Binary search for the last line start <= clamped.
16
+ let low = 0;
17
+ let high = lineStarts.length - 1;
18
+ while (low < high) {
19
+ const mid = (low + high + 1) >> 1;
20
+ if ((lineStarts[mid] ?? 0) <= clamped)
21
+ low = mid;
22
+ else
23
+ high = mid - 1;
24
+ }
25
+ return { line: low, character: clamped - (lineStarts[low] ?? 0) };
26
+ };
27
+ return { positionAt };
28
+ };
@@ -0,0 +1,50 @@
1
+ /** A path into a parsed document: object keys and array indices from the root. */
2
+ export type JsonPath = (string | number)[];
3
+ /** A zero-based line/character position, matching LSP and Linter conventions. */
4
+ export type IPosition = {
5
+ /** Zero-based line number. */
6
+ line: number;
7
+ /** Zero-based character offset within the line. */
8
+ character: number;
9
+ };
10
+ /** An inclusive-start, exclusive-end span between two positions. */
11
+ export type IRange = {
12
+ start: IPosition;
13
+ end: IPosition;
14
+ };
15
+ /** A resolved source location — currently just the range a node occupies. */
16
+ export type ILocation = {
17
+ range: IRange;
18
+ };
19
+ /** Severity levels, ordered most-to-least severe to match LSP's numeric scale. */
20
+ export declare enum DiagnosticSeverity {
21
+ Error = 0,
22
+ Warning = 1,
23
+ Information = 2,
24
+ Hint = 3
25
+ }
26
+ /** A problem reported by the parser itself (e.g. a syntax or duplicate-key error). */
27
+ export type IDiagnostic = {
28
+ code?: string | number;
29
+ message: string;
30
+ path?: JsonPath;
31
+ range: IRange;
32
+ severity: DiagnosticSeverity;
33
+ };
34
+ /** The result of parsing a document: its data, parser diagnostics, and a position lookup. */
35
+ export type IParseResult<T = unknown> = {
36
+ data: T;
37
+ diagnostics: IDiagnostic[];
38
+ /**
39
+ * Returns the source location for a JSON path. When `closest` is true and the
40
+ * exact path is not found, walks up to the nearest ancestor that is.
41
+ */
42
+ getLocationForJsonPath(path: JsonPath, closest?: boolean): ILocation | undefined;
43
+ };
44
+ /** Tuning for how strictly the parser treats YAML/JSON edge cases. */
45
+ export type IParserOptions = {
46
+ /** Severity for duplicate object keys. Default: error. `false`/`"off"` disables. */
47
+ duplicateKeys?: DiagnosticSeverity | 'off' | false;
48
+ /** Severity for YAML values incompatible with JSON (e.g. bigints). Default: error. */
49
+ incompatibleValues?: DiagnosticSeverity | 'off' | false;
50
+ };
@@ -0,0 +1,8 @@
1
+ /** Severity levels, ordered most-to-least severe to match LSP's numeric scale. */
2
+ export var DiagnosticSeverity;
3
+ (function (DiagnosticSeverity) {
4
+ DiagnosticSeverity[DiagnosticSeverity["Error"] = 0] = "Error";
5
+ DiagnosticSeverity[DiagnosticSeverity["Warning"] = 1] = "Warning";
6
+ DiagnosticSeverity[DiagnosticSeverity["Information"] = 2] = "Information";
7
+ DiagnosticSeverity[DiagnosticSeverity["Hint"] = 3] = "Hint";
8
+ })(DiagnosticSeverity || (DiagnosticSeverity = {}));
@@ -0,0 +1,6 @@
1
+ import { type IParseResult, type IParserOptions } from './types.js';
2
+ /**
3
+ * Parses YAML (a JSON superset, so this handles both) into data plus a source
4
+ * map, surfacing duplicate-key and incompatible-value diagnostics per `options`.
5
+ */
6
+ export declare const parseYaml: <T = unknown>(source: string, options?: IParserOptions) => IParseResult<T>;
@@ -0,0 +1,65 @@
1
+ import { isMap, isPair, isScalar, isSeq, parseDocument } from '@amritk/yaml';
2
+ import { createLineMap } from './lines.js';
3
+ import { DiagnosticSeverity, } from './types.js';
4
+ const pathKey = (path) => path.join('\0');
5
+ /**
6
+ * Parses YAML (a JSON superset, so this handles both) into data plus a source
7
+ * map, surfacing duplicate-key and incompatible-value diagnostics per `options`.
8
+ */
9
+ export const parseYaml = (source, options = {}) => {
10
+ const lineMap = createLineMap(source);
11
+ const dedupe = options.duplicateKeys === 'off' || options.duplicateKeys === false;
12
+ const doc = parseDocument(source, { uniqueKeys: !dedupe });
13
+ const index = new Map();
14
+ const rangeOf = (node) => ({
15
+ start: lineMap.positionAt(node.start),
16
+ end: lineMap.positionAt(node.end),
17
+ });
18
+ const walk = (node, path) => {
19
+ if (node == null)
20
+ return;
21
+ index.set(pathKey(path), rangeOf(node));
22
+ if (isMap(node)) {
23
+ for (const item of node.items) {
24
+ if (!isPair(item))
25
+ continue;
26
+ const key = item.key;
27
+ const keyName = isScalar(key) ? key.value : String(key);
28
+ walk(item.value, [...path, keyName]);
29
+ }
30
+ }
31
+ else if (isSeq(node)) {
32
+ node.items.forEach((item, i) => {
33
+ walk(item, [...path, i]);
34
+ });
35
+ }
36
+ };
37
+ walk(doc.contents, []);
38
+ const data = doc.toJS();
39
+ const diagnostics = [];
40
+ const pushError = (severity, message, start, end) => {
41
+ diagnostics.push({
42
+ message,
43
+ severity,
44
+ range: { start: lineMap.positionAt(start), end: lineMap.positionAt(end) },
45
+ });
46
+ };
47
+ for (const err of doc.errors) {
48
+ pushError(DiagnosticSeverity.Error, err.message, err.start, err.end);
49
+ }
50
+ for (const warn of doc.warnings) {
51
+ pushError(DiagnosticSeverity.Warning, warn.message, warn.start, warn.end);
52
+ }
53
+ const getLocationForJsonPath = (path, closest = false) => {
54
+ const p = path.slice();
55
+ while (true) {
56
+ const range = index.get(pathKey(p));
57
+ if (range)
58
+ return { range };
59
+ if (!closest || p.length === 0)
60
+ return undefined;
61
+ p.pop();
62
+ }
63
+ };
64
+ return { data, diagnostics, getLocationForJsonPath };
65
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/lint",
3
- "version": "0.0.0",
3
+ "version": "0.1.0",
4
4
  "description": "A fast, format-agnostic JSON/YAML style-guide linter with JSON Schema and custom rules.",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",
@@ -40,14 +40,13 @@
40
40
  "exports": {
41
41
  "./package.json": "./package.json",
42
42
  ".": {
43
- "development": "./src/index.ts",
44
43
  "types": "./dist/index.d.ts",
45
44
  "default": "./dist/index.js"
46
45
  }
47
46
  },
48
47
  "dependencies": {
49
- "@amritk/runtime-validators": "workspace:*",
50
- "@amritk/yaml": "workspace:*",
48
+ "@amritk/runtime-validators": "0.6.4",
49
+ "@amritk/yaml": "0.2.3",
51
50
  "jsonc-parser": "^3.3.1"
52
51
  }
53
52
  }