@craftrpgs/cli 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -10
- package/dist/bin.js +348 -178
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -44,7 +44,6 @@ know how to work with the project the moment you open it.
|
|
|
44
44
|
| `craft type new <Name>` | Author a new file type locally |
|
|
45
45
|
| `craft image generate/upload` | Generate (including local or workspace reference images; opt-in in Settings) or upload images |
|
|
46
46
|
| `craft image expressions/cutouts` | Preflight and persist character expression or cutout assets |
|
|
47
|
-
| `craft env [name]` | Show or pin the environment for a directory |
|
|
48
47
|
|
|
49
48
|
Every command takes `--json` for machine-readable output. Auth is via
|
|
50
49
|
`craft login` (browser OAuth); credentials are stored locally and refreshed
|
|
@@ -52,16 +51,14 @@ automatically.
|
|
|
52
51
|
|
|
53
52
|
Run `craft help <command>` for details on any of them.
|
|
54
53
|
|
|
55
|
-
##
|
|
54
|
+
## Staying up to date
|
|
56
55
|
|
|
57
|
-
The
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
developers: set `CRAFT_DEV=1` to enable the internal `local` and `staging`
|
|
64
|
-
environment names.)
|
|
56
|
+
The server only accepts the latest published version of the CLI. When a
|
|
57
|
+
command is refused with a `cli_outdated` error, update and retry:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install -g @craftrpgs/cli@latest
|
|
61
|
+
```
|
|
65
62
|
|
|
66
63
|
## Requirements
|
|
67
64
|
|
package/dist/bin.js
CHANGED
|
@@ -26773,6 +26773,7 @@ function truncateImageStyleInstructions(instructions) {
|
|
|
26773
26773
|
function normalizeImageGenerationPrompt(prompt) {
|
|
26774
26774
|
return truncateImageGenerationPrompt(prompt.trim());
|
|
26775
26775
|
}
|
|
26776
|
+
var NON_DETAIL_KEYS = new Set(["name", "title", "description", "content"]);
|
|
26776
26777
|
|
|
26777
26778
|
// ../shared/src/context-visibility.ts
|
|
26778
26779
|
var CONTEXT_VISIBILITY_VALUES = [
|
|
@@ -26839,8 +26840,18 @@ function isAllowedImageUrl(value) {
|
|
|
26839
26840
|
return false;
|
|
26840
26841
|
}
|
|
26841
26842
|
}
|
|
26843
|
+
var CHAT_ATTACHMENT_PATH_PREFIX = "/attachments/";
|
|
26844
|
+
function isChatAttachmentUrl(value) {
|
|
26845
|
+
try {
|
|
26846
|
+
return new URL(value).pathname.startsWith(CHAT_ATTACHMENT_PATH_PREFIX);
|
|
26847
|
+
} catch {
|
|
26848
|
+
return false;
|
|
26849
|
+
}
|
|
26850
|
+
}
|
|
26842
26851
|
var imageUrlSchema = exports_external.string().trim().min(1).max(2048).url().refine(isAllowedImageUrl, {
|
|
26843
26852
|
message: "Image URL must use an approved media host."
|
|
26853
|
+
}).refine((value) => !isChatAttachmentUrl(value), {
|
|
26854
|
+
message: "Chat attachments can't be saved as images. Upload the image instead."
|
|
26844
26855
|
});
|
|
26845
26856
|
|
|
26846
26857
|
// ../shared/src/validators/image-object.ts
|
|
@@ -26939,6 +26950,63 @@ var imageObjectSchema = exports_external.preprocess((input) => normalizeImageInp
|
|
|
26939
26950
|
variations: exports_external.array(imageVariationSchema).max(MAX_FILE_TYPE_STATES).optional()
|
|
26940
26951
|
}).strict());
|
|
26941
26952
|
|
|
26953
|
+
// ../shared/src/projects/first-steps.ts
|
|
26954
|
+
var FIRST_STEPS_VERSION = 1;
|
|
26955
|
+
var MAX_FIRST_STEPS_STEPS = 8;
|
|
26956
|
+
var MAX_FIRST_STEPS_WELCOME_LENGTH = 500;
|
|
26957
|
+
var MAX_FIRST_STEPS_STEP_TITLE_LENGTH = 80;
|
|
26958
|
+
var MAX_FIRST_STEPS_STEP_BODY_LENGTH = 300;
|
|
26959
|
+
var firstStepsStepIdSchema = exports_external.string().min(1).max(64);
|
|
26960
|
+
var firstStepsStepTitleSchema = exports_external.string().trim().min(1).max(MAX_FIRST_STEPS_STEP_TITLE_LENGTH);
|
|
26961
|
+
var firstStepsStepBodySchema = exports_external.string().trim().max(MAX_FIRST_STEPS_STEP_BODY_LENGTH);
|
|
26962
|
+
var firstStepsActionSchema = exports_external.discriminatedUnion("type", [
|
|
26963
|
+
exports_external.object({
|
|
26964
|
+
type: exports_external.literal("create-file"),
|
|
26965
|
+
fileTypeSlug: exports_external.string().trim().min(1).max(120),
|
|
26966
|
+
setAsRootMap: exports_external.boolean().optional()
|
|
26967
|
+
}),
|
|
26968
|
+
exports_external.object({
|
|
26969
|
+
type: exports_external.literal("open-folder"),
|
|
26970
|
+
folderPath: exports_external.string().trim().min(1).max(512)
|
|
26971
|
+
}),
|
|
26972
|
+
exports_external.object({
|
|
26973
|
+
type: exports_external.literal("open-file"),
|
|
26974
|
+
folderPath: exports_external.string().trim().max(512),
|
|
26975
|
+
fileName: exports_external.string().trim().min(1).max(255)
|
|
26976
|
+
}),
|
|
26977
|
+
exports_external.object({
|
|
26978
|
+
type: exports_external.literal("read-handbook"),
|
|
26979
|
+
book: exports_external.enum(["player", "builder"]),
|
|
26980
|
+
chapterId: exports_external.string().min(1).max(64).nullable().optional()
|
|
26981
|
+
}),
|
|
26982
|
+
exports_external.object({ type: exports_external.literal("open-assistant") }),
|
|
26983
|
+
exports_external.object({ type: exports_external.literal("set-cover-image") }),
|
|
26984
|
+
exports_external.object({ type: exports_external.literal("edit-overview") })
|
|
26985
|
+
]);
|
|
26986
|
+
var firstStepsStepSchema = exports_external.discriminatedUnion("kind", [
|
|
26987
|
+
exports_external.object({
|
|
26988
|
+
kind: exports_external.literal("action"),
|
|
26989
|
+
id: firstStepsStepIdSchema,
|
|
26990
|
+
title: firstStepsStepTitleSchema,
|
|
26991
|
+
body: firstStepsStepBodySchema.optional(),
|
|
26992
|
+
action: firstStepsActionSchema
|
|
26993
|
+
}),
|
|
26994
|
+
exports_external.object({
|
|
26995
|
+
kind: exports_external.literal("info"),
|
|
26996
|
+
id: firstStepsStepIdSchema,
|
|
26997
|
+
title: firstStepsStepTitleSchema,
|
|
26998
|
+
body: firstStepsStepBodySchema.optional()
|
|
26999
|
+
})
|
|
27000
|
+
]);
|
|
27001
|
+
var firstStepsSchema = exports_external.object({
|
|
27002
|
+
version: exports_external.literal(FIRST_STEPS_VERSION),
|
|
27003
|
+
updatedAt: exports_external.string().max(40).optional(),
|
|
27004
|
+
image: imageObjectSchema.nullable().optional(),
|
|
27005
|
+
welcome: exports_external.string().trim().max(MAX_FIRST_STEPS_WELCOME_LENGTH).optional(),
|
|
27006
|
+
steps: exports_external.array(firstStepsStepSchema).max(MAX_FIRST_STEPS_STEPS)
|
|
27007
|
+
});
|
|
27008
|
+
var RETIRED_ACTION_TYPES = new Set(["start-game"]);
|
|
27009
|
+
|
|
26942
27010
|
// ../shared/src/projects/manual.ts
|
|
26943
27011
|
var MANUAL_VERSION = 1;
|
|
26944
27012
|
var MAX_MANUAL_CHAPTERS = 50;
|
|
@@ -27045,7 +27113,8 @@ var projectImportProjectSettingsSchema = exports_external.object({
|
|
|
27045
27113
|
gm: projectImportGameMasterSettingsSchema.optional(),
|
|
27046
27114
|
preludeFlow: exports_external.unknown().nullable().optional(),
|
|
27047
27115
|
playerHandbook: manualSchema.nullable().optional(),
|
|
27048
|
-
builderManual: manualSchema.nullable().optional()
|
|
27116
|
+
builderManual: manualSchema.nullable().optional(),
|
|
27117
|
+
firstSteps: firstStepsSchema.nullable().optional()
|
|
27049
27118
|
}).strict();
|
|
27050
27119
|
var projectImportProjectSchema = exports_external.object({
|
|
27051
27120
|
name: exports_external.string().trim().min(1),
|
|
@@ -27059,17 +27128,12 @@ var projectImportFileTypeDesignationSchema = exports_external.enum([
|
|
|
27059
27128
|
"gm_instructions",
|
|
27060
27129
|
"game_start"
|
|
27061
27130
|
]);
|
|
27062
|
-
var projectImportFileTypeCategorySchema = exports_external.enum([
|
|
27063
|
-
"world",
|
|
27064
|
-
"game_master",
|
|
27065
|
-
"game_system"
|
|
27066
|
-
]);
|
|
27067
27131
|
var projectImportFileTypeSchema = exports_external.object({
|
|
27068
27132
|
key: projectImportKeySchema,
|
|
27069
27133
|
name: exports_external.string().trim().min(1),
|
|
27070
27134
|
contentType: exports_external.enum(["markdown", "json"]),
|
|
27071
27135
|
designation: projectImportFileTypeDesignationSchema.nullable().optional(),
|
|
27072
|
-
category:
|
|
27136
|
+
category: exports_external.unknown().optional(),
|
|
27073
27137
|
contextVisibility: exports_external.enum(CONTEXT_VISIBILITY_VALUES).optional(),
|
|
27074
27138
|
agentEditable: exports_external.boolean().optional(),
|
|
27075
27139
|
schema: projectImportJsonValueSchema.nullable().optional(),
|
|
@@ -27189,7 +27253,7 @@ var workspaceFileTypeFileSchema = exports_external.object({
|
|
|
27189
27253
|
name: exports_external.string().min(1),
|
|
27190
27254
|
contentType: exports_external.enum(["markdown", "json"]),
|
|
27191
27255
|
designation: projectImportFileTypeDesignationSchema.nullable(),
|
|
27192
|
-
category: exports_external.
|
|
27256
|
+
category: exports_external.unknown().optional(),
|
|
27193
27257
|
schemaHash: schemaHashSchema.optional(),
|
|
27194
27258
|
schema: projectImportJsonValueSchema.nullable(),
|
|
27195
27259
|
layout: projectImportJsonValueSchema.nullable(),
|
|
@@ -27307,7 +27371,7 @@ var cliPushCreateFileTypeOpSchema = exports_external.object({
|
|
|
27307
27371
|
contentType: exports_external.enum(["markdown", "json"]),
|
|
27308
27372
|
schema: projectImportJsonValueSchema.nullable().optional(),
|
|
27309
27373
|
layout: projectImportJsonValueSchema.nullable().optional(),
|
|
27310
|
-
category: exports_external.
|
|
27374
|
+
category: exports_external.unknown().optional(),
|
|
27311
27375
|
designation: projectImportFileTypeDesignationSchema.nullable().optional(),
|
|
27312
27376
|
imageStyleInstructions: exports_external.string().transform(truncateImageStyleInstructions).nullable().optional(),
|
|
27313
27377
|
showCoverImage: exports_external.boolean().optional(),
|
|
@@ -27740,6 +27804,12 @@ var cliFileRemoteStateSchema = exports_external.enum([
|
|
|
27740
27804
|
"moved"
|
|
27741
27805
|
]);
|
|
27742
27806
|
|
|
27807
|
+
// ../shared/src/uuid.ts
|
|
27808
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27809
|
+
function isUuid(value) {
|
|
27810
|
+
return UUID_REGEX.test(value);
|
|
27811
|
+
}
|
|
27812
|
+
|
|
27743
27813
|
// ../shared/src/expression/values.ts
|
|
27744
27814
|
class ExpressionLambda {
|
|
27745
27815
|
invoke;
|
|
@@ -28010,14 +28080,13 @@ var GLOBAL_BUILTINS_TABLE = {
|
|
|
28010
28080
|
}
|
|
28011
28081
|
}
|
|
28012
28082
|
};
|
|
28013
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
28014
28083
|
function referenceIdFromValue(value) {
|
|
28015
28084
|
if (typeof value === "string") {
|
|
28016
|
-
return
|
|
28085
|
+
return isUuid(value) ? value : null;
|
|
28017
28086
|
}
|
|
28018
28087
|
if (isPlainObjectValue(value)) {
|
|
28019
28088
|
const id = value.referenceId;
|
|
28020
|
-
return typeof id === "string" &&
|
|
28089
|
+
return typeof id === "string" && isUuid(id) ? id : null;
|
|
28021
28090
|
}
|
|
28022
28091
|
return null;
|
|
28023
28092
|
}
|
|
@@ -35455,7 +35524,6 @@ var LOCKED_DESIGNATION_CONFIGS = {
|
|
|
35455
35524
|
game_start: {
|
|
35456
35525
|
name: "Game Start",
|
|
35457
35526
|
contentType: "json",
|
|
35458
|
-
category: "game_master",
|
|
35459
35527
|
contextVisibility: "searchable",
|
|
35460
35528
|
schemaMode: "base_fields_only",
|
|
35461
35529
|
layoutMode: "none"
|
|
@@ -36009,7 +36077,6 @@ var extraTargetCandidatesCache = new WeakMap;
|
|
|
36009
36077
|
|
|
36010
36078
|
// ../shared/src/cli/craft-block.ts
|
|
36011
36079
|
var CRAFT_BLOCK_KEY = "$craft";
|
|
36012
|
-
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
36013
36080
|
var KNOWN_BLOCK_KEYS = new Set(["referenceId", "settings", "metadata"]);
|
|
36014
36081
|
var KNOWN_SETTINGS_KEYS = new Set([
|
|
36015
36082
|
"contextVisibility",
|
|
@@ -36044,7 +36111,7 @@ function parseCraftBlockValue(value) {
|
|
|
36044
36111
|
}
|
|
36045
36112
|
}
|
|
36046
36113
|
if (value.referenceId !== undefined) {
|
|
36047
|
-
if (typeof value.referenceId === "string" &&
|
|
36114
|
+
if (typeof value.referenceId === "string" && isUuid(value.referenceId)) {
|
|
36048
36115
|
block.referenceId = value.referenceId.toLowerCase();
|
|
36049
36116
|
} else {
|
|
36050
36117
|
warnings.push("$craft.referenceId is not a UUID — treated as absent (the file imports as id-less)");
|
|
@@ -37887,8 +37954,22 @@ var {
|
|
|
37887
37954
|
} = shadcnComponentDefinitions;
|
|
37888
37955
|
var roundedEnum = exports_external.nullable(exports_external.enum(["none", "sm", "md", "lg", "xl", "2xl", "full"]));
|
|
37889
37956
|
var aspectRatioEnum = exports_external.nullable(exports_external.enum(["video", "square", "portrait", "tall", "ultrawide", "ultratall"]));
|
|
37957
|
+
var bgImageProp = exports_external.optional(exports_external.nullable(exports_external.string()));
|
|
37958
|
+
var bgImageFitEnum = exports_external.optional(exports_external.nullable(exports_external.enum(["cover", "contain", "tile", "tile-x", "tile-y"])));
|
|
37959
|
+
var BG_IMAGE_DOC = 'bgImage sets a background image URL (children render on top); bgImageFit controls how it fills: "cover" (default, crop to fill), "contain" (fit inside), "tile" / "tile-x" / "tile-y" (repeat at natural size for seamless textures).';
|
|
37890
37960
|
var editPathProp = exports_external.optional(exports_external.nullable(exports_external.record(exports_external.string(), exports_external.string())));
|
|
37891
37961
|
var EDIT_PATH_DOC = 'editPath redirects where an editable prop saves — e.g. editPath: { "value": "/resourceState/{key}/current" } writes there instead of the bound path, with {placeholders} filled from the current repeat item; this is how a control repeated over a computed (expression) array stays editable: display the computed row, write to the stored field.';
|
|
37962
|
+
var classNameProp = exports_external.optional(exports_external.nullable(exports_external.string()));
|
|
37963
|
+
function withClassNameProp(definition) {
|
|
37964
|
+
const props = definition.props;
|
|
37965
|
+
if (typeof props?.extend !== "function") {
|
|
37966
|
+
return definition;
|
|
37967
|
+
}
|
|
37968
|
+
return {
|
|
37969
|
+
...definition,
|
|
37970
|
+
props: props.extend({ className: classNameProp })
|
|
37971
|
+
};
|
|
37972
|
+
}
|
|
37892
37973
|
var extendedShadcnComponents = {
|
|
37893
37974
|
Image: {
|
|
37894
37975
|
props: exports_external.object({
|
|
@@ -37897,7 +37978,8 @@ var extendedShadcnComponents = {
|
|
|
37897
37978
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg", "full"])),
|
|
37898
37979
|
align: exports_external.nullable(exports_external.enum(["left", "center", "right"])),
|
|
37899
37980
|
aspectRatio: exports_external.optional(aspectRatioEnum),
|
|
37900
|
-
stateKey: exports_external.optional(exports_external.nullable(exports_external.string()))
|
|
37981
|
+
stateKey: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
37982
|
+
className: classNameProp
|
|
37901
37983
|
}),
|
|
37902
37984
|
description: 'Image display with configurable size and alignment. size controls max width: sm (200px), md (400px), lg (600px), full (100%). align controls horizontal alignment: left, center, right. Defaults to full size, left aligned. aspectRatio crops the image to a fixed ratio: "video" (16:9), "square" (1:1), "portrait" (3:4), "tall" (9:16), "ultrawide" (32:9), "ultratall" (9:32); omit to keep the natural ratio.',
|
|
37903
37985
|
example: {
|
|
@@ -37915,11 +37997,13 @@ var extendedShadcnComponents = {
|
|
|
37915
37997
|
justify: exports_external.nullable(exports_external.enum(["start", "center", "end", "between", "around"])),
|
|
37916
37998
|
wrap: exports_external.nullable(exports_external.boolean()),
|
|
37917
37999
|
bgColor: exports_external.nullable(exports_external.string()),
|
|
38000
|
+
bgImage: bgImageProp,
|
|
38001
|
+
bgImageFit: bgImageFitEnum,
|
|
37918
38002
|
rounded: roundedEnum,
|
|
37919
38003
|
className: exports_external.nullable(exports_external.string())
|
|
37920
38004
|
}),
|
|
37921
38005
|
slots: shadcnComponentDefinitions.Stack.slots,
|
|
37922
|
-
description:
|
|
38006
|
+
description: `Flex layout container. bgColor sets background color (any CSS color value). ${BG_IMAGE_DOC} Use className for extra Tailwind utilities (e.g. col-span-*, mt-4). Set wrap=true to allow line wrapping.`,
|
|
37923
38007
|
example: { direction: "vertical", gap: "md" }
|
|
37924
38008
|
},
|
|
37925
38009
|
Grid: {
|
|
@@ -37927,11 +38011,13 @@ var extendedShadcnComponents = {
|
|
|
37927
38011
|
columns: exports_external.nullable(exports_external.number()),
|
|
37928
38012
|
gap: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
37929
38013
|
bgColor: exports_external.nullable(exports_external.string()),
|
|
38014
|
+
bgImage: bgImageProp,
|
|
38015
|
+
bgImageFit: bgImageFitEnum,
|
|
37930
38016
|
rounded: roundedEnum,
|
|
37931
38017
|
className: exports_external.nullable(exports_external.string())
|
|
37932
38018
|
}),
|
|
37933
38019
|
slots: shadcnComponentDefinitions.Grid.slots,
|
|
37934
|
-
description:
|
|
38020
|
+
description: `CSS grid layout. columns sets equal column count (supports 1-12). bgColor sets background color (any CSS color value). ${BG_IMAGE_DOC} Use className for extra Tailwind utilities. Children can use className with col-span-* for responsive multi-column layouts.`,
|
|
37935
38021
|
example: { columns: 2, gap: "md" }
|
|
37936
38022
|
},
|
|
37937
38023
|
Card: {
|
|
@@ -37941,12 +38027,14 @@ var extendedShadcnComponents = {
|
|
|
37941
38027
|
maxWidth: exports_external.nullable(exports_external.enum(["sm", "md", "lg", "full"])),
|
|
37942
38028
|
centered: exports_external.nullable(exports_external.boolean()),
|
|
37943
38029
|
bgColor: exports_external.nullable(exports_external.string()),
|
|
38030
|
+
bgImage: bgImageProp,
|
|
38031
|
+
bgImageFit: bgImageFitEnum,
|
|
37944
38032
|
borderColor: exports_external.nullable(exports_external.string()),
|
|
37945
38033
|
rounded: roundedEnum,
|
|
37946
38034
|
className: exports_external.nullable(exports_external.string())
|
|
37947
38035
|
}),
|
|
37948
38036
|
slots: shadcnComponentDefinitions.Card.slots,
|
|
37949
|
-
description:
|
|
38037
|
+
description: `Container card with optional title/description. bgColor and borderColor accept any CSS color value. ${BG_IMAGE_DOC} Use className for extra Tailwind utilities (e.g. col-span-*).`,
|
|
37950
38038
|
example: {
|
|
37951
38039
|
title: "Character Stats",
|
|
37952
38040
|
description: null
|
|
@@ -37956,7 +38044,8 @@ var extendedShadcnComponents = {
|
|
|
37956
38044
|
props: exports_external.object({
|
|
37957
38045
|
text: exports_external.string(),
|
|
37958
38046
|
level: exports_external.nullable(exports_external.enum(["h1", "h2", "h3", "h4"])),
|
|
37959
|
-
color: exports_external.nullable(exports_external.string())
|
|
38047
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38048
|
+
className: classNameProp
|
|
37960
38049
|
}),
|
|
37961
38050
|
description: "Section heading (h1–h4). Use color for custom text color (any CSS color value). Defaults to h2 if level is omitted.",
|
|
37962
38051
|
example: { text: "Character Stats", level: "h3", color: "#ef4444" }
|
|
@@ -37966,6 +38055,7 @@ var extendedShadcnComponents = {
|
|
|
37966
38055
|
text: exports_external.string(),
|
|
37967
38056
|
variant: exports_external.nullable(exports_external.enum(["caption", "body", "muted", "lead", "code"])),
|
|
37968
38057
|
color: exports_external.nullable(exports_external.string()),
|
|
38058
|
+
className: classNameProp,
|
|
37969
38059
|
editPath: editPathProp
|
|
37970
38060
|
}),
|
|
37971
38061
|
description: `Text paragraph with optional variant and custom color. Accepts any CSS color value. Bound text edits inline. ${EDIT_PATH_DOC}`,
|
|
@@ -37975,7 +38065,8 @@ var extendedShadcnComponents = {
|
|
|
37975
38065
|
props: exports_external.object({
|
|
37976
38066
|
text: exports_external.string(),
|
|
37977
38067
|
variant: exports_external.nullable(exports_external.enum(["default", "secondary", "destructive", "outline"])),
|
|
37978
|
-
color: exports_external.nullable(exports_external.string())
|
|
38068
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38069
|
+
className: classNameProp
|
|
37979
38070
|
}),
|
|
37980
38071
|
description: "Small inline badge/tag. When color is set (any CSS color value), it overrides the variant with a custom background color and auto-contrasted text.",
|
|
37981
38072
|
example: { text: "Active", variant: "default", color: null }
|
|
@@ -37989,6 +38080,7 @@ var extendedShadcnComponents = {
|
|
|
37989
38080
|
trackColor: exports_external.nullable(exports_external.string()),
|
|
37990
38081
|
showValue: exports_external.nullable(exports_external.boolean()),
|
|
37991
38082
|
stepper: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38083
|
+
className: classNameProp,
|
|
37992
38084
|
editPath: editPathProp
|
|
37993
38085
|
}),
|
|
37994
38086
|
description: `Progress bar with optional label. color sets the indicator bar color, trackColor sets the background track color. showValue displays "value / max" text. stepper adds hover −/+ buttons that bump the bound value by 1 (clamped to 0..max) — prefer this over pairing a bar with a separate Stepper for the same field. All colors accept any CSS color value. ${EDIT_PATH_DOC}`,
|
|
@@ -38006,7 +38098,8 @@ var extendedShadcnComponents = {
|
|
|
38006
38098
|
tabs: exports_external.array(exports_external.object({ label: exports_external.string(), value: exports_external.string() })),
|
|
38007
38099
|
defaultValue: exports_external.nullable(exports_external.string()),
|
|
38008
38100
|
value: exports_external.nullable(exports_external.string()),
|
|
38009
|
-
bgColor: exports_external.nullable(exports_external.string())
|
|
38101
|
+
bgColor: exports_external.nullable(exports_external.string()),
|
|
38102
|
+
className: classNameProp
|
|
38010
38103
|
}),
|
|
38011
38104
|
slots: _ShadcnTabs.slots,
|
|
38012
38105
|
description: "Tab navigation. bgColor sets the tab list background color (any CSS color value).",
|
|
@@ -38023,6 +38116,10 @@ var referenceTargetSlugProps = {
|
|
|
38023
38116
|
fileTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
38024
38117
|
pageTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string()))
|
|
38025
38118
|
};
|
|
38119
|
+
var multiReferenceTargetSlugProps = {
|
|
38120
|
+
...referenceTargetSlugProps,
|
|
38121
|
+
fileTypeSlugs: exports_external.optional(exports_external.nullable(exports_external.array(exports_external.string())))
|
|
38122
|
+
};
|
|
38026
38123
|
var referenceValue = exports_external.union([
|
|
38027
38124
|
exports_external.string(),
|
|
38028
38125
|
exports_external.number(),
|
|
@@ -38035,7 +38132,7 @@ var referenceValue = exports_external.union([
|
|
|
38035
38132
|
]);
|
|
38036
38133
|
var fileReferenceGridProps = exports_external.object({
|
|
38037
38134
|
items: exports_external.array(exports_external.unknown()),
|
|
38038
|
-
...
|
|
38135
|
+
...multiReferenceTargetSlugProps,
|
|
38039
38136
|
referenceField: exports_external.nullable(exports_external.string()),
|
|
38040
38137
|
columns: exports_external.nullable(exports_external.number()),
|
|
38041
38138
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
@@ -38045,18 +38142,24 @@ var fileReferenceGridProps = exports_external.object({
|
|
|
38045
38142
|
showAddNewOnHover: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38046
38143
|
addNewVariant: exports_external.optional(exports_external.nullable(exports_external.enum(["inline", "aside"]))),
|
|
38047
38144
|
emptyState: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
38145
|
+
titlePosition: exports_external.optional(exports_external.nullable(exports_external.enum(["bottom", "top", "overlay", "hidden"]))),
|
|
38146
|
+
metadataPosition: exports_external.optional(exports_external.nullable(exports_external.enum(["inline", "below", "hidden"]))),
|
|
38048
38147
|
metadataFields: exports_external.optional(exports_external.nullable(exports_external.array(exports_external.object({
|
|
38049
38148
|
name: exports_external.string(),
|
|
38050
38149
|
type: exports_external.enum(["string", "number", "boolean"]),
|
|
38051
|
-
enum: exports_external.optional(exports_external.array(exports_external.string()))
|
|
38052
|
-
|
|
38150
|
+
enum: exports_external.optional(exports_external.array(exports_external.string())),
|
|
38151
|
+
hidden: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38152
|
+
label: exports_external.optional(exports_external.nullable(exports_external.string()))
|
|
38153
|
+
})))),
|
|
38154
|
+
className: classNameProp
|
|
38053
38155
|
});
|
|
38054
38156
|
var craftComponents = {
|
|
38055
38157
|
Checkbox: {
|
|
38056
38158
|
props: exports_external.object({
|
|
38057
38159
|
checked: exports_external.boolean(),
|
|
38058
38160
|
label: exports_external.nullable(exports_external.string()),
|
|
38059
|
-
color: exports_external.nullable(exports_external.string())
|
|
38161
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38162
|
+
className: classNameProp
|
|
38060
38163
|
}),
|
|
38061
38164
|
description: "Labeled checkbox for a boolean field. Bind checked to toggle it directly from the rendered view. color sets the checked box color (any CSS color value).",
|
|
38062
38165
|
example: { checked: true, label: "Inspiration", color: null }
|
|
@@ -38065,7 +38168,8 @@ var craftComponents = {
|
|
|
38065
38168
|
props: exports_external.object({
|
|
38066
38169
|
checked: exports_external.boolean(),
|
|
38067
38170
|
label: exports_external.nullable(exports_external.string()),
|
|
38068
|
-
color: exports_external.nullable(exports_external.string())
|
|
38171
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38172
|
+
className: classNameProp
|
|
38069
38173
|
}),
|
|
38070
38174
|
description: "Labeled toggle switch for a boolean field — same data shape as Checkbox with a switch look. Bind checked to flip it directly from the rendered view. color sets the on-state color (any CSS color value).",
|
|
38071
38175
|
example: { checked: true, label: "Concentrating", color: "#34d399" }
|
|
@@ -38080,7 +38184,8 @@ var craftComponents = {
|
|
|
38080
38184
|
color: exports_external.nullable(exports_external.string()),
|
|
38081
38185
|
emptyText: exports_external.nullable(exports_external.string()),
|
|
38082
38186
|
showAddNew: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38083
|
-
showAddNewOnHover: exports_external.optional(exports_external.nullable(exports_external.boolean()))
|
|
38187
|
+
showAddNewOnHover: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38188
|
+
className: classNameProp
|
|
38084
38189
|
}),
|
|
38085
38190
|
description: 'Plain list of values — traits, features, languages, rumors. items can be strings or objects (map object fields with labelField and descriptionField). variant "bullet" (default) and "numbered" stack items; "inline" flows them on one line joined by separator (default " · "). Bound string lists are editable inline. showAddNew defaults to true; set it false to hide the add control. showAddNewOnHover defaults to true; set it false to keep Add visible on desktop. color sets the item text color.',
|
|
38086
38191
|
example: {
|
|
@@ -38103,7 +38208,8 @@ var craftComponents = {
|
|
|
38103
38208
|
icon: exports_external.nullable(exports_external.string()),
|
|
38104
38209
|
variant: exports_external.nullable(exports_external.enum(["quote", "panel"])),
|
|
38105
38210
|
color: exports_external.nullable(exports_external.string()),
|
|
38106
|
-
bgColor: exports_external.nullable(exports_external.string())
|
|
38211
|
+
bgColor: exports_external.nullable(exports_external.string()),
|
|
38212
|
+
className: classNameProp
|
|
38107
38213
|
}),
|
|
38108
38214
|
description: 'Framed lore/flavor block. variant "quote" (default) renders italic text behind a left accent border with an optional em-dash attribution; "panel" renders a soft filled box with an optional icon and title. icon accepts any text/emoji (e.g. "\uD83D\uDCDC"). color tints the accent and title, bgColor sets the panel background.',
|
|
38109
38215
|
example: {
|
|
@@ -38126,7 +38232,8 @@ var craftComponents = {
|
|
|
38126
38232
|
color: exports_external.nullable(exports_external.string()),
|
|
38127
38233
|
fileTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
38128
38234
|
fileTypeSlugs: exports_external.optional(exports_external.nullable(exports_external.array(exports_external.string()))),
|
|
38129
|
-
pageTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string()))
|
|
38235
|
+
pageTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
38236
|
+
className: classNameProp
|
|
38130
38237
|
}),
|
|
38131
38238
|
description: `Live value pulled from a referenced file — display another file type's data without copying it. Bind source to a reference field (single or list) and set field to the path to read from each referenced file's content (e.g. "acBonus", "stats.speed"); "$title"/"$name" read the file name. Multiple referenced files join with separator (default ", ") or render as chips with format "badge". Read-only — the value lives on the referenced file. Provide fileTypeSlug when the schema does not already annotate the reference field.`,
|
|
38132
38239
|
example: {
|
|
@@ -38142,7 +38249,8 @@ var craftComponents = {
|
|
|
38142
38249
|
Markdown: {
|
|
38143
38250
|
props: exports_external.object({
|
|
38144
38251
|
content: exports_external.string(),
|
|
38145
|
-
color: exports_external.nullable(exports_external.string())
|
|
38252
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38253
|
+
className: classNameProp
|
|
38146
38254
|
}),
|
|
38147
38255
|
description: "Renders markdown text with prose styling. Supports bold, italic, code, links, and lists. Use color for custom text color.",
|
|
38148
38256
|
example: {
|
|
@@ -38155,7 +38263,8 @@ var craftComponents = {
|
|
|
38155
38263
|
items: exports_external.array(exports_external.tuple([exports_external.string(), exports_external.union([exports_external.string(), exports_external.number()])])),
|
|
38156
38264
|
cols: exports_external.nullable(exports_external.number()),
|
|
38157
38265
|
color: exports_external.nullable(exports_external.string()),
|
|
38158
|
-
bgColor: exports_external.nullable(exports_external.string())
|
|
38266
|
+
bgColor: exports_external.nullable(exports_external.string()),
|
|
38267
|
+
className: classNameProp
|
|
38159
38268
|
}),
|
|
38160
38269
|
description: "Grid of labeled stat values. Each item is a [label, value] tuple. Use color for value text color and bgColor for cell background color.",
|
|
38161
38270
|
example: {
|
|
@@ -38180,7 +38289,8 @@ var craftComponents = {
|
|
|
38180
38289
|
derivedLabel: exports_external.nullable(exports_external.string()),
|
|
38181
38290
|
cols: exports_external.nullable(exports_external.number()),
|
|
38182
38291
|
color: exports_external.nullable(exports_external.string()),
|
|
38183
|
-
bgColor: exports_external.nullable(exports_external.string())
|
|
38292
|
+
bgColor: exports_external.nullable(exports_external.string()),
|
|
38293
|
+
className: classNameProp
|
|
38184
38294
|
}),
|
|
38185
38295
|
description: "Grid of labeled stat cells that pair an editable base value with a derived/calculated value, such as ability score plus modifier.",
|
|
38186
38296
|
example: {
|
|
@@ -38201,12 +38311,12 @@ var craftComponents = {
|
|
|
38201
38311
|
options: exports_external.optional(exports_external.nullable(exports_external.array(exports_external.string()))),
|
|
38202
38312
|
variant: exports_external.nullable(exports_external.enum(["default", "secondary", "outline", "destructive"])),
|
|
38203
38313
|
color: exports_external.nullable(exports_external.string()),
|
|
38204
|
-
|
|
38205
|
-
pageTypeSlug: exports_external.optional(exports_external.nullable(exports_external.string())),
|
|
38314
|
+
...multiReferenceTargetSlugProps,
|
|
38206
38315
|
showAddNew: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38207
|
-
showAddNewOnHover: exports_external.optional(exports_external.nullable(exports_external.boolean()))
|
|
38316
|
+
showAddNewOnHover: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38317
|
+
className: classNameProp
|
|
38208
38318
|
}),
|
|
38209
|
-
description: "Wrapped row of badges. Use for tags, abilities, skills, etc. Provide options to show a preset add menu for fixed vocabularies. showAddNew defaults to true; set it false to hide the add control. showAddNewOnHover defaults to true; set it false to keep Add visible on desktop. When color is set, it overrides the variant with a custom background color. For compact reference arrays, provide fileTypeSlug so the rendered view can resolve names and add references with a picker.",
|
|
38319
|
+
description: "Wrapped row of badges. Use for tags, abilities, skills, etc. Provide options to show a preset add menu for fixed vocabularies. showAddNew defaults to true; set it false to hide the add control. showAddNewOnHover defaults to true; set it false to keep Add visible on desktop. When color is set, it overrides the variant with a custom background color. For compact reference arrays, provide fileTypeSlug (or fileTypeSlugs when the field targets multiple file types) so the rendered view can resolve names and add references with a picker; fields whose schema already declares reference targets need no slug prop.",
|
|
38210
38320
|
example: {
|
|
38211
38321
|
items: ["Slash", "Block", "Charge"],
|
|
38212
38322
|
options: ["Slash", "Block", "Charge", "Parry"],
|
|
@@ -38227,7 +38337,8 @@ var craftComponents = {
|
|
|
38227
38337
|
field: exports_external.string()
|
|
38228
38338
|
}))),
|
|
38229
38339
|
showProgress: exports_external.nullable(exports_external.boolean()),
|
|
38230
|
-
emptyText: exports_external.nullable(exports_external.string())
|
|
38340
|
+
emptyText: exports_external.nullable(exports_external.string()),
|
|
38341
|
+
className: classNameProp
|
|
38231
38342
|
}),
|
|
38232
38343
|
description: "Read-only checklist for arrays of tasks or objectives. Items can be strings or objects. Use labelField, checkedField, and descriptionField to map object fields; metaFields renders extra badges.",
|
|
38233
38344
|
example: {
|
|
@@ -38287,6 +38398,7 @@ var craftComponents = {
|
|
|
38287
38398
|
emptyColor: exports_external.nullable(exports_external.string()),
|
|
38288
38399
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
38289
38400
|
showValue: exports_external.nullable(exports_external.boolean()),
|
|
38401
|
+
className: classNameProp,
|
|
38290
38402
|
editPath: editPathProp
|
|
38291
38403
|
}),
|
|
38292
38404
|
description: `Row of filled/empty dots for small resource pools — spell slots, ki points, uses per rest, condition pips. Bind value to a number field; when the field is editable, clicking a dot sets the value (clicking the topmost filled dot clears it). max is the pool size (defaults to 5, capped at 25 dots) and can also bind to a field. color sets filled dots, emptyColor unfilled dots (any CSS color value). showValue displays "value / max" text. Values bound to expression fields render read-only unless editPath provides a stored write target. ${EDIT_PATH_DOC}`,
|
|
@@ -38310,6 +38422,7 @@ var craftComponents = {
|
|
|
38310
38422
|
showMax: exports_external.nullable(exports_external.boolean()),
|
|
38311
38423
|
color: exports_external.nullable(exports_external.string()),
|
|
38312
38424
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
38425
|
+
className: classNameProp,
|
|
38313
38426
|
editPath: editPathProp
|
|
38314
38427
|
}),
|
|
38315
38428
|
description: `Numeric counter with −/+ buttons for one-tap turn-time edits — hit points, ammo, sorcery points, momentum. Bind value to a number field; each tap saves immediately. min defaults to 0 (set a negative min to allow values below zero), max is uncapped when null and can bind to a field (e.g. {"$state": "/hitPointMax"}), step defaults to 1. showMax renders "23 / 40". The value is also click-to-type editable. ${EDIT_PATH_DOC}`,
|
|
@@ -38332,6 +38445,7 @@ var craftComponents = {
|
|
|
38332
38445
|
onLabel: exports_external.nullable(exports_external.string()),
|
|
38333
38446
|
offLabel: exports_external.nullable(exports_external.string()),
|
|
38334
38447
|
color: exports_external.nullable(exports_external.string()),
|
|
38448
|
+
className: classNameProp,
|
|
38335
38449
|
editPath: editPathProp
|
|
38336
38450
|
}),
|
|
38337
38451
|
description: `Single boolean as a one-tap control — inspiration, concentration, death-save boxes, armor-used flags. Bind value to a boolean field; clicking flips and saves it. variant: "switch" (default), "checkbox", or "chip" (a lit/dim pill; onLabel/offLabel override the pill text per state). ${EDIT_PATH_DOC}`,
|
|
@@ -38355,6 +38469,7 @@ var craftComponents = {
|
|
|
38355
38469
|
color: exports_external.nullable(exports_external.string()),
|
|
38356
38470
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
38357
38471
|
showValue: exports_external.nullable(exports_external.boolean()),
|
|
38472
|
+
className: classNameProp,
|
|
38358
38473
|
editPath: editPathProp
|
|
38359
38474
|
}),
|
|
38360
38475
|
description: `Row of square boxes for health/stress/harm tracks. Two modes: bind value to a number field for a filled-count track (click box N to set, click the topmost filled box to clear), or bind states to a string-array field for multi-state tracks where clicking a box cycles empty → each stateOption → empty (e.g. World of Darkness bashing/lethal/aggravated). stateOptions is [{label, symbol}]; the stored array holds labels. boxes is the track length (default 10, cap 30). groupEvery adds a visual gap every N boxes (e.g. 3 for Blades stress). ${EDIT_PATH_DOC}`,
|
|
@@ -38386,7 +38501,8 @@ var craftComponents = {
|
|
|
38386
38501
|
})
|
|
38387
38502
|
]))),
|
|
38388
38503
|
label: exports_external.nullable(exports_external.string()),
|
|
38389
|
-
color: exports_external.nullable(exports_external.string())
|
|
38504
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38505
|
+
className: classNameProp
|
|
38390
38506
|
}),
|
|
38391
38507
|
description: "Always-visible roster of toggle chips bound to a string-array field — conditions (poisoned, prone, grappled), exhaustion, status effects. Active chips are lit, inactive ones dim; clicking toggles membership and saves. Unlike BadgeList, the full option set stays visible for at-a-glance combat state. options entries are strings or {label, value?, color?}.",
|
|
38392
38508
|
example: {
|
|
@@ -38405,6 +38521,7 @@ var craftComponents = {
|
|
|
38405
38521
|
emptyColor: exports_external.nullable(exports_external.string()),
|
|
38406
38522
|
size: exports_external.nullable(exports_external.enum(["sm", "md", "lg"])),
|
|
38407
38523
|
showValue: exports_external.nullable(exports_external.boolean()),
|
|
38524
|
+
className: classNameProp,
|
|
38408
38525
|
editPath: editPathProp
|
|
38409
38526
|
}),
|
|
38410
38527
|
description: `Segmented circular progress clock (Blades in the Dark style) for project clocks, countdowns, and faction progress. Bind value to a number field; clicking a segment fills up to it, clicking the last filled segment clears it. segments is 2-12 (default 4). color fills segments, emptyColor the unfilled ones. ${EDIT_PATH_DOC}`,
|
|
@@ -38427,7 +38544,8 @@ var craftComponents = {
|
|
|
38427
38544
|
type: exports_external.nullable(exports_external.enum(["string", "number", "boolean"]))
|
|
38428
38545
|
})),
|
|
38429
38546
|
label: exports_external.nullable(exports_external.string()),
|
|
38430
|
-
emptyText: exports_external.nullable(exports_external.string())
|
|
38547
|
+
emptyText: exports_external.nullable(exports_external.string()),
|
|
38548
|
+
className: classNameProp
|
|
38431
38549
|
}),
|
|
38432
38550
|
description: 'Table bound to an array of objects with declared columns — spell lists, inventories with quantity/weight, attack tables. Each column maps a field (dot paths supported, e.g. "item.name"); cells edit inline and save back to that row when the array is a stored field — rows of a computed (expression) array render read-only. Use type: "number" for numeric columns. For arrays of file references prefer FileReferenceGrid; DataTable is for structured plain-object rows.',
|
|
38433
38551
|
example: {
|
|
@@ -38448,7 +38566,8 @@ var craftComponents = {
|
|
|
38448
38566
|
props: exports_external.object({
|
|
38449
38567
|
items: exports_external.array(exports_external.tuple([exports_external.string(), exports_external.string()])),
|
|
38450
38568
|
labelColor: exports_external.nullable(exports_external.string()),
|
|
38451
|
-
valueColor: exports_external.nullable(exports_external.string())
|
|
38569
|
+
valueColor: exports_external.nullable(exports_external.string()),
|
|
38570
|
+
className: classNameProp
|
|
38452
38571
|
}),
|
|
38453
38572
|
description: "Vertical list of labeled field/value pairs. Use labelColor and valueColor for custom text colors.",
|
|
38454
38573
|
example: {
|
|
@@ -38466,7 +38585,8 @@ var craftComponents = {
|
|
|
38466
38585
|
src: exports_external.nullable(exports_external.string()),
|
|
38467
38586
|
title: exports_external.nullable(exports_external.string()),
|
|
38468
38587
|
subtitle: exports_external.nullable(exports_external.string()),
|
|
38469
|
-
aspectRatio: aspectRatioEnum
|
|
38588
|
+
aspectRatio: aspectRatioEnum,
|
|
38589
|
+
className: classNameProp
|
|
38470
38590
|
}),
|
|
38471
38591
|
description: 'Hero image with optional text overlay. Always renders a gradient fallback when no image is set. aspectRatio defaults to "video" (16:9); also supports "square" (1:1), "portrait" (3:4), "tall" (9:16), "ultrawide" (32:9) for slim banner rows, and "ultratall" (9:32) for narrow full-height columns.',
|
|
38472
38592
|
example: {
|
|
@@ -38480,7 +38600,8 @@ var craftComponents = {
|
|
|
38480
38600
|
props: exports_external.object({
|
|
38481
38601
|
value: exports_external.union([exports_external.string(), exports_external.number()]),
|
|
38482
38602
|
format: exports_external.nullable(exports_external.enum(["date", "relative", "distance"])),
|
|
38483
|
-
color: exports_external.nullable(exports_external.string())
|
|
38603
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38604
|
+
className: classNameProp
|
|
38484
38605
|
}),
|
|
38485
38606
|
description: 'Formatted date display. "date" shows "April 29, 2024", "relative" shows "yesterday", "distance" shows "2 days ago". Use color for custom text color.',
|
|
38486
38607
|
example: { value: 1714400000000, format: "distance", color: null }
|
|
@@ -38490,7 +38611,8 @@ var craftComponents = {
|
|
|
38490
38611
|
value: exports_external.number(),
|
|
38491
38612
|
style: exports_external.nullable(exports_external.enum(["decimal", "currency", "percent"])),
|
|
38492
38613
|
currency: exports_external.nullable(exports_external.string()),
|
|
38493
|
-
color: exports_external.nullable(exports_external.string())
|
|
38614
|
+
color: exports_external.nullable(exports_external.string()),
|
|
38615
|
+
className: classNameProp
|
|
38494
38616
|
}),
|
|
38495
38617
|
description: 'Formatted number display. "decimal" shows "1,234.56", "currency" shows "$1,234.56", "percent" shows "85%". Use color for custom text color.',
|
|
38496
38618
|
example: {
|
|
@@ -38509,9 +38631,10 @@ var craftComponents = {
|
|
|
38509
38631
|
label: exports_external.string(),
|
|
38510
38632
|
value: exports_external.union([exports_external.string(), exports_external.number()])
|
|
38511
38633
|
}))),
|
|
38512
|
-
...
|
|
38634
|
+
...multiReferenceTargetSlugProps,
|
|
38635
|
+
className: classNameProp
|
|
38513
38636
|
}),
|
|
38514
|
-
description: "Dropdown select. Provide static options array, a fileTypeSlug to populate from files of that type, or both. value is the selected option's value or an object with referenceId plus a readable name.",
|
|
38637
|
+
description: "Dropdown select. Provide static options array, a fileTypeSlug to populate from files of that type (or fileTypeSlugs when the field targets multiple file types), or both. value is the selected option's value or an object with referenceId plus a readable name. Fields whose schema already declares reference targets need no slug prop.",
|
|
38515
38638
|
example: {
|
|
38516
38639
|
value: "fighter",
|
|
38517
38640
|
label: "Class",
|
|
@@ -38527,7 +38650,8 @@ var craftComponents = {
|
|
|
38527
38650
|
value: exports_external.nullable(exports_external.string()),
|
|
38528
38651
|
label: exports_external.nullable(exports_external.string()),
|
|
38529
38652
|
placeholder: exports_external.nullable(exports_external.string()),
|
|
38530
|
-
showLabel: exports_external.optional(exports_external.nullable(exports_external.boolean()))
|
|
38653
|
+
showLabel: exports_external.optional(exports_external.nullable(exports_external.boolean())),
|
|
38654
|
+
className: classNameProp
|
|
38531
38655
|
}),
|
|
38532
38656
|
description: 'Voice picker for character dialogue. Bind value to a string field with format "voice". A blank value inherits the GM voice, and the web renderer shows preview controls for each voice. showLabel defaults to true; set it false to hide the label.',
|
|
38533
38657
|
example: {
|
|
@@ -38539,7 +38663,7 @@ var craftComponents = {
|
|
|
38539
38663
|
},
|
|
38540
38664
|
FileReferenceGrid: {
|
|
38541
38665
|
props: fileReferenceGridProps,
|
|
38542
|
-
description:
|
|
38666
|
+
description: `Grid of cards showing referenced files with their images and titles. Provide items (array of file reference ids, slugs, names, reference objects, or objects), fileTypeSlug to identify the file type — or fileTypeSlugs listing every target type for multi-type reference fields (the add picker then offers per-type filtering and stores qualified "type/slug" values) — and referenceField for object arrays (e.g. "item" for [{item: {referenceId, name}, quantity: 2}]). Fields whose schema already declares reference targets need no slug prop. Metadata fields like quantity render as badges. titlePosition moves each card's name: "bottom" (default, below the image), "top" (above the image), "overlay" (over the lower edge of the image), or "hidden". metadataPosition moves the metadata badges: "inline" (default, beside the name), "below" (their own wrapping row under the name — fits longer text values), or "hidden". metadataFields entries accept hidden: true to keep a field editable in the card's edit dialog without displaying it, and label to rename it there; omitting a field from the list removes it from display, editing, and new-row defaults alike. emptyState customizes the full-width empty message and defaults to "None.". showAddNew defaults to true; set it false to hide the add control. showAddNewOnHover defaults to true; set it false to keep Add visible on desktop. addNewVariant defaults to "inline" and accepts "aside" to place one compact add control beside the grid label. imageAspectRatio overrides the card image ratio: "video" (16:9), "square" (1:1), "portrait" (3:4), "tall" (9:16), "ultrawide" (32:9), "ultratall" (9:32, e.g. tall party-roster portraits).`,
|
|
38543
38667
|
example: {
|
|
38544
38668
|
items: [
|
|
38545
38669
|
{
|
|
@@ -38594,7 +38718,8 @@ var craftComponents = {
|
|
|
38594
38718
|
display: exports_external.nullable(exports_external.enum(["bar", "fraction", "badges", "text"]))
|
|
38595
38719
|
})),
|
|
38596
38720
|
conditionsField: exports_external.nullable(exports_external.string()),
|
|
38597
|
-
notesField: exports_external.nullable(exports_external.string())
|
|
38721
|
+
notesField: exports_external.nullable(exports_external.string()),
|
|
38722
|
+
className: classNameProp
|
|
38598
38723
|
}),
|
|
38599
38724
|
description: 'Turn order tracker for encounters/combat. Displays a sorted list of combatants with configurable stats. Each combatant has a "type" field: "character" (stats pulled live from a character page via "page" VFS path and pageFieldMapping) or "monster" (all stats inline — hp, maxHp, ac, etc. — with optional "statBlockPage" for reference only). pageFieldMapping maps combatant field names to character page content fields (e.g. {"hp": "hitPoints"}). Special values: "$title" for page title, "$coverImage" for page image. stats defines which columns to show.',
|
|
38600
38725
|
example: {
|
|
@@ -38643,12 +38768,12 @@ var craftComponents = {
|
|
|
38643
38768
|
};
|
|
38644
38769
|
var craftCatalog = defineCatalog(schema, {
|
|
38645
38770
|
components: {
|
|
38646
|
-
Separator,
|
|
38647
|
-
Accordion,
|
|
38648
|
-
Collapsible,
|
|
38649
|
-
Avatar,
|
|
38650
|
-
Alert,
|
|
38651
|
-
Table,
|
|
38771
|
+
Separator: withClassNameProp(Separator),
|
|
38772
|
+
Accordion: withClassNameProp(Accordion),
|
|
38773
|
+
Collapsible: withClassNameProp(Collapsible),
|
|
38774
|
+
Avatar: withClassNameProp(Avatar),
|
|
38775
|
+
Alert: withClassNameProp(Alert),
|
|
38776
|
+
Table: withClassNameProp(Table),
|
|
38652
38777
|
...extendedShadcnComponents,
|
|
38653
38778
|
...craftComponents
|
|
38654
38779
|
},
|
|
@@ -40424,7 +40549,7 @@ function printLines(lines) {
|
|
|
40424
40549
|
}
|
|
40425
40550
|
|
|
40426
40551
|
// src/commands/check.ts
|
|
40427
|
-
var
|
|
40552
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
40428
40553
|
async function runCheck(argv) {
|
|
40429
40554
|
const args = parseCommandArgs({
|
|
40430
40555
|
argv,
|
|
@@ -40671,7 +40796,7 @@ function checkReferenceIds({
|
|
|
40671
40796
|
const malformed = [];
|
|
40672
40797
|
for (const file2 of scan.files) {
|
|
40673
40798
|
const blockId = file2.craftBlock?.referenceId;
|
|
40674
|
-
if (blockId !== undefined && !
|
|
40799
|
+
if (blockId !== undefined && !UUID_RE.test(blockId)) {
|
|
40675
40800
|
malformed.push(`${file2.path} ($craft.referenceId is not a UUID)`);
|
|
40676
40801
|
continue;
|
|
40677
40802
|
}
|
|
@@ -40907,7 +41032,7 @@ function isReferenceValue(record2) {
|
|
|
40907
41032
|
return false;
|
|
40908
41033
|
}
|
|
40909
41034
|
if ("referenceId" in record2) {
|
|
40910
|
-
return typeof record2.referenceId === "string" &&
|
|
41035
|
+
return typeof record2.referenceId === "string" && UUID_RE.test(record2.referenceId);
|
|
40911
41036
|
}
|
|
40912
41037
|
return nonBlankString(record2.slug);
|
|
40913
41038
|
}
|
|
@@ -41900,7 +42025,7 @@ function describeRemoteSource(resolved) {
|
|
|
41900
42025
|
// package.json
|
|
41901
42026
|
var package_default = {
|
|
41902
42027
|
name: "@craftrpgs/cli",
|
|
41903
|
-
version: "0.1.
|
|
42028
|
+
version: "0.1.7",
|
|
41904
42029
|
description: "Sync Craft projects with a local folder — clone, edit with any coding agent, push back.",
|
|
41905
42030
|
license: "UNLICENSED",
|
|
41906
42031
|
homepage: "https://craftrpgs.com",
|
|
@@ -41927,7 +42052,7 @@ var package_default = {
|
|
|
41927
42052
|
"@craft/flow": "workspace:*",
|
|
41928
42053
|
"@craft/shared": "workspace:*",
|
|
41929
42054
|
fflate: "^0.8.3",
|
|
41930
|
-
typescript: "
|
|
42055
|
+
typescript: "7.0.2",
|
|
41931
42056
|
uuid: "11.1.0",
|
|
41932
42057
|
zod: "4.3.6"
|
|
41933
42058
|
}
|
|
@@ -42039,6 +42164,16 @@ function createCliClient({
|
|
|
42039
42164
|
if (response.status === 401) {
|
|
42040
42165
|
throw new CliError(UNAUTHORIZED_HELP, 2);
|
|
42041
42166
|
}
|
|
42167
|
+
if (response.status === 426) {
|
|
42168
|
+
const { code, message, details } = await readErrorBody(response);
|
|
42169
|
+
throw new CliApiError({
|
|
42170
|
+
message,
|
|
42171
|
+
code: code ?? "cli_outdated",
|
|
42172
|
+
status: response.status,
|
|
42173
|
+
exitCode: 2,
|
|
42174
|
+
details
|
|
42175
|
+
});
|
|
42176
|
+
}
|
|
42042
42177
|
return response;
|
|
42043
42178
|
}
|
|
42044
42179
|
async function parseJson(response, schema2, what) {
|
|
@@ -43835,7 +43970,7 @@ var SYSTEM_ACCOUNT_IDS = new Set(Object.values(SYSTEM_ACCOUNTS));
|
|
|
43835
43970
|
import { randomUUID } from "node:crypto";
|
|
43836
43971
|
var LEADING_SLASH_RE = /^\//;
|
|
43837
43972
|
var CONTENT_EXTENSION_RE = /\.(json|md)$/i;
|
|
43838
|
-
var
|
|
43973
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
43839
43974
|
function entryName(entry) {
|
|
43840
43975
|
const livePath = entry.movedTo ?? entry.path;
|
|
43841
43976
|
const base = (livePath.split("/").at(-1) ?? livePath).replace(CONTENT_EXTENSION_RE, "");
|
|
@@ -43871,8 +44006,12 @@ function resolveLink({
|
|
|
43871
44006
|
if (!trimmed) {
|
|
43872
44007
|
return { status: "unknown" };
|
|
43873
44008
|
}
|
|
43874
|
-
const fromEntry = (entry) => entry.fileId ? {
|
|
43875
|
-
|
|
44009
|
+
const fromEntry = (entry) => entry.fileId ? {
|
|
44010
|
+
status: "resolved",
|
|
44011
|
+
referenceId: entry.referenceId,
|
|
44012
|
+
name: entryName(entry)
|
|
44013
|
+
} : { status: "unpushed" };
|
|
44014
|
+
if (UUID_RE2.test(trimmed)) {
|
|
43876
44015
|
const lowered = trimmed.toLowerCase();
|
|
43877
44016
|
const byReference = ledger.files.find((entry) => entry.referenceId.toLowerCase() === lowered);
|
|
43878
44017
|
if (byReference) {
|
|
@@ -44230,7 +44369,7 @@ async function runImageGenerate(argv) {
|
|
|
44230
44369
|
styleLine = "Style: none stored — set settings.imageStyleInstructions in .craft/project.json for consistent art.";
|
|
44231
44370
|
}
|
|
44232
44371
|
printLines([
|
|
44233
|
-
`Generated image (${result.model}, ${result.size ?? "default size"}, ${result.unitsSpent} ${result.currency}):`,
|
|
44372
|
+
`Generated image (${result.model}, ${result.size ?? "default size"}, ${toDisplay(result.unitsSpent)} ${result.currency}):`,
|
|
44234
44373
|
` ${result.image.url ?? "<no url returned>"}`,
|
|
44235
44374
|
styleLine,
|
|
44236
44375
|
"",
|
|
@@ -44271,7 +44410,7 @@ function toActionableError(error48, operation = "generation") {
|
|
|
44271
44410
|
if (currency === "credits") {
|
|
44272
44411
|
return actionable("Not enough credits to generate this image. Buy credits in Craft, then retry.", 1);
|
|
44273
44412
|
}
|
|
44274
|
-
return actionable("Not enough energy to generate this image.
|
|
44413
|
+
return actionable("Not enough energy to generate this image. Retry with --credits to spend " + "purchased credits, or subscribe in Craft for a daily energy allowance.", 2);
|
|
44275
44414
|
}
|
|
44276
44415
|
if (error48.code === "validation_error" && error48.status === 422) {
|
|
44277
44416
|
return actionable(`The provider refused this generation: ${error48.message}. ` + "Adjust the prompt (or reference images) and retry.", 1);
|
|
@@ -45668,6 +45807,123 @@ ${remedies.join(`
|
|
|
45668
45807
|
|
|
45669
45808
|
// src/commands/meta.ts
|
|
45670
45809
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
45810
|
+
|
|
45811
|
+
// ../shared/src/game-starts/authoring.ts
|
|
45812
|
+
function speakerNameForLink(link) {
|
|
45813
|
+
const base = link.split("/").filter(Boolean).at(-1);
|
|
45814
|
+
const name = base?.split(".")[0]?.trim();
|
|
45815
|
+
return name || undefined;
|
|
45816
|
+
}
|
|
45817
|
+
function isRecord14(value) {
|
|
45818
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45819
|
+
}
|
|
45820
|
+
function translateOpening(opening, where, resolveLink2) {
|
|
45821
|
+
if (!isRecord14(opening)) {
|
|
45822
|
+
return opening;
|
|
45823
|
+
}
|
|
45824
|
+
const openingInput = { ...opening };
|
|
45825
|
+
if (!Array.isArray(openingInput.beats)) {
|
|
45826
|
+
return openingInput;
|
|
45827
|
+
}
|
|
45828
|
+
const beats = openingInput.beats.map((beat, index) => {
|
|
45829
|
+
if (!isRecord14(beat)) {
|
|
45830
|
+
return beat;
|
|
45831
|
+
}
|
|
45832
|
+
const beatInput = { ...beat };
|
|
45833
|
+
if (typeof beatInput.id !== "string") {
|
|
45834
|
+
beatInput.id = crypto.randomUUID();
|
|
45835
|
+
}
|
|
45836
|
+
const speaker = beatInput.speaker;
|
|
45837
|
+
const context = {
|
|
45838
|
+
where: `${where}.beats[${index}].speaker`,
|
|
45839
|
+
expects: "character"
|
|
45840
|
+
};
|
|
45841
|
+
if (speaker === "gm") {
|
|
45842
|
+
beatInput.speaker = { kind: "gm" };
|
|
45843
|
+
} else if (typeof speaker === "string") {
|
|
45844
|
+
const resolved = resolveLink2(speaker, context);
|
|
45845
|
+
beatInput.speaker = {
|
|
45846
|
+
kind: "character",
|
|
45847
|
+
fileReferenceId: resolved?.referenceId ?? null,
|
|
45848
|
+
name: resolved?.name ?? speakerNameForLink(speaker)
|
|
45849
|
+
};
|
|
45850
|
+
} else if (isRecord14(speaker) && "character" in speaker) {
|
|
45851
|
+
const { character, ...speakerRest } = speaker;
|
|
45852
|
+
const resolved = resolveLink2(character, {
|
|
45853
|
+
...context,
|
|
45854
|
+
where: `${context.where}.character`
|
|
45855
|
+
});
|
|
45856
|
+
beatInput.speaker = {
|
|
45857
|
+
kind: "character",
|
|
45858
|
+
name: resolved?.name ?? (typeof character === "string" ? speakerNameForLink(character) : undefined),
|
|
45859
|
+
...speakerRest,
|
|
45860
|
+
fileReferenceId: resolved?.referenceId ?? null
|
|
45861
|
+
};
|
|
45862
|
+
}
|
|
45863
|
+
return beatInput;
|
|
45864
|
+
});
|
|
45865
|
+
openingInput.beats = beats;
|
|
45866
|
+
if (typeof openingInput.message !== "string" && openingInput.kind === "static") {
|
|
45867
|
+
const projectable = beats.filter((beat) => isRecord14(beat) && typeof beat.text === "string");
|
|
45868
|
+
openingInput.message = projectable.map((beat) => {
|
|
45869
|
+
const speaker = isRecord14(beat.speaker) ? beat.speaker : undefined;
|
|
45870
|
+
const name = speaker && speaker.kind === "character" && typeof speaker.name === "string" ? speaker.name : null;
|
|
45871
|
+
return name ? `${name}: ${beat.text}` : beat.text;
|
|
45872
|
+
}).join(`
|
|
45873
|
+
|
|
45874
|
+
`).slice(0, GAME_START_OPENING_MAX_LENGTH);
|
|
45875
|
+
}
|
|
45876
|
+
return openingInput;
|
|
45877
|
+
}
|
|
45878
|
+
function translateGameStartAuthoringInput({
|
|
45879
|
+
raw,
|
|
45880
|
+
resolveLink: resolveLink2
|
|
45881
|
+
}) {
|
|
45882
|
+
const input = { ...raw };
|
|
45883
|
+
if ("startingLocation" in input) {
|
|
45884
|
+
input.startingLocationFileReferenceId = resolveLink2(input.startingLocation, {
|
|
45885
|
+
where: "startingLocation",
|
|
45886
|
+
expects: "location"
|
|
45887
|
+
})?.referenceId ?? null;
|
|
45888
|
+
input.startingLocation = undefined;
|
|
45889
|
+
}
|
|
45890
|
+
if (Array.isArray(input.startingCharacters)) {
|
|
45891
|
+
input.startingCharacters = input.startingCharacters.map((character, index) => {
|
|
45892
|
+
if (typeof character === "string") {
|
|
45893
|
+
return {
|
|
45894
|
+
fileReferenceId: resolveLink2(character, {
|
|
45895
|
+
where: `startingCharacters[${index}]`,
|
|
45896
|
+
expects: "character"
|
|
45897
|
+
})?.referenceId ?? null
|
|
45898
|
+
};
|
|
45899
|
+
}
|
|
45900
|
+
return character;
|
|
45901
|
+
});
|
|
45902
|
+
}
|
|
45903
|
+
if ("opening" in input) {
|
|
45904
|
+
input.opening = translateOpening(input.opening, "opening", resolveLink2);
|
|
45905
|
+
}
|
|
45906
|
+
if (Array.isArray(input.characterOpenings)) {
|
|
45907
|
+
input.characterOpenings = input.characterOpenings.map((characterOpening, index) => {
|
|
45908
|
+
if (!isRecord14(characterOpening)) {
|
|
45909
|
+
return characterOpening;
|
|
45910
|
+
}
|
|
45911
|
+
const entry = { ...characterOpening };
|
|
45912
|
+
if ("character" in entry) {
|
|
45913
|
+
entry.characterFileReferenceId = resolveLink2(entry.character, {
|
|
45914
|
+
where: `characterOpenings[${index}].character`,
|
|
45915
|
+
expects: "character"
|
|
45916
|
+
})?.referenceId ?? null;
|
|
45917
|
+
entry.character = undefined;
|
|
45918
|
+
}
|
|
45919
|
+
entry.opening = translateOpening(entry.opening, `characterOpenings[${index}].opening`, resolveLink2);
|
|
45920
|
+
return entry;
|
|
45921
|
+
});
|
|
45922
|
+
}
|
|
45923
|
+
return input;
|
|
45924
|
+
}
|
|
45925
|
+
|
|
45926
|
+
// src/commands/meta.ts
|
|
45671
45927
|
var META_USAGE = `Usage: craft meta get <path> [--json]
|
|
45672
45928
|
` + ` craft meta set-game-start <game-start-path> --file <json>
|
|
45673
45929
|
` + ` craft meta set-gm-trigger <gm-instruction-path> (--file <json> | --clear)
|
|
@@ -45772,112 +46028,29 @@ function projectOpeningForOutput(workspace, opening) {
|
|
|
45772
46028
|
}))
|
|
45773
46029
|
};
|
|
45774
46030
|
}
|
|
45775
|
-
function speakerNameForLink(link) {
|
|
45776
|
-
const base = link.split("/").filter(Boolean).at(-1);
|
|
45777
|
-
const name = base?.split(".")[0]?.trim();
|
|
45778
|
-
return name || undefined;
|
|
45779
|
-
}
|
|
45780
46031
|
function translateGameStartInput(workspace, raw) {
|
|
45781
46032
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
45782
46033
|
throw new CliError("The game start JSON must be a single object.", 2);
|
|
45783
46034
|
}
|
|
45784
|
-
const input = { ...raw };
|
|
45785
46035
|
const failures = [];
|
|
45786
|
-
const
|
|
45787
|
-
|
|
45788
|
-
|
|
45789
|
-
|
|
45790
|
-
|
|
45791
|
-
failures.push(`${where}: expected a path/slug string`);
|
|
45792
|
-
return null;
|
|
45793
|
-
}
|
|
45794
|
-
const resolution = resolveLink({ ledger: workspace.ledger, link });
|
|
45795
|
-
if (resolution.status === "resolved") {
|
|
45796
|
-
return resolution.referenceId;
|
|
45797
|
-
}
|
|
45798
|
-
failures.push(resolution.status === "unpushed" ? `${where}: "${link}" has not been pushed yet — push it first` : `${where}: "${link}" does not resolve to a tracked file`);
|
|
45799
|
-
return null;
|
|
45800
|
-
};
|
|
45801
|
-
const translateOpening = (opening, where) => {
|
|
45802
|
-
if (typeof opening !== "object" || opening === null) {
|
|
45803
|
-
return opening;
|
|
45804
|
-
}
|
|
45805
|
-
const openingInput = { ...opening };
|
|
45806
|
-
if (!Array.isArray(openingInput.beats)) {
|
|
45807
|
-
return openingInput;
|
|
45808
|
-
}
|
|
45809
|
-
const beats = openingInput.beats.map((beat, index) => {
|
|
45810
|
-
if (typeof beat !== "object" || beat === null) {
|
|
45811
|
-
return beat;
|
|
46036
|
+
const input = translateGameStartAuthoringInput({
|
|
46037
|
+
raw: { ...raw },
|
|
46038
|
+
resolveLink: (link, { where }) => {
|
|
46039
|
+
if (link === null || link === undefined) {
|
|
46040
|
+
return null;
|
|
45812
46041
|
}
|
|
45813
|
-
|
|
45814
|
-
|
|
45815
|
-
|
|
46042
|
+
if (typeof link !== "string") {
|
|
46043
|
+
failures.push(`${where}: expected a path/slug string`);
|
|
46044
|
+
return null;
|
|
45816
46045
|
}
|
|
45817
|
-
const
|
|
45818
|
-
if (
|
|
45819
|
-
|
|
45820
|
-
kind: "character",
|
|
45821
|
-
fileReferenceId: resolve6(speaker, `${where}.beats[${index}].speaker`),
|
|
45822
|
-
name: speakerNameForLink(speaker)
|
|
45823
|
-
};
|
|
45824
|
-
} else if (speaker === "gm") {
|
|
45825
|
-
beatInput.speaker = { kind: "gm" };
|
|
45826
|
-
} else if (typeof speaker === "object" && speaker !== null && "character" in speaker) {
|
|
45827
|
-
const { character, ...speakerRest } = speaker;
|
|
45828
|
-
beatInput.speaker = {
|
|
45829
|
-
kind: "character",
|
|
45830
|
-
name: typeof character === "string" ? speakerNameForLink(character) : undefined,
|
|
45831
|
-
...speakerRest,
|
|
45832
|
-
fileReferenceId: resolve6(character, `${where}.beats[${index}].speaker.character`)
|
|
45833
|
-
};
|
|
46046
|
+
const resolution = resolveLink({ ledger: workspace.ledger, link });
|
|
46047
|
+
if (resolution.status === "resolved") {
|
|
46048
|
+
return { referenceId: resolution.referenceId, name: resolution.name };
|
|
45834
46049
|
}
|
|
45835
|
-
|
|
45836
|
-
|
|
45837
|
-
openingInput.beats = beats;
|
|
45838
|
-
if (typeof openingInput.message !== "string" && openingInput.kind === "static") {
|
|
45839
|
-
const projectable = beats.filter((beat) => typeof beat === "object" && beat !== null && typeof beat.text === "string");
|
|
45840
|
-
openingInput.message = projectable.map((beat) => {
|
|
45841
|
-
const speaker = beat.speaker;
|
|
45842
|
-
const name = speaker && speaker.kind === "character" && typeof speaker.name === "string" ? speaker.name : null;
|
|
45843
|
-
return name ? `${name}: ${beat.text}` : beat.text;
|
|
45844
|
-
}).join(`
|
|
45845
|
-
|
|
45846
|
-
`).slice(0, GAME_START_OPENING_MAX_LENGTH);
|
|
46050
|
+
failures.push(resolution.status === "unpushed" ? `${where}: "${link}" has not been pushed yet — push it first` : `${where}: "${link}" does not resolve to a tracked file`);
|
|
46051
|
+
return null;
|
|
45847
46052
|
}
|
|
45848
|
-
|
|
45849
|
-
};
|
|
45850
|
-
if ("startingLocation" in input) {
|
|
45851
|
-
input.startingLocationFileReferenceId = resolve6(input.startingLocation, "startingLocation");
|
|
45852
|
-
input.startingLocation = undefined;
|
|
45853
|
-
}
|
|
45854
|
-
if (Array.isArray(input.startingCharacters)) {
|
|
45855
|
-
input.startingCharacters = input.startingCharacters.map((character, index) => {
|
|
45856
|
-
if (typeof character === "string") {
|
|
45857
|
-
return {
|
|
45858
|
-
fileReferenceId: resolve6(character, `startingCharacters[${index}]`)
|
|
45859
|
-
};
|
|
45860
|
-
}
|
|
45861
|
-
return character;
|
|
45862
|
-
});
|
|
45863
|
-
}
|
|
45864
|
-
if ("opening" in input) {
|
|
45865
|
-
input.opening = translateOpening(input.opening, "opening");
|
|
45866
|
-
}
|
|
45867
|
-
if (Array.isArray(input.characterOpenings)) {
|
|
45868
|
-
input.characterOpenings = input.characterOpenings.map((characterOpening, index) => {
|
|
45869
|
-
if (typeof characterOpening !== "object" || characterOpening === null) {
|
|
45870
|
-
return characterOpening;
|
|
45871
|
-
}
|
|
45872
|
-
const entry = { ...characterOpening };
|
|
45873
|
-
if ("character" in entry) {
|
|
45874
|
-
entry.characterFileReferenceId = resolve6(entry.character, `characterOpenings[${index}].character`);
|
|
45875
|
-
entry.character = undefined;
|
|
45876
|
-
}
|
|
45877
|
-
entry.opening = translateOpening(entry.opening, `characterOpenings[${index}].opening`);
|
|
45878
|
-
return entry;
|
|
45879
|
-
});
|
|
45880
|
-
}
|
|
46053
|
+
});
|
|
45881
46054
|
if (failures.length > 0) {
|
|
45882
46055
|
throw new CliError(`Nothing was saved — some references do not resolve to pushed files:
|
|
45883
46056
|
` + `${failures.map((f) => ` ${f}`).join(`
|
|
@@ -46209,7 +46382,7 @@ function escapeRegExp(value) {
|
|
|
46209
46382
|
// src/commands/project-completeness.ts
|
|
46210
46383
|
var TRIVIAL_DESCRIPTION_LENGTH = 40;
|
|
46211
46384
|
var CROSS_LINK_FILE_THRESHOLD = 5;
|
|
46212
|
-
var
|
|
46385
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
46213
46386
|
var SCRATCH_NAME_RE = /\b(?:test|asdf|scratch|repro|tmp|todo|example)\b/i;
|
|
46214
46387
|
async function runProjectCompleteness(argv) {
|
|
46215
46388
|
const args = parseCommandArgs({
|
|
@@ -46575,7 +46748,7 @@ function isReferenceValue2(record2) {
|
|
|
46575
46748
|
return false;
|
|
46576
46749
|
}
|
|
46577
46750
|
if ("referenceId" in record2) {
|
|
46578
|
-
return typeof record2.referenceId === "string" &&
|
|
46751
|
+
return typeof record2.referenceId === "string" && UUID_RE3.test(record2.referenceId);
|
|
46579
46752
|
}
|
|
46580
46753
|
return nonBlankString(record2.slug);
|
|
46581
46754
|
}
|
|
@@ -46981,7 +47154,7 @@ async function removeStaleManagedSkills({
|
|
|
46981
47154
|
// src/engine/pull.ts
|
|
46982
47155
|
import { mkdir as mkdir6, rename as rename4, rm as rm7, rmdir } from "node:fs/promises";
|
|
46983
47156
|
import { dirname as dirname7 } from "node:path";
|
|
46984
|
-
function
|
|
47157
|
+
function isRecord15(value) {
|
|
46985
47158
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46986
47159
|
}
|
|
46987
47160
|
function serializeContentForDisk({
|
|
@@ -46994,9 +47167,9 @@ function serializeContentForDisk({
|
|
|
46994
47167
|
const craftBlock = referenceId ? craftBlockForEmbedding({
|
|
46995
47168
|
referenceId,
|
|
46996
47169
|
...settings ? { settings } : {},
|
|
46997
|
-
...
|
|
47170
|
+
...isRecord15(metadata) ? { metadata } : {}
|
|
46998
47171
|
}) : null;
|
|
46999
|
-
if (contentType === "markdown" &&
|
|
47172
|
+
if (contentType === "markdown" && isRecord15(content)) {
|
|
47000
47173
|
return serializeMarkdown({
|
|
47001
47174
|
name: typeof content.name === "string" ? content.name : undefined,
|
|
47002
47175
|
description: typeof content.description === "string" ? content.description : undefined,
|
|
@@ -47004,7 +47177,7 @@ function serializeContentForDisk({
|
|
|
47004
47177
|
content: typeof content.content === "string" ? content.content : ""
|
|
47005
47178
|
}, { craftBlock });
|
|
47006
47179
|
}
|
|
47007
|
-
if (craftBlock &&
|
|
47180
|
+
if (craftBlock && isRecord15(content)) {
|
|
47008
47181
|
return `${JSON.stringify({
|
|
47009
47182
|
[CRAFT_BLOCK_KEY]: craftBlock,
|
|
47010
47183
|
...stripCraftBlock(content)
|
|
@@ -47019,7 +47192,7 @@ function contentTypeForPath2(path) {
|
|
|
47019
47192
|
}
|
|
47020
47193
|
function applyMetaBase(entry, body) {
|
|
47021
47194
|
entry.settings = craftFileSettingsFromWire(body.settings);
|
|
47022
|
-
entry.metadataHash =
|
|
47195
|
+
entry.metadataHash = isRecord15(body.metadata) ? hashCanonicalJson(body.metadata) : undefined;
|
|
47023
47196
|
}
|
|
47024
47197
|
function emptyResult() {
|
|
47025
47198
|
return {
|
|
@@ -47908,7 +48081,7 @@ import { join as join7 } from "node:path";
|
|
|
47908
48081
|
|
|
47909
48082
|
// src/engine/plan.ts
|
|
47910
48083
|
var MAX_CLI_PUSH_OPS = 500;
|
|
47911
|
-
function
|
|
48084
|
+
function isRecord16(value) {
|
|
47912
48085
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47913
48086
|
}
|
|
47914
48087
|
var PATHSPEC_LEADING_DOT_SLASH = /^\.\//;
|
|
@@ -48029,7 +48202,6 @@ function buildPushPlan(input) {
|
|
|
48029
48202
|
contentType: local.contentType,
|
|
48030
48203
|
schema: local.schema,
|
|
48031
48204
|
...local.layout != null ? { layout: local.layout } : {},
|
|
48032
|
-
...local.category !== undefined ? { category: local.category } : {},
|
|
48033
48205
|
designation: local.designation,
|
|
48034
48206
|
...local.imageStyleInstructions !== undefined ? { imageStyleInstructions: local.imageStyleInstructions } : {},
|
|
48035
48207
|
...local.showCoverImage !== undefined ? { showCoverImage: local.showCoverImage } : {},
|
|
@@ -48093,7 +48265,7 @@ function buildPushPlan(input) {
|
|
|
48093
48265
|
continue;
|
|
48094
48266
|
}
|
|
48095
48267
|
let content = scanned.content;
|
|
48096
|
-
if (
|
|
48268
|
+
if (isRecord16(content) && content.name !== newBaseName.value.baseName) {
|
|
48097
48269
|
content = { ...content, name: newBaseName.value.baseName };
|
|
48098
48270
|
nameRewrites.push({
|
|
48099
48271
|
diskPath: toPath,
|
|
@@ -50233,7 +50405,7 @@ async function workspaceRemote2() {
|
|
|
50233
50405
|
|
|
50234
50406
|
// src/commands/type.ts
|
|
50235
50407
|
import { existsSync as existsSync9 } from "node:fs";
|
|
50236
|
-
var TYPE_USAGE = "Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50408
|
+
var TYPE_USAGE = "Usage: craft type new <Name> [--markdown] [--designation <token>]";
|
|
50237
50409
|
var STARTER_JSON_SCHEMA = {
|
|
50238
50410
|
type: "object",
|
|
50239
50411
|
properties: {},
|
|
@@ -50252,7 +50424,6 @@ async function runTypeNew(argv) {
|
|
|
50252
50424
|
flags: {
|
|
50253
50425
|
markdown: { type: "boolean" },
|
|
50254
50426
|
designation: { type: "string" },
|
|
50255
|
-
category: { type: "string" },
|
|
50256
50427
|
json: { type: "boolean" }
|
|
50257
50428
|
},
|
|
50258
50429
|
maxPositionals: 1
|
|
@@ -50284,7 +50455,6 @@ async function runTypeNew(argv) {
|
|
|
50284
50455
|
name,
|
|
50285
50456
|
contentType,
|
|
50286
50457
|
designation,
|
|
50287
|
-
category: stringFlag(args, "category") ?? null,
|
|
50288
50458
|
schema: contentType === "json" ? STARTER_JSON_SCHEMA : null,
|
|
50289
50459
|
layout: null,
|
|
50290
50460
|
imageStyleInstructions: null,
|
|
@@ -50298,7 +50468,7 @@ async function runTypeNew(argv) {
|
|
|
50298
50468
|
`Create files of the type as <Anything>.${typeSlugExtension} anywhere in the workspace.`,
|
|
50299
50469
|
"Push the new type and its files together with `craft push --include-types`."
|
|
50300
50470
|
] : [
|
|
50301
|
-
`Markdown types need no schema — edit ${typeFilePath} only if you want a designation
|
|
50471
|
+
`Markdown types need no schema — edit ${typeFilePath} only if you want a designation.`,
|
|
50302
50472
|
`Create files of the type as <Anything>.${typeSlugExtension} anywhere in the workspace.`,
|
|
50303
50473
|
"Push the new type and its files together with `craft push --include-types`."
|
|
50304
50474
|
];
|
|
@@ -50440,7 +50610,7 @@ var HELP_COMMAND_LINES = ` clone <projectIdOrUrl> [dir] Download a project as
|
|
|
50440
50610
|
resolve <path> Mark a conflict resolved \u2014 your version wins
|
|
50441
50611
|
checkout <path> Take the remote version of a conflicted file
|
|
50442
50612
|
mv <from> <to> Rename/move a file, keeping its identity
|
|
50443
|
-
type new <Name> [--markdown] [--designation <t>]
|
|
50613
|
+
type new <Name> [--markdown] [--designation <t>]
|
|
50444
50614
|
Author a new file type locally (push with --include-types)
|
|
50445
50615
|
voices [--language <code>] [--gender <t>] [--age <t>]
|
|
50446
50616
|
List voice ids and traits for characters and the GM
|
|
@@ -50701,7 +50871,7 @@ Rename/move a file while keeping its identity (history, references). The
|
|
|
50701
50871
|
move is recorded in the ledger and pushed as a move op on the next
|
|
50702
50872
|
\`craft push\`; editing the file's content before pushing is fine.
|
|
50703
50873
|
`,
|
|
50704
|
-
type: `Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50874
|
+
type: `Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50705
50875
|
|
|
50706
50876
|
Scaffold a new file type at .craft/file-types/<slug>.json. Edit its schema,
|
|
50707
50877
|
create files as <Anything>.<slug>.json, then push everything together with
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craftrpgs/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Sync Craft projects with a local folder — clone, edit with any coding agent, push back.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://craftrpgs.com",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"typecheck": "tsc --noEmit"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@craft/flow": "
|
|
28
|
-
"@craft/shared": "
|
|
27
|
+
"@craft/flow": "0.0.1",
|
|
28
|
+
"@craft/shared": "0.0.1",
|
|
29
29
|
"fflate": "^0.8.3",
|
|
30
|
-
"typescript": "
|
|
30
|
+
"typescript": "7.0.2",
|
|
31
31
|
"uuid": "11.1.0",
|
|
32
32
|
"zod": "4.3.6"
|
|
33
33
|
}
|