@parity-app/cli 0.6.1 → 0.6.3

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,13 +1,15 @@
1
- import { D as collectCustomProperties, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, j as lengthToPixels, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-C4faIpux.mjs";
2
- import "./src-5CrSA_RX.mjs";
1
+ import { a as plainObject, i as parseData, n as jsonText, t as finiteNumber } from "./schema-CiVy9tZT.mjs";
2
+ import { D as collectCustomProperties, M as packageManifest, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, j as lengthToPixels, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-YQY8r4mh.mjs";
3
+ import { r as readLibraryEdits, s as parseJsonc } from "./src-DzU4U2rh.mjs";
3
4
  import { a as publishedVersions, n as packageFile, o as repositoryFiles, r as publishedSource } from "./published-CdXoUgfD.mjs";
4
5
  import { createRequire } from "node:module";
5
6
  import { mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
6
7
  import { basename, dirname, extname, join, posix, relative, resolve, sep } from "node:path";
7
8
  import { promisify } from "node:util";
8
9
  import { createHash } from "node:crypto";
9
- import { existsSync, realpathSync } from "node:fs";
10
+ import { existsSync, realpathSync, statSync } from "node:fs";
10
11
  import { homedir } from "node:os";
12
+ import { z } from "zod";
11
13
  import { pathToFileURL } from "node:url";
12
14
  import ts from "typescript";
13
15
  import "semver";
@@ -526,28 +528,182 @@ function slashes(path) {
526
528
  return path.replaceAll("\\", "/");
527
529
  }
528
530
  ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.NonPrimitive | ts.TypeFlags.TypeParameter;
529
- // ../project/src/jsonc.ts
530
- /** Parses JSON with comments and trailing commas, as tsconfig files allow. Comment markers inside strings are kept. */
531
- function parseJsonc(text) {
532
- let output = "";
533
- let index = 0;
534
- while (index < text.length) {
535
- const char = text[index];
536
- if (char === "\"") {
537
- const start = index++;
538
- while (index < text.length && text[index] !== "\"") index += text[index] === "\\" ? 2 : 1;
539
- output += text.slice(start, ++index);
540
- } else if (char === "/" && text[index + 1] === "/") while (index < text.length && text[index] !== "\n") index++;
541
- else if (char === "/" && text[index + 1] === "*") {
542
- const end = text.indexOf("*/", index + 2);
543
- index = end === -1 ? text.length : end + 2;
544
- } else {
545
- output += char;
546
- index++;
547
- }
548
- }
549
- return JSON.parse(output.replace(/,(\s*[}\]])/g, "$1"));
550
- }
531
+ // ../tokens/src/dtcg-values.ts
532
+ /** A value written as CSS. */
533
+ const css = z.string();
534
+ const colorSpace = z.enum([
535
+ "srgb",
536
+ "srgb-linear",
537
+ "hsl",
538
+ "hwb",
539
+ "lab",
540
+ "lch",
541
+ "oklab",
542
+ "oklch",
543
+ "display-p3",
544
+ "a98-rgb",
545
+ "prophoto-rgb",
546
+ "rec2020",
547
+ "xyz-d65",
548
+ "xyz-d50"
549
+ ]);
550
+ const colorObject = z.object({
551
+ colorSpace,
552
+ components: z.array(z.union([finiteNumber, z.literal("none")])).length(3, "expected 3 components"),
553
+ alpha: finiteNumber.min(0).max(1).optional(),
554
+ hex: z.string().regex(/^#[\da-f]{6}$/i, "expected a 6-digit hex color such as #0a0a0a").optional()
555
+ });
556
+ const color = z.union([css, colorObject]);
557
+ const dimensionObject = z.object({
558
+ value: finiteNumber,
559
+ unit: z.string().regex(/^([a-z]+|%)$/i, "expected a unit such as px or rem")
560
+ });
561
+ const dimension = z.union([css, dimensionObject]);
562
+ const duration = z.union([css, z.object({
563
+ value: finiteNumber,
564
+ unit: z.enum(["ms", "s"])
565
+ })]);
566
+ /** A cubic Bézier's x coordinates, which CSS keeps between 0 and 1. */
567
+ const unitInterval = finiteNumber.min(0).max(1);
568
+ const cubicBezier = z.union([css, z.tuple([
569
+ unitInterval,
570
+ finiteNumber,
571
+ unitInterval,
572
+ finiteNumber
573
+ ])]);
574
+ const fontFamily = z.union([css, z.array(z.string()).min(1)]);
575
+ const fontWeight = z.union([css, finiteNumber.min(1).max(1e3)]);
576
+ const number = z.union([css, finiteNumber]);
577
+ const strokeStyle = z.union([css, z.object({
578
+ dashArray: z.array(dimension).min(1),
579
+ lineCap: z.enum([
580
+ "round",
581
+ "butt",
582
+ "square"
583
+ ])
584
+ })]);
585
+ const border = z.union([css, z.object({
586
+ color,
587
+ width: dimension,
588
+ style: strokeStyle
589
+ })]);
590
+ const transition = z.union([css, z.object({
591
+ duration,
592
+ delay: duration,
593
+ timingFunction: cubicBezier
594
+ })]);
595
+ const shadowLayer = z.object({
596
+ color,
597
+ offsetX: dimension.default("0"),
598
+ offsetY: dimension.default("0"),
599
+ blur: dimension.default("0"),
600
+ spread: dimension.default("0"),
601
+ inset: z.boolean().default(false)
602
+ });
603
+ const shadow = z.union([
604
+ css,
605
+ shadowLayer,
606
+ z.array(z.union([css, shadowLayer])).min(1)
607
+ ]);
608
+ const gradient = z.union([css, z.array(z.object({
609
+ color,
610
+ position: finiteNumber
611
+ })).min(1)]);
612
+ const typography = z.union([css, z.object({
613
+ fontFamily,
614
+ fontSize: dimension,
615
+ fontWeight: fontWeight.default("normal"),
616
+ letterSpacing: dimension.optional(),
617
+ lineHeight: z.union([number, dimensionObject]).optional()
618
+ })]);
619
+ border.transform(borderCss), color.transform(colorCss), cubicBezier.transform(cubicBezierCss), dimension.transform(dimensionCss), duration.transform(dimensionCss), fontFamily.transform(fontFamilyCss), fontWeight.transform(String), gradient.transform(gradientCss), number.transform(String), shadow.transform(shadowCss), strokeStyle.transform(strokeStyleCss), transition.transform(transitionCss), typography.transform(typographyCss);
620
+ const colorFunctions = /* @__PURE__ */ new Set([
621
+ "hsl",
622
+ "hwb",
623
+ "lab",
624
+ "lch",
625
+ "oklab",
626
+ "oklch"
627
+ ]);
628
+ function colorCss(value) {
629
+ if (typeof value === "string") return value;
630
+ const alpha = value.alpha !== void 0 && value.alpha < 1 ? value.alpha : void 0;
631
+ if (value.hex && alpha === void 0) return value.hex;
632
+ const slash = alpha === void 0 ? "" : ` / ${alpha}`;
633
+ if (value.colorSpace === "srgb") {
634
+ const [r, g, b] = value.components.map((part) => part === "none" ? part : Math.round(part * 255));
635
+ return `rgb(${r} ${g} ${b}${slash})`;
636
+ }
637
+ const components = value.components.join(" ");
638
+ if (colorFunctions.has(value.colorSpace)) return `${value.colorSpace}(${components}${slash})`;
639
+ return `color(${value.colorSpace} ${components}${slash})`;
640
+ }
641
+ function dimensionCss(value) {
642
+ return typeof value === "string" ? value : `${value.value}${value.unit}`;
643
+ }
644
+ function cubicBezierCss(value) {
645
+ return typeof value === "string" ? value : `cubic-bezier(${value.join(", ")})`;
646
+ }
647
+ function fontFamilyCss(value) {
648
+ return typeof value === "string" ? value : value.map(fontName).join(", ");
649
+ }
650
+ function fontName(name) {
651
+ return /^[\w-]+$/.test(name) ? name : `"${name}"`;
652
+ }
653
+ /** A stroke style as CSS: a border can't draw a dash pattern, so one is written as dashed. */
654
+ function strokeStyleCss(value) {
655
+ return typeof value === "string" ? value : "dashed";
656
+ }
657
+ function borderCss(value) {
658
+ if (typeof value === "string") return value;
659
+ return `${dimensionCss(value.width)} ${strokeStyleCss(value.style)} ${colorCss(value.color)}`;
660
+ }
661
+ function transitionCss(value) {
662
+ if (typeof value === "string") return value;
663
+ return `${dimensionCss(value.duration)} ${cubicBezierCss(value.timingFunction)} ${dimensionCss(value.delay)}`;
664
+ }
665
+ function shadowCss(value) {
666
+ if (typeof value === "string") return value;
667
+ return (Array.isArray(value) ? value : [value]).map((layer) => typeof layer === "string" ? layer : shadowLayerCss(layer)).join(", ");
668
+ }
669
+ function shadowLayerCss(layer) {
670
+ const lengths = [
671
+ layer.offsetX,
672
+ layer.offsetY,
673
+ layer.blur,
674
+ layer.spread
675
+ ].map(dimensionCss).join(" ");
676
+ return `${layer.inset ? "inset " : ""}${lengths} ${colorCss(layer.color)}`;
677
+ }
678
+ function gradientCss(value) {
679
+ if (typeof value === "string") return value;
680
+ return `linear-gradient(${value.map((stop) => `${colorCss(stop.color)} ${Math.round(stop.position * 1e3) / 10}%`).join(", ")})`;
681
+ }
682
+ function typographyCss(value) {
683
+ if (typeof value === "string") return value;
684
+ const { lineHeight } = value;
685
+ const line = lineHeight === void 0 ? "" : `/${typeof lineHeight === "object" ? dimensionCss(lineHeight) : lineHeight}`;
686
+ return `${value.fontWeight} ${dimensionCss(value.fontSize)}${line} ${fontFamilyCss(value.fontFamily)}`;
687
+ }
688
+ // ../tokens/src/dtcg.ts
689
+ /** Token groups, or `$ref`s to them in this file or another. */
690
+ const tokenSources = z.array(plainObject);
691
+ z.object({ sources: tokenSources });
692
+ const resolverModifier = z.object({
693
+ contexts: z.record(z.string(), tokenSources).transform((contexts) => new Map(Object.entries(contexts))),
694
+ default: z.string().optional()
695
+ });
696
+ z.object({ $ref: z.string() });
697
+ resolverModifier.extend({ name: z.string().optional() });
698
+ z.object({
699
+ $type: z.string().optional(),
700
+ $description: z.string().optional(),
701
+ $extensions: z.object({ parity: z.object({
702
+ var: z.string().optional(),
703
+ category: z.string().optional(),
704
+ lineHeight: z.string().optional()
705
+ }).optional() }).optional()
706
+ });
551
707
  // ../tokens/src/policy.ts
552
708
  /**
553
709
  * At-rules that don't pick a theme: a cascade layer only orders rules, and a feature check holds whatever the theme.
@@ -757,6 +913,247 @@ new Intl.Collator("en", {
757
913
  numeric: true,
758
914
  sensitivity: "base"
759
915
  });
916
+ // ../project/src/packages.ts
917
+ /**
918
+ * The package a folder's code gets for `name`, found the way Node finds packages: in `node_modules` here or in a folder
919
+ * above, with links followed. It reads the package's own package.json, which its `exports` may leave out of reach of
920
+ * `require.resolve`, and never falls back to NODE_PATH, which pnpm's bin shims point at Parity's own dependencies.
921
+ * Throws when the manifest isn't a package's.
922
+ */
923
+ async function findPackage(from, name) {
924
+ for (let folder = resolve(from);; folder = dirname(folder)) {
925
+ const installedAt = join(folder, "node_modules", name);
926
+ const text = await readFile(join(installedAt, "package.json"), "utf8").catch(() => void 0);
927
+ if (text !== void 0) {
928
+ const manifest = readManifest(text, join(installedAt, "package.json"));
929
+ return {
930
+ dir: await realpath(installedAt),
931
+ installedAt,
932
+ manifest
933
+ };
934
+ }
935
+ if (dirname(folder) === folder) return void 0;
936
+ }
937
+ }
938
+ /** The package in a folder, or nothing when it has no package.json. Throws when the manifest isn't a package's. */
939
+ async function readPackage(dir) {
940
+ const file = join(dir, "package.json");
941
+ const text = await readFile(file, "utf8").catch(() => void 0);
942
+ return text === void 0 ? void 0 : {
943
+ dir,
944
+ manifest: readManifest(text, file)
945
+ };
946
+ }
947
+ function readManifest(text, file) {
948
+ try {
949
+ return parseData(jsonText(packageManifest), text);
950
+ } catch (error) {
951
+ throw new TypeError(`${file}: ${error instanceof Error ? error.message : String(error)}`);
952
+ }
953
+ }
954
+ /** A bare specifier's package and the entry point in it: `@acme/ui/button` is `@acme/ui` and `./button`. */
955
+ function splitSpecifier(specifier) {
956
+ const parts = specifier.split("/");
957
+ const length = specifier.startsWith("@") ? 2 : 1;
958
+ const rest = parts.slice(length).join("/");
959
+ return {
960
+ name: parts.slice(0, length).join("/"),
961
+ subpath: rest ? `./${rest}` : "."
962
+ };
963
+ }
964
+ const conditions = {
965
+ types: [
966
+ "types",
967
+ "import",
968
+ "default",
969
+ "require"
970
+ ],
971
+ runtime: [
972
+ "node",
973
+ "import",
974
+ "default"
975
+ ],
976
+ source: [
977
+ "source",
978
+ "types",
979
+ "import",
980
+ "default"
981
+ ],
982
+ style: [
983
+ "style",
984
+ "import",
985
+ "default"
986
+ ]
987
+ };
988
+ /** Which files a target may lead to for each use: declarations for types, anything but them otherwise. */
989
+ const accepts = {
990
+ types: (file) => isDeclaration(file),
991
+ runtime: (file) => !isDeclaration(file),
992
+ source: () => true,
993
+ style: (file) => !isDeclaration(file)
994
+ };
995
+ /**
996
+ * The file one of a package's entry points leads to for a use, or nothing when no file is there. `subpath` is the
997
+ * entry point as `exports` names it: `.` for the package itself, or one such as `./tailwind.css`, which can be written
998
+ * `tailwind.css`. A package that doesn't list an entry point in `exports` is read as older packages are: `types` or
999
+ * `typings` for declarations, `module` or `main` for its module, and `style` for its stylesheet.
1000
+ */
1001
+ function packageEntry(pkg, use, subpath = ".") {
1002
+ const entry = subpath === "." || subpath.startsWith("./") ? subpath : `./${subpath}`;
1003
+ for (const candidate of entryCandidates(pkg.manifest, use, entry)) {
1004
+ const file = candidate && join(pkg.dir, candidate);
1005
+ if (file && isFile(file)) return file;
1006
+ }
1007
+ }
1008
+ function entryCandidates(manifest, use, entry) {
1009
+ const root = entry === ".";
1010
+ const path = entry.slice(2);
1011
+ const exported = exportTarget(manifest.exports, entry, conditions[use], accepts[use]);
1012
+ switch (use) {
1013
+ case "types": return [
1014
+ exported,
1015
+ ...root ? [manifest.types, manifest.typings] : [],
1016
+ ...entryCandidates(manifest, "runtime", entry).map((file) => file && declarationOf(file)),
1017
+ root ? "index.d.ts" : `${path}/index.d.ts`,
1018
+ root ? void 0 : `${path}.d.ts`
1019
+ ];
1020
+ case "runtime": return [
1021
+ exported,
1022
+ ...root ? [manifest.module, ...moduleFiles(manifest.main)] : [],
1023
+ ...root || manifest.exports !== void 0 ? [] : moduleFiles(path)
1024
+ ];
1025
+ case "source": {
1026
+ const named = [exported, ...root ? [
1027
+ manifest.types,
1028
+ manifest.typings,
1029
+ manifest.module,
1030
+ manifest.main
1031
+ ] : []].find((file) => file !== void 0);
1032
+ return [...named && isBuilt(named) ? sourcesOf(named) : [named], ...root ? [
1033
+ "src/index.tsx",
1034
+ "src/index.ts",
1035
+ "src/index.jsx",
1036
+ "src/index.js",
1037
+ "index.tsx",
1038
+ "index.ts"
1039
+ ] : []];
1040
+ }
1041
+ case "style": return root ? [manifest.style, exported] : [exported, path];
1042
+ }
1043
+ }
1044
+ /** A `main` as Node reads it: the file, the file with `.js`, or a folder's `index.js`; `index.js` without one. */
1045
+ function moduleFiles(main) {
1046
+ return main ? [
1047
+ main,
1048
+ `${main}.js`,
1049
+ `${main}/index.js`
1050
+ ] : ["index.js"];
1051
+ }
1052
+ const stylesheetNames = [
1053
+ "tailwind.css",
1054
+ "styles.css",
1055
+ "style.css",
1056
+ "index.css",
1057
+ "theme.css"
1058
+ ];
1059
+ /**
1060
+ * The stylesheet a project imports to use a package, as a path from the package: its `style` field, else the CSS its
1061
+ * `exports` lists, the usual names first. Only one that leads to a file counts.
1062
+ */
1063
+ function packageStylesheet(pkg) {
1064
+ const { style, exports } = pkg.manifest;
1065
+ if (style && isFile(join(pkg.dir, style))) return style;
1066
+ const css = Object.keys(exports === void 0 ? {} : subpaths(exports)).filter((key) => key.endsWith(".css") && !key.includes("*")).map((key) => key.slice(2));
1067
+ const pick = stylesheetNames.find((name) => css.includes(name)) ?? css[0];
1068
+ return pick && packageEntry(pkg, "style", pick) ? pick : void 0;
1069
+ }
1070
+ /** `exports` by subpath: a map as written, or the package's one entry point, which is `.`. */
1071
+ function subpaths(exports) {
1072
+ if (typeof exports !== "object" || exports === null || Array.isArray(exports)) return { ".": exports };
1073
+ return Object.keys(exports).some((key) => key.startsWith(".")) ? exports : { ".": exports };
1074
+ }
1075
+ /**
1076
+ * Where `exports` leads for an entry point under these conditions: the entry point as written, else the longest
1077
+ * pattern that matches it (`./icons/*`), with what `*` stood for put in.
1078
+ */
1079
+ function exportTarget(exports, entry, wanted, accept) {
1080
+ if (exports === void 0) return void 0;
1081
+ const map = subpaths(exports);
1082
+ if (Object.hasOwn(map, entry)) return resolveTarget(map[entry], wanted, accept);
1083
+ let best;
1084
+ for (const key of Object.keys(map)) {
1085
+ const star = key.indexOf("*");
1086
+ if (star === -1) continue;
1087
+ const [prefix, suffix] = [key.slice(0, star), key.slice(star + 1)];
1088
+ if (entry.length < key.length || !entry.startsWith(prefix) || !entry.endsWith(suffix)) continue;
1089
+ if (!best || prefix.length > best.prefix.length) best = {
1090
+ key,
1091
+ prefix,
1092
+ match: entry.slice(prefix.length, entry.length - suffix.length)
1093
+ };
1094
+ }
1095
+ if (!best) return void 0;
1096
+ const { key, match } = best;
1097
+ return resolveTarget(map[key], wanted, (file) => accept(file.replaceAll("*", match)))?.replaceAll("*", match);
1098
+ }
1099
+ /** The first file a target leads to under the wanted conditions, taken in the order they're wanted. */
1100
+ function resolveTarget(target, wanted, accept) {
1101
+ if (typeof target === "string") return accept(target) ? target : void 0;
1102
+ if (target === null) return void 0;
1103
+ if (Array.isArray(target)) {
1104
+ for (const each of target) {
1105
+ const found = resolveTarget(each, wanted, accept);
1106
+ if (found) return found;
1107
+ }
1108
+ return;
1109
+ }
1110
+ for (const condition of wanted) {
1111
+ const found = Object.hasOwn(target, condition) ? resolveTarget(target[condition], wanted, accept) : void 0;
1112
+ if (found) return found;
1113
+ }
1114
+ }
1115
+ function isDeclaration(file) {
1116
+ return /\.d\.[cm]?ts$/.test(file);
1117
+ }
1118
+ /** The declarations TypeScript looks for beside a module: `index.d.ts` for `index.js`, `index.d.mts` for `index.mjs`. */
1119
+ function declarationOf(file) {
1120
+ const match = /\.([cm]?)jsx?$/.exec(file);
1121
+ return match ? `${file.slice(0, match.index)}.d.${match[1]}ts` : void 0;
1122
+ }
1123
+ /** Folders a package's build writes to, which its source isn't in. */
1124
+ const builtFolders = /* @__PURE__ */ new Set([
1125
+ "dist",
1126
+ "build",
1127
+ "lib",
1128
+ "out",
1129
+ "esm",
1130
+ "cjs"
1131
+ ]);
1132
+ /** A file a build wrote: declarations, or anything in a build folder at the package's root. */
1133
+ function isBuilt(file) {
1134
+ return isDeclaration(file) || builtFolders.has(file.replace(/^\.\//, "").split("/")[0]);
1135
+ }
1136
+ const sourceExtensions = [
1137
+ ".tsx",
1138
+ ".ts",
1139
+ ".jsx",
1140
+ ".js"
1141
+ ];
1142
+ /**
1143
+ * Where a built file's source may be, in the order to look: `dist/index.js` and `dist/index.d.ts` were built from
1144
+ * `src/index.tsx`, `src/index.ts`, `src/index.jsx` or `src/index.js`, and `dist/esm/button.js` from `src/button.tsx`.
1145
+ */
1146
+ function sourcesOf(file) {
1147
+ const parts = file.replace(/^\.\//, "").split("/");
1148
+ let start = 0;
1149
+ while (start < parts.length - 1 && builtFolders.has(parts[start])) start++;
1150
+ const rest = parts.slice(start).join("/").replace(/\.d\.[cm]?ts$|\.[cm]?jsx?$/, "");
1151
+ const stem = start > 0 ? `src/${rest}` : rest;
1152
+ return sourceExtensions.map((extension) => stem + extension);
1153
+ }
1154
+ function isFile(path) {
1155
+ return statSync(path, { throwIfNoEntry: false })?.isFile() ?? false;
1156
+ }
760
1157
  // ../project/src/styles.ts
761
1158
  /**
762
1159
  * Where an app keeps its global styles when neither `components.json` nor the entry says: Vite's and Create React App's
@@ -869,21 +1266,6 @@ async function readText(path) {
869
1266
  function toPosix(path) {
870
1267
  return path.replaceAll("\\", "/").replace(/^\.\//, "");
871
1268
  }
872
- // ../project/src/libraries.ts
873
- /**
874
- * Where a dependency is installed, found the way Node finds packages: in `node_modules` here or in a folder above. It
875
- * doesn't resolve `<name>/package.json`, because a package whose `exports` leaves that out can't be resolved that way.
876
- */
877
- async function installedPackage(root, importName) {
878
- for (let folder = resolve(root);; folder = dirname(folder)) {
879
- const candidate = join(folder, "node_modules", importName);
880
- if (await isFile(join(candidate, "package.json"))) return realpath(candidate);
881
- if (dirname(folder) === folder) return void 0;
882
- }
883
- }
884
- async function isFile(path) {
885
- return stat(path).then((stats) => stats.isFile(), () => false);
886
- }
887
1269
  /** A sentence that ends this far in is kept whole, rather than its words cut down to the length. */
888
1270
  const shortestSentence = 20;
889
1271
  /**
@@ -3746,7 +4128,6 @@ const presets = {
3746
4128
  id: style,
3747
4129
  name: `Shadcn ${style.charAt(0).toUpperCase()}${style.slice(1)}`,
3748
4130
  description: `Every shadcn component on Base UI, in the ${style} style, kept in step with upstream.`,
3749
- styles: "tailwind.css",
3750
4131
  examples: {
3751
4132
  paths: ["apps/v4/examples/base/"],
3752
4133
  anatomy: ["apps/v4/content/docs/components/base/"]
@@ -4449,16 +4830,16 @@ async function generateLibrary(options) {
4449
4830
  }
4450
4831
  async function describePackage(options, importName) {
4451
4832
  const root = resolve(options.root);
4452
- const dir = await installedPackage(root, importName);
4453
- if (!dir) throw new Error(`${importName} isn't installed in ${root}. Install it with the project's package manager first.`);
4454
- const pkg = JSON.parse(await readFile(join(dir, "package.json"), "utf8"));
4833
+ const installed = await findPackage(root, importName);
4834
+ if (!installed) throw new Error(`${importName} isn't installed in ${root}. Install it with the project's package manager first.`);
4835
+ const { dir, manifest: pkg } = installed;
4455
4836
  const name = pkg.name ?? importName;
4456
4837
  const version = pkg.version ?? "0.0.0";
4457
4838
  const preset = presets[name];
4458
4839
  const notes = [...preset?.notes ?? []];
4459
4840
  const iconImport = preset?.icons?.import;
4460
4841
  const componentImport = iconImport ?? preset?.components;
4461
- const entry = typesEntry(dir, pkg, componentImport ? subpath(componentImport, name) : ".");
4842
+ const entry = packageEntry(installed, "types", componentImport ? splitSpecifier(componentImport).subpath : ".")?.replaceAll("\\", "/");
4462
4843
  if (!entry) notes.push("No type declarations were found, so no components could be read.");
4463
4844
  const scan = entry ? findComponents({
4464
4845
  entries: [entry],
@@ -4473,8 +4854,9 @@ async function describePackage(options, importName) {
4473
4854
  const dataIcons = preset?.icons?.render !== void 0 && preset.icons.render !== "export";
4474
4855
  const isIcons = preset?.icons !== void 0 || looksLikeIcons(scan);
4475
4856
  const tokens = /* @__PURE__ */ new Map();
4476
- const styles = preset?.styles ?? stylesheetOf(dir, pkg);
4477
- if (styles) for (const token of cssTokens(await readStylesheet(exportedFile(dir, pkg, styles)))) tokens.set(token.var, token);
4857
+ const styles = preset?.styles ?? packageStylesheet(installed);
4858
+ const stylesheet = styles && packageEntry(installed, "style", styles);
4859
+ if (stylesheet) for (const token of cssTokens(await readStylesheet(stylesheet))) tokens.set(token.var, token);
4478
4860
  let breakpoints;
4479
4861
  if (preset?.theme) try {
4480
4862
  const theme = await preset.theme(loader(root, dir));
@@ -4522,7 +4904,7 @@ async function describePackage(options, importName) {
4522
4904
  if (preset?.icons?.variants) icons.variants = preset.icons.variants;
4523
4905
  if (!dataIcons) {
4524
4906
  const load = loader(root, dir);
4525
- const modules = await styleModules(name, typeof pkg.exports === "object" && pkg.exports !== null ? Object.keys(pkg.exports) : [], iconImport ?? name, load, await iconDrawer(load));
4907
+ const modules = await styleModules(name, typeof pkg.exports === "object" && pkg.exports !== null && !Array.isArray(pkg.exports) ? Object.keys(pkg.exports) : [], iconImport ?? name, load, await iconDrawer(load));
4526
4908
  if (modules) {
4527
4909
  const main = Object.keys(modules).find((style) => modules[style] === (iconImport ?? name));
4528
4910
  icons.variants = {
@@ -4663,7 +5045,7 @@ async function reviseLibrary(generated, options) {
4663
5045
  const edits = options.edits ?? kept;
4664
5046
  if (edits !== void 0) {
4665
5047
  manifest.edits = edits;
4666
- const resolved = parseLibraryEdits(typeof edits === "string" ? parseJsonc(await readFile(resolve(options.editsBase ?? options.root, edits), "utf8")) : edits);
5048
+ const resolved = await readLibraryEdits(edits, resolve(options.editsBase ?? options.root));
4667
5049
  const { orphans } = applyLibraryEdits(parseLibraryManifest(manifest), resolved);
4668
5050
  if (orphans.length > 0) report.orphanEdits = orphans;
4669
5051
  }
@@ -4753,7 +5135,7 @@ function summarizeParts(relations) {
4753
5135
  const appExtensions = [".tsx", ".jsx"];
4754
5136
  async function describeApp(options) {
4755
5137
  const root = resolve(options.root);
4756
- const pkg = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
5138
+ const pkg = (await readPackage(root))?.manifest ?? {};
4757
5139
  const notes = [];
4758
5140
  const tsconfig = readTsconfig(root);
4759
5141
  const { files } = await appFiles(root, { componentExtensions: appExtensions }, tsconfig);
@@ -4810,8 +5192,8 @@ async function describeApp(options) {
4810
5192
  async function appManifestPath(root) {
4811
5193
  const existing = (await readdir(root)).find((file) => file.endsWith(libraryManifestExtension));
4812
5194
  if (existing) return join(root, existing);
4813
- const pkg = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
4814
- return join(root, `${(pkg.name ?? basename(root)).replace(/^@[^/]+\//, "")}${libraryManifestExtension}`);
5195
+ const name = (await readPackage(root))?.manifest.name ?? basename(root);
5196
+ return join(root, `${name.replace(/^@[^/]+\//, "")}${libraryManifestExtension}`);
4815
5197
  }
4816
5198
  /**
4817
5199
  * A generated manifest laid over the file already there: what generating finds replaces what it found before, and
@@ -4872,56 +5254,6 @@ function defaultRange(version) {
4872
5254
  const [major = "0", minor = "0"] = version.split(/[.-]/);
4873
5255
  return major === "0" ? `^0.${minor}.0` : `^${major}.0.0`;
4874
5256
  }
4875
- function subpath(specifier, packageName) {
4876
- return specifier === packageName ? "." : `.${specifier.slice(packageName.length)}`;
4877
- }
4878
- /** The type declarations for one of a package's entry points, from `exports`, else `types`, else `index.d.ts`. */
4879
- function typesEntry(dir, pkg, entry) {
4880
- const exported = typeof pkg.exports === "object" && pkg.exports !== null ? pkg.exports : {};
4881
- const condition = (value) => {
4882
- if (typeof value === "string") return /\.d\.[cm]?ts$/.test(value) ? value : void 0;
4883
- if (typeof value !== "object" || value === null) return void 0;
4884
- const record = value;
4885
- for (const key of [
4886
- "types",
4887
- "import",
4888
- "default",
4889
- "require"
4890
- ]) {
4891
- const found = condition(record[key]);
4892
- if (found) return found;
4893
- }
4894
- };
4895
- const candidates = [
4896
- condition(exported[entry]),
4897
- entry === "." ? pkg.types ?? pkg.typings : void 0,
4898
- entry === "." ? "index.d.ts" : `${entry.slice(2)}/index.d.ts`,
4899
- entry === "." ? void 0 : `${entry.slice(2)}.d.ts`
4900
- ];
4901
- for (const candidate of candidates) if (candidate && existsSync(join(dir, candidate))) return join(dir, candidate).replaceAll("\\", "/");
4902
- }
4903
- /** The stylesheet a project imports to use a package: its `style` field, else the CSS its `exports` list first. */
4904
- function stylesheetOf(dir, pkg) {
4905
- if (pkg.style && existsSync(join(dir, pkg.style))) return pkg.style;
4906
- const css = (typeof pkg.exports === "object" && pkg.exports !== null ? Object.keys(pkg.exports) : []).filter((key) => key.endsWith(".css")).map((key) => key.slice(2));
4907
- const pick = [
4908
- "tailwind.css",
4909
- "styles.css",
4910
- "style.css",
4911
- "index.css",
4912
- "theme.css"
4913
- ].find((name) => css.includes(name)) ?? css[0];
4914
- if (!pick) return void 0;
4915
- const target = pkg.exports[`./${pick}`];
4916
- const file = typeof target === "string" ? target : target?.default;
4917
- return typeof file === "string" && existsSync(join(dir, file)) ? pick : void 0;
4918
- }
4919
- /** The file an export such as `tailwind.css` points at: `dist/tailwind.css` for Buildkit's styles. */
4920
- function exportedFile(dir, pkg, specifier) {
4921
- const target = (typeof pkg.exports === "object" && pkg.exports !== null ? pkg.exports : {})[`./${specifier}`];
4922
- const file = typeof target === "string" ? target : target?.default;
4923
- return join(dir, typeof file === "string" ? file : specifier);
4924
- }
4925
5257
  /** A DTCG token file the package ships, if it has one in the format; Buildkit's `tokens.json` isn't yet. */
4926
5258
  async function dtcgIn(dir) {
4927
5259
  for (const candidate of [
@@ -5052,25 +5384,8 @@ function resolveRequire(from, specifier) {
5052
5384
  }
5053
5385
  /** An ESM-only package's entry, from the `import` condition of its `exports`, which `require` can't see. */
5054
5386
  async function resolveImport(from, specifier) {
5055
- const name = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
5056
- const dir = await installedPackage(from, name);
5057
- if (!dir) return void 0;
5058
- const pkg = JSON.parse(await readFile(join(dir, "package.json"), "utf8"));
5059
- const exported = typeof pkg.exports === "object" && pkg.exports !== null ? pkg.exports : {};
5060
- const pick = (value) => {
5061
- if (typeof value === "string") return /\.d\.[cm]?ts$/.test(value) ? void 0 : value;
5062
- if (typeof value !== "object" || value === null) return void 0;
5063
- const record = value;
5064
- for (const key of [
5065
- "node",
5066
- "import",
5067
- "default"
5068
- ]) {
5069
- const found = pick(record[key]);
5070
- if (found) return found;
5071
- }
5072
- };
5073
- const file = pick(exported[subpath(specifier, name)]) ?? (specifier === name ? pkg.module : void 0);
5074
- return file ? join(dir, file) : void 0;
5387
+ const { name, subpath } = splitSpecifier(specifier);
5388
+ const installed = await findPackage(from, name);
5389
+ return installed && packageEntry(installed, "runtime", subpath);
5075
5390
  }
5076
5391
  export { appManifestPath, generateLibrary, manifestText, mergeManifest, parseLibraryEdits, reviseLibrary, iconVariants as t };