@sightmap/sightmap 0.2.1 → 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 +17 -0
- package/dist/{browser-ChD_xQt8.d.ts → browser-2wvcIicU.d.ts} +4 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.js +432 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +20 -3
- package/dist/index.js +303 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -74,6 +74,9 @@ var DUPLICATE_ROUTE = "duplicate-route";
|
|
|
74
74
|
var ROUTE_SHADOWING = "route-shadowing";
|
|
75
75
|
var UNKNOWN_SOURCE = "unknown-source";
|
|
76
76
|
var SELECTOR_SYNTAX = "selector-syntax";
|
|
77
|
+
var FMT_NOT_CANONICAL = "fmt.not-canonical";
|
|
78
|
+
var FMT_PARSE_ERROR = "fmt.parse-error";
|
|
79
|
+
var FMT_SCHEMA_INVALID = "fmt.schema-invalid";
|
|
77
80
|
|
|
78
81
|
// src/validate.ts
|
|
79
82
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -649,17 +652,58 @@ async function lint(sightmap, opts = {}) {
|
|
|
649
652
|
|
|
650
653
|
// src/format/index.ts
|
|
651
654
|
import { stringify } from "yaml";
|
|
652
|
-
|
|
655
|
+
|
|
656
|
+
// src/format/canonical-rules.ts
|
|
657
|
+
var TOP_LEVEL_KEY_ORDER = [
|
|
653
658
|
"version",
|
|
654
659
|
"memory",
|
|
655
660
|
"views",
|
|
656
661
|
"components",
|
|
657
662
|
"requests"
|
|
658
663
|
];
|
|
664
|
+
var VIEW_KEY_ORDER = [
|
|
665
|
+
"name",
|
|
666
|
+
"route",
|
|
667
|
+
"description",
|
|
668
|
+
"components",
|
|
669
|
+
"memory",
|
|
670
|
+
"requests"
|
|
671
|
+
];
|
|
672
|
+
var COMPONENT_KEY_ORDER = [
|
|
673
|
+
"name",
|
|
674
|
+
"selector",
|
|
675
|
+
"description",
|
|
676
|
+
"children",
|
|
677
|
+
"memory"
|
|
678
|
+
];
|
|
679
|
+
var REQUEST_KEY_ORDER = [
|
|
680
|
+
"name",
|
|
681
|
+
"route",
|
|
682
|
+
"method",
|
|
683
|
+
"description",
|
|
684
|
+
"source",
|
|
685
|
+
"request",
|
|
686
|
+
"response",
|
|
687
|
+
"headers",
|
|
688
|
+
"memory"
|
|
689
|
+
];
|
|
690
|
+
function compareByName(a, b) {
|
|
691
|
+
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
692
|
+
}
|
|
693
|
+
function compareRequests(a, b) {
|
|
694
|
+
if (a.route !== b.route) return a.route < b.route ? -1 : 1;
|
|
695
|
+
const am = a.method ?? "";
|
|
696
|
+
const bm = b.method ?? "";
|
|
697
|
+
return am < bm ? -1 : am > bm ? 1 : 0;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// src/format/index.ts
|
|
659
701
|
function format(input) {
|
|
660
702
|
const ordered = {};
|
|
661
|
-
for (const key of
|
|
662
|
-
if (input[key] !== void 0)
|
|
703
|
+
for (const key of TOP_LEVEL_KEY_ORDER) {
|
|
704
|
+
if (input[key] !== void 0) {
|
|
705
|
+
ordered[key] = input[key];
|
|
706
|
+
}
|
|
663
707
|
}
|
|
664
708
|
for (const key of Object.keys(input)) {
|
|
665
709
|
if (key.startsWith("__")) continue;
|
|
@@ -672,9 +716,264 @@ function format(input) {
|
|
|
672
716
|
});
|
|
673
717
|
return yaml3.endsWith("\n") ? yaml3 : yaml3 + "\n";
|
|
674
718
|
}
|
|
719
|
+
|
|
720
|
+
// src/format/canonicalize.ts
|
|
721
|
+
import { parseDocument, isMap, isSeq, isScalar } from "yaml";
|
|
722
|
+
function canonicalize(input, opts) {
|
|
723
|
+
const doc = parseDocument(input, { keepSourceTokens: false });
|
|
724
|
+
const first = doc.errors[0];
|
|
725
|
+
if (first !== void 0) {
|
|
726
|
+
const loc = first.linePos?.[0] ? { line: first.linePos[0].line, column: first.linePos[0].col } : void 0;
|
|
727
|
+
return {
|
|
728
|
+
kind: "parse-error",
|
|
729
|
+
diagnostics: [
|
|
730
|
+
{
|
|
731
|
+
severity: "error",
|
|
732
|
+
code: FMT_PARSE_ERROR,
|
|
733
|
+
message: first.message,
|
|
734
|
+
file: opts.file,
|
|
735
|
+
...loc !== void 0 ? { loc } : {}
|
|
736
|
+
}
|
|
737
|
+
]
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
const v = validate(input, { sourceFile: opts.file });
|
|
741
|
+
if (!v.ok) {
|
|
742
|
+
const diagnostics = v.diagnostics.map((d) => ({
|
|
743
|
+
...d,
|
|
744
|
+
severity: "error",
|
|
745
|
+
code: FMT_SCHEMA_INVALID,
|
|
746
|
+
file: opts.file
|
|
747
|
+
}));
|
|
748
|
+
return { kind: "schema-invalid", diagnostics };
|
|
749
|
+
}
|
|
750
|
+
if (isMap(doc.contents)) {
|
|
751
|
+
reorderTopLevelKeys(doc.contents);
|
|
752
|
+
reorderEntriesUnder(doc.contents, "views", VIEW_KEY_ORDER);
|
|
753
|
+
reorderEntriesUnder(doc.contents, "components", COMPONENT_KEY_ORDER);
|
|
754
|
+
reorderEntriesUnder(doc.contents, "requests", REQUEST_KEY_ORDER);
|
|
755
|
+
forEachViewEntry(doc.contents, (view) => {
|
|
756
|
+
reorderEntriesUnder(view, "components", COMPONENT_KEY_ORDER);
|
|
757
|
+
reorderEntriesUnder(view, "requests", REQUEST_KEY_ORDER);
|
|
758
|
+
forEachComponentEntry(view, "components", (cmp) => {
|
|
759
|
+
reorderChildrenRecursive(cmp);
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
forEachComponentEntry(doc.contents, "components", (cmp) => {
|
|
763
|
+
reorderChildrenRecursive(cmp);
|
|
764
|
+
});
|
|
765
|
+
sortTopLevelSeq(doc.contents, "views", (a, b) => {
|
|
766
|
+
const an = scalarPropFromMapItem(a, "name");
|
|
767
|
+
const bn = scalarPropFromMapItem(b, "name");
|
|
768
|
+
return compareByName({ name: an ?? "" }, { name: bn ?? "" });
|
|
769
|
+
});
|
|
770
|
+
sortTopLevelSeq(doc.contents, "components", (a, b) => {
|
|
771
|
+
const an = scalarPropFromMapItem(a, "name");
|
|
772
|
+
const bn = scalarPropFromMapItem(b, "name");
|
|
773
|
+
return compareByName({ name: an ?? "" }, { name: bn ?? "" });
|
|
774
|
+
});
|
|
775
|
+
sortTopLevelSeq(doc.contents, "requests", (a, b) => {
|
|
776
|
+
return compareRequests(
|
|
777
|
+
{ route: scalarPropFromMapItem(a, "route") ?? "", method: scalarPropFromMapItem(a, "method") },
|
|
778
|
+
{ route: scalarPropFromMapItem(b, "route") ?? "", method: scalarPropFromMapItem(b, "method") }
|
|
779
|
+
);
|
|
780
|
+
});
|
|
781
|
+
visitAllScalars(doc, (scalar) => {
|
|
782
|
+
if (typeof scalar.value !== "string") return;
|
|
783
|
+
scalar.type = chooseQuoteType(scalar.value);
|
|
784
|
+
});
|
|
785
|
+
normalizeBlankLines(doc);
|
|
786
|
+
}
|
|
787
|
+
const output = serialize(doc);
|
|
788
|
+
return { kind: "canonical", text: output, changed: output !== input };
|
|
789
|
+
}
|
|
790
|
+
function reorderTopLevelKeys(map) {
|
|
791
|
+
reorderMapKeys(map, TOP_LEVEL_KEY_ORDER);
|
|
792
|
+
}
|
|
793
|
+
function reorderMapKeys(map, keyOrder) {
|
|
794
|
+
const items = map.items;
|
|
795
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
796
|
+
const unknownInOrder = [];
|
|
797
|
+
for (const item of items) {
|
|
798
|
+
const key = scalarKey(item);
|
|
799
|
+
if (key === null) {
|
|
800
|
+
unknownInOrder.push(item);
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
if (keyOrder.includes(key)) {
|
|
804
|
+
byKey.set(key, item);
|
|
805
|
+
} else {
|
|
806
|
+
unknownInOrder.push(item);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
const reordered = [];
|
|
810
|
+
for (const k of keyOrder) {
|
|
811
|
+
const p = byKey.get(k);
|
|
812
|
+
if (p !== void 0) reordered.push(p);
|
|
813
|
+
}
|
|
814
|
+
reordered.push(...unknownInOrder);
|
|
815
|
+
map.items = reordered;
|
|
816
|
+
}
|
|
817
|
+
function reorderEntriesUnder(map, key, keyOrder) {
|
|
818
|
+
const seq = lookupSeq(map, key);
|
|
819
|
+
if (seq === null) return;
|
|
820
|
+
for (const item of seq.items) {
|
|
821
|
+
if (isMap(item)) reorderMapKeys(item, keyOrder);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
function forEachViewEntry(root, fn) {
|
|
825
|
+
const seq = lookupSeq(root, "views");
|
|
826
|
+
if (seq === null) return;
|
|
827
|
+
for (const item of seq.items) {
|
|
828
|
+
if (isMap(item)) fn(item);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
function forEachComponentEntry(root, key, fn) {
|
|
832
|
+
const seq = lookupSeq(root, key);
|
|
833
|
+
if (seq === null) return;
|
|
834
|
+
for (const item of seq.items) {
|
|
835
|
+
if (isMap(item)) fn(item);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
function reorderChildrenRecursive(cmp) {
|
|
839
|
+
const children = lookupSeq(cmp, "children");
|
|
840
|
+
if (children === null) return;
|
|
841
|
+
for (const child of children.items) {
|
|
842
|
+
if (!isMap(child)) continue;
|
|
843
|
+
reorderMapKeys(child, COMPONENT_KEY_ORDER);
|
|
844
|
+
reorderChildrenRecursive(child);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
function lookupSeq(map, key) {
|
|
848
|
+
for (const item of map.items) {
|
|
849
|
+
if (scalarKey(item) === key && isSeq(item.value)) return item.value;
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
function scalarKey(pair) {
|
|
854
|
+
const k = pair.key ?? null;
|
|
855
|
+
if (k === null) return null;
|
|
856
|
+
const v = typeof k === "object" && k !== null && "value" in k ? k.value : k;
|
|
857
|
+
return typeof v === "string" ? v : null;
|
|
858
|
+
}
|
|
859
|
+
function sortTopLevelSeq(root, key, cmp) {
|
|
860
|
+
const seq = lookupSeq(root, key);
|
|
861
|
+
if (seq === null) return;
|
|
862
|
+
seq.items = seq.items.slice().sort(cmp);
|
|
863
|
+
}
|
|
864
|
+
function scalarPropFromMapItem(item, key) {
|
|
865
|
+
if (!isMap(item)) return void 0;
|
|
866
|
+
for (const pair of item.items) {
|
|
867
|
+
if (scalarKey(pair) !== key) continue;
|
|
868
|
+
const v = pair.value;
|
|
869
|
+
if (v !== null && typeof v === "object" && "value" in v) {
|
|
870
|
+
const inner = v.value;
|
|
871
|
+
return typeof inner === "string" ? inner : void 0;
|
|
872
|
+
}
|
|
873
|
+
return typeof v === "string" ? v : void 0;
|
|
874
|
+
}
|
|
875
|
+
return void 0;
|
|
876
|
+
}
|
|
877
|
+
function visitAllScalars(doc, fn) {
|
|
878
|
+
walk(doc.contents, fn);
|
|
879
|
+
}
|
|
880
|
+
function walk(node, fn) {
|
|
881
|
+
if (node === null || node === void 0) return;
|
|
882
|
+
if (isScalar(node)) {
|
|
883
|
+
fn(node);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
if (isMap(node)) {
|
|
887
|
+
for (const pair of node.items) {
|
|
888
|
+
walk(pair.key, fn);
|
|
889
|
+
walk(pair.value, fn);
|
|
890
|
+
}
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
if (isSeq(node)) {
|
|
894
|
+
for (const item of node.items) walk(item, fn);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function normalizeBlankLines(doc) {
|
|
898
|
+
const root = doc.contents;
|
|
899
|
+
if (!isMap(root)) return;
|
|
900
|
+
const firstPair = root.items[0];
|
|
901
|
+
if (firstPair !== void 0) {
|
|
902
|
+
const keyNode = firstPair.key;
|
|
903
|
+
const docMutable = doc;
|
|
904
|
+
const keyComment = keyNode?.commentBefore;
|
|
905
|
+
const docComment = docMutable.commentBefore;
|
|
906
|
+
if (typeof keyComment === "string" && keyComment.length > 0) {
|
|
907
|
+
docMutable.commentBefore = keyComment;
|
|
908
|
+
keyNode.commentBefore = null;
|
|
909
|
+
}
|
|
910
|
+
const hasHeader = typeof docMutable.commentBefore === "string" && docMutable.commentBefore.length > 0 || typeof docComment === "string" && docComment.length > 0;
|
|
911
|
+
firstPair.spaceBefore = hasHeader;
|
|
912
|
+
}
|
|
913
|
+
for (const key of ["views", "components", "requests"]) {
|
|
914
|
+
const seq = lookupSeq(root, key);
|
|
915
|
+
if (seq === null) continue;
|
|
916
|
+
seq.items.forEach((item, idx) => {
|
|
917
|
+
if (typeof item === "object" && item !== null) {
|
|
918
|
+
item.spaceBefore = idx > 0;
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
for (const item of seq.items) {
|
|
922
|
+
if (isMap(item)) clearInnerBlankLines(item);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
function clearInnerBlankLines(map) {
|
|
927
|
+
for (const pair of map.items) {
|
|
928
|
+
pair.spaceBefore = false;
|
|
929
|
+
if (isSeq(pair.value)) {
|
|
930
|
+
for (const item of pair.value.items) {
|
|
931
|
+
if (typeof item === "object" && item !== null) {
|
|
932
|
+
item.spaceBefore = false;
|
|
933
|
+
}
|
|
934
|
+
if (isMap(item)) clearInnerBlankLines(item);
|
|
935
|
+
}
|
|
936
|
+
} else if (isMap(pair.value)) {
|
|
937
|
+
clearInnerBlankLines(pair.value);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function chooseQuoteType(value) {
|
|
942
|
+
if (requiresDoubleQuotes(value)) return "QUOTE_DOUBLE";
|
|
943
|
+
if (value.includes('"')) return "QUOTE_SINGLE";
|
|
944
|
+
if (isPlainSafe(value)) return "PLAIN";
|
|
945
|
+
return "QUOTE_SINGLE";
|
|
946
|
+
}
|
|
947
|
+
function requiresDoubleQuotes(s) {
|
|
948
|
+
return /[\x00-\x1f]/.test(s);
|
|
949
|
+
}
|
|
950
|
+
function isPlainSafe(s) {
|
|
951
|
+
if (s.length === 0) return false;
|
|
952
|
+
const first = s[0];
|
|
953
|
+
if ("-?:,[]{}#&*!|>'\"%@`".includes(first)) return false;
|
|
954
|
+
if (first === " " || first === " ") return false;
|
|
955
|
+
if (s.includes(": ")) return false;
|
|
956
|
+
if (s.includes(" #")) return false;
|
|
957
|
+
if (/^(true|false|null|~|y|n|yes|no|on|off|True|False|Null|Yes|No|On|Off|TRUE|FALSE|NULL|YES|NO|ON|OFF)$/.test(s)) return false;
|
|
958
|
+
if (/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(s)) return false;
|
|
959
|
+
if (/^0[xob]/.test(s)) return false;
|
|
960
|
+
return true;
|
|
961
|
+
}
|
|
962
|
+
function serialize(doc) {
|
|
963
|
+
const out = doc.toString({
|
|
964
|
+
indent: 2,
|
|
965
|
+
lineWidth: 0,
|
|
966
|
+
minContentWidth: 0,
|
|
967
|
+
blockQuote: "literal"
|
|
968
|
+
});
|
|
969
|
+
return out.endsWith("\n") ? out : out + "\n";
|
|
970
|
+
}
|
|
675
971
|
export {
|
|
676
972
|
DUPLICATE_ROUTE,
|
|
677
973
|
DUPLICATE_VIEW_NAME,
|
|
974
|
+
FMT_NOT_CANONICAL,
|
|
975
|
+
FMT_PARSE_ERROR,
|
|
976
|
+
FMT_SCHEMA_INVALID,
|
|
678
977
|
MERGE_COLLISION_COMPONENT,
|
|
679
978
|
MERGE_COLLISION_VIEW,
|
|
680
979
|
PARSE_ERROR,
|
|
@@ -683,6 +982,7 @@ export {
|
|
|
683
982
|
SELECTOR_SYNTAX,
|
|
684
983
|
UNKNOWN_SOURCE,
|
|
685
984
|
UNKNOWN_VERSION,
|
|
985
|
+
canonicalize,
|
|
686
986
|
explain,
|
|
687
987
|
format,
|
|
688
988
|
lint,
|