@craftrpgs/cli 0.1.5 → 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 +437 -114
- 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,9 +43970,10 @@ 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
|
-
const
|
|
43975
|
+
const livePath = entry.movedTo ?? entry.path;
|
|
43976
|
+
const base = (livePath.split("/").at(-1) ?? livePath).replace(CONTENT_EXTENSION_RE, "");
|
|
43841
43977
|
const suffix = `.${entry.fileType}`;
|
|
43842
43978
|
return base.endsWith(suffix) ? base.slice(0, -suffix.length) : base;
|
|
43843
43979
|
}
|
|
@@ -43870,8 +44006,12 @@ function resolveLink({
|
|
|
43870
44006
|
if (!trimmed) {
|
|
43871
44007
|
return { status: "unknown" };
|
|
43872
44008
|
}
|
|
43873
|
-
const fromEntry = (entry) => entry.fileId ? {
|
|
43874
|
-
|
|
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)) {
|
|
43875
44015
|
const lowered = trimmed.toLowerCase();
|
|
43876
44016
|
const byReference = ledger.files.find((entry) => entry.referenceId.toLowerCase() === lowered);
|
|
43877
44017
|
if (byReference) {
|
|
@@ -43889,6 +44029,13 @@ function resolveLink({
|
|
|
43889
44029
|
if (bySlug) {
|
|
43890
44030
|
return fromEntry(bySlug);
|
|
43891
44031
|
}
|
|
44032
|
+
const nameKey = generateSlug(trimmed.replace(/^<@|>$/g, ""));
|
|
44033
|
+
if (nameKey) {
|
|
44034
|
+
const byName = ledger.files.find((entry) => generateSlug(entryName(entry)) === nameKey);
|
|
44035
|
+
if (byName) {
|
|
44036
|
+
return fromEntry(byName);
|
|
44037
|
+
}
|
|
44038
|
+
}
|
|
43892
44039
|
return { status: "unknown" };
|
|
43893
44040
|
}
|
|
43894
44041
|
function referenceIdToPath({
|
|
@@ -44222,7 +44369,7 @@ async function runImageGenerate(argv) {
|
|
|
44222
44369
|
styleLine = "Style: none stored — set settings.imageStyleInstructions in .craft/project.json for consistent art.";
|
|
44223
44370
|
}
|
|
44224
44371
|
printLines([
|
|
44225
|
-
`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}):`,
|
|
44226
44373
|
` ${result.image.url ?? "<no url returned>"}`,
|
|
44227
44374
|
styleLine,
|
|
44228
44375
|
"",
|
|
@@ -44263,7 +44410,7 @@ function toActionableError(error48, operation = "generation") {
|
|
|
44263
44410
|
if (currency === "credits") {
|
|
44264
44411
|
return actionable("Not enough credits to generate this image. Buy credits in Craft, then retry.", 1);
|
|
44265
44412
|
}
|
|
44266
|
-
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);
|
|
44267
44414
|
}
|
|
44268
44415
|
if (error48.code === "validation_error" && error48.status === 422) {
|
|
44269
44416
|
return actionable(`The provider refused this generation: ${error48.message}. ` + "Adjust the prompt (or reference images) and retry.", 1);
|
|
@@ -44935,6 +45082,8 @@ var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V6 = "file-designation-metadata:v6"
|
|
|
44935
45082
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V7 = "file-designation-metadata:v7";
|
|
44936
45083
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V8 = "file-designation-metadata:v8";
|
|
44937
45084
|
var GAME_START_OPENING_MAX_LENGTH = 1e4;
|
|
45085
|
+
var GAME_START_MAX_OPENING_BEATS = 50;
|
|
45086
|
+
var GAME_START_MAX_CHARACTER_OPENINGS = 100;
|
|
44938
45087
|
var GM_INSTRUCTION_TRIGGER_PHASES = [
|
|
44939
45088
|
"post_player_message",
|
|
44940
45089
|
"post_gm_message"
|
|
@@ -45137,10 +45286,25 @@ var GmInstructionMetadataSchema = exports_external.union([
|
|
|
45137
45286
|
GmInstructionToolMetadataSchema,
|
|
45138
45287
|
GmInstructionNarrativeMetadataSchema
|
|
45139
45288
|
]);
|
|
45289
|
+
var GameStartOpeningBeatSpeakerSchema = exports_external.discriminatedUnion("kind", [
|
|
45290
|
+
exports_external.object({ kind: exports_external.literal("gm") }),
|
|
45291
|
+
exports_external.object({
|
|
45292
|
+
kind: exports_external.literal("character"),
|
|
45293
|
+
fileReferenceId: exports_external.string().uuid(),
|
|
45294
|
+
name: exports_external.string().trim().max(200).optional()
|
|
45295
|
+
})
|
|
45296
|
+
]);
|
|
45297
|
+
var GameStartOpeningBeatSchema = exports_external.object({
|
|
45298
|
+
id: exports_external.string().uuid(),
|
|
45299
|
+
speaker: GameStartOpeningBeatSpeakerSchema,
|
|
45300
|
+
text: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45301
|
+
expression: exports_external.string().trim().max(80).nullish()
|
|
45302
|
+
});
|
|
45140
45303
|
var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
45141
45304
|
exports_external.object({
|
|
45142
45305
|
kind: exports_external.literal("static"),
|
|
45143
|
-
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH)
|
|
45306
|
+
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45307
|
+
beats: exports_external.array(GameStartOpeningBeatSchema).max(GAME_START_MAX_OPENING_BEATS).optional()
|
|
45144
45308
|
}),
|
|
45145
45309
|
exports_external.object({
|
|
45146
45310
|
kind: exports_external.literal("dynamic"),
|
|
@@ -45150,16 +45314,55 @@ var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
|
45150
45314
|
var GameStartCharacterSchema = exports_external.object({
|
|
45151
45315
|
fileReferenceId: exports_external.string().uuid()
|
|
45152
45316
|
});
|
|
45153
|
-
var
|
|
45317
|
+
var GameStartCharacterOpeningSchema = exports_external.object({
|
|
45318
|
+
characterFileReferenceId: exports_external.string().uuid(),
|
|
45319
|
+
opening: GameStartOpeningSchema
|
|
45320
|
+
});
|
|
45321
|
+
function combinedOpeningLength(opening) {
|
|
45322
|
+
if (opening.kind !== "static" || !opening.beats) {
|
|
45323
|
+
return 0;
|
|
45324
|
+
}
|
|
45325
|
+
return opening.beats.reduce((total, beat) => total + beat.text.length, 0);
|
|
45326
|
+
}
|
|
45327
|
+
var GameStartMetadataObjectSchema = exports_external.object({
|
|
45154
45328
|
startingLocationFileReferenceId: exports_external.string().uuid().nullable().optional(),
|
|
45155
45329
|
startingCharacters: exports_external.array(GameStartCharacterSchema).default([]),
|
|
45156
45330
|
opening: GameStartOpeningSchema.default({
|
|
45157
45331
|
kind: "static",
|
|
45158
45332
|
message: "Welcome to the game. What would you like to do first?"
|
|
45159
45333
|
}),
|
|
45334
|
+
characterOpenings: exports_external.array(GameStartCharacterOpeningSchema).max(GAME_START_MAX_CHARACTER_OPENINGS).default([]),
|
|
45160
45335
|
displayOrder: exports_external.number().int().default(0),
|
|
45161
45336
|
openingInstructions: exports_external.string().max(GAME_START_OPENING_MAX_LENGTH).default("")
|
|
45162
45337
|
});
|
|
45338
|
+
var GameStartMetadataSchema = GameStartMetadataObjectSchema.superRefine((metadata, ctx) => {
|
|
45339
|
+
if (combinedOpeningLength(metadata.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45340
|
+
ctx.addIssue({
|
|
45341
|
+
code: "custom",
|
|
45342
|
+
path: ["opening", "beats"],
|
|
45343
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45344
|
+
});
|
|
45345
|
+
}
|
|
45346
|
+
const seenCharacterReferenceIds = new Set;
|
|
45347
|
+
metadata.characterOpenings.forEach((characterOpening, index) => {
|
|
45348
|
+
const referenceId = characterOpening.characterFileReferenceId.toLowerCase();
|
|
45349
|
+
if (seenCharacterReferenceIds.has(referenceId)) {
|
|
45350
|
+
ctx.addIssue({
|
|
45351
|
+
code: "custom",
|
|
45352
|
+
path: ["characterOpenings", index, "characterFileReferenceId"],
|
|
45353
|
+
message: "Each character can only have one opening override."
|
|
45354
|
+
});
|
|
45355
|
+
}
|
|
45356
|
+
seenCharacterReferenceIds.add(referenceId);
|
|
45357
|
+
if (combinedOpeningLength(characterOpening.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45358
|
+
ctx.addIssue({
|
|
45359
|
+
code: "custom",
|
|
45360
|
+
path: ["characterOpenings", index, "opening", "beats"],
|
|
45361
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45362
|
+
});
|
|
45363
|
+
}
|
|
45364
|
+
});
|
|
45365
|
+
});
|
|
45163
45366
|
var FileDesignationMetadataV1Schema = exports_external.object({
|
|
45164
45367
|
schemaVersionId: exports_external.literal(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1).default(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1),
|
|
45165
45368
|
map: MapDataV1Schema.optional(),
|
|
@@ -45604,6 +45807,123 @@ ${remedies.join(`
|
|
|
45604
45807
|
|
|
45605
45808
|
// src/commands/meta.ts
|
|
45606
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
|
|
45607
45927
|
var META_USAGE = `Usage: craft meta get <path> [--json]
|
|
45608
45928
|
` + ` craft meta set-game-start <game-start-path> --file <json>
|
|
45609
45929
|
` + ` craft meta set-gm-trigger <gm-instruction-path> (--file <json> | --clear)
|
|
@@ -45669,7 +45989,12 @@ async function runMetaGet(argv) {
|
|
|
45669
45989
|
const gameStart = parsed?.gameStart ? {
|
|
45670
45990
|
...parsed.gameStart,
|
|
45671
45991
|
startingLocation: pathForReference(workspace, parsed.gameStart.startingLocationFileReferenceId),
|
|
45672
|
-
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId)
|
|
45992
|
+
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId),
|
|
45993
|
+
opening: projectOpeningForOutput(workspace, parsed.gameStart.opening),
|
|
45994
|
+
characterOpenings: parsed.gameStart.characterOpenings.map((characterOpening) => ({
|
|
45995
|
+
character: pathForReference(workspace, characterOpening.characterFileReferenceId) ?? characterOpening.characterFileReferenceId,
|
|
45996
|
+
opening: projectOpeningForOutput(workspace, characterOpening.opening)
|
|
45997
|
+
}))
|
|
45673
45998
|
} : null;
|
|
45674
45999
|
if (gameStart) {
|
|
45675
46000
|
gameStart.startingLocationFileReferenceId = undefined;
|
|
@@ -45690,46 +46015,47 @@ async function runMetaGet(argv) {
|
|
|
45690
46015
|
});
|
|
45691
46016
|
return 0;
|
|
45692
46017
|
}
|
|
46018
|
+
function projectOpeningForOutput(workspace, opening) {
|
|
46019
|
+
if (opening.kind !== "static" || !opening.beats?.length) {
|
|
46020
|
+
return opening;
|
|
46021
|
+
}
|
|
46022
|
+
return {
|
|
46023
|
+
kind: "static",
|
|
46024
|
+
beats: opening.beats.map((beat) => ({
|
|
46025
|
+
speaker: beat.speaker.kind === "gm" ? "gm" : pathForReference(workspace, beat.speaker.fileReferenceId) ?? beat.speaker.fileReferenceId,
|
|
46026
|
+
text: beat.text,
|
|
46027
|
+
...beat.expression ? { expression: beat.expression } : {}
|
|
46028
|
+
}))
|
|
46029
|
+
};
|
|
46030
|
+
}
|
|
45693
46031
|
function translateGameStartInput(workspace, raw) {
|
|
45694
46032
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
45695
46033
|
throw new CliError("The game start JSON must be a single object.", 2);
|
|
45696
46034
|
}
|
|
45697
|
-
const input = { ...raw };
|
|
45698
46035
|
const failures = [];
|
|
45699
|
-
const
|
|
45700
|
-
|
|
45701
|
-
|
|
45702
|
-
|
|
45703
|
-
|
|
45704
|
-
|
|
46036
|
+
const input = translateGameStartAuthoringInput({
|
|
46037
|
+
raw: { ...raw },
|
|
46038
|
+
resolveLink: (link, { where }) => {
|
|
46039
|
+
if (link === null || link === undefined) {
|
|
46040
|
+
return null;
|
|
46041
|
+
}
|
|
46042
|
+
if (typeof link !== "string") {
|
|
46043
|
+
failures.push(`${where}: expected a path/slug string`);
|
|
46044
|
+
return null;
|
|
46045
|
+
}
|
|
46046
|
+
const resolution = resolveLink({ ledger: workspace.ledger, link });
|
|
46047
|
+
if (resolution.status === "resolved") {
|
|
46048
|
+
return { referenceId: resolution.referenceId, name: resolution.name };
|
|
46049
|
+
}
|
|
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`);
|
|
45705
46051
|
return null;
|
|
45706
46052
|
}
|
|
45707
|
-
|
|
45708
|
-
if (resolution.status === "resolved") {
|
|
45709
|
-
return resolution.referenceId;
|
|
45710
|
-
}
|
|
45711
|
-
failures.push(resolution.status === "unpushed" ? `${where}: "${link}" has not been pushed yet — push it first` : `${where}: "${link}" does not resolve to a tracked file`);
|
|
45712
|
-
return null;
|
|
45713
|
-
};
|
|
45714
|
-
if ("startingLocation" in input) {
|
|
45715
|
-
input.startingLocationFileReferenceId = resolve6(input.startingLocation, "startingLocation");
|
|
45716
|
-
input.startingLocation = undefined;
|
|
45717
|
-
}
|
|
45718
|
-
if (Array.isArray(input.startingCharacters)) {
|
|
45719
|
-
input.startingCharacters = input.startingCharacters.map((character, index) => {
|
|
45720
|
-
if (typeof character === "string") {
|
|
45721
|
-
return {
|
|
45722
|
-
fileReferenceId: resolve6(character, `startingCharacters[${index}]`)
|
|
45723
|
-
};
|
|
45724
|
-
}
|
|
45725
|
-
return character;
|
|
45726
|
-
});
|
|
45727
|
-
}
|
|
46053
|
+
});
|
|
45728
46054
|
if (failures.length > 0) {
|
|
45729
46055
|
throw new CliError(`Nothing was saved — some references do not resolve to pushed files:
|
|
45730
46056
|
` + `${failures.map((f) => ` ${f}`).join(`
|
|
45731
46057
|
`)}
|
|
45732
|
-
` + "Use workspace paths, slug.type tokens, or
|
|
46058
|
+
` + "Use workspace paths (preferred), slug.type tokens, slugs, or file names of PUSHED files.", 2);
|
|
45733
46059
|
}
|
|
45734
46060
|
return input;
|
|
45735
46061
|
}
|
|
@@ -46056,7 +46382,7 @@ function escapeRegExp(value) {
|
|
|
46056
46382
|
// src/commands/project-completeness.ts
|
|
46057
46383
|
var TRIVIAL_DESCRIPTION_LENGTH = 40;
|
|
46058
46384
|
var CROSS_LINK_FILE_THRESHOLD = 5;
|
|
46059
|
-
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;
|
|
46060
46386
|
var SCRATCH_NAME_RE = /\b(?:test|asdf|scratch|repro|tmp|todo|example)\b/i;
|
|
46061
46387
|
async function runProjectCompleteness(argv) {
|
|
46062
46388
|
const args = parseCommandArgs({
|
|
@@ -46422,7 +46748,7 @@ function isReferenceValue2(record2) {
|
|
|
46422
46748
|
return false;
|
|
46423
46749
|
}
|
|
46424
46750
|
if ("referenceId" in record2) {
|
|
46425
|
-
return typeof record2.referenceId === "string" &&
|
|
46751
|
+
return typeof record2.referenceId === "string" && UUID_RE3.test(record2.referenceId);
|
|
46426
46752
|
}
|
|
46427
46753
|
return nonBlankString(record2.slug);
|
|
46428
46754
|
}
|
|
@@ -46828,7 +47154,7 @@ async function removeStaleManagedSkills({
|
|
|
46828
47154
|
// src/engine/pull.ts
|
|
46829
47155
|
import { mkdir as mkdir6, rename as rename4, rm as rm7, rmdir } from "node:fs/promises";
|
|
46830
47156
|
import { dirname as dirname7 } from "node:path";
|
|
46831
|
-
function
|
|
47157
|
+
function isRecord15(value) {
|
|
46832
47158
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46833
47159
|
}
|
|
46834
47160
|
function serializeContentForDisk({
|
|
@@ -46841,9 +47167,9 @@ function serializeContentForDisk({
|
|
|
46841
47167
|
const craftBlock = referenceId ? craftBlockForEmbedding({
|
|
46842
47168
|
referenceId,
|
|
46843
47169
|
...settings ? { settings } : {},
|
|
46844
|
-
...
|
|
47170
|
+
...isRecord15(metadata) ? { metadata } : {}
|
|
46845
47171
|
}) : null;
|
|
46846
|
-
if (contentType === "markdown" &&
|
|
47172
|
+
if (contentType === "markdown" && isRecord15(content)) {
|
|
46847
47173
|
return serializeMarkdown({
|
|
46848
47174
|
name: typeof content.name === "string" ? content.name : undefined,
|
|
46849
47175
|
description: typeof content.description === "string" ? content.description : undefined,
|
|
@@ -46851,7 +47177,7 @@ function serializeContentForDisk({
|
|
|
46851
47177
|
content: typeof content.content === "string" ? content.content : ""
|
|
46852
47178
|
}, { craftBlock });
|
|
46853
47179
|
}
|
|
46854
|
-
if (craftBlock &&
|
|
47180
|
+
if (craftBlock && isRecord15(content)) {
|
|
46855
47181
|
return `${JSON.stringify({
|
|
46856
47182
|
[CRAFT_BLOCK_KEY]: craftBlock,
|
|
46857
47183
|
...stripCraftBlock(content)
|
|
@@ -46866,7 +47192,7 @@ function contentTypeForPath2(path) {
|
|
|
46866
47192
|
}
|
|
46867
47193
|
function applyMetaBase(entry, body) {
|
|
46868
47194
|
entry.settings = craftFileSettingsFromWire(body.settings);
|
|
46869
|
-
entry.metadataHash =
|
|
47195
|
+
entry.metadataHash = isRecord15(body.metadata) ? hashCanonicalJson(body.metadata) : undefined;
|
|
46870
47196
|
}
|
|
46871
47197
|
function emptyResult() {
|
|
46872
47198
|
return {
|
|
@@ -47755,7 +48081,7 @@ import { join as join7 } from "node:path";
|
|
|
47755
48081
|
|
|
47756
48082
|
// src/engine/plan.ts
|
|
47757
48083
|
var MAX_CLI_PUSH_OPS = 500;
|
|
47758
|
-
function
|
|
48084
|
+
function isRecord16(value) {
|
|
47759
48085
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47760
48086
|
}
|
|
47761
48087
|
var PATHSPEC_LEADING_DOT_SLASH = /^\.\//;
|
|
@@ -47876,7 +48202,6 @@ function buildPushPlan(input) {
|
|
|
47876
48202
|
contentType: local.contentType,
|
|
47877
48203
|
schema: local.schema,
|
|
47878
48204
|
...local.layout != null ? { layout: local.layout } : {},
|
|
47879
|
-
...local.category !== undefined ? { category: local.category } : {},
|
|
47880
48205
|
designation: local.designation,
|
|
47881
48206
|
...local.imageStyleInstructions !== undefined ? { imageStyleInstructions: local.imageStyleInstructions } : {},
|
|
47882
48207
|
...local.showCoverImage !== undefined ? { showCoverImage: local.showCoverImage } : {},
|
|
@@ -47940,7 +48265,7 @@ function buildPushPlan(input) {
|
|
|
47940
48265
|
continue;
|
|
47941
48266
|
}
|
|
47942
48267
|
let content = scanned.content;
|
|
47943
|
-
if (
|
|
48268
|
+
if (isRecord16(content) && content.name !== newBaseName.value.baseName) {
|
|
47944
48269
|
content = { ...content, name: newBaseName.value.baseName };
|
|
47945
48270
|
nameRewrites.push({
|
|
47946
48271
|
diskPath: toPath,
|
|
@@ -50080,7 +50405,7 @@ async function workspaceRemote2() {
|
|
|
50080
50405
|
|
|
50081
50406
|
// src/commands/type.ts
|
|
50082
50407
|
import { existsSync as existsSync9 } from "node:fs";
|
|
50083
|
-
var TYPE_USAGE = "Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50408
|
+
var TYPE_USAGE = "Usage: craft type new <Name> [--markdown] [--designation <token>]";
|
|
50084
50409
|
var STARTER_JSON_SCHEMA = {
|
|
50085
50410
|
type: "object",
|
|
50086
50411
|
properties: {},
|
|
@@ -50099,7 +50424,6 @@ async function runTypeNew(argv) {
|
|
|
50099
50424
|
flags: {
|
|
50100
50425
|
markdown: { type: "boolean" },
|
|
50101
50426
|
designation: { type: "string" },
|
|
50102
|
-
category: { type: "string" },
|
|
50103
50427
|
json: { type: "boolean" }
|
|
50104
50428
|
},
|
|
50105
50429
|
maxPositionals: 1
|
|
@@ -50131,7 +50455,6 @@ async function runTypeNew(argv) {
|
|
|
50131
50455
|
name,
|
|
50132
50456
|
contentType,
|
|
50133
50457
|
designation,
|
|
50134
|
-
category: stringFlag(args, "category") ?? null,
|
|
50135
50458
|
schema: contentType === "json" ? STARTER_JSON_SCHEMA : null,
|
|
50136
50459
|
layout: null,
|
|
50137
50460
|
imageStyleInstructions: null,
|
|
@@ -50145,7 +50468,7 @@ async function runTypeNew(argv) {
|
|
|
50145
50468
|
`Create files of the type as <Anything>.${typeSlugExtension} anywhere in the workspace.`,
|
|
50146
50469
|
"Push the new type and its files together with `craft push --include-types`."
|
|
50147
50470
|
] : [
|
|
50148
|
-
`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.`,
|
|
50149
50472
|
`Create files of the type as <Anything>.${typeSlugExtension} anywhere in the workspace.`,
|
|
50150
50473
|
"Push the new type and its files together with `craft push --include-types`."
|
|
50151
50474
|
];
|
|
@@ -50287,7 +50610,7 @@ var HELP_COMMAND_LINES = ` clone <projectIdOrUrl> [dir] Download a project as
|
|
|
50287
50610
|
resolve <path> Mark a conflict resolved \u2014 your version wins
|
|
50288
50611
|
checkout <path> Take the remote version of a conflicted file
|
|
50289
50612
|
mv <from> <to> Rename/move a file, keeping its identity
|
|
50290
|
-
type new <Name> [--markdown] [--designation <t>]
|
|
50613
|
+
type new <Name> [--markdown] [--designation <t>]
|
|
50291
50614
|
Author a new file type locally (push with --include-types)
|
|
50292
50615
|
voices [--language <code>] [--gender <t>] [--age <t>]
|
|
50293
50616
|
List voice ids and traits for characters and the GM
|
|
@@ -50548,7 +50871,7 @@ Rename/move a file while keeping its identity (history, references). The
|
|
|
50548
50871
|
move is recorded in the ledger and pushed as a move op on the next
|
|
50549
50872
|
\`craft push\`; editing the file's content before pushing is fine.
|
|
50550
50873
|
`,
|
|
50551
|
-
type: `Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50874
|
+
type: `Usage: craft type new <Name> [--markdown] [--designation <token>]
|
|
50552
50875
|
|
|
50553
50876
|
Scaffold a new file type at .craft/file-types/<slug>.json. Edit its schema,
|
|
50554
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
|
}
|