@akii09/pdfx-cli 0.1.2 → 0.1.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.
- package/dist/index.js +606 -203
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ var __export = (target, all) => {
|
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
|
|
11
11
|
// src/commands/add.ts
|
|
12
|
-
import
|
|
12
|
+
import path3 from "path";
|
|
13
13
|
|
|
14
14
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
15
15
|
var external_exports = {};
|
|
@@ -489,8 +489,8 @@ function getErrorMap() {
|
|
|
489
489
|
|
|
490
490
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
491
491
|
var makeIssue = (params) => {
|
|
492
|
-
const { data, path:
|
|
493
|
-
const fullPath = [...
|
|
492
|
+
const { data, path: path11, errorMaps, issueData } = params;
|
|
493
|
+
const fullPath = [...path11, ...issueData.path || []];
|
|
494
494
|
const fullIssue = {
|
|
495
495
|
...issueData,
|
|
496
496
|
path: fullPath
|
|
@@ -606,11 +606,11 @@ var errorUtil;
|
|
|
606
606
|
|
|
607
607
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
608
608
|
var ParseInputLazyPath = class {
|
|
609
|
-
constructor(parent, value,
|
|
609
|
+
constructor(parent, value, path11, key) {
|
|
610
610
|
this._cachedPath = [];
|
|
611
611
|
this.parent = parent;
|
|
612
612
|
this.data = value;
|
|
613
|
-
this._path =
|
|
613
|
+
this._path = path11;
|
|
614
614
|
this._key = key;
|
|
615
615
|
}
|
|
616
616
|
get path() {
|
|
@@ -4461,30 +4461,156 @@ import chalk from "chalk";
|
|
|
4461
4461
|
import ora from "ora";
|
|
4462
4462
|
import prompts from "prompts";
|
|
4463
4463
|
|
|
4464
|
-
// src/utils/
|
|
4465
|
-
import
|
|
4464
|
+
// src/utils/dependency-validator.ts
|
|
4465
|
+
import fs2 from "fs";
|
|
4466
4466
|
import path from "path";
|
|
4467
|
+
import semver from "semver";
|
|
4468
|
+
|
|
4469
|
+
// src/utils/read-json.ts
|
|
4470
|
+
import fs from "fs";
|
|
4471
|
+
function readJsonFile(filePath) {
|
|
4472
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
4473
|
+
try {
|
|
4474
|
+
return JSON.parse(raw);
|
|
4475
|
+
} catch (error) {
|
|
4476
|
+
const details = error instanceof Error ? error.message : String(error);
|
|
4477
|
+
throw new ConfigError(`Invalid JSON in ${filePath}: ${details}`);
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
|
|
4481
|
+
// src/utils/dependency-validator.ts
|
|
4482
|
+
var REQUIRED_VERSIONS = {
|
|
4483
|
+
"@react-pdf/renderer": ">=3.0.0",
|
|
4484
|
+
react: ">=16.8.0",
|
|
4485
|
+
node: ">=24.0.0"
|
|
4486
|
+
};
|
|
4487
|
+
function getPackageJson(cwd = process.cwd()) {
|
|
4488
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
4489
|
+
if (!fs2.existsSync(pkgPath)) {
|
|
4490
|
+
return null;
|
|
4491
|
+
}
|
|
4492
|
+
return readJsonFile(pkgPath);
|
|
4493
|
+
}
|
|
4494
|
+
function getInstalledVersion(packageName, cwd = process.cwd()) {
|
|
4495
|
+
const pkg = getPackageJson(cwd);
|
|
4496
|
+
if (!pkg) return null;
|
|
4497
|
+
const deps = {
|
|
4498
|
+
...pkg.dependencies,
|
|
4499
|
+
...pkg.devDependencies
|
|
4500
|
+
};
|
|
4501
|
+
const version = deps[packageName];
|
|
4502
|
+
if (!version) return null;
|
|
4503
|
+
return semver.clean(version) || semver.coerce(version)?.version || null;
|
|
4504
|
+
}
|
|
4505
|
+
function validateReactPdfRenderer(cwd = process.cwd()) {
|
|
4506
|
+
const version = getInstalledVersion("@react-pdf/renderer", cwd);
|
|
4507
|
+
const required = REQUIRED_VERSIONS["@react-pdf/renderer"];
|
|
4508
|
+
if (!version) {
|
|
4509
|
+
return {
|
|
4510
|
+
valid: false,
|
|
4511
|
+
installed: false,
|
|
4512
|
+
requiredVersion: required,
|
|
4513
|
+
message: "@react-pdf/renderer is not installed"
|
|
4514
|
+
};
|
|
4515
|
+
}
|
|
4516
|
+
const isCompatible = semver.satisfies(version, required);
|
|
4517
|
+
return {
|
|
4518
|
+
valid: isCompatible,
|
|
4519
|
+
installed: true,
|
|
4520
|
+
currentVersion: version,
|
|
4521
|
+
requiredVersion: required,
|
|
4522
|
+
message: isCompatible ? "@react-pdf/renderer version is compatible" : `@react-pdf/renderer version ${version} does not meet requirement ${required}`
|
|
4523
|
+
};
|
|
4524
|
+
}
|
|
4525
|
+
function validateReact(cwd = process.cwd()) {
|
|
4526
|
+
const version = getInstalledVersion("react", cwd);
|
|
4527
|
+
const required = REQUIRED_VERSIONS.react;
|
|
4528
|
+
if (!version) {
|
|
4529
|
+
return {
|
|
4530
|
+
valid: false,
|
|
4531
|
+
installed: false,
|
|
4532
|
+
requiredVersion: required,
|
|
4533
|
+
message: "React is not installed"
|
|
4534
|
+
};
|
|
4535
|
+
}
|
|
4536
|
+
const isCompatible = semver.satisfies(version, required);
|
|
4537
|
+
return {
|
|
4538
|
+
valid: isCompatible,
|
|
4539
|
+
installed: true,
|
|
4540
|
+
currentVersion: version,
|
|
4541
|
+
requiredVersion: required,
|
|
4542
|
+
message: isCompatible ? "React version is compatible" : `React version ${version} does not meet requirement ${required}`
|
|
4543
|
+
};
|
|
4544
|
+
}
|
|
4545
|
+
function validateNodeVersion() {
|
|
4546
|
+
const version = process.version;
|
|
4547
|
+
const required = REQUIRED_VERSIONS.node;
|
|
4548
|
+
const cleanVersion = semver.clean(version);
|
|
4549
|
+
if (!cleanVersion) {
|
|
4550
|
+
return {
|
|
4551
|
+
valid: false,
|
|
4552
|
+
installed: true,
|
|
4553
|
+
currentVersion: version,
|
|
4554
|
+
requiredVersion: required,
|
|
4555
|
+
message: `Unable to parse Node.js version: ${version}`
|
|
4556
|
+
};
|
|
4557
|
+
}
|
|
4558
|
+
const isCompatible = semver.satisfies(cleanVersion, required);
|
|
4559
|
+
return {
|
|
4560
|
+
valid: isCompatible,
|
|
4561
|
+
installed: true,
|
|
4562
|
+
currentVersion: cleanVersion,
|
|
4563
|
+
requiredVersion: required,
|
|
4564
|
+
message: isCompatible ? "Node.js version is compatible" : `Node.js version ${cleanVersion} does not meet requirement ${required}`
|
|
4565
|
+
};
|
|
4566
|
+
}
|
|
4567
|
+
function validateTypeScript(cwd = process.cwd()) {
|
|
4568
|
+
const tsVersion = getInstalledVersion("typescript", cwd);
|
|
4569
|
+
if (!tsVersion) {
|
|
4570
|
+
return null;
|
|
4571
|
+
}
|
|
4572
|
+
const typesInstalled = getInstalledVersion("@types/react-pdf", cwd);
|
|
4573
|
+
return {
|
|
4574
|
+
valid: !!typesInstalled,
|
|
4575
|
+
installed: !!typesInstalled,
|
|
4576
|
+
currentVersion: typesInstalled || void 0,
|
|
4577
|
+
requiredVersion: "latest",
|
|
4578
|
+
message: typesInstalled ? "TypeScript types for @react-pdf/renderer are installed" : "@types/react-pdf is recommended for TypeScript projects"
|
|
4579
|
+
};
|
|
4580
|
+
}
|
|
4581
|
+
function validateDependencies(cwd = process.cwd()) {
|
|
4582
|
+
return {
|
|
4583
|
+
reactPdfRenderer: validateReactPdfRenderer(cwd),
|
|
4584
|
+
react: validateReact(cwd),
|
|
4585
|
+
nodeJs: validateNodeVersion(),
|
|
4586
|
+
typescript: validateTypeScript(cwd) || void 0
|
|
4587
|
+
};
|
|
4588
|
+
}
|
|
4589
|
+
|
|
4590
|
+
// src/utils/file-system.ts
|
|
4591
|
+
import fs3 from "fs";
|
|
4592
|
+
import path2 from "path";
|
|
4467
4593
|
function ensureDir(dir) {
|
|
4468
|
-
if (!
|
|
4469
|
-
|
|
4594
|
+
if (!fs3.existsSync(dir)) {
|
|
4595
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
4470
4596
|
}
|
|
4471
4597
|
}
|
|
4472
4598
|
function writeFile(filePath, content) {
|
|
4473
|
-
const dir =
|
|
4599
|
+
const dir = path2.dirname(filePath);
|
|
4474
4600
|
ensureDir(dir);
|
|
4475
|
-
|
|
4601
|
+
fs3.writeFileSync(filePath, content, "utf-8");
|
|
4476
4602
|
}
|
|
4477
4603
|
function checkFileExists(filePath) {
|
|
4478
|
-
return
|
|
4604
|
+
return fs3.existsSync(filePath);
|
|
4479
4605
|
}
|
|
4480
4606
|
function normalizePath(...segments) {
|
|
4481
|
-
return
|
|
4607
|
+
return path2.resolve(...segments);
|
|
4482
4608
|
}
|
|
4483
4609
|
function isPathWithinDirectory(resolvedPath, targetDir) {
|
|
4484
4610
|
const normalizedTarget = normalizePath(targetDir);
|
|
4485
4611
|
const normalizedResolved = normalizePath(resolvedPath);
|
|
4486
4612
|
if (normalizedResolved === normalizedTarget) return true;
|
|
4487
|
-
const prefix = normalizedTarget.endsWith(
|
|
4613
|
+
const prefix = normalizedTarget.endsWith(path2.sep) ? normalizedTarget : normalizedTarget + path2.sep;
|
|
4488
4614
|
return normalizedResolved.startsWith(prefix);
|
|
4489
4615
|
}
|
|
4490
4616
|
function safePath(targetDir, fileName) {
|
|
@@ -4754,18 +4880,6 @@ export function useSafeMemo<T>(factory: () => T, deps: DependencyList): T {
|
|
|
4754
4880
|
`;
|
|
4755
4881
|
}
|
|
4756
4882
|
|
|
4757
|
-
// src/utils/read-json.ts
|
|
4758
|
-
import fs2 from "fs";
|
|
4759
|
-
function readJsonFile(filePath) {
|
|
4760
|
-
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
4761
|
-
try {
|
|
4762
|
-
return JSON.parse(raw);
|
|
4763
|
-
} catch (error) {
|
|
4764
|
-
const details = error instanceof Error ? error.message : String(error);
|
|
4765
|
-
throw new ConfigError(`Invalid JSON in ${filePath}: ${details}`);
|
|
4766
|
-
}
|
|
4767
|
-
}
|
|
4768
|
-
|
|
4769
4883
|
// src/commands/add.ts
|
|
4770
4884
|
function readConfig(configPath) {
|
|
4771
4885
|
const raw = readJsonFile(configPath);
|
|
@@ -4810,15 +4924,15 @@ async function fetchComponent(name, registryUrl) {
|
|
|
4810
4924
|
return result.data;
|
|
4811
4925
|
}
|
|
4812
4926
|
function resolveThemeImport(componentDir, themePath, fileContent) {
|
|
4813
|
-
const absComponentDir =
|
|
4814
|
-
const absThemePath =
|
|
4927
|
+
const absComponentDir = path3.resolve(process.cwd(), componentDir);
|
|
4928
|
+
const absThemePath = path3.resolve(process.cwd(), themePath);
|
|
4815
4929
|
const themeImportTarget = absThemePath.replace(/\.tsx?$/, "");
|
|
4816
|
-
let relativePath =
|
|
4930
|
+
let relativePath = path3.relative(absComponentDir, themeImportTarget);
|
|
4817
4931
|
if (!relativePath.startsWith(".")) {
|
|
4818
4932
|
relativePath = `./${relativePath}`;
|
|
4819
4933
|
}
|
|
4820
|
-
const absContextPath =
|
|
4821
|
-
let relativeContextPath =
|
|
4934
|
+
const absContextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context");
|
|
4935
|
+
let relativeContextPath = path3.relative(absComponentDir, absContextPath);
|
|
4822
4936
|
if (!relativeContextPath.startsWith(".")) {
|
|
4823
4937
|
relativeContextPath = `./${relativeContextPath}`;
|
|
4824
4938
|
}
|
|
@@ -4834,13 +4948,13 @@ function resolveThemeImport(componentDir, themePath, fileContent) {
|
|
|
4834
4948
|
}
|
|
4835
4949
|
async function installComponent(name, config, force) {
|
|
4836
4950
|
const component = await fetchComponent(name, config.registry);
|
|
4837
|
-
const targetDir =
|
|
4838
|
-
const componentDir =
|
|
4951
|
+
const targetDir = path3.resolve(process.cwd(), config.componentDir);
|
|
4952
|
+
const componentDir = path3.join(targetDir, component.name);
|
|
4839
4953
|
ensureDir(componentDir);
|
|
4840
|
-
const componentRelDir =
|
|
4954
|
+
const componentRelDir = path3.join(config.componentDir, component.name);
|
|
4841
4955
|
const filesToWrite = [];
|
|
4842
4956
|
for (const file of component.files) {
|
|
4843
|
-
const fileName =
|
|
4957
|
+
const fileName = path3.basename(file.path);
|
|
4844
4958
|
const filePath = safePath(componentDir, fileName);
|
|
4845
4959
|
let content = file.content;
|
|
4846
4960
|
if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
|
|
@@ -4851,7 +4965,7 @@ async function installComponent(name, config, force) {
|
|
|
4851
4965
|
if (!force) {
|
|
4852
4966
|
const existing = filesToWrite.filter((f) => checkFileExists(f.filePath));
|
|
4853
4967
|
if (existing.length > 0) {
|
|
4854
|
-
const fileNames = existing.map((f) =>
|
|
4968
|
+
const fileNames = existing.map((f) => path3.basename(f.filePath)).join(", ");
|
|
4855
4969
|
const { overwrite } = await prompts({
|
|
4856
4970
|
type: "confirm",
|
|
4857
4971
|
name: "overwrite",
|
|
@@ -4867,17 +4981,35 @@ async function installComponent(name, config, force) {
|
|
|
4867
4981
|
writeFile(file.filePath, file.content);
|
|
4868
4982
|
}
|
|
4869
4983
|
if (config.theme) {
|
|
4870
|
-
const absThemePath =
|
|
4871
|
-
const contextPath =
|
|
4984
|
+
const absThemePath = path3.resolve(process.cwd(), config.theme);
|
|
4985
|
+
const contextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context.tsx");
|
|
4872
4986
|
if (!checkFileExists(contextPath)) {
|
|
4873
|
-
ensureDir(
|
|
4987
|
+
ensureDir(path3.dirname(contextPath));
|
|
4874
4988
|
writeFile(contextPath, generateThemeContextFile());
|
|
4875
4989
|
}
|
|
4876
4990
|
}
|
|
4877
4991
|
return;
|
|
4878
4992
|
}
|
|
4879
4993
|
async function add(components, options = {}) {
|
|
4880
|
-
const
|
|
4994
|
+
const reactPdfCheck = validateReactPdfRenderer();
|
|
4995
|
+
if (!reactPdfCheck.installed) {
|
|
4996
|
+
console.error(chalk.red("\nError: @react-pdf/renderer is not installed\n"));
|
|
4997
|
+
console.log(chalk.yellow(" PDFx components require @react-pdf/renderer to work.\n"));
|
|
4998
|
+
console.log(chalk.cyan(" Run: pdfx init"));
|
|
4999
|
+
console.log(chalk.dim(" or install manually: npm install @react-pdf/renderer\n"));
|
|
5000
|
+
process.exit(1);
|
|
5001
|
+
}
|
|
5002
|
+
if (!reactPdfCheck.valid) {
|
|
5003
|
+
console.log(
|
|
5004
|
+
chalk.yellow(
|
|
5005
|
+
`
|
|
5006
|
+
\u26A0 Warning: ${reactPdfCheck.message}
|
|
5007
|
+
${chalk.dim("\u2192")} You may encounter compatibility issues
|
|
5008
|
+
`
|
|
5009
|
+
)
|
|
5010
|
+
);
|
|
5011
|
+
}
|
|
5012
|
+
const configPath = path3.join(process.cwd(), "pdfx.json");
|
|
4881
5013
|
if (!checkFileExists(configPath)) {
|
|
4882
5014
|
console.error(chalk.red("Error: pdfx.json not found"));
|
|
4883
5015
|
console.log(chalk.yellow("Run: pdfx init"));
|
|
@@ -4933,7 +5065,7 @@ async function add(components, options = {}) {
|
|
|
4933
5065
|
console.log(chalk.yellow(`Failed to add: ${failed.join(", ")}`));
|
|
4934
5066
|
}
|
|
4935
5067
|
if (failed.length < components.length) {
|
|
4936
|
-
const resolvedDir =
|
|
5068
|
+
const resolvedDir = path3.resolve(process.cwd(), config.componentDir);
|
|
4937
5069
|
console.log(chalk.green("Done!"));
|
|
4938
5070
|
console.log(chalk.dim(`Components installed to: ${resolvedDir}
|
|
4939
5071
|
`));
|
|
@@ -4944,13 +5076,13 @@ async function add(components, options = {}) {
|
|
|
4944
5076
|
}
|
|
4945
5077
|
|
|
4946
5078
|
// src/commands/diff.ts
|
|
4947
|
-
import
|
|
4948
|
-
import
|
|
5079
|
+
import fs4 from "fs";
|
|
5080
|
+
import path4 from "path";
|
|
4949
5081
|
import chalk2 from "chalk";
|
|
4950
5082
|
import ora2 from "ora";
|
|
4951
5083
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
4952
5084
|
async function diff(components) {
|
|
4953
|
-
const configPath =
|
|
5085
|
+
const configPath = path4.join(process.cwd(), "pdfx.json");
|
|
4954
5086
|
if (!checkFileExists(configPath)) {
|
|
4955
5087
|
console.error(chalk2.red("Error: pdfx.json not found"));
|
|
4956
5088
|
console.log(chalk2.yellow("Run: pdfx init"));
|
|
@@ -4963,7 +5095,7 @@ async function diff(components) {
|
|
|
4963
5095
|
process.exit(1);
|
|
4964
5096
|
}
|
|
4965
5097
|
const config = configResult.data;
|
|
4966
|
-
const targetDir =
|
|
5098
|
+
const targetDir = path4.resolve(process.cwd(), config.componentDir);
|
|
4967
5099
|
for (const componentName of components) {
|
|
4968
5100
|
const nameResult = componentNameSchema.safeParse(componentName);
|
|
4969
5101
|
if (!nameResult.success) {
|
|
@@ -4995,17 +5127,17 @@ async function diff(components) {
|
|
|
4995
5127
|
}
|
|
4996
5128
|
const component = result.data;
|
|
4997
5129
|
spinner.stop();
|
|
4998
|
-
const componentSubDir =
|
|
5130
|
+
const componentSubDir = path4.join(targetDir, component.name);
|
|
4999
5131
|
for (const file of component.files) {
|
|
5000
|
-
const fileName =
|
|
5132
|
+
const fileName = path4.basename(file.path);
|
|
5001
5133
|
const localPath = safePath(componentSubDir, fileName);
|
|
5002
5134
|
if (!checkFileExists(localPath)) {
|
|
5003
5135
|
console.log(chalk2.yellow(` ${fileName}: not installed locally`));
|
|
5004
5136
|
continue;
|
|
5005
5137
|
}
|
|
5006
|
-
const localContent =
|
|
5138
|
+
const localContent = fs4.readFileSync(localPath, "utf-8");
|
|
5007
5139
|
const registryContent = config.theme && (file.content.includes("pdfx-theme") || file.content.includes("pdfx-theme-context")) ? resolveThemeImport(
|
|
5008
|
-
|
|
5140
|
+
path4.join(config.componentDir, component.name),
|
|
5009
5141
|
config.theme,
|
|
5010
5142
|
file.content
|
|
5011
5143
|
) : file.content;
|
|
@@ -5028,11 +5160,11 @@ async function diff(components) {
|
|
|
5028
5160
|
}
|
|
5029
5161
|
|
|
5030
5162
|
// src/commands/init.ts
|
|
5031
|
-
import
|
|
5032
|
-
import
|
|
5033
|
-
import
|
|
5034
|
-
import
|
|
5035
|
-
import
|
|
5163
|
+
import fs7 from "fs";
|
|
5164
|
+
import path7 from "path";
|
|
5165
|
+
import chalk5 from "chalk";
|
|
5166
|
+
import ora4 from "ora";
|
|
5167
|
+
import prompts3 from "prompts";
|
|
5036
5168
|
|
|
5037
5169
|
// src/constants.ts
|
|
5038
5170
|
var DEFAULTS = {
|
|
@@ -5046,23 +5178,294 @@ var REGISTRY_SUBPATHS = {
|
|
|
5046
5178
|
TEMPLATES: "templates"
|
|
5047
5179
|
};
|
|
5048
5180
|
|
|
5181
|
+
// src/utils/install-dependencies.ts
|
|
5182
|
+
import chalk3 from "chalk";
|
|
5183
|
+
import { execa } from "execa";
|
|
5184
|
+
import ora3 from "ora";
|
|
5185
|
+
import prompts2 from "prompts";
|
|
5186
|
+
|
|
5187
|
+
// src/utils/package-manager.ts
|
|
5188
|
+
import fs5 from "fs";
|
|
5189
|
+
import path5 from "path";
|
|
5190
|
+
var PACKAGE_MANAGERS = {
|
|
5191
|
+
pnpm: {
|
|
5192
|
+
name: "pnpm",
|
|
5193
|
+
lockfile: "pnpm-lock.yaml",
|
|
5194
|
+
installCommand: "pnpm add"
|
|
5195
|
+
},
|
|
5196
|
+
yarn: {
|
|
5197
|
+
name: "yarn",
|
|
5198
|
+
lockfile: "yarn.lock",
|
|
5199
|
+
installCommand: "yarn add"
|
|
5200
|
+
},
|
|
5201
|
+
bun: {
|
|
5202
|
+
name: "bun",
|
|
5203
|
+
lockfile: "bun.lockb",
|
|
5204
|
+
installCommand: "bun add"
|
|
5205
|
+
},
|
|
5206
|
+
npm: {
|
|
5207
|
+
name: "npm",
|
|
5208
|
+
lockfile: "package-lock.json",
|
|
5209
|
+
installCommand: "npm install"
|
|
5210
|
+
}
|
|
5211
|
+
};
|
|
5212
|
+
function detectPackageManager(cwd = process.cwd()) {
|
|
5213
|
+
const managers = ["pnpm", "yarn", "bun", "npm"];
|
|
5214
|
+
for (const manager of managers) {
|
|
5215
|
+
const info = PACKAGE_MANAGERS[manager];
|
|
5216
|
+
const lockfilePath = path5.join(cwd, info.lockfile);
|
|
5217
|
+
if (fs5.existsSync(lockfilePath)) {
|
|
5218
|
+
return info;
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
return PACKAGE_MANAGERS.npm;
|
|
5222
|
+
}
|
|
5223
|
+
function getInstallCommand(packageManager, packages, devDependency = false) {
|
|
5224
|
+
const pm = PACKAGE_MANAGERS[packageManager];
|
|
5225
|
+
const devFlag = devDependency ? packageManager === "npm" ? "--save-dev" : "-D" : "";
|
|
5226
|
+
return `${pm.installCommand} ${packages.join(" ")} ${devFlag}`.trim();
|
|
5227
|
+
}
|
|
5228
|
+
|
|
5229
|
+
// src/utils/install-dependencies.ts
|
|
5230
|
+
async function promptAndInstallReactPdf(validation, cwd = process.cwd()) {
|
|
5231
|
+
if (validation.installed && validation.valid) {
|
|
5232
|
+
return {
|
|
5233
|
+
success: true,
|
|
5234
|
+
message: "@react-pdf/renderer is already installed and compatible"
|
|
5235
|
+
};
|
|
5236
|
+
}
|
|
5237
|
+
const pm = detectPackageManager(cwd);
|
|
5238
|
+
const packageName = "@react-pdf/renderer";
|
|
5239
|
+
const installCmd = getInstallCommand(pm.name, [packageName]);
|
|
5240
|
+
console.log(chalk3.yellow("\n \u26A0 @react-pdf/renderer is required but not installed\n"));
|
|
5241
|
+
console.log(chalk3.dim(` This command will run: ${installCmd}
|
|
5242
|
+
`));
|
|
5243
|
+
const { shouldInstall } = await prompts2({
|
|
5244
|
+
type: "confirm",
|
|
5245
|
+
name: "shouldInstall",
|
|
5246
|
+
message: "Install @react-pdf/renderer now?",
|
|
5247
|
+
initial: true
|
|
5248
|
+
});
|
|
5249
|
+
if (!shouldInstall) {
|
|
5250
|
+
return {
|
|
5251
|
+
success: false,
|
|
5252
|
+
message: `Installation cancelled. Please install manually:
|
|
5253
|
+
${chalk3.cyan(installCmd)}`
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
const spinner = ora3("Installing @react-pdf/renderer...").start();
|
|
5257
|
+
try {
|
|
5258
|
+
await execa(pm.name, ["add", packageName], {
|
|
5259
|
+
cwd,
|
|
5260
|
+
stdio: "pipe"
|
|
5261
|
+
});
|
|
5262
|
+
spinner.succeed("Installed @react-pdf/renderer");
|
|
5263
|
+
return {
|
|
5264
|
+
success: true,
|
|
5265
|
+
message: "@react-pdf/renderer installed successfully"
|
|
5266
|
+
};
|
|
5267
|
+
} catch (error) {
|
|
5268
|
+
spinner.fail("Failed to install @react-pdf/renderer");
|
|
5269
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5270
|
+
return {
|
|
5271
|
+
success: false,
|
|
5272
|
+
message: `Installation failed: ${message}
|
|
5273
|
+
Try manually: ${chalk3.cyan(installCmd)}`
|
|
5274
|
+
};
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
5277
|
+
async function ensureReactPdfRenderer(validation, cwd = process.cwd()) {
|
|
5278
|
+
if (!validation.installed) {
|
|
5279
|
+
const result = await promptAndInstallReactPdf(validation, cwd);
|
|
5280
|
+
if (!result.success) {
|
|
5281
|
+
console.error(chalk3.red(`
|
|
5282
|
+
${result.message}
|
|
5283
|
+
`));
|
|
5284
|
+
return false;
|
|
5285
|
+
}
|
|
5286
|
+
return true;
|
|
5287
|
+
}
|
|
5288
|
+
if (!validation.valid) {
|
|
5289
|
+
console.log(
|
|
5290
|
+
chalk3.yellow(
|
|
5291
|
+
`
|
|
5292
|
+
\u26A0 ${validation.message}
|
|
5293
|
+
${chalk3.dim("\u2192")} You may encounter compatibility issues
|
|
5294
|
+
`
|
|
5295
|
+
)
|
|
5296
|
+
);
|
|
5297
|
+
}
|
|
5298
|
+
return true;
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
// src/utils/pre-flight.ts
|
|
5302
|
+
import chalk4 from "chalk";
|
|
5303
|
+
|
|
5304
|
+
// src/utils/environment-validator.ts
|
|
5305
|
+
import fs6 from "fs";
|
|
5306
|
+
import path6 from "path";
|
|
5307
|
+
function validatePackageJson(cwd = process.cwd()) {
|
|
5308
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
5309
|
+
const exists = fs6.existsSync(pkgPath);
|
|
5310
|
+
return {
|
|
5311
|
+
valid: exists,
|
|
5312
|
+
message: exists ? "package.json found" : "No package.json found in current directory",
|
|
5313
|
+
fixCommand: exists ? void 0 : 'Run "npm init" or "pnpm init" to create a package.json'
|
|
5314
|
+
};
|
|
5315
|
+
}
|
|
5316
|
+
function validateReactProject(cwd = process.cwd()) {
|
|
5317
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
5318
|
+
if (!fs6.existsSync(pkgPath)) {
|
|
5319
|
+
return {
|
|
5320
|
+
valid: false,
|
|
5321
|
+
message: "Cannot validate React project without package.json"
|
|
5322
|
+
};
|
|
5323
|
+
}
|
|
5324
|
+
try {
|
|
5325
|
+
const pkg = readJsonFile(pkgPath);
|
|
5326
|
+
const deps = {
|
|
5327
|
+
...pkg.dependencies,
|
|
5328
|
+
...pkg.devDependencies
|
|
5329
|
+
};
|
|
5330
|
+
const hasReact = "react" in deps;
|
|
5331
|
+
return {
|
|
5332
|
+
valid: hasReact,
|
|
5333
|
+
message: hasReact ? "React is installed" : "This does not appear to be a React project",
|
|
5334
|
+
fixCommand: hasReact ? void 0 : "Install React: npx create-vite@latest or npx create-react-app"
|
|
5335
|
+
};
|
|
5336
|
+
} catch {
|
|
5337
|
+
return {
|
|
5338
|
+
valid: false,
|
|
5339
|
+
message: "Failed to read package.json"
|
|
5340
|
+
};
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
function validatePdfxConfig(cwd = process.cwd()) {
|
|
5344
|
+
const configPath = path6.join(cwd, "pdfx.json");
|
|
5345
|
+
const exists = fs6.existsSync(configPath);
|
|
5346
|
+
return {
|
|
5347
|
+
valid: true,
|
|
5348
|
+
// Not blocking
|
|
5349
|
+
message: exists ? "pdfx.json already exists (will prompt to overwrite)" : "No existing pdfx.json"
|
|
5350
|
+
};
|
|
5351
|
+
}
|
|
5352
|
+
function validateEnvironment(cwd = process.cwd()) {
|
|
5353
|
+
return {
|
|
5354
|
+
hasPackageJson: validatePackageJson(cwd),
|
|
5355
|
+
isReactProject: validateReactProject(cwd),
|
|
5356
|
+
hasPdfxConfig: validatePdfxConfig(cwd)
|
|
5357
|
+
};
|
|
5358
|
+
}
|
|
5359
|
+
|
|
5360
|
+
// src/utils/pre-flight.ts
|
|
5361
|
+
function runPreFlightChecks(cwd = process.cwd()) {
|
|
5362
|
+
const environment = validateEnvironment(cwd);
|
|
5363
|
+
const dependencies = validateDependencies(cwd);
|
|
5364
|
+
const blockingErrors = [];
|
|
5365
|
+
const warnings = [];
|
|
5366
|
+
if (!environment.hasPackageJson.valid) {
|
|
5367
|
+
blockingErrors.push(
|
|
5368
|
+
`${environment.hasPackageJson.message}
|
|
5369
|
+
${chalk4.dim("\u2192")} ${environment.hasPackageJson.fixCommand}`
|
|
5370
|
+
);
|
|
5371
|
+
}
|
|
5372
|
+
if (!environment.isReactProject.valid) {
|
|
5373
|
+
blockingErrors.push(
|
|
5374
|
+
`${environment.isReactProject.message}
|
|
5375
|
+
${chalk4.dim("\u2192")} ${environment.isReactProject.fixCommand}`
|
|
5376
|
+
);
|
|
5377
|
+
}
|
|
5378
|
+
if (!dependencies.nodeJs.valid) {
|
|
5379
|
+
blockingErrors.push(
|
|
5380
|
+
`${dependencies.nodeJs.message}
|
|
5381
|
+
${chalk4.dim("\u2192")} Current: ${dependencies.nodeJs.currentVersion}, Required: ${dependencies.nodeJs.requiredVersion}
|
|
5382
|
+
${chalk4.dim("\u2192")} Visit https://nodejs.org to upgrade`
|
|
5383
|
+
);
|
|
5384
|
+
}
|
|
5385
|
+
if (!dependencies.react.valid && dependencies.react.installed) {
|
|
5386
|
+
warnings.push(
|
|
5387
|
+
`${dependencies.react.message}
|
|
5388
|
+
${chalk4.dim("\u2192")} Current: ${dependencies.react.currentVersion}, Required: ${dependencies.react.requiredVersion}`
|
|
5389
|
+
);
|
|
5390
|
+
} else if (!dependencies.react.installed) {
|
|
5391
|
+
blockingErrors.push(
|
|
5392
|
+
`${dependencies.react.message}
|
|
5393
|
+
${chalk4.dim("\u2192")} This should have been caught by React project check`
|
|
5394
|
+
);
|
|
5395
|
+
}
|
|
5396
|
+
if (dependencies.reactPdfRenderer.installed && !dependencies.reactPdfRenderer.valid) {
|
|
5397
|
+
warnings.push(
|
|
5398
|
+
`${dependencies.reactPdfRenderer.message}
|
|
5399
|
+
${chalk4.dim("\u2192")} Consider upgrading: npm install @react-pdf/renderer@latest`
|
|
5400
|
+
);
|
|
5401
|
+
}
|
|
5402
|
+
if (dependencies.typescript && !dependencies.typescript.valid) {
|
|
5403
|
+
warnings.push(
|
|
5404
|
+
`${dependencies.typescript.message}
|
|
5405
|
+
${chalk4.dim("\u2192")} Install types: npm install -D @types/react-pdf`
|
|
5406
|
+
);
|
|
5407
|
+
}
|
|
5408
|
+
return {
|
|
5409
|
+
environment,
|
|
5410
|
+
dependencies,
|
|
5411
|
+
blockingErrors,
|
|
5412
|
+
warnings,
|
|
5413
|
+
canProceed: blockingErrors.length === 0
|
|
5414
|
+
};
|
|
5415
|
+
}
|
|
5416
|
+
function displayPreFlightResults(result) {
|
|
5417
|
+
console.log(chalk4.bold("\n Pre-flight Checks:\n"));
|
|
5418
|
+
if (result.blockingErrors.length > 0) {
|
|
5419
|
+
console.log(chalk4.red(" \u2717 Blocking Issues:\n"));
|
|
5420
|
+
for (const error of result.blockingErrors) {
|
|
5421
|
+
console.log(chalk4.red(` \u2022 ${error}
|
|
5422
|
+
`));
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
if (result.warnings.length > 0) {
|
|
5426
|
+
console.log(chalk4.yellow(" \u26A0 Warnings:\n"));
|
|
5427
|
+
for (const warning of result.warnings) {
|
|
5428
|
+
console.log(chalk4.yellow(` \u2022 ${warning}
|
|
5429
|
+
`));
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
if (result.blockingErrors.length === 0 && result.warnings.length === 0) {
|
|
5433
|
+
console.log(chalk4.green(" \u2713 All checks passed!\n"));
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
|
|
5049
5437
|
// src/commands/init.ts
|
|
5050
5438
|
async function init() {
|
|
5051
|
-
console.log(
|
|
5052
|
-
const
|
|
5053
|
-
|
|
5054
|
-
|
|
5439
|
+
console.log(chalk5.bold.cyan("\n Welcome to the pdfx cli\n"));
|
|
5440
|
+
const preFlightResult = runPreFlightChecks();
|
|
5441
|
+
displayPreFlightResults(preFlightResult);
|
|
5442
|
+
if (!preFlightResult.canProceed) {
|
|
5443
|
+
console.error(
|
|
5444
|
+
chalk5.red("\n Cannot proceed due to blocking issues. Please fix them and try again.\n")
|
|
5445
|
+
);
|
|
5446
|
+
process.exit(1);
|
|
5447
|
+
}
|
|
5448
|
+
const hasReactPdf = await ensureReactPdfRenderer(preFlightResult.dependencies.reactPdfRenderer);
|
|
5449
|
+
if (!hasReactPdf) {
|
|
5450
|
+
console.error(
|
|
5451
|
+
chalk5.red("\n @react-pdf/renderer is required. Please install it and try again.\n")
|
|
5452
|
+
);
|
|
5453
|
+
process.exit(1);
|
|
5454
|
+
}
|
|
5455
|
+
const existingConfig = path7.join(process.cwd(), "pdfx.json");
|
|
5456
|
+
if (fs7.existsSync(existingConfig)) {
|
|
5457
|
+
const { overwrite } = await prompts3({
|
|
5055
5458
|
type: "confirm",
|
|
5056
5459
|
name: "overwrite",
|
|
5057
5460
|
message: "pdfx.json already exists. Overwrite?",
|
|
5058
5461
|
initial: false
|
|
5059
5462
|
});
|
|
5060
5463
|
if (!overwrite) {
|
|
5061
|
-
console.log(
|
|
5464
|
+
console.log(chalk5.yellow("Init cancelled \u2014 existing config preserved."));
|
|
5062
5465
|
return;
|
|
5063
5466
|
}
|
|
5064
5467
|
}
|
|
5065
|
-
const answers = await
|
|
5468
|
+
const answers = await prompts3(
|
|
5066
5469
|
[
|
|
5067
5470
|
{
|
|
5068
5471
|
type: "text",
|
|
@@ -5108,13 +5511,13 @@ async function init() {
|
|
|
5108
5511
|
],
|
|
5109
5512
|
{
|
|
5110
5513
|
onCancel: () => {
|
|
5111
|
-
console.log(
|
|
5514
|
+
console.log(chalk5.yellow("\nSetup cancelled."));
|
|
5112
5515
|
process.exit(0);
|
|
5113
5516
|
}
|
|
5114
5517
|
}
|
|
5115
5518
|
);
|
|
5116
5519
|
if (!answers.componentDir || !answers.registry) {
|
|
5117
|
-
console.error(
|
|
5520
|
+
console.error(chalk5.red("Missing required fields. Run pdfx init again."));
|
|
5118
5521
|
process.exit(1);
|
|
5119
5522
|
}
|
|
5120
5523
|
const config = {
|
|
@@ -5126,54 +5529,54 @@ async function init() {
|
|
|
5126
5529
|
const validation = configSchema.safeParse(config);
|
|
5127
5530
|
if (!validation.success) {
|
|
5128
5531
|
const issues = validation.error.issues.map((i) => i.message).join(", ");
|
|
5129
|
-
console.error(
|
|
5532
|
+
console.error(chalk5.red(`Invalid configuration: ${issues}`));
|
|
5130
5533
|
process.exit(1);
|
|
5131
5534
|
}
|
|
5132
|
-
const spinner =
|
|
5535
|
+
const spinner = ora4("Creating config and theme files...").start();
|
|
5133
5536
|
try {
|
|
5134
|
-
|
|
5537
|
+
fs7.writeFileSync(path7.join(process.cwd(), "pdfx.json"), JSON.stringify(config, null, 2));
|
|
5135
5538
|
const presetName = answers.themePreset || "professional";
|
|
5136
5539
|
const preset = themePresets[presetName];
|
|
5137
|
-
const themePath =
|
|
5138
|
-
ensureDir(
|
|
5139
|
-
|
|
5140
|
-
const contextPath =
|
|
5141
|
-
|
|
5540
|
+
const themePath = path7.resolve(process.cwd(), config.theme);
|
|
5541
|
+
ensureDir(path7.dirname(themePath));
|
|
5542
|
+
fs7.writeFileSync(themePath, generateThemeFile(preset), "utf-8");
|
|
5543
|
+
const contextPath = path7.join(path7.dirname(themePath), "pdfx-theme-context.tsx");
|
|
5544
|
+
fs7.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
|
|
5142
5545
|
spinner.succeed(`Created pdfx.json + ${config.theme} (${presetName} theme)`);
|
|
5143
|
-
console.log(
|
|
5144
|
-
console.log(
|
|
5145
|
-
console.log(
|
|
5146
|
-
Components: ${
|
|
5147
|
-
console.log(
|
|
5546
|
+
console.log(chalk5.green("\nSuccess! You can now run:"));
|
|
5547
|
+
console.log(chalk5.cyan(" pdfx add heading"));
|
|
5548
|
+
console.log(chalk5.dim(`
|
|
5549
|
+
Components: ${path7.resolve(process.cwd(), answers.componentDir)}`));
|
|
5550
|
+
console.log(chalk5.dim(` Theme: ${path7.resolve(process.cwd(), config.theme)}
|
|
5148
5551
|
`));
|
|
5149
5552
|
} catch (error) {
|
|
5150
5553
|
spinner.fail("Failed to create config");
|
|
5151
5554
|
const message = error instanceof Error ? error.message : String(error);
|
|
5152
|
-
console.error(
|
|
5555
|
+
console.error(chalk5.dim(` ${message}`));
|
|
5153
5556
|
process.exit(1);
|
|
5154
5557
|
}
|
|
5155
5558
|
}
|
|
5156
5559
|
|
|
5157
5560
|
// src/commands/list.ts
|
|
5158
|
-
import
|
|
5159
|
-
import
|
|
5160
|
-
import
|
|
5561
|
+
import path8 from "path";
|
|
5562
|
+
import chalk6 from "chalk";
|
|
5563
|
+
import ora5 from "ora";
|
|
5161
5564
|
var FETCH_TIMEOUT_MS2 = 1e4;
|
|
5162
5565
|
async function list() {
|
|
5163
|
-
const configPath =
|
|
5566
|
+
const configPath = path8.join(process.cwd(), "pdfx.json");
|
|
5164
5567
|
if (!checkFileExists(configPath)) {
|
|
5165
|
-
console.error(
|
|
5166
|
-
console.log(
|
|
5568
|
+
console.error(chalk6.red("Error: pdfx.json not found"));
|
|
5569
|
+
console.log(chalk6.yellow("Run: pdfx init"));
|
|
5167
5570
|
process.exit(1);
|
|
5168
5571
|
}
|
|
5169
5572
|
const raw = readJsonFile(configPath);
|
|
5170
5573
|
const configResult = configSchema.safeParse(raw);
|
|
5171
5574
|
if (!configResult.success) {
|
|
5172
|
-
console.error(
|
|
5575
|
+
console.error(chalk6.red("Invalid pdfx.json"));
|
|
5173
5576
|
process.exit(1);
|
|
5174
5577
|
}
|
|
5175
5578
|
const config = configResult.data;
|
|
5176
|
-
const spinner =
|
|
5579
|
+
const spinner = ora5("Fetching component list...").start();
|
|
5177
5580
|
try {
|
|
5178
5581
|
let response;
|
|
5179
5582
|
try {
|
|
@@ -5195,17 +5598,17 @@ async function list() {
|
|
|
5195
5598
|
throw new RegistryError("Invalid registry format");
|
|
5196
5599
|
}
|
|
5197
5600
|
spinner.stop();
|
|
5198
|
-
const targetDir =
|
|
5601
|
+
const targetDir = path8.resolve(process.cwd(), config.componentDir);
|
|
5199
5602
|
const components = result.data.items.filter((item) => item.type === "registry:ui");
|
|
5200
|
-
console.log(
|
|
5603
|
+
console.log(chalk6.bold(`
|
|
5201
5604
|
Available Components (${components.length})
|
|
5202
5605
|
`));
|
|
5203
5606
|
for (const item of components) {
|
|
5204
|
-
const componentSubDir =
|
|
5607
|
+
const componentSubDir = path8.join(targetDir, item.name);
|
|
5205
5608
|
const localPath = safePath(componentSubDir, `pdfx-${item.name}.tsx`);
|
|
5206
5609
|
const installed = checkFileExists(localPath);
|
|
5207
|
-
const status = installed ?
|
|
5208
|
-
console.log(` ${
|
|
5610
|
+
const status = installed ? chalk6.green("[installed]") : chalk6.dim("[not installed]");
|
|
5611
|
+
console.log(` ${chalk6.cyan(item.name.padEnd(20))} ${item.description}`);
|
|
5209
5612
|
console.log(` ${"".padEnd(20)} ${status}`);
|
|
5210
5613
|
console.log();
|
|
5211
5614
|
}
|
|
@@ -5217,10 +5620,10 @@ async function list() {
|
|
|
5217
5620
|
}
|
|
5218
5621
|
|
|
5219
5622
|
// src/commands/template.ts
|
|
5220
|
-
import
|
|
5221
|
-
import
|
|
5222
|
-
import
|
|
5223
|
-
import
|
|
5623
|
+
import path9 from "path";
|
|
5624
|
+
import chalk7 from "chalk";
|
|
5625
|
+
import ora6 from "ora";
|
|
5626
|
+
import prompts4 from "prompts";
|
|
5224
5627
|
function readConfig2(configPath) {
|
|
5225
5628
|
const raw = readJsonFile(configPath);
|
|
5226
5629
|
const result = configSchema.safeParse(raw);
|
|
@@ -5228,7 +5631,7 @@ function readConfig2(configPath) {
|
|
|
5228
5631
|
const issues = result.error.issues.map((i) => i.message).join(", ");
|
|
5229
5632
|
throw new ConfigError(
|
|
5230
5633
|
`Invalid pdfx.json: ${issues}`,
|
|
5231
|
-
`Fix the config or re-run ${
|
|
5634
|
+
`Fix the config or re-run ${chalk7.cyan("pdfx init")}`
|
|
5232
5635
|
);
|
|
5233
5636
|
}
|
|
5234
5637
|
return result.data;
|
|
@@ -5295,7 +5698,7 @@ async function fetchComponent2(name, registryUrl) {
|
|
|
5295
5698
|
}
|
|
5296
5699
|
function resolveTemplateImports(content, templateName, config) {
|
|
5297
5700
|
const cwd = process.cwd();
|
|
5298
|
-
const templateSubdir =
|
|
5701
|
+
const templateSubdir = path9.resolve(
|
|
5299
5702
|
cwd,
|
|
5300
5703
|
config.templateDir ?? DEFAULTS.TEMPLATE_DIR,
|
|
5301
5704
|
templateName
|
|
@@ -5303,26 +5706,26 @@ function resolveTemplateImports(content, templateName, config) {
|
|
|
5303
5706
|
let result = content.replace(
|
|
5304
5707
|
/from '\.\.\/\.\.\/components\/pdfx\/([a-z][a-z0-9-]*)\/pdfx-([a-z][a-z0-9-]*)'/g,
|
|
5305
5708
|
(_match, componentName) => {
|
|
5306
|
-
const absCompFile =
|
|
5709
|
+
const absCompFile = path9.resolve(
|
|
5307
5710
|
cwd,
|
|
5308
5711
|
config.componentDir,
|
|
5309
5712
|
componentName,
|
|
5310
5713
|
`pdfx-${componentName}`
|
|
5311
5714
|
);
|
|
5312
|
-
let rel =
|
|
5715
|
+
let rel = path9.relative(templateSubdir, absCompFile);
|
|
5313
5716
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
5314
5717
|
return `from '${rel}'`;
|
|
5315
5718
|
}
|
|
5316
5719
|
);
|
|
5317
5720
|
if (config.theme) {
|
|
5318
|
-
const absThemePath =
|
|
5319
|
-
let relTheme =
|
|
5721
|
+
const absThemePath = path9.resolve(cwd, config.theme).replace(/\.tsx?$/, "");
|
|
5722
|
+
let relTheme = path9.relative(templateSubdir, absThemePath);
|
|
5320
5723
|
if (!relTheme.startsWith(".")) relTheme = `./${relTheme}`;
|
|
5321
|
-
const absContextPath =
|
|
5322
|
-
|
|
5724
|
+
const absContextPath = path9.join(
|
|
5725
|
+
path9.dirname(path9.resolve(cwd, config.theme)),
|
|
5323
5726
|
"pdfx-theme-context"
|
|
5324
5727
|
);
|
|
5325
|
-
let relContext =
|
|
5728
|
+
let relContext = path9.relative(templateSubdir, absContextPath);
|
|
5326
5729
|
if (!relContext.startsWith(".")) relContext = `./${relContext}`;
|
|
5327
5730
|
result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme'/g, `from '${relTheme}'`);
|
|
5328
5731
|
result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme-context'/g, `from '${relContext}'`);
|
|
@@ -5331,10 +5734,10 @@ function resolveTemplateImports(content, templateName, config) {
|
|
|
5331
5734
|
}
|
|
5332
5735
|
async function resolveConflict(fileName, currentDecision) {
|
|
5333
5736
|
if (currentDecision === "overwrite-all") return "overwrite-all";
|
|
5334
|
-
const { action } = await
|
|
5737
|
+
const { action } = await prompts4({
|
|
5335
5738
|
type: "select",
|
|
5336
5739
|
name: "action",
|
|
5337
|
-
message: `${
|
|
5740
|
+
message: `${chalk7.yellow(fileName)} already exists. What would you like to do?`,
|
|
5338
5741
|
choices: [
|
|
5339
5742
|
{ title: "Skip", value: "skip", description: "Keep the existing file unchanged" },
|
|
5340
5743
|
{ title: "Overwrite", value: "overwrite", description: "Replace this file only" },
|
|
@@ -5355,14 +5758,14 @@ async function ensurePeerComponents(template, config, force) {
|
|
|
5355
5758
|
if (!template.peerComponents || template.peerComponents.length === 0) {
|
|
5356
5759
|
return { installedPeers, peerWarnings };
|
|
5357
5760
|
}
|
|
5358
|
-
const componentBaseDir =
|
|
5761
|
+
const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
|
|
5359
5762
|
for (const componentName of template.peerComponents) {
|
|
5360
|
-
const componentDir =
|
|
5361
|
-
const expectedMain =
|
|
5763
|
+
const componentDir = path9.join(componentBaseDir, componentName);
|
|
5764
|
+
const expectedMain = path9.join(componentDir, `pdfx-${componentName}.tsx`);
|
|
5362
5765
|
if (checkFileExists(componentDir)) {
|
|
5363
5766
|
if (!checkFileExists(expectedMain)) {
|
|
5364
5767
|
peerWarnings.push(
|
|
5365
|
-
`${componentName}: directory exists but expected file missing (${
|
|
5768
|
+
`${componentName}: directory exists but expected file missing (${path9.basename(expectedMain)})`
|
|
5366
5769
|
);
|
|
5367
5770
|
} else {
|
|
5368
5771
|
peerWarnings.push(
|
|
@@ -5373,9 +5776,9 @@ async function ensurePeerComponents(template, config, force) {
|
|
|
5373
5776
|
}
|
|
5374
5777
|
const component = await fetchComponent2(componentName, config.registry);
|
|
5375
5778
|
ensureDir(componentDir);
|
|
5376
|
-
const componentRelDir =
|
|
5779
|
+
const componentRelDir = path9.join(config.componentDir, component.name);
|
|
5377
5780
|
for (const file of component.files) {
|
|
5378
|
-
const fileName =
|
|
5781
|
+
const fileName = path9.basename(file.path);
|
|
5379
5782
|
const filePath = safePath(componentDir, fileName);
|
|
5380
5783
|
let content = file.content;
|
|
5381
5784
|
if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
|
|
@@ -5396,12 +5799,12 @@ async function ensurePeerComponents(template, config, force) {
|
|
|
5396
5799
|
async function installTemplate(name, config, force) {
|
|
5397
5800
|
const template = await fetchTemplate(name, config.registry);
|
|
5398
5801
|
const peerResult = await ensurePeerComponents(template, config, force);
|
|
5399
|
-
const templateBaseDir =
|
|
5400
|
-
const templateDir =
|
|
5802
|
+
const templateBaseDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
|
|
5803
|
+
const templateDir = path9.join(templateBaseDir, template.name);
|
|
5401
5804
|
ensureDir(templateDir);
|
|
5402
5805
|
const filesToWrite = [];
|
|
5403
5806
|
for (const file of template.files) {
|
|
5404
|
-
const fileName =
|
|
5807
|
+
const fileName = path9.basename(file.path);
|
|
5405
5808
|
const filePath = safePath(templateDir, fileName);
|
|
5406
5809
|
let content = file.content;
|
|
5407
5810
|
if (/\.(tsx?|jsx?)$/.test(fileName) && content.includes("../../")) {
|
|
@@ -5414,7 +5817,7 @@ async function installTemplate(name, config, force) {
|
|
|
5414
5817
|
const resolved = [];
|
|
5415
5818
|
for (const file of filesToWrite) {
|
|
5416
5819
|
if (checkFileExists(file.filePath)) {
|
|
5417
|
-
const decision = await resolveConflict(
|
|
5820
|
+
const decision = await resolveConflict(path9.basename(file.filePath), globalDecision);
|
|
5418
5821
|
if (decision === "overwrite-all") {
|
|
5419
5822
|
globalDecision = "overwrite-all";
|
|
5420
5823
|
}
|
|
@@ -5427,7 +5830,7 @@ async function installTemplate(name, config, force) {
|
|
|
5427
5830
|
if (!file.skip) {
|
|
5428
5831
|
writeFile(file.filePath, file.content);
|
|
5429
5832
|
} else {
|
|
5430
|
-
console.log(
|
|
5833
|
+
console.log(chalk7.dim(` skipped ${path9.basename(file.filePath)}`));
|
|
5431
5834
|
}
|
|
5432
5835
|
}
|
|
5433
5836
|
} else {
|
|
@@ -5436,37 +5839,37 @@ async function installTemplate(name, config, force) {
|
|
|
5436
5839
|
}
|
|
5437
5840
|
}
|
|
5438
5841
|
if (template.peerComponents && template.peerComponents.length > 0) {
|
|
5439
|
-
const componentBaseDir =
|
|
5842
|
+
const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
|
|
5440
5843
|
const missing = [];
|
|
5441
5844
|
for (const comp of template.peerComponents) {
|
|
5442
|
-
const compDir =
|
|
5845
|
+
const compDir = path9.join(componentBaseDir, comp);
|
|
5443
5846
|
if (!checkFileExists(compDir)) {
|
|
5444
5847
|
missing.push(comp);
|
|
5445
5848
|
}
|
|
5446
5849
|
}
|
|
5447
5850
|
if (missing.length > 0) {
|
|
5448
5851
|
console.log();
|
|
5449
|
-
console.log(
|
|
5852
|
+
console.log(chalk7.yellow(" Missing peer components:"));
|
|
5450
5853
|
for (const comp of missing) {
|
|
5451
|
-
console.log(
|
|
5854
|
+
console.log(chalk7.dim(` ${comp} \u2192 run: ${chalk7.cyan(`pdfx add ${comp}`)}`));
|
|
5452
5855
|
}
|
|
5453
5856
|
}
|
|
5454
5857
|
}
|
|
5455
5858
|
if (config.theme) {
|
|
5456
|
-
const absThemePath =
|
|
5457
|
-
const contextPath =
|
|
5859
|
+
const absThemePath = path9.resolve(process.cwd(), config.theme);
|
|
5860
|
+
const contextPath = path9.join(path9.dirname(absThemePath), "pdfx-theme-context.tsx");
|
|
5458
5861
|
if (!checkFileExists(contextPath)) {
|
|
5459
|
-
ensureDir(
|
|
5862
|
+
ensureDir(path9.dirname(contextPath));
|
|
5460
5863
|
writeFile(contextPath, generateThemeContextFile());
|
|
5461
5864
|
}
|
|
5462
5865
|
}
|
|
5463
5866
|
return peerResult;
|
|
5464
5867
|
}
|
|
5465
5868
|
async function templateAdd(names, options = {}) {
|
|
5466
|
-
const configPath =
|
|
5869
|
+
const configPath = path9.join(process.cwd(), "pdfx.json");
|
|
5467
5870
|
if (!checkFileExists(configPath)) {
|
|
5468
|
-
console.error(
|
|
5469
|
-
console.log(
|
|
5871
|
+
console.error(chalk7.red("Error: pdfx.json not found"));
|
|
5872
|
+
console.log(chalk7.yellow("Run: pdfx init"));
|
|
5470
5873
|
process.exit(1);
|
|
5471
5874
|
}
|
|
5472
5875
|
let config;
|
|
@@ -5474,11 +5877,11 @@ async function templateAdd(names, options = {}) {
|
|
|
5474
5877
|
config = readConfig2(configPath);
|
|
5475
5878
|
} catch (error) {
|
|
5476
5879
|
if (error instanceof ConfigError) {
|
|
5477
|
-
console.error(
|
|
5478
|
-
if (error.suggestion) console.log(
|
|
5880
|
+
console.error(chalk7.red(error.message));
|
|
5881
|
+
if (error.suggestion) console.log(chalk7.yellow(` Hint: ${error.suggestion}`));
|
|
5479
5882
|
} else {
|
|
5480
5883
|
const message = error instanceof Error ? error.message : String(error);
|
|
5481
|
-
console.error(
|
|
5884
|
+
console.error(chalk7.red(message));
|
|
5482
5885
|
}
|
|
5483
5886
|
process.exit(1);
|
|
5484
5887
|
}
|
|
@@ -5487,24 +5890,24 @@ async function templateAdd(names, options = {}) {
|
|
|
5487
5890
|
for (const templateName of names) {
|
|
5488
5891
|
const nameResult = componentNameSchema.safeParse(templateName);
|
|
5489
5892
|
if (!nameResult.success) {
|
|
5490
|
-
console.error(
|
|
5893
|
+
console.error(chalk7.red(`Invalid template name: "${templateName}"`));
|
|
5491
5894
|
console.log(
|
|
5492
|
-
|
|
5895
|
+
chalk7.dim(' Names must be lowercase alphanumeric with hyphens (e.g., "invoice-classic")')
|
|
5493
5896
|
);
|
|
5494
5897
|
failed.push(templateName);
|
|
5495
5898
|
continue;
|
|
5496
5899
|
}
|
|
5497
|
-
const spinner =
|
|
5900
|
+
const spinner = ora6(`Adding template ${templateName}...`).start();
|
|
5498
5901
|
try {
|
|
5499
5902
|
const result = await installTemplate(templateName, config, force);
|
|
5500
|
-
spinner.succeed(`Added template ${
|
|
5903
|
+
spinner.succeed(`Added template ${chalk7.cyan(templateName)}`);
|
|
5501
5904
|
if (result.installedPeers.length > 0) {
|
|
5502
5905
|
console.log(
|
|
5503
|
-
|
|
5906
|
+
chalk7.green(` Installed required components: ${result.installedPeers.join(", ")}`)
|
|
5504
5907
|
);
|
|
5505
5908
|
}
|
|
5506
5909
|
for (const warning of result.peerWarnings) {
|
|
5507
|
-
console.log(
|
|
5910
|
+
console.log(chalk7.yellow(` Warning: ${warning}`));
|
|
5508
5911
|
}
|
|
5509
5912
|
} catch (error) {
|
|
5510
5913
|
if (error instanceof ValidationError && error.message.includes("Cancelled")) {
|
|
@@ -5513,24 +5916,24 @@ async function templateAdd(names, options = {}) {
|
|
|
5513
5916
|
} else if (error instanceof NetworkError || error instanceof RegistryError || error instanceof ValidationError) {
|
|
5514
5917
|
spinner.fail(error.message);
|
|
5515
5918
|
if (error.suggestion) {
|
|
5516
|
-
console.log(
|
|
5919
|
+
console.log(chalk7.dim(` Hint: ${error.suggestion}`));
|
|
5517
5920
|
}
|
|
5518
5921
|
} else {
|
|
5519
5922
|
spinner.fail(`Failed to add template ${templateName}`);
|
|
5520
5923
|
const message = error instanceof Error ? error.message : String(error);
|
|
5521
|
-
console.error(
|
|
5924
|
+
console.error(chalk7.dim(` ${message}`));
|
|
5522
5925
|
}
|
|
5523
5926
|
failed.push(templateName);
|
|
5524
5927
|
}
|
|
5525
5928
|
}
|
|
5526
5929
|
console.log();
|
|
5527
5930
|
if (failed.length > 0) {
|
|
5528
|
-
console.log(
|
|
5931
|
+
console.log(chalk7.yellow(`Failed: ${failed.join(", ")}`));
|
|
5529
5932
|
}
|
|
5530
5933
|
if (failed.length < names.length) {
|
|
5531
|
-
const resolvedDir =
|
|
5532
|
-
console.log(
|
|
5533
|
-
console.log(
|
|
5934
|
+
const resolvedDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
|
|
5935
|
+
console.log(chalk7.green("Done!"));
|
|
5936
|
+
console.log(chalk7.dim(`Templates installed to: ${resolvedDir}
|
|
5534
5937
|
`));
|
|
5535
5938
|
}
|
|
5536
5939
|
if (failed.length > 0) {
|
|
@@ -5538,20 +5941,20 @@ async function templateAdd(names, options = {}) {
|
|
|
5538
5941
|
}
|
|
5539
5942
|
}
|
|
5540
5943
|
async function templateList() {
|
|
5541
|
-
const configPath =
|
|
5944
|
+
const configPath = path9.join(process.cwd(), "pdfx.json");
|
|
5542
5945
|
if (!checkFileExists(configPath)) {
|
|
5543
|
-
console.error(
|
|
5544
|
-
console.log(
|
|
5946
|
+
console.error(chalk7.red("Error: pdfx.json not found"));
|
|
5947
|
+
console.log(chalk7.yellow("Run: pdfx init"));
|
|
5545
5948
|
process.exit(1);
|
|
5546
5949
|
}
|
|
5547
5950
|
const raw = readJsonFile(configPath);
|
|
5548
5951
|
const configResult = configSchema.safeParse(raw);
|
|
5549
5952
|
if (!configResult.success) {
|
|
5550
|
-
console.error(
|
|
5953
|
+
console.error(chalk7.red("Invalid pdfx.json"));
|
|
5551
5954
|
process.exit(1);
|
|
5552
5955
|
}
|
|
5553
5956
|
const config = configResult.data;
|
|
5554
|
-
const spinner =
|
|
5957
|
+
const spinner = ora6("Fetching template list...").start();
|
|
5555
5958
|
try {
|
|
5556
5959
|
let response;
|
|
5557
5960
|
try {
|
|
@@ -5575,28 +5978,28 @@ async function templateList() {
|
|
|
5575
5978
|
spinner.stop();
|
|
5576
5979
|
const templates = result.data.items.filter((item) => item.type === "registry:template");
|
|
5577
5980
|
if (templates.length === 0) {
|
|
5578
|
-
console.log(
|
|
5981
|
+
console.log(chalk7.dim("\n No templates available in the registry.\n"));
|
|
5579
5982
|
return;
|
|
5580
5983
|
}
|
|
5581
|
-
const templateBaseDir =
|
|
5984
|
+
const templateBaseDir = path9.resolve(
|
|
5582
5985
|
process.cwd(),
|
|
5583
5986
|
config.templateDir ?? DEFAULTS.TEMPLATE_DIR
|
|
5584
5987
|
);
|
|
5585
|
-
console.log(
|
|
5988
|
+
console.log(chalk7.bold(`
|
|
5586
5989
|
Available Templates (${templates.length})
|
|
5587
5990
|
`));
|
|
5588
5991
|
for (const item of templates) {
|
|
5589
|
-
const templateDir =
|
|
5992
|
+
const templateDir = path9.join(templateBaseDir, item.name);
|
|
5590
5993
|
const installed = checkFileExists(templateDir);
|
|
5591
|
-
const status = installed ?
|
|
5592
|
-
console.log(` ${
|
|
5994
|
+
const status = installed ? chalk7.green("[installed]") : chalk7.dim("[not installed]");
|
|
5995
|
+
console.log(` ${chalk7.cyan(item.name.padEnd(22))} ${item.description ?? ""}`);
|
|
5593
5996
|
console.log(` ${"".padEnd(22)} ${status}`);
|
|
5594
5997
|
if (item.peerComponents && item.peerComponents.length > 0) {
|
|
5595
|
-
console.log(
|
|
5998
|
+
console.log(chalk7.dim(` ${"".padEnd(22)} requires: ${item.peerComponents.join(", ")}`));
|
|
5596
5999
|
}
|
|
5597
6000
|
console.log();
|
|
5598
6001
|
}
|
|
5599
|
-
console.log(
|
|
6002
|
+
console.log(chalk7.dim(` Install with: ${chalk7.cyan("pdfx template add <template-name>")}
|
|
5600
6003
|
`));
|
|
5601
6004
|
} catch (error) {
|
|
5602
6005
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -5606,15 +6009,15 @@ async function templateList() {
|
|
|
5606
6009
|
}
|
|
5607
6010
|
|
|
5608
6011
|
// src/commands/theme.ts
|
|
5609
|
-
import
|
|
5610
|
-
import
|
|
5611
|
-
import
|
|
5612
|
-
import
|
|
5613
|
-
import
|
|
6012
|
+
import fs8 from "fs";
|
|
6013
|
+
import path10 from "path";
|
|
6014
|
+
import chalk8 from "chalk";
|
|
6015
|
+
import ora7 from "ora";
|
|
6016
|
+
import prompts5 from "prompts";
|
|
5614
6017
|
import ts from "typescript";
|
|
5615
6018
|
async function themeInit() {
|
|
5616
|
-
console.log(
|
|
5617
|
-
const answers = await
|
|
6019
|
+
console.log(chalk8.bold.cyan("\n PDFx Theme Setup\n"));
|
|
6020
|
+
const answers = await prompts5(
|
|
5618
6021
|
[
|
|
5619
6022
|
{
|
|
5620
6023
|
type: "select",
|
|
@@ -5648,47 +6051,47 @@ async function themeInit() {
|
|
|
5648
6051
|
],
|
|
5649
6052
|
{
|
|
5650
6053
|
onCancel: () => {
|
|
5651
|
-
console.log(
|
|
6054
|
+
console.log(chalk8.yellow("\nTheme setup cancelled."));
|
|
5652
6055
|
process.exit(0);
|
|
5653
6056
|
}
|
|
5654
6057
|
}
|
|
5655
6058
|
);
|
|
5656
6059
|
if (!answers.preset || !answers.themePath) {
|
|
5657
|
-
console.error(
|
|
6060
|
+
console.error(chalk8.red("Missing required fields."));
|
|
5658
6061
|
process.exit(1);
|
|
5659
6062
|
}
|
|
5660
6063
|
const presetName = answers.preset;
|
|
5661
6064
|
const themePath = answers.themePath;
|
|
5662
6065
|
const preset = themePresets[presetName];
|
|
5663
|
-
const spinner =
|
|
6066
|
+
const spinner = ora7(`Scaffolding ${presetName} theme...`).start();
|
|
5664
6067
|
try {
|
|
5665
|
-
const absThemePath =
|
|
5666
|
-
ensureDir(
|
|
5667
|
-
|
|
5668
|
-
const contextPath =
|
|
5669
|
-
|
|
6068
|
+
const absThemePath = path10.resolve(process.cwd(), themePath);
|
|
6069
|
+
ensureDir(path10.dirname(absThemePath));
|
|
6070
|
+
fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
|
|
6071
|
+
const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
|
|
6072
|
+
fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
|
|
5670
6073
|
spinner.succeed(`Created ${themePath} with ${presetName} theme`);
|
|
5671
|
-
const configPath =
|
|
5672
|
-
if (
|
|
6074
|
+
const configPath = path10.join(process.cwd(), "pdfx.json");
|
|
6075
|
+
if (fs8.existsSync(configPath)) {
|
|
5673
6076
|
try {
|
|
5674
6077
|
const rawConfig = readJsonFile(configPath);
|
|
5675
6078
|
const result = configSchema.safeParse(rawConfig);
|
|
5676
6079
|
if (result.success) {
|
|
5677
6080
|
const updatedConfig = { ...result.data, theme: themePath };
|
|
5678
|
-
|
|
5679
|
-
console.log(
|
|
6081
|
+
fs8.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), "utf-8");
|
|
6082
|
+
console.log(chalk8.green(" Updated pdfx.json with theme path"));
|
|
5680
6083
|
}
|
|
5681
6084
|
} catch {
|
|
5682
|
-
console.log(
|
|
6085
|
+
console.log(chalk8.yellow(' Could not update pdfx.json \u2014 add "theme" field manually'));
|
|
5683
6086
|
}
|
|
5684
6087
|
}
|
|
5685
|
-
console.log(
|
|
6088
|
+
console.log(chalk8.dim(`
|
|
5686
6089
|
Edit ${themePath} to customize your theme.
|
|
5687
6090
|
`));
|
|
5688
6091
|
} catch (error) {
|
|
5689
6092
|
spinner.fail("Failed to create theme file");
|
|
5690
6093
|
const message = error instanceof Error ? error.message : String(error);
|
|
5691
|
-
console.error(
|
|
6094
|
+
console.error(chalk8.dim(` ${message}`));
|
|
5692
6095
|
process.exit(1);
|
|
5693
6096
|
}
|
|
5694
6097
|
}
|
|
@@ -5696,54 +6099,54 @@ async function themeSwitch(presetName) {
|
|
|
5696
6099
|
const validPresets = Object.keys(themePresets);
|
|
5697
6100
|
if (!validPresets.includes(presetName)) {
|
|
5698
6101
|
console.error(
|
|
5699
|
-
|
|
6102
|
+
chalk8.red(`Invalid preset: "${presetName}". Valid presets: ${validPresets.join(", ")}`)
|
|
5700
6103
|
);
|
|
5701
6104
|
process.exit(1);
|
|
5702
6105
|
}
|
|
5703
6106
|
const validatedPreset = presetName;
|
|
5704
|
-
const configPath =
|
|
5705
|
-
if (!
|
|
5706
|
-
console.error(
|
|
6107
|
+
const configPath = path10.join(process.cwd(), "pdfx.json");
|
|
6108
|
+
if (!fs8.existsSync(configPath)) {
|
|
6109
|
+
console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
|
|
5707
6110
|
process.exit(1);
|
|
5708
6111
|
}
|
|
5709
6112
|
const rawConfig = readJsonFile(configPath);
|
|
5710
6113
|
const result = configSchema.safeParse(rawConfig);
|
|
5711
6114
|
if (!result.success) {
|
|
5712
|
-
console.error(
|
|
6115
|
+
console.error(chalk8.red("Invalid pdfx.json configuration."));
|
|
5713
6116
|
process.exit(1);
|
|
5714
6117
|
}
|
|
5715
6118
|
const config = result.data;
|
|
5716
6119
|
if (!config.theme) {
|
|
5717
6120
|
console.error(
|
|
5718
|
-
|
|
6121
|
+
chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
|
|
5719
6122
|
);
|
|
5720
6123
|
process.exit(1);
|
|
5721
6124
|
}
|
|
5722
|
-
const answer = await
|
|
6125
|
+
const answer = await prompts5({
|
|
5723
6126
|
type: "confirm",
|
|
5724
6127
|
name: "confirm",
|
|
5725
6128
|
message: `This will overwrite ${config.theme} with the ${validatedPreset} preset. Continue?`,
|
|
5726
6129
|
initial: false
|
|
5727
6130
|
});
|
|
5728
6131
|
if (!answer.confirm) {
|
|
5729
|
-
console.log(
|
|
6132
|
+
console.log(chalk8.yellow("Cancelled."));
|
|
5730
6133
|
return;
|
|
5731
6134
|
}
|
|
5732
|
-
const spinner =
|
|
6135
|
+
const spinner = ora7(`Switching to ${validatedPreset} theme...`).start();
|
|
5733
6136
|
try {
|
|
5734
6137
|
const preset = themePresets[validatedPreset];
|
|
5735
|
-
const absThemePath =
|
|
5736
|
-
|
|
5737
|
-
const contextPath =
|
|
5738
|
-
if (!
|
|
5739
|
-
ensureDir(
|
|
5740
|
-
|
|
6138
|
+
const absThemePath = path10.resolve(process.cwd(), config.theme);
|
|
6139
|
+
fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
|
|
6140
|
+
const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
|
|
6141
|
+
if (!fs8.existsSync(contextPath)) {
|
|
6142
|
+
ensureDir(path10.dirname(contextPath));
|
|
6143
|
+
fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
|
|
5741
6144
|
}
|
|
5742
6145
|
spinner.succeed(`Switched to ${validatedPreset} theme`);
|
|
5743
6146
|
} catch (error) {
|
|
5744
6147
|
spinner.fail("Failed to switch theme");
|
|
5745
6148
|
const message = error instanceof Error ? error.message : String(error);
|
|
5746
|
-
console.error(
|
|
6149
|
+
console.error(chalk8.dim(` ${message}`));
|
|
5747
6150
|
process.exit(1);
|
|
5748
6151
|
}
|
|
5749
6152
|
}
|
|
@@ -5785,7 +6188,7 @@ function toPlainValue(node) {
|
|
|
5785
6188
|
return void 0;
|
|
5786
6189
|
}
|
|
5787
6190
|
function parseThemeObject(themePath) {
|
|
5788
|
-
const content =
|
|
6191
|
+
const content = fs8.readFileSync(themePath, "utf-8");
|
|
5789
6192
|
const sourceFile = ts.createSourceFile(
|
|
5790
6193
|
themePath,
|
|
5791
6194
|
content,
|
|
@@ -5811,29 +6214,29 @@ function parseThemeObject(themePath) {
|
|
|
5811
6214
|
throw new Error("No exported `theme` object found.");
|
|
5812
6215
|
}
|
|
5813
6216
|
async function themeValidate() {
|
|
5814
|
-
const configPath =
|
|
5815
|
-
if (!
|
|
5816
|
-
console.error(
|
|
6217
|
+
const configPath = path10.join(process.cwd(), "pdfx.json");
|
|
6218
|
+
if (!fs8.existsSync(configPath)) {
|
|
6219
|
+
console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
|
|
5817
6220
|
process.exit(1);
|
|
5818
6221
|
}
|
|
5819
6222
|
const rawConfig = readJsonFile(configPath);
|
|
5820
6223
|
const configResult = configSchema.safeParse(rawConfig);
|
|
5821
6224
|
if (!configResult.success) {
|
|
5822
|
-
console.error(
|
|
6225
|
+
console.error(chalk8.red("Invalid pdfx.json configuration."));
|
|
5823
6226
|
process.exit(1);
|
|
5824
6227
|
}
|
|
5825
6228
|
if (!configResult.data.theme) {
|
|
5826
6229
|
console.error(
|
|
5827
|
-
|
|
6230
|
+
chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
|
|
5828
6231
|
);
|
|
5829
6232
|
process.exit(1);
|
|
5830
6233
|
}
|
|
5831
|
-
const absThemePath =
|
|
5832
|
-
if (!
|
|
5833
|
-
console.error(
|
|
6234
|
+
const absThemePath = path10.resolve(process.cwd(), configResult.data.theme);
|
|
6235
|
+
if (!fs8.existsSync(absThemePath)) {
|
|
6236
|
+
console.error(chalk8.red(`Theme file not found: ${configResult.data.theme}`));
|
|
5834
6237
|
process.exit(1);
|
|
5835
6238
|
}
|
|
5836
|
-
const spinner =
|
|
6239
|
+
const spinner = ora7("Validating theme file...").start();
|
|
5837
6240
|
try {
|
|
5838
6241
|
const parsedTheme = parseThemeObject(absThemePath);
|
|
5839
6242
|
const result = themeSchema.safeParse(parsedTheme);
|
|
@@ -5843,13 +6246,13 @@ async function themeValidate() {
|
|
|
5843
6246
|
process.exit(1);
|
|
5844
6247
|
}
|
|
5845
6248
|
spinner.succeed("Theme file is valid");
|
|
5846
|
-
console.log(
|
|
6249
|
+
console.log(chalk8.dim(`
|
|
5847
6250
|
Validated: ${configResult.data.theme}
|
|
5848
6251
|
`));
|
|
5849
6252
|
} catch (error) {
|
|
5850
6253
|
spinner.fail("Failed to validate theme");
|
|
5851
6254
|
const message = error instanceof Error ? error.message : String(error);
|
|
5852
|
-
console.error(
|
|
6255
|
+
console.error(chalk8.dim(` ${message}`));
|
|
5853
6256
|
process.exit(1);
|
|
5854
6257
|
}
|
|
5855
6258
|
}
|