@proveanything/smartlinks 2.0.13 → 2.0.14

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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.13 | Generated: 2026-09-22T11:06:35.662Z
3
+ Version: 2.0.14 | Generated: 2026-09-22T11:19:25.044Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.13 | Generated: 2026-09-22T11:06:35.662Z
3
+ Version: 2.0.14 | Generated: 2026-09-22T11:19:25.044Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "2.0.13",
3
+ "version": "2.0.14",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -36,6 +36,7 @@
36
36
  "scripts/register-release.mjs",
37
37
  "scripts/publish.mjs",
38
38
  "scripts/doctor.mjs",
39
+ "scripts/lib/",
39
40
  "openapi.yaml",
40
41
  "README.md"
41
42
  ],
@@ -143,6 +143,47 @@ if (!checkEsm && problems.length === 0) {
143
143
  console.log(`${DIM}moduleFormat "${format}" — ESM path not in use; UMD bundles resolve shared deps from window globals.${RESET}`);
144
144
  }
145
145
 
146
+ // ---- CSS baseline (sl-baseline) --------------------------------------------
147
+ // If the app declares meta.cssBaseline, warn on any `sl-*` class it uses that isn't in
148
+ // the declared baseline version — those render nothing once the host's baseline is the
149
+ // only source. Heuristic (scans built bundle text for the distinctive `sl-` namespace)
150
+ // and WARN-only: it never fails the build.
151
+ if (meta.cssBaseline) {
152
+ let baseline = null;
153
+ try {
154
+ baseline = JSON.parse(readFileSync(resolve(here, '../dist/baseline.classes.json'), 'utf8'));
155
+ } catch {
156
+ warnings.push(`meta.cssBaseline is "${meta.cssBaseline}" but this SDK build has no baseline class list to check against.`);
157
+ }
158
+ if (baseline) {
159
+ if (baseline.version !== meta.cssBaseline) {
160
+ warnings.push(`meta.cssBaseline is "${meta.cssBaseline}" but this SDK ships baseline "${baseline.version}" — the host may serve a different set.`);
161
+ }
162
+ const baseSet = new Set(baseline.classes || []);
163
+ // Class usage lives in compiled markup strings — present in every bundle regardless
164
+ // of module format, so scan both umd + esm across all surfaces.
165
+ const used = new Set();
166
+ for (const [, block] of surfaces) {
167
+ for (const p of [block?.files?.js?.umd, block?.files?.js?.esm]) {
168
+ if (!p) continue;
169
+ const bp = resolveBundle(p);
170
+ if (!bp) continue;
171
+ for (const m of readFileSync(bp, 'utf8').matchAll(/\bsl-[a-z0-9-]+/g)) used.add(m[0]);
172
+ }
173
+ }
174
+ const unknown = [...used].filter((c) => !baseSet.has(c)).sort();
175
+ if (used.size === 0) {
176
+ console.log(`${DIM}cssBaseline (${baseline.version}) — declared; no sl-* classes found in the bundles.${RESET}`);
177
+ } else if (unknown.length === 0) {
178
+ console.log(`${GREEN}✓${RESET} cssBaseline ${DIM}(${baseline.version})${RESET} — all ${used.size} sl-* classes used are in the baseline`);
179
+ } else {
180
+ console.log(`${YELLOW}⚠${RESET} cssBaseline ${DIM}(${baseline.version})${RESET} — ${unknown.length} sl-* class${unknown.length === 1 ? '' : 'es'} used but not in the baseline (they will not render):`);
181
+ for (const c of unknown) console.log(` ${YELLOW}${c}${RESET}`);
182
+ warnings.push(`sl-* classes used but not in cssBaseline "${baseline.version}": ${unknown.join(', ')} — define them in your own CSS, fix the typo, or drop them.`);
183
+ }
184
+ }
185
+ }
186
+
146
187
  console.log('');
147
188
  for (const w of warnings) console.log(`${YELLOW}⚠ ${w}${RESET}`);
148
189
 
@@ -0,0 +1,57 @@
1
+ // Extract the *real* bare import specifiers from a (usually minified) ESM bundle.
2
+ //
3
+ // We LEX the module with es-module-lexer rather than text-scanning, so specifiers only
4
+ // come from genuine `import`/`export … from`/`import()` statements. Data that merely
5
+ // contains the word `from` — e.g. tailwind-merge's class map `{"gradient-from":[{from:…}]}`
6
+ // — can no longer masquerade as an import (the historical false-positive class).
7
+ //
8
+ // Relative, absolute-path, and http(s) specifiers are dropped (never contract entries);
9
+ // `node:` specifiers are kept so the caller can flag them (they must never appear in a
10
+ // browser bundle).
11
+
12
+ import { init, parse } from 'es-module-lexer';
13
+
14
+ await init;
15
+
16
+ // Legacy conservative regex — only used if the lexer throws (unexpected for valid ESM).
17
+ // Kept so the doctor degrades to "runs, approximately" rather than crashing.
18
+ function regexFallback(code) {
19
+ const specs = new Set();
20
+ const patterns = [
21
+ /\bfrom\s*["']([^"']+)["']/g,
22
+ /\bimport\s*["']([^"']+)["']/g,
23
+ /\bimport\(\s*["']([^"']+)["']\s*\)/g,
24
+ ];
25
+ for (const re of patterns) {
26
+ let m;
27
+ while ((m = re.exec(code))) specs.add(m[1]);
28
+ }
29
+ return [...specs].filter(keep);
30
+ }
31
+
32
+ function keep(spec) {
33
+ if (!spec) return false;
34
+ if (spec.startsWith('.') || spec.startsWith('/')) return false; // internal/relative
35
+ if (/^https?:/.test(spec)) return false; // absolute URL import
36
+ return true;
37
+ }
38
+
39
+ /**
40
+ * @param {string} code ESM bundle source
41
+ * @returns {string[]} deduped bare import specifiers (may include `node:` ones)
42
+ */
43
+ export function bareImportsOf(code) {
44
+ let imports;
45
+ try {
46
+ [imports] = parse(code);
47
+ } catch {
48
+ return regexFallback(code);
49
+ }
50
+ const specs = new Set();
51
+ for (const imp of imports) {
52
+ // `imp.n` is the resolved specifier for static imports, re-exports, and
53
+ // string-literal dynamic imports; undefined for `import(expr)` we can't resolve.
54
+ if (imp.n && keep(imp.n)) specs.add(imp.n);
55
+ }
56
+ return [...specs];
57
+ }