thurview 0.6.0 → 0.8.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 +38 -18
- package/dist/cli.js +273 -16
- package/dist/cli.js.map +1 -1
- package/dist/coverage.js +208 -0
- package/dist/coverage.js.map +1 -0
- package/dist/document/compile.js +25 -10
- package/dist/document/compile.js.map +1 -1
- package/dist/graph.js +25 -4
- package/dist/graph.js.map +1 -1
- package/dist/server/server.js +4 -2
- package/dist/server/server.js.map +1 -1
- package/dist/store.js +4 -0
- package/dist/store.js.map +1 -1
- package/dist/ui/app.css +282 -5
- package/dist/ui/app.js +718 -190
- package/dist/ui/app.js.map +4 -4
- package/package.json +1 -1
- package/skills/thurview/SKILL.md +43 -15
- package/skills/thurview/references/code-explainer.md +166 -0
- package/skills/thurview/references/software-map.md +71 -10
package/dist/ui/app.css
CHANGED
|
@@ -854,7 +854,48 @@ kbd {
|
|
|
854
854
|
font-size: 12.5px;
|
|
855
855
|
}
|
|
856
856
|
|
|
857
|
-
/* Map
|
|
857
|
+
/* Map. The tab opens with what it is for, because a reader who has to guess
|
|
858
|
+
reads it once and never returns. */
|
|
859
|
+
.map-intro {
|
|
860
|
+
max-width: 72ch;
|
|
861
|
+
margin-bottom: 18px;
|
|
862
|
+
}
|
|
863
|
+
.map-intro h2 {
|
|
864
|
+
font-family: var(--font-mono);
|
|
865
|
+
font-size: 15px;
|
|
866
|
+
margin: 0 0 5px;
|
|
867
|
+
}
|
|
868
|
+
.map-intro p {
|
|
869
|
+
margin: 0;
|
|
870
|
+
color: var(--fg2);
|
|
871
|
+
font-size: 13px;
|
|
872
|
+
line-height: 1.55;
|
|
873
|
+
}
|
|
874
|
+
.map-route {
|
|
875
|
+
display: flex;
|
|
876
|
+
flex-wrap: wrap;
|
|
877
|
+
align-items: center;
|
|
878
|
+
gap: 8px;
|
|
879
|
+
margin-top: 12px;
|
|
880
|
+
font-size: 12px;
|
|
881
|
+
}
|
|
882
|
+
.map-group {
|
|
883
|
+
margin-bottom: 22px;
|
|
884
|
+
}
|
|
885
|
+
.map-group h3,
|
|
886
|
+
.map-edges h3 {
|
|
887
|
+
font-family: var(--font-mono);
|
|
888
|
+
font-size: 11px;
|
|
889
|
+
font-weight: 700;
|
|
890
|
+
text-transform: uppercase;
|
|
891
|
+
letter-spacing: 0.08em;
|
|
892
|
+
color: var(--muted);
|
|
893
|
+
margin: 0 0 10px;
|
|
894
|
+
}
|
|
895
|
+
.map-note {
|
|
896
|
+
font-size: 12px;
|
|
897
|
+
margin-bottom: 10px;
|
|
898
|
+
}
|
|
858
899
|
.map-layout {
|
|
859
900
|
display: flex;
|
|
860
901
|
height: 100%;
|
|
@@ -929,22 +970,41 @@ kbd {
|
|
|
929
970
|
font-size: 12.5px;
|
|
930
971
|
color: var(--fg2);
|
|
931
972
|
}
|
|
932
|
-
.map-node .
|
|
973
|
+
.map-node .meta {
|
|
933
974
|
font-family: var(--font-mono);
|
|
934
975
|
font-size: 11px;
|
|
935
976
|
color: var(--muted);
|
|
936
|
-
margin-top:
|
|
977
|
+
margin-top: 10px;
|
|
978
|
+
display: flex;
|
|
979
|
+
flex-wrap: wrap;
|
|
980
|
+
align-items: center;
|
|
981
|
+
gap: 6px 10px;
|
|
982
|
+
}
|
|
983
|
+
.map-node .meta .warn-text {
|
|
984
|
+
color: var(--warn);
|
|
985
|
+
}
|
|
986
|
+
.map-node .meta button.drill {
|
|
987
|
+
padding: 3px 8px;
|
|
988
|
+
font-size: 11px;
|
|
937
989
|
}
|
|
938
990
|
.map-node.added {
|
|
939
991
|
border-color: var(--ok);
|
|
940
992
|
}
|
|
941
993
|
.map-node.removed {
|
|
942
994
|
border-color: var(--del);
|
|
943
|
-
opacity: 0.7;
|
|
944
995
|
}
|
|
945
996
|
.map-node.changed {
|
|
946
997
|
border-color: var(--warn);
|
|
947
998
|
}
|
|
999
|
+
/* Untouched parts stay on the board - they are the context that makes the
|
|
1000
|
+
change readable - but they must not compete with it for attention. */
|
|
1001
|
+
.map-node.quiet {
|
|
1002
|
+
opacity: 0.6;
|
|
1003
|
+
background: transparent;
|
|
1004
|
+
}
|
|
1005
|
+
.map-node.quiet:hover {
|
|
1006
|
+
opacity: 1;
|
|
1007
|
+
}
|
|
948
1008
|
.map-node .status {
|
|
949
1009
|
position: absolute;
|
|
950
1010
|
top: 8px;
|
|
@@ -955,17 +1015,43 @@ kbd {
|
|
|
955
1015
|
font-size: 13px;
|
|
956
1016
|
}
|
|
957
1017
|
.map-edges .edge {
|
|
958
|
-
padding: 5px 0;
|
|
1018
|
+
padding: 5px 0 5px 10px;
|
|
959
1019
|
border-top: 1px solid var(--line);
|
|
1020
|
+
border-left: 2px solid transparent;
|
|
960
1021
|
display: flex;
|
|
1022
|
+
flex-wrap: wrap;
|
|
961
1023
|
gap: 8px;
|
|
962
1024
|
font-family: var(--font-mono);
|
|
963
1025
|
font-size: 12px;
|
|
964
1026
|
}
|
|
1027
|
+
/* A link into a changed part is the seam a reviewer has to check; one between
|
|
1028
|
+
two untouched parts is only there to place it. */
|
|
1029
|
+
.map-edges .edge.hot {
|
|
1030
|
+
border-left-color: var(--warn);
|
|
1031
|
+
}
|
|
1032
|
+
.map-edges .edge:not(.hot) {
|
|
1033
|
+
opacity: 0.6;
|
|
1034
|
+
}
|
|
965
1035
|
.map-edges .edge b {
|
|
966
1036
|
cursor: pointer;
|
|
967
1037
|
color: var(--link);
|
|
968
1038
|
}
|
|
1039
|
+
.map-side .neighbours {
|
|
1040
|
+
font-size: 12px;
|
|
1041
|
+
}
|
|
1042
|
+
.map-side .neighbour {
|
|
1043
|
+
display: flex;
|
|
1044
|
+
flex-wrap: wrap;
|
|
1045
|
+
align-items: center;
|
|
1046
|
+
gap: 6px;
|
|
1047
|
+
padding: 4px 0;
|
|
1048
|
+
border-top: 1px solid var(--line);
|
|
1049
|
+
}
|
|
1050
|
+
.map-side .neighbour .nb {
|
|
1051
|
+
font-family: var(--font-mono);
|
|
1052
|
+
color: var(--link);
|
|
1053
|
+
cursor: pointer;
|
|
1054
|
+
}
|
|
969
1055
|
.map-side .file {
|
|
970
1056
|
font-family: var(--font-mono);
|
|
971
1057
|
font-size: 12px;
|
|
@@ -1341,6 +1427,13 @@ kbd {
|
|
|
1341
1427
|
font-family: var(--font-mono);
|
|
1342
1428
|
font-size: 13px;
|
|
1343
1429
|
}
|
|
1430
|
+
/* An empty state that explains itself runs to a paragraph, and a paragraph the
|
|
1431
|
+
width of the viewport is unreadable. */
|
|
1432
|
+
.empty-state p {
|
|
1433
|
+
max-width: 62ch;
|
|
1434
|
+
margin: 0 auto 8px;
|
|
1435
|
+
line-height: 1.6;
|
|
1436
|
+
}
|
|
1344
1437
|
|
|
1345
1438
|
/* ---- Interface delta ----
|
|
1346
1439
|
Above the document, because "what does this let us do now" is the reader's
|
|
@@ -1663,3 +1756,187 @@ kbd {
|
|
|
1663
1756
|
overflow: visible;
|
|
1664
1757
|
}
|
|
1665
1758
|
}
|
|
1759
|
+
|
|
1760
|
+
/* ---- Coverage (explainers) ----
|
|
1761
|
+
Deliberately neutral: covered/uncovered is a fact about the DOCUMENT, not a
|
|
1762
|
+
grade on the code, so nothing here borrows the ok/warn/del palette that the
|
|
1763
|
+
review views use to mark a change. */
|
|
1764
|
+
.cov-intro,
|
|
1765
|
+
.cov-section {
|
|
1766
|
+
max-width: 1000px;
|
|
1767
|
+
margin: 0 auto 26px;
|
|
1768
|
+
padding: 0 24px;
|
|
1769
|
+
}
|
|
1770
|
+
.cov-intro {
|
|
1771
|
+
padding-top: 24px;
|
|
1772
|
+
}
|
|
1773
|
+
.cov-intro h2,
|
|
1774
|
+
.cov-section h3 {
|
|
1775
|
+
font-family: var(--font-mono);
|
|
1776
|
+
font-size: 15px;
|
|
1777
|
+
margin: 0 0 6px;
|
|
1778
|
+
}
|
|
1779
|
+
.cov-section h3 {
|
|
1780
|
+
font-size: 11px;
|
|
1781
|
+
font-weight: 700;
|
|
1782
|
+
text-transform: uppercase;
|
|
1783
|
+
letter-spacing: 0.08em;
|
|
1784
|
+
color: var(--muted);
|
|
1785
|
+
margin-bottom: 10px;
|
|
1786
|
+
}
|
|
1787
|
+
.cov-section h4 {
|
|
1788
|
+
font-family: var(--font-mono);
|
|
1789
|
+
font-size: 12px;
|
|
1790
|
+
margin: 18px 0 6px;
|
|
1791
|
+
}
|
|
1792
|
+
.cov-intro p,
|
|
1793
|
+
.cov-section p {
|
|
1794
|
+
margin: 0 0 12px;
|
|
1795
|
+
color: var(--fg2);
|
|
1796
|
+
font-size: 13px;
|
|
1797
|
+
line-height: 1.55;
|
|
1798
|
+
max-width: 72ch;
|
|
1799
|
+
}
|
|
1800
|
+
.cov-bar {
|
|
1801
|
+
display: flex;
|
|
1802
|
+
height: 10px;
|
|
1803
|
+
border: 1px solid var(--line);
|
|
1804
|
+
border-radius: var(--radius);
|
|
1805
|
+
overflow: hidden;
|
|
1806
|
+
background: var(--bg2);
|
|
1807
|
+
}
|
|
1808
|
+
.cov-seg.explained {
|
|
1809
|
+
background: var(--accent);
|
|
1810
|
+
}
|
|
1811
|
+
.cov-seg.placed {
|
|
1812
|
+
background: var(--accent-bg);
|
|
1813
|
+
}
|
|
1814
|
+
.cov-seg.uncovered {
|
|
1815
|
+
background: var(--bg3);
|
|
1816
|
+
}
|
|
1817
|
+
.cov-key {
|
|
1818
|
+
display: flex;
|
|
1819
|
+
flex-wrap: wrap;
|
|
1820
|
+
gap: 14px;
|
|
1821
|
+
margin: 8px 0 16px;
|
|
1822
|
+
font-size: 12px;
|
|
1823
|
+
color: var(--fg2);
|
|
1824
|
+
}
|
|
1825
|
+
.cov-key-item {
|
|
1826
|
+
display: inline-flex;
|
|
1827
|
+
align-items: center;
|
|
1828
|
+
gap: 6px;
|
|
1829
|
+
}
|
|
1830
|
+
.cov-dot {
|
|
1831
|
+
width: 9px;
|
|
1832
|
+
height: 9px;
|
|
1833
|
+
border: 1px solid var(--line);
|
|
1834
|
+
border-radius: 2px;
|
|
1835
|
+
}
|
|
1836
|
+
.cov-dot.explained {
|
|
1837
|
+
background: var(--accent);
|
|
1838
|
+
}
|
|
1839
|
+
.cov-dot.placed {
|
|
1840
|
+
background: var(--accent-bg);
|
|
1841
|
+
}
|
|
1842
|
+
.cov-dot.uncovered {
|
|
1843
|
+
background: var(--bg3);
|
|
1844
|
+
}
|
|
1845
|
+
.cov-facts {
|
|
1846
|
+
display: flex;
|
|
1847
|
+
flex-wrap: wrap;
|
|
1848
|
+
gap: 10px;
|
|
1849
|
+
}
|
|
1850
|
+
.cov-fact {
|
|
1851
|
+
border: 1px solid var(--line);
|
|
1852
|
+
border-radius: var(--radius);
|
|
1853
|
+
padding: 7px 10px;
|
|
1854
|
+
min-width: 0;
|
|
1855
|
+
font-size: 12px;
|
|
1856
|
+
}
|
|
1857
|
+
.cov-fact b {
|
|
1858
|
+
display: block;
|
|
1859
|
+
font-family: var(--font-mono);
|
|
1860
|
+
font-size: 13px;
|
|
1861
|
+
}
|
|
1862
|
+
.cov-cluster {
|
|
1863
|
+
border: 1px solid var(--line);
|
|
1864
|
+
border-radius: var(--radius);
|
|
1865
|
+
padding: 10px 12px;
|
|
1866
|
+
margin-bottom: 10px;
|
|
1867
|
+
background: var(--bg2);
|
|
1868
|
+
}
|
|
1869
|
+
.cov-cluster-head {
|
|
1870
|
+
display: flex;
|
|
1871
|
+
flex-wrap: wrap;
|
|
1872
|
+
align-items: center;
|
|
1873
|
+
gap: 8px;
|
|
1874
|
+
font-size: 12px;
|
|
1875
|
+
}
|
|
1876
|
+
.cov-cluster-head .spacer {
|
|
1877
|
+
flex: 1;
|
|
1878
|
+
}
|
|
1879
|
+
.cov-label {
|
|
1880
|
+
font-weight: 600;
|
|
1881
|
+
}
|
|
1882
|
+
.cov-hubs {
|
|
1883
|
+
font-size: 12px;
|
|
1884
|
+
margin-top: 6px;
|
|
1885
|
+
}
|
|
1886
|
+
.cov-hubs code {
|
|
1887
|
+
margin-right: 6px;
|
|
1888
|
+
}
|
|
1889
|
+
.cov-files {
|
|
1890
|
+
display: flex;
|
|
1891
|
+
flex-wrap: wrap;
|
|
1892
|
+
gap: 6px;
|
|
1893
|
+
margin-top: 8px;
|
|
1894
|
+
}
|
|
1895
|
+
.cov-file {
|
|
1896
|
+
font-size: 11px;
|
|
1897
|
+
color: var(--muted);
|
|
1898
|
+
border: 1px dashed var(--line);
|
|
1899
|
+
border-radius: var(--radius);
|
|
1900
|
+
padding: 1px 5px;
|
|
1901
|
+
}
|
|
1902
|
+
.cov-b-explained {
|
|
1903
|
+
color: var(--accent);
|
|
1904
|
+
border-color: var(--accent);
|
|
1905
|
+
}
|
|
1906
|
+
.cov-b-placed {
|
|
1907
|
+
color: var(--accent);
|
|
1908
|
+
border-color: var(--accent);
|
|
1909
|
+
background: var(--accent-bg);
|
|
1910
|
+
}
|
|
1911
|
+
.cov-b-uncovered {
|
|
1912
|
+
color: var(--muted);
|
|
1913
|
+
border-color: var(--line);
|
|
1914
|
+
background: var(--bg3);
|
|
1915
|
+
}
|
|
1916
|
+
.cov-links,
|
|
1917
|
+
.cov-shared {
|
|
1918
|
+
display: flex;
|
|
1919
|
+
flex-direction: column;
|
|
1920
|
+
border: 1px solid var(--line);
|
|
1921
|
+
border-radius: var(--radius);
|
|
1922
|
+
overflow: hidden;
|
|
1923
|
+
}
|
|
1924
|
+
.cov-link {
|
|
1925
|
+
display: flex;
|
|
1926
|
+
flex-wrap: wrap;
|
|
1927
|
+
align-items: baseline;
|
|
1928
|
+
gap: 8px;
|
|
1929
|
+
padding: 6px 10px;
|
|
1930
|
+
font-size: 12px;
|
|
1931
|
+
border-top: 1px solid var(--line2);
|
|
1932
|
+
min-width: 0;
|
|
1933
|
+
}
|
|
1934
|
+
.cov-link:first-child {
|
|
1935
|
+
border-top: 0;
|
|
1936
|
+
}
|
|
1937
|
+
.cov-link:hover {
|
|
1938
|
+
background: var(--bg3);
|
|
1939
|
+
}
|
|
1940
|
+
.cov-link > .muted {
|
|
1941
|
+
overflow-wrap: anywhere;
|
|
1942
|
+
}
|