@marlinjai/clearify 1.9.0 → 1.11.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.
@@ -449,25 +449,26 @@ function NavItem({ item, depth, onNavigate, expandedGroups, onToggleGroup, group
449
449
  display: 'flex',
450
450
  alignItems: 'center',
451
451
  width: '100%',
452
- padding: '0.4rem 0.75rem',
452
+ padding: depth === 0 ? '0.4rem 0.75rem' : '0.35rem 0.75rem',
453
+ paddingLeft: `${0.75 + depth * 0.75}rem`,
453
454
  background: 'none',
454
455
  border: 'none',
455
456
  cursor: 'pointer',
456
- fontSize: '0.6875rem',
457
- fontWeight: 600,
458
- textTransform: 'uppercase',
459
- letterSpacing: '0.06em',
460
- color: 'var(--clearify-text-tertiary)',
461
- marginTop: depth === 0 ? '1.25rem' : 0,
457
+ fontSize: depth === 0 ? '0.6875rem' : '0.75rem',
458
+ fontWeight: depth === 0 ? 600 : 500,
459
+ textTransform: depth === 0 ? 'uppercase' : 'none',
460
+ letterSpacing: depth === 0 ? '0.06em' : '0.01em',
461
+ color: depth === 0 ? 'var(--clearify-text-tertiary)' : 'var(--clearify-text-secondary)',
462
+ marginTop: depth === 0 ? '1.25rem' : '0.375rem',
462
463
  borderRadius: 'var(--clearify-radius-sm)',
463
464
  transition: 'color 0.15s',
464
465
  }}
465
- onMouseEnter={(e) => (e.currentTarget.style.color = 'var(--clearify-text-secondary)')}
466
- onMouseLeave={(e) => (e.currentTarget.style.color = 'var(--clearify-text-tertiary)')}
466
+ onMouseEnter={(e) => (e.currentTarget.style.color = depth === 0 ? 'var(--clearify-text-secondary)' : 'var(--clearify-text)')}
467
+ onMouseLeave={(e) => (e.currentTarget.style.color = depth === 0 ? 'var(--clearify-text-tertiary)' : 'var(--clearify-text-secondary)')}
467
468
  >
468
469
  <svg
469
- width="12"
470
- height="12"
470
+ width={depth === 0 ? '12' : '10'}
471
+ height={depth === 0 ? '12' : '10'}
471
472
  viewBox="0 0 24 24"
472
473
  fill="none"
473
474
  stroke="currentColor"
@@ -479,6 +480,7 @@ function NavItem({ item, depth, onNavigate, expandedGroups, onToggleGroup, group
479
480
  transition: 'transform 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
480
481
  transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)',
481
482
  flexShrink: 0,
483
+ opacity: depth === 0 ? 1 : 0.7,
482
484
  }}
483
485
  >
484
486
  <polyline points="9 18 15 12 9 6" />
@@ -1,136 +0,0 @@
1
- import {
2
- loadUserConfig,
3
- resolveConfig,
4
- resolveSections
5
- } from "./chunk-PQMKRFBQ.js";
6
- import {
7
- scanDocs
8
- } from "./chunk-QNC5QRIO.js";
9
-
10
- // src/node/check.ts
11
- import { resolve } from "path";
12
- import { readFileSync, existsSync } from "fs";
13
- async function checkLinks() {
14
- const userRoot = process.cwd();
15
- const userConfig = await loadUserConfig(userRoot);
16
- const config = resolveConfig(userConfig, userRoot);
17
- const sections = resolveSections(config, userRoot);
18
- const validRoutes = /* @__PURE__ */ new Set();
19
- const allDocs = [];
20
- for (const section of sections) {
21
- const docs = scanDocs(section.docsDir, section.exclude, section.basePath);
22
- for (const doc of docs) {
23
- validRoutes.add(doc.routePath);
24
- allDocs.push(doc);
25
- }
26
- }
27
- validRoutes.add("/");
28
- const changelogPath = resolve(userRoot, "CHANGELOG.md");
29
- if (existsSync(changelogPath)) {
30
- validRoutes.add("/changelog");
31
- }
32
- const expandedRoutes = new Set(validRoutes);
33
- for (const route of validRoutes) {
34
- expandedRoutes.add(route.replace(/\/$/, ""));
35
- if (route !== "/") expandedRoutes.add(route + "/");
36
- }
37
- const mdLinkRegex = /\[(?:[^\]]*)\]\(([^)]+)\)/g;
38
- const hrefRegex = /href=["']([^"']+)["']/g;
39
- const brokenLinks = [];
40
- for (const doc of allDocs) {
41
- if (!existsSync(doc.filePath)) continue;
42
- const content = readFileSync(doc.filePath, "utf-8");
43
- const lines = content.split("\n");
44
- for (let i = 0; i < lines.length; i++) {
45
- const line = lines[i];
46
- const lineNum = i + 1;
47
- if (line.trimStart().startsWith("```")) continue;
48
- for (const regex of [mdLinkRegex, hrefRegex]) {
49
- regex.lastIndex = 0;
50
- let match;
51
- while ((match = regex.exec(line)) !== null) {
52
- const rawLink = match[1].split(/[\s"'#]/)[0];
53
- if (!rawLink || rawLink.startsWith("http://") || rawLink.startsWith("https://") || rawLink.startsWith("#") || rawLink.startsWith("mailto:") || rawLink.startsWith("tel:") || rawLink.startsWith("//") || rawLink.startsWith("{") || rawLink.startsWith("data:")) {
54
- continue;
55
- }
56
- if (/\.(png|jpe?g|gif|svg|webp|ico|pdf|zip|tar|gz)$/i.test(rawLink)) {
57
- continue;
58
- }
59
- let normalized = rawLink;
60
- normalized = normalized.replace(/\.(mdx?|html?)$/, "");
61
- if (!normalized.startsWith("/")) {
62
- const docDir = doc.routePath.substring(0, doc.routePath.lastIndexOf("/")) || "/";
63
- normalized = docDir === "/" ? "/" + normalized : docDir + "/" + normalized;
64
- }
65
- const check = normalized === "/" ? "/" : normalized.replace(/\/$/, "");
66
- const checkNoIndex = check.replace(/\/index$/, "") || "/";
67
- if (!expandedRoutes.has(check) && !expandedRoutes.has(checkNoIndex)) {
68
- const suggestion = findClosest(check, validRoutes);
69
- brokenLinks.push({
70
- file: doc.filePath,
71
- line: lineNum,
72
- link: rawLink,
73
- ...suggestion ? { suggestion } : {}
74
- });
75
- }
76
- }
77
- }
78
- }
79
- }
80
- if (brokenLinks.length === 0) {
81
- console.log("\n No broken links found.\n");
82
- return;
83
- }
84
- console.log(`
85
- Found ${brokenLinks.length} broken link${brokenLinks.length === 1 ? "" : "s"}:
86
- `);
87
- const byFile = /* @__PURE__ */ new Map();
88
- for (const bl of brokenLinks) {
89
- const relative = bl.file.replace(userRoot + "/", "");
90
- if (!byFile.has(relative)) byFile.set(relative, []);
91
- byFile.get(relative).push(bl);
92
- }
93
- for (const [file, links] of byFile) {
94
- console.log(` ${file}`);
95
- for (const link of links) {
96
- const suggestion = link.suggestion ? ` (did you mean ${link.suggestion}?)` : "";
97
- console.log(` line ${link.line}: ${link.link}${suggestion}`);
98
- }
99
- console.log();
100
- }
101
- process.exitCode = 1;
102
- }
103
- function findClosest(target, routes) {
104
- let best;
105
- let bestScore = Infinity;
106
- const targetSegments = target.split("/").filter(Boolean);
107
- for (const route of routes) {
108
- const routeSegments = route.split("/").filter(Boolean);
109
- const dist = levenshtein(target, route);
110
- const common = targetSegments.filter((s) => routeSegments.includes(s)).length;
111
- const score = dist - common * 2;
112
- if (score < bestScore) {
113
- bestScore = score;
114
- best = route;
115
- }
116
- }
117
- if (best && bestScore < target.length * 0.6) return best;
118
- return void 0;
119
- }
120
- function levenshtein(a, b) {
121
- const m = a.length;
122
- const n = b.length;
123
- const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
124
- for (let i = 0; i <= m; i++) dp[i][0] = i;
125
- for (let j = 0; j <= n; j++) dp[0][j] = j;
126
- for (let i = 1; i <= m; i++) {
127
- for (let j = 1; j <= n; j++) {
128
- dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
129
- }
130
- }
131
- return dp[m][n];
132
- }
133
-
134
- export {
135
- checkLinks
136
- };