@input/pen-core 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +53 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.mjs +53 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -715,6 +715,20 @@ var suggestion = {
|
|
|
715
715
|
};
|
|
716
716
|
|
|
717
717
|
// src/schema/registry.ts
|
|
718
|
+
var RESERVED_INLINE_ATOM_PROP = "type";
|
|
719
|
+
function assertInlineAtomPropKeys(schema) {
|
|
720
|
+
if (schema.kind !== "node") {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
if (schema.propSchema != null && Object.prototype.hasOwnProperty.call(
|
|
724
|
+
schema.propSchema,
|
|
725
|
+
RESERVED_INLINE_ATOM_PROP
|
|
726
|
+
)) {
|
|
727
|
+
throw new Error(
|
|
728
|
+
`Inline atom schema "${schema.type}" cannot declare a prop named "${RESERVED_INLINE_ATOM_PROP}": that key is the Y.Text embed discriminator, so the prop cannot be stored (SCH1). Rename the prop.`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
718
732
|
function passthroughBlockSchema(type) {
|
|
719
733
|
return {
|
|
720
734
|
type,
|
|
@@ -737,6 +751,12 @@ var SchemaRegistryImpl = class _SchemaRegistryImpl {
|
|
|
737
751
|
_onUnknownBlock;
|
|
738
752
|
_onUnknownInline;
|
|
739
753
|
constructor(config) {
|
|
754
|
+
for (const schema of config.inlines ?? []) {
|
|
755
|
+
assertInlineAtomPropKeys(schema);
|
|
756
|
+
}
|
|
757
|
+
for (const schema of config.systemMarks ?? []) {
|
|
758
|
+
assertInlineAtomPropKeys(schema);
|
|
759
|
+
}
|
|
740
760
|
this._blocks = new Map(
|
|
741
761
|
config.blocks?.map((schema) => [schema.type, schema])
|
|
742
762
|
);
|
|
@@ -4234,6 +4254,27 @@ function getProviderRecord(provider) {
|
|
|
4234
4254
|
}
|
|
4235
4255
|
|
|
4236
4256
|
// src/facets/coreFacets.ts
|
|
4257
|
+
function isClipboardHandlerTable(value) {
|
|
4258
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
4259
|
+
}
|
|
4260
|
+
function mergeClipboardHandlers(inputs) {
|
|
4261
|
+
const merged = {};
|
|
4262
|
+
for (const input of inputs) {
|
|
4263
|
+
if (!isClipboardHandlerTable(input)) {
|
|
4264
|
+
continue;
|
|
4265
|
+
}
|
|
4266
|
+
if (input.html !== void 0) {
|
|
4267
|
+
merged.html = input.html;
|
|
4268
|
+
}
|
|
4269
|
+
if (input.markdown !== void 0) {
|
|
4270
|
+
merged.markdown = input.markdown;
|
|
4271
|
+
}
|
|
4272
|
+
if (input.assets !== void 0) {
|
|
4273
|
+
merged.assets = input.assets;
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
return merged;
|
|
4277
|
+
}
|
|
4237
4278
|
var keymapFacet = defineFacet({
|
|
4238
4279
|
name: "pen.keymap",
|
|
4239
4280
|
combine: (inputs) => inputs.flat()
|
|
@@ -4272,7 +4313,7 @@ var ariaReadOnlyFacet = defineFacet({
|
|
|
4272
4313
|
});
|
|
4273
4314
|
var clipboardFacet = defineFacet({
|
|
4274
4315
|
name: "pen.clipboard",
|
|
4275
|
-
combine:
|
|
4316
|
+
combine: mergeClipboardHandlers
|
|
4276
4317
|
});
|
|
4277
4318
|
|
|
4278
4319
|
// src/editor/decorations.ts
|
|
@@ -9057,6 +9098,17 @@ function handleVerticalCaret(editor, param, direction) {
|
|
|
9057
9098
|
}
|
|
9058
9099
|
const measured = measureVerticalStep(editor, focus, direction);
|
|
9059
9100
|
if (measured) {
|
|
9101
|
+
const measuredBlockId = measured.point.blockId;
|
|
9102
|
+
if (!isEditableTextBlock(editor, measuredBlockId) && getBlockInputMode(editor, measuredBlockId) !== "table") {
|
|
9103
|
+
setVerticalCaretGoalX(editor, null);
|
|
9104
|
+
return {
|
|
9105
|
+
selection: extendSelection(
|
|
9106
|
+
editor,
|
|
9107
|
+
param.extend,
|
|
9108
|
+
blockSelectionResult([measuredBlockId])
|
|
9109
|
+
)
|
|
9110
|
+
};
|
|
9111
|
+
}
|
|
9060
9112
|
setVerticalCaretGoalX(editor, measured.goalX);
|
|
9061
9113
|
return {
|
|
9062
9114
|
selection: extendSelection(editor, param.extend, measured.point)
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _input_pen_types from '@input/pen-types';
|
|
2
|
-
import { ImportOptions, DocumentOp, DocumentProfile, FlowBlockCapability, InsertBlockOp, SetPropsOp, ImportResult, SchemaRegistry, BlockAuthoring, BlockSelectionRole, Editor, BlockSchema, InlineSchema, AppSchema, ComposableSchema, LayoutSchema, BlockDisplay, PropSchema, ContentType, BlockA11ySpec, Extension, DocumentState, DecorationSet, CreateEditorOptions, SchemaEngine, PenDocument, CRDTDocument, DiagnosticEvent, AppHandle, BlockHandle, CRDTAdapter, DocumentSession, Unsubscribe, Decoration, InlineCompletionController, DocumentRange, TextSelection, EditorAnchors, Anchor, AnchorTarget, Assoc, AnchorRange, ResolvedAnchorRange, SelectionRecord, SelectionState, SelectionOrigin, ChangeSummary, Point, Affinity, ReadonlySelectionState, CommitEvent, KeyBinding, CellSelection, ModelOperationRangeTarget, Block, FacetSpec, Facet, FacetProvider, FacetOutput, ApplyOptions, CommandHandlerRegistration, InputRule, AIRequestFilter, AIRequestContext, ModelAdapter, ModelRequestedOperation, ModelToolChoice, ModelStreamEvent, Command, StructuralOriginTag, SpliceTextOp, CommandHandler, Precedence, OpOrigin, MessageCatalog, A11yLabel, MessageKey, MessageArgs, MutationGroupMetadata, ToolExecutionResult, FieldEditorBehavior, FieldEditorInputMode, A11yMessageKey, TextSplice } from '@input/pen-types';
|
|
2
|
+
import { ImportOptions, DocumentOp, DocumentProfile, FlowBlockCapability, InsertBlockOp, SetPropsOp, ImportResult, SchemaRegistry, BlockAuthoring, BlockSelectionRole, Editor, BlockSchema, InlineSchema, AppSchema, ComposableSchema, LayoutSchema, BlockDisplay, PropSchema, ContentType, BlockA11ySpec, Extension, DocumentState, DecorationSet, CreateEditorOptions, SchemaEngine, PenDocument, CRDTDocument, DiagnosticEvent, AppHandle, BlockHandle, CRDTAdapter, DocumentSession, Unsubscribe, Decoration, InlineCompletionController, DocumentRange, TextSelection, EditorAnchors, Anchor, AnchorTarget, Assoc, AnchorRange, ResolvedAnchorRange, SelectionRecord, SelectionState, SelectionOrigin, ChangeSummary, Point, Affinity, ReadonlySelectionState, CommitEvent, KeyBinding, CellSelection, ModelOperationRangeTarget, Block, FacetSpec, Facet, FacetProvider, FacetOutput, ApplyOptions, Importer, AssetProvider, CommandHandlerRegistration, InputRule, AIRequestFilter, AIRequestContext, ModelAdapter, ModelRequestedOperation, ModelToolChoice, ModelStreamEvent, Command, StructuralOriginTag, SpliceTextOp, CommandHandler, Precedence, OpOrigin, MessageCatalog, A11yLabel, MessageKey, MessageArgs, MutationGroupMetadata, ToolExecutionResult, FieldEditorBehavior, FieldEditorInputMode, A11yMessageKey, TextSplice } from '@input/pen-types';
|
|
3
3
|
export { ImportOptions as ImporterOptions } from '@input/pen-types';
|
|
4
4
|
|
|
5
5
|
type PendingInlineSegment = {
|
|
@@ -143,8 +143,9 @@ type DefineBlockConfig = Omit<Partial<BlockSchema<string, Record<string, PropSch
|
|
|
143
143
|
propSchema?: Record<string, unknown>;
|
|
144
144
|
aiDescription?: string;
|
|
145
145
|
};
|
|
146
|
+
type DefinedA11y<Type extends string> = BlockA11ySpec & ((spec: BlockA11ySpec) => BlockSchema<Type, Record<string, PropSchema>, ContentType>);
|
|
146
147
|
type DefinedBlockSchema<Type extends string = string> = Omit<BlockSchema<Type, Record<string, PropSchema>, ContentType>, "a11y"> & {
|
|
147
|
-
a11y
|
|
148
|
+
a11y: DefinedA11y<Type>;
|
|
148
149
|
};
|
|
149
150
|
declare function defineBlock<Type extends string>(type: Type, config: DefineBlockConfig): DefinedBlockSchema<Type>;
|
|
150
151
|
declare function defineBlock<Type extends string>(config: DefineBlockConfig & {
|
|
@@ -663,7 +664,11 @@ declare function createFacetRegistry(options?: CreateFacetRegistryOptions): Face
|
|
|
663
664
|
type Keymap = readonly KeyBinding[];
|
|
664
665
|
type BeforeApplyHook = (ops: DocumentOp[], options: ApplyOptions) => DocumentOp[];
|
|
665
666
|
type DecorationSource = ((state: DocumentState, editor: Editor) => DecorationSet) | DecorationSet;
|
|
666
|
-
type ClipboardHandler =
|
|
667
|
+
type ClipboardHandler = {
|
|
668
|
+
readonly html?: Importer;
|
|
669
|
+
readonly markdown?: Importer;
|
|
670
|
+
readonly assets?: AssetProvider;
|
|
671
|
+
};
|
|
667
672
|
type CommandHandlerTable = {
|
|
668
673
|
readonly [commandName: string]: readonly CommandHandlerRegistration[];
|
|
669
674
|
};
|
|
@@ -673,7 +678,7 @@ declare const decorationsFacet: _input_pen_types.Facet<DecorationSource, readonl
|
|
|
673
678
|
declare const inputRulesFacet: _input_pen_types.Facet<InputRule, readonly InputRule[]>;
|
|
674
679
|
declare const commandsFacet: _input_pen_types.Facet<CommandHandlerRegistration<unknown>, CommandHandlerTable>;
|
|
675
680
|
declare const ariaReadOnlyFacet: _input_pen_types.Facet<boolean, boolean>;
|
|
676
|
-
declare const clipboardFacet: _input_pen_types.Facet<
|
|
681
|
+
declare const clipboardFacet: _input_pen_types.Facet<ClipboardHandler, ClipboardHandler>;
|
|
677
682
|
|
|
678
683
|
type UrlContext = "link" | "image" | "media" | "download";
|
|
679
684
|
interface UrlPolicy {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _input_pen_types from '@input/pen-types';
|
|
2
|
-
import { ImportOptions, DocumentOp, DocumentProfile, FlowBlockCapability, InsertBlockOp, SetPropsOp, ImportResult, SchemaRegistry, BlockAuthoring, BlockSelectionRole, Editor, BlockSchema, InlineSchema, AppSchema, ComposableSchema, LayoutSchema, BlockDisplay, PropSchema, ContentType, BlockA11ySpec, Extension, DocumentState, DecorationSet, CreateEditorOptions, SchemaEngine, PenDocument, CRDTDocument, DiagnosticEvent, AppHandle, BlockHandle, CRDTAdapter, DocumentSession, Unsubscribe, Decoration, InlineCompletionController, DocumentRange, TextSelection, EditorAnchors, Anchor, AnchorTarget, Assoc, AnchorRange, ResolvedAnchorRange, SelectionRecord, SelectionState, SelectionOrigin, ChangeSummary, Point, Affinity, ReadonlySelectionState, CommitEvent, KeyBinding, CellSelection, ModelOperationRangeTarget, Block, FacetSpec, Facet, FacetProvider, FacetOutput, ApplyOptions, CommandHandlerRegistration, InputRule, AIRequestFilter, AIRequestContext, ModelAdapter, ModelRequestedOperation, ModelToolChoice, ModelStreamEvent, Command, StructuralOriginTag, SpliceTextOp, CommandHandler, Precedence, OpOrigin, MessageCatalog, A11yLabel, MessageKey, MessageArgs, MutationGroupMetadata, ToolExecutionResult, FieldEditorBehavior, FieldEditorInputMode, A11yMessageKey, TextSplice } from '@input/pen-types';
|
|
2
|
+
import { ImportOptions, DocumentOp, DocumentProfile, FlowBlockCapability, InsertBlockOp, SetPropsOp, ImportResult, SchemaRegistry, BlockAuthoring, BlockSelectionRole, Editor, BlockSchema, InlineSchema, AppSchema, ComposableSchema, LayoutSchema, BlockDisplay, PropSchema, ContentType, BlockA11ySpec, Extension, DocumentState, DecorationSet, CreateEditorOptions, SchemaEngine, PenDocument, CRDTDocument, DiagnosticEvent, AppHandle, BlockHandle, CRDTAdapter, DocumentSession, Unsubscribe, Decoration, InlineCompletionController, DocumentRange, TextSelection, EditorAnchors, Anchor, AnchorTarget, Assoc, AnchorRange, ResolvedAnchorRange, SelectionRecord, SelectionState, SelectionOrigin, ChangeSummary, Point, Affinity, ReadonlySelectionState, CommitEvent, KeyBinding, CellSelection, ModelOperationRangeTarget, Block, FacetSpec, Facet, FacetProvider, FacetOutput, ApplyOptions, Importer, AssetProvider, CommandHandlerRegistration, InputRule, AIRequestFilter, AIRequestContext, ModelAdapter, ModelRequestedOperation, ModelToolChoice, ModelStreamEvent, Command, StructuralOriginTag, SpliceTextOp, CommandHandler, Precedence, OpOrigin, MessageCatalog, A11yLabel, MessageKey, MessageArgs, MutationGroupMetadata, ToolExecutionResult, FieldEditorBehavior, FieldEditorInputMode, A11yMessageKey, TextSplice } from '@input/pen-types';
|
|
3
3
|
export { ImportOptions as ImporterOptions } from '@input/pen-types';
|
|
4
4
|
|
|
5
5
|
type PendingInlineSegment = {
|
|
@@ -143,8 +143,9 @@ type DefineBlockConfig = Omit<Partial<BlockSchema<string, Record<string, PropSch
|
|
|
143
143
|
propSchema?: Record<string, unknown>;
|
|
144
144
|
aiDescription?: string;
|
|
145
145
|
};
|
|
146
|
+
type DefinedA11y<Type extends string> = BlockA11ySpec & ((spec: BlockA11ySpec) => BlockSchema<Type, Record<string, PropSchema>, ContentType>);
|
|
146
147
|
type DefinedBlockSchema<Type extends string = string> = Omit<BlockSchema<Type, Record<string, PropSchema>, ContentType>, "a11y"> & {
|
|
147
|
-
a11y
|
|
148
|
+
a11y: DefinedA11y<Type>;
|
|
148
149
|
};
|
|
149
150
|
declare function defineBlock<Type extends string>(type: Type, config: DefineBlockConfig): DefinedBlockSchema<Type>;
|
|
150
151
|
declare function defineBlock<Type extends string>(config: DefineBlockConfig & {
|
|
@@ -663,7 +664,11 @@ declare function createFacetRegistry(options?: CreateFacetRegistryOptions): Face
|
|
|
663
664
|
type Keymap = readonly KeyBinding[];
|
|
664
665
|
type BeforeApplyHook = (ops: DocumentOp[], options: ApplyOptions) => DocumentOp[];
|
|
665
666
|
type DecorationSource = ((state: DocumentState, editor: Editor) => DecorationSet) | DecorationSet;
|
|
666
|
-
type ClipboardHandler =
|
|
667
|
+
type ClipboardHandler = {
|
|
668
|
+
readonly html?: Importer;
|
|
669
|
+
readonly markdown?: Importer;
|
|
670
|
+
readonly assets?: AssetProvider;
|
|
671
|
+
};
|
|
667
672
|
type CommandHandlerTable = {
|
|
668
673
|
readonly [commandName: string]: readonly CommandHandlerRegistration[];
|
|
669
674
|
};
|
|
@@ -673,7 +678,7 @@ declare const decorationsFacet: _input_pen_types.Facet<DecorationSource, readonl
|
|
|
673
678
|
declare const inputRulesFacet: _input_pen_types.Facet<InputRule, readonly InputRule[]>;
|
|
674
679
|
declare const commandsFacet: _input_pen_types.Facet<CommandHandlerRegistration<unknown>, CommandHandlerTable>;
|
|
675
680
|
declare const ariaReadOnlyFacet: _input_pen_types.Facet<boolean, boolean>;
|
|
676
|
-
declare const clipboardFacet: _input_pen_types.Facet<
|
|
681
|
+
declare const clipboardFacet: _input_pen_types.Facet<ClipboardHandler, ClipboardHandler>;
|
|
677
682
|
|
|
678
683
|
type UrlContext = "link" | "image" | "media" | "download";
|
|
679
684
|
interface UrlPolicy {
|
package/dist/index.mjs
CHANGED
|
@@ -479,6 +479,20 @@ var suggestion = {
|
|
|
479
479
|
};
|
|
480
480
|
|
|
481
481
|
// src/schema/registry.ts
|
|
482
|
+
var RESERVED_INLINE_ATOM_PROP = "type";
|
|
483
|
+
function assertInlineAtomPropKeys(schema) {
|
|
484
|
+
if (schema.kind !== "node") {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
if (schema.propSchema != null && Object.prototype.hasOwnProperty.call(
|
|
488
|
+
schema.propSchema,
|
|
489
|
+
RESERVED_INLINE_ATOM_PROP
|
|
490
|
+
)) {
|
|
491
|
+
throw new Error(
|
|
492
|
+
`Inline atom schema "${schema.type}" cannot declare a prop named "${RESERVED_INLINE_ATOM_PROP}": that key is the Y.Text embed discriminator, so the prop cannot be stored (SCH1). Rename the prop.`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
482
496
|
function passthroughBlockSchema(type) {
|
|
483
497
|
return {
|
|
484
498
|
type,
|
|
@@ -501,6 +515,12 @@ var SchemaRegistryImpl = class _SchemaRegistryImpl {
|
|
|
501
515
|
_onUnknownBlock;
|
|
502
516
|
_onUnknownInline;
|
|
503
517
|
constructor(config) {
|
|
518
|
+
for (const schema of config.inlines ?? []) {
|
|
519
|
+
assertInlineAtomPropKeys(schema);
|
|
520
|
+
}
|
|
521
|
+
for (const schema of config.systemMarks ?? []) {
|
|
522
|
+
assertInlineAtomPropKeys(schema);
|
|
523
|
+
}
|
|
504
524
|
this._blocks = new Map(
|
|
505
525
|
config.blocks?.map((schema) => [schema.type, schema])
|
|
506
526
|
);
|
|
@@ -4002,6 +4022,27 @@ function getProviderRecord(provider) {
|
|
|
4002
4022
|
}
|
|
4003
4023
|
|
|
4004
4024
|
// src/facets/coreFacets.ts
|
|
4025
|
+
function isClipboardHandlerTable(value) {
|
|
4026
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
4027
|
+
}
|
|
4028
|
+
function mergeClipboardHandlers(inputs) {
|
|
4029
|
+
const merged = {};
|
|
4030
|
+
for (const input of inputs) {
|
|
4031
|
+
if (!isClipboardHandlerTable(input)) {
|
|
4032
|
+
continue;
|
|
4033
|
+
}
|
|
4034
|
+
if (input.html !== void 0) {
|
|
4035
|
+
merged.html = input.html;
|
|
4036
|
+
}
|
|
4037
|
+
if (input.markdown !== void 0) {
|
|
4038
|
+
merged.markdown = input.markdown;
|
|
4039
|
+
}
|
|
4040
|
+
if (input.assets !== void 0) {
|
|
4041
|
+
merged.assets = input.assets;
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
return merged;
|
|
4045
|
+
}
|
|
4005
4046
|
var keymapFacet = defineFacet({
|
|
4006
4047
|
name: "pen.keymap",
|
|
4007
4048
|
combine: (inputs) => inputs.flat()
|
|
@@ -4040,7 +4081,7 @@ var ariaReadOnlyFacet = defineFacet({
|
|
|
4040
4081
|
});
|
|
4041
4082
|
var clipboardFacet = defineFacet({
|
|
4042
4083
|
name: "pen.clipboard",
|
|
4043
|
-
combine:
|
|
4084
|
+
combine: mergeClipboardHandlers
|
|
4044
4085
|
});
|
|
4045
4086
|
|
|
4046
4087
|
// src/editor/decorations.ts
|
|
@@ -8838,6 +8879,17 @@ function handleVerticalCaret(editor, param, direction) {
|
|
|
8838
8879
|
}
|
|
8839
8880
|
const measured = measureVerticalStep(editor, focus, direction);
|
|
8840
8881
|
if (measured) {
|
|
8882
|
+
const measuredBlockId = measured.point.blockId;
|
|
8883
|
+
if (!isEditableTextBlock(editor, measuredBlockId) && getBlockInputMode(editor, measuredBlockId) !== "table") {
|
|
8884
|
+
setVerticalCaretGoalX(editor, null);
|
|
8885
|
+
return {
|
|
8886
|
+
selection: extendSelection(
|
|
8887
|
+
editor,
|
|
8888
|
+
param.extend,
|
|
8889
|
+
blockSelectionResult([measuredBlockId])
|
|
8890
|
+
)
|
|
8891
|
+
};
|
|
8892
|
+
}
|
|
8841
8893
|
setVerticalCaretGoalX(editor, measured.goalX);
|
|
8842
8894
|
return {
|
|
8843
8895
|
selection: extendSelection(editor, param.extend, measured.point)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@input/pen-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Headless, extension-first editor engine for human-AI co-authoring",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/input-systems/pen#readme",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@input/pen-yjs": "^0.1.
|
|
47
|
-
"@input/pen-types": "^0.1.
|
|
46
|
+
"@input/pen-yjs": "^0.1.6",
|
|
47
|
+
"@input/pen-types": "^0.1.6"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"tsup": "^8.4.0",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsup",
|
|
57
|
+
"dev": "tsup --watch --no-clean",
|
|
57
58
|
"typecheck": "tsc --noEmit",
|
|
58
59
|
"lint": "eslint .",
|
|
59
60
|
"catalog:check": "node ../../scripts/catalog-check.mjs",
|