tsondb 0.20.6 → 0.20.8
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/src/node/bin/tsondb.js +14 -2
- package/dist/src/node/index.d.ts +24 -0
- package/dist/src/node/index.js +29 -3
- package/dist/src/node/schema/treeOperations/validation.d.ts +4 -2
- package/dist/src/node/schema/treeOperations/validation.js +83 -11
- package/dist/src/node/server/index.js +1 -1
- package/dist/src/node/utils/files.d.ts +1 -0
- package/dist/src/node/utils/files.js +4 -1
- package/dist/src/shared/validation/string.js +2 -2
- package/dist/src/web/web.js +109 -35
- package/package.json +8 -8
|
@@ -48,6 +48,12 @@ const passedArguments = parseArguments({
|
|
|
48
48
|
},
|
|
49
49
|
format: {
|
|
50
50
|
name: "format",
|
|
51
|
+
options: {
|
|
52
|
+
check: {
|
|
53
|
+
name: "check",
|
|
54
|
+
type: Boolean,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
51
57
|
},
|
|
52
58
|
name: {
|
|
53
59
|
name: "name",
|
|
@@ -144,9 +150,15 @@ else {
|
|
|
144
150
|
break;
|
|
145
151
|
}
|
|
146
152
|
case "format": {
|
|
147
|
-
debug(`running command: format`);
|
|
148
153
|
const db = await createDB(config, config.validationOptions, true);
|
|
149
|
-
|
|
154
|
+
if (passedArguments.command.options?.check === true) {
|
|
155
|
+
debug(`running command: format --check`);
|
|
156
|
+
await db.checkFormat();
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
debug(`running command: format`);
|
|
160
|
+
await db.format();
|
|
161
|
+
}
|
|
150
162
|
break;
|
|
151
163
|
}
|
|
152
164
|
case "name": {
|
package/dist/src/node/index.d.ts
CHANGED
|
@@ -64,6 +64,26 @@ export interface ValidationOptions {
|
|
|
64
64
|
* If set, translations will be validated according to the provided options.
|
|
65
65
|
*/
|
|
66
66
|
checkTranslations?: TranslationValidationOptions;
|
|
67
|
+
/**
|
|
68
|
+
* Special options for validating Markdown content in the database.
|
|
69
|
+
*/
|
|
70
|
+
markdown?: Partial<MarkdownValidationOptions>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Special options for validating Markdown content in the database.
|
|
74
|
+
*/
|
|
75
|
+
export interface MarkdownValidationOptions {
|
|
76
|
+
/**
|
|
77
|
+
* Checks for the existence of referenced entities and possibly instances in attributed strings. If the attribute names are not specified via an object, the default attribute names `entity` and `instance` will be used.
|
|
78
|
+
*/
|
|
79
|
+
checkInstanceReferencesInAttributedStrings?: boolean | {
|
|
80
|
+
entityKey: string;
|
|
81
|
+
instanceKey: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* If set, keys in attributed strings will be checked agains the provided list of keys or regular expression. Keys for `checkInstanceReferencesInAttributedStrings` are included automatically and do not need to be specified again.
|
|
85
|
+
*/
|
|
86
|
+
checkAttributedStringKeys?: string[] | RegExp;
|
|
67
87
|
}
|
|
68
88
|
/**
|
|
69
89
|
* Options for validating translations in the database.
|
|
@@ -114,6 +134,10 @@ export declare class TSONDB<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
114
134
|
* Formats the data on disk according to the current in-memory representation.
|
|
115
135
|
*/
|
|
116
136
|
format(): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Checks if the data on disk is formatted according to the current in-memory representation.
|
|
139
|
+
*/
|
|
140
|
+
checkFormat(): Promise<void>;
|
|
117
141
|
/**
|
|
118
142
|
* Reloads the data from disk into memory.
|
|
119
143
|
*/
|
package/dist/src/node/index.js
CHANGED
|
@@ -15,14 +15,14 @@ import {} from "./schema/dsl/index.js";
|
|
|
15
15
|
import {} from "./schema/generatedTypeHelpers.js";
|
|
16
16
|
import { isEntityDeclWithParentReference } from "./schema/guards.js";
|
|
17
17
|
import { serializeNode } from "./schema/treeOperations/serialization.js";
|
|
18
|
-
import { createReferenceValidator, validateDeclReferentialIntegrity, validateDeclStructuralIntegrity, } from "./schema/treeOperations/validation.js";
|
|
18
|
+
import { createEntityNameValidator, createReferenceValidator, validateDeclReferentialIntegrity, validateDeclStructuralIntegrity, } from "./schema/treeOperations/validation.js";
|
|
19
19
|
import { Transaction } from "./transaction.js";
|
|
20
20
|
import { checkCustomConstraintsForAllEntities } from "./utils/customConstraints.js";
|
|
21
21
|
import { DatabaseInMemory } from "./utils/databaseInMemory.js";
|
|
22
22
|
import { applyStepsToDisk } from "./utils/databaseOnDisk.js";
|
|
23
23
|
import { getAllInstanceOverviewsByEntityName, getDisplayNameFromEntityInstance, getInstanceOverview, getInstanceOverviewsByEntityName, } from "./utils/displayName.js";
|
|
24
24
|
import { countError, countErrors, getErrorMessageForDisplay, HTTPError, wrapErrorsIfAny, } from "./utils/error.js";
|
|
25
|
-
import { getFileNameForId, writeInstance } from "./utils/files.js";
|
|
25
|
+
import { formatInstance, getFileNameForId, readInstance, writeInstance } from "./utils/files.js";
|
|
26
26
|
import { attachGitStatusToDatabaseInMemory } from "./utils/git.js";
|
|
27
27
|
import { getReferencesToInstances, isReferencedByOtherInstances, } from "./utils/references.js";
|
|
28
28
|
import { checkUniqueConstraintsForAllEntities } from "./utils/unique.js";
|
|
@@ -210,11 +210,12 @@ export class TSONDB {
|
|
|
210
210
|
if (!skipStructuralValidation) {
|
|
211
211
|
if (checkReferentialIntegrity) {
|
|
212
212
|
debug("Checking referential integrity ...");
|
|
213
|
+
const entityNameValidator = createEntityNameValidator(this.#schema.isEntityName.bind(this.#schema), true);
|
|
213
214
|
const referenceValidator = createReferenceValidator(this.#schema.isEntityName.bind(this.#schema), data, true);
|
|
214
215
|
const referenceErrors = onlyEntities
|
|
215
216
|
.flatMap(entity => parallelizeErrors(data
|
|
216
217
|
.getAllInstanceContainersOfEntity(entity.name)
|
|
217
|
-
.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateDeclReferentialIntegrity(validationContext, referenceValidator, [], entity, [], instance.content)))))
|
|
218
|
+
.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateDeclReferentialIntegrity(validationContext, entityNameValidator, referenceValidator, [], entity, [], instance.content)))))
|
|
218
219
|
.toSorted((a, b) => a.message.localeCompare(b.message));
|
|
219
220
|
if (referenceErrors.length > 0) {
|
|
220
221
|
const errorCount = countErrors(referenceErrors);
|
|
@@ -287,6 +288,31 @@ export class TSONDB {
|
|
|
287
288
|
}, true);
|
|
288
289
|
debug("All data is formatted");
|
|
289
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Checks if the data on disk is formatted according to the current in-memory representation.
|
|
293
|
+
*/
|
|
294
|
+
async checkFormat() {
|
|
295
|
+
debug("Check database formatting ...");
|
|
296
|
+
let counter = 0;
|
|
297
|
+
await this.#data.forEachInstance(async (entityName, instance) => {
|
|
298
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
299
|
+
const entity = this.#schema.getEntity(entityName);
|
|
300
|
+
const instanceOnDisk = await readInstance(this.#dataRootPath, entity, instance.id);
|
|
301
|
+
const currentFormatted = formatInstance(entity, instance.content, this.#formatterOptions);
|
|
302
|
+
if (instanceOnDisk !== currentFormatted) {
|
|
303
|
+
console.log(`Instance ${styleText("yellow", instance.id)} of entity ${styleText("cyan", entityName)} is not formatted correctly.`);
|
|
304
|
+
counter++;
|
|
305
|
+
}
|
|
306
|
+
}, true);
|
|
307
|
+
if (counter === 0) {
|
|
308
|
+
console.log(styleText("green", "All data is formatted"));
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
console.error(styleText("red", `${counter.toFixed()} formatting error${counter === 1 ? "" : "s"} found`, {
|
|
312
|
+
stream: stderr,
|
|
313
|
+
}));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
290
316
|
/**
|
|
291
317
|
* Reloads the data from disk into memory.
|
|
292
318
|
*/
|
|
@@ -7,13 +7,15 @@ export type IdentifierToCheck = {
|
|
|
7
7
|
name: string;
|
|
8
8
|
value: unknown;
|
|
9
9
|
};
|
|
10
|
+
export type EntityNameValidator = (entityName: unknown) => Error[];
|
|
10
11
|
export type ReferenceValidator = (entityName: string, instanceId: unknown) => ReferenceError[];
|
|
11
12
|
export interface ValidationContext {
|
|
12
13
|
useStyling: boolean;
|
|
13
14
|
validationOptions: ValidationOptions;
|
|
14
15
|
}
|
|
16
|
+
export declare const createEntityNameValidator: (isEntityName: (name: string) => boolean, useStyling: boolean) => EntityNameValidator;
|
|
15
17
|
export declare const createReferenceValidator: <EM extends AnyEntityMap>(isEntityName: (name: string) => name is Extract<keyof EM, string>, databaseInMemory: DatabaseInMemory<EM>, useStyling: boolean) => ReferenceValidator;
|
|
16
18
|
export declare const validateDeclStructuralIntegrity: (helpers: ValidationContext, inDecls: Decl[], decl: Decl, typeArgs: Type[], value: unknown) => TypeError[];
|
|
17
19
|
export declare const validateTypeStructuralIntegrity: (helpers: ValidationContext, inDecls: Decl[], type: Type, value: unknown) => TypeError[];
|
|
18
|
-
export declare const validateDeclReferentialIntegrity: (helpers: ValidationContext, checkReferentialIntegrity: ReferenceValidator, inDecls: Decl[], decl: Decl, typeArgs: Type[], value: unknown) => ReferenceError[];
|
|
19
|
-
export declare const validateTypeReferentialIntegrity: (helpers: ValidationContext, checkReferentialIntegrity: ReferenceValidator, inDecls: Decl[], type: Type, value: unknown) => ReferenceError[];
|
|
20
|
+
export declare const validateDeclReferentialIntegrity: (helpers: ValidationContext, checkEntityName: EntityNameValidator, checkReferentialIntegrity: ReferenceValidator, inDecls: Decl[], decl: Decl, typeArgs: Type[], value: unknown) => ReferenceError[];
|
|
21
|
+
export declare const validateTypeReferentialIntegrity: (helpers: ValidationContext, checkEntityName: EntityNameValidator, checkReferentialIntegrity: ReferenceValidator, inDecls: Decl[], type: Type, value: unknown) => ReferenceError[];
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { validate as validateBlockMarkdown, validateInline as validateInlineMarkdown, } from "@elyukai/markdown/validate";
|
|
2
|
+
import { isNotNullish } from "@elyukai/utils/nullable";
|
|
1
3
|
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
2
4
|
import { MessageError, parseMessage, validate } from "messageformat";
|
|
3
5
|
import { ENUM_DISCRIMINATOR_KEY } from "../../../shared/schema/declarations/EnumDecl.js";
|
|
@@ -16,6 +18,9 @@ import { getTypeArgumentsRecord } from "../dsl/declarations/Decl.js";
|
|
|
16
18
|
import { createEntityIdentifierType } from "../dsl/declarations/EntityDecl.js";
|
|
17
19
|
import { isChildEntitiesType } from "../guards.js";
|
|
18
20
|
import { resolveTypeArguments } from "./typeResolution.js";
|
|
21
|
+
export const createEntityNameValidator = (isEntityName, useStyling) => entityName => typeof entityName === "string" && isEntityName(entityName)
|
|
22
|
+
? []
|
|
23
|
+
: [ReferenceError(`Invalid entity name ${json(entityName, useStyling)}`)];
|
|
19
24
|
export const createReferenceValidator = (isEntityName, databaseInMemory, useStyling) => (entityName, instanceId) => isEntityName(entityName)
|
|
20
25
|
? typeof instanceId === "string" &&
|
|
21
26
|
databaseInMemory.hasInstanceOfEntityById(entityName, instanceId)
|
|
@@ -86,6 +91,69 @@ const validateTranslationObjectStructuralIntegrity = (context, allKeysAreRequire
|
|
|
86
91
|
}),
|
|
87
92
|
]);
|
|
88
93
|
};
|
|
94
|
+
const DEFAULT_ENTITY_KEY = "entity";
|
|
95
|
+
const DEFAULT_INSTANCE_KEY = "instance";
|
|
96
|
+
const normalizeAttributedStringReferenceKeys = (option) => option === true ? { entityKey: DEFAULT_ENTITY_KEY, instanceKey: DEFAULT_INSTANCE_KEY } : option;
|
|
97
|
+
const createStructuralAttributedStringKeyValidator = (validationOptions) => {
|
|
98
|
+
const { checkInstanceReferencesInAttributedStrings: checkAttrRefs, checkAttributedStringKeys } = validationOptions.markdown ?? {};
|
|
99
|
+
if (checkAttributedStringKeys !== undefined) {
|
|
100
|
+
const generalTest = Array.isArray(checkAttributedStringKeys)
|
|
101
|
+
? key => checkAttributedStringKeys.includes(key)
|
|
102
|
+
: key => checkAttributedStringKeys.test(key);
|
|
103
|
+
if (checkAttrRefs === true || typeof checkAttrRefs === "object") {
|
|
104
|
+
const { entityKey, instanceKey } = normalizeAttributedStringReferenceKeys(checkAttrRefs);
|
|
105
|
+
const additionalValidKeys = [entityKey, instanceKey];
|
|
106
|
+
return key => generalTest(key) || additionalValidKeys.includes(key);
|
|
107
|
+
}
|
|
108
|
+
return generalTest;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
};
|
|
112
|
+
const createStructuralAttributedStringValidator = (validationOptions) => {
|
|
113
|
+
const keyValidator = createStructuralAttributedStringKeyValidator(validationOptions);
|
|
114
|
+
if (keyValidator === undefined) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return attributes => Object.keys(attributes)
|
|
118
|
+
.map(attributeName => keyValidator(attributeName)
|
|
119
|
+
? undefined
|
|
120
|
+
: new TypeError(`invalid attribute key "${attributeName}" in attributed string`))
|
|
121
|
+
.filter(isNotNullish);
|
|
122
|
+
};
|
|
123
|
+
const createReferentialAttributedStringValidator = (entityValidator, referenceValidator, validationOptions) => {
|
|
124
|
+
const { checkInstanceReferencesInAttributedStrings: checkAttrRefs } = validationOptions.markdown ?? {};
|
|
125
|
+
if (checkAttrRefs === true || typeof checkAttrRefs === "object") {
|
|
126
|
+
const { entityKey, instanceKey } = normalizeAttributedStringReferenceKeys(checkAttrRefs);
|
|
127
|
+
return attributes => {
|
|
128
|
+
if (entityKey in attributes) {
|
|
129
|
+
const entityName = attributes[entityKey];
|
|
130
|
+
const entityErrors = entityValidator(entityName);
|
|
131
|
+
if (entityErrors.length > 0) {
|
|
132
|
+
return entityErrors;
|
|
133
|
+
}
|
|
134
|
+
if (instanceKey in attributes && typeof entityName === "string") {
|
|
135
|
+
const instanceId = attributes[instanceKey];
|
|
136
|
+
return referenceValidator(entityName, instanceId);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return [];
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
};
|
|
144
|
+
const validateMarkdownString = (type, value, validator) => {
|
|
145
|
+
if (type.markdown !== undefined && typeof value === "string") {
|
|
146
|
+
switch (type.markdown) {
|
|
147
|
+
case "inline":
|
|
148
|
+
return validateInlineMarkdown(value, { validateAttributes: validator });
|
|
149
|
+
case "block":
|
|
150
|
+
return validateBlockMarkdown(value, { validateAttributes: validator });
|
|
151
|
+
default:
|
|
152
|
+
return assertExhaustive(type.markdown);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return [];
|
|
156
|
+
};
|
|
89
157
|
export const validateTypeStructuralIntegrity = (helpers, inDecls, type, value) => {
|
|
90
158
|
switch (type.kind) {
|
|
91
159
|
case NodeKind.ArrayType: {
|
|
@@ -149,7 +217,10 @@ export const validateTypeStructuralIntegrity = (helpers, inDecls, type, value) =
|
|
|
149
217
|
if (typeof value !== "string") {
|
|
150
218
|
return [TypeError(`expected a string, but got ${json(value, helpers.useStyling)}`)];
|
|
151
219
|
}
|
|
152
|
-
return
|
|
220
|
+
return parallelizeErrors([
|
|
221
|
+
...validateStringConstraints(type, value),
|
|
222
|
+
...validateMarkdownString(type, value, createStructuralAttributedStringValidator(helpers.validationOptions)),
|
|
223
|
+
]);
|
|
153
224
|
}
|
|
154
225
|
case NodeKind.TypeArgumentType: {
|
|
155
226
|
throw new TypeError(`generic argument "${type.argument.name}" has not been replaced with a concrete type`);
|
|
@@ -212,13 +283,13 @@ export const validateTypeStructuralIntegrity = (helpers, inDecls, type, value) =
|
|
|
212
283
|
return assertExhaustive(type);
|
|
213
284
|
}
|
|
214
285
|
};
|
|
215
|
-
export const validateDeclReferentialIntegrity = (helpers, checkReferentialIntegrity, inDecls, decl, typeArgs, value) => {
|
|
286
|
+
export const validateDeclReferentialIntegrity = (helpers, checkEntityName, checkReferentialIntegrity, inDecls, decl, typeArgs, value) => {
|
|
216
287
|
switch (decl.kind) {
|
|
217
288
|
case NodeKind.EntityDecl:
|
|
218
|
-
return validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, decl.type.value, value);
|
|
289
|
+
return validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, decl.type.value, value);
|
|
219
290
|
case NodeKind.EnumDecl:
|
|
220
291
|
case NodeKind.TypeAliasDecl:
|
|
221
|
-
return validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, [...inDecls, decl], resolveTypeArguments(getTypeArgumentsRecord(decl, typeArgs), decl.type.value, [
|
|
292
|
+
return validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, [...inDecls, decl], resolveTypeArguments(getTypeArgumentsRecord(decl, typeArgs), decl.type.value, [
|
|
222
293
|
...inDecls,
|
|
223
294
|
decl,
|
|
224
295
|
]), value);
|
|
@@ -226,11 +297,11 @@ export const validateDeclReferentialIntegrity = (helpers, checkReferentialIntegr
|
|
|
226
297
|
return assertExhaustive(decl);
|
|
227
298
|
}
|
|
228
299
|
};
|
|
229
|
-
export const validateTypeReferentialIntegrity = (helpers, checkReferentialIntegrity, inDecls, type, value) => {
|
|
300
|
+
export const validateTypeReferentialIntegrity = (helpers, checkEntityName, checkReferentialIntegrity, inDecls, type, value) => {
|
|
230
301
|
switch (type.kind) {
|
|
231
302
|
case NodeKind.ArrayType:
|
|
232
303
|
return Array.isArray(value)
|
|
233
|
-
? parallelizeErrors(value.map((item, index) => wrapErrorsIfAny(`at index ${key(index.toString(), helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, type.items, item))))
|
|
304
|
+
? parallelizeErrors(value.map((item, index) => wrapErrorsIfAny(`at index ${key(index.toString(), helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, type.items, item))))
|
|
234
305
|
: [];
|
|
235
306
|
case NodeKind.ObjectType: {
|
|
236
307
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -242,7 +313,7 @@ export const validateTypeReferentialIntegrity = (helpers, checkReferentialIntegr
|
|
|
242
313
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
243
314
|
const prop = type.properties[propName];
|
|
244
315
|
if (value[propName] !== undefined) {
|
|
245
|
-
return wrapErrorsIfAny(`at object key ${key(`"${propName}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, prop.type, value[propName]));
|
|
316
|
+
return wrapErrorsIfAny(`at object key ${key(`"${propName}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, prop.type, value[propName]));
|
|
246
317
|
}
|
|
247
318
|
return undefined;
|
|
248
319
|
}));
|
|
@@ -253,12 +324,12 @@ export const validateTypeReferentialIntegrity = (helpers, checkReferentialIntegr
|
|
|
253
324
|
case NodeKind.ReferenceIdentifierType:
|
|
254
325
|
return checkReferentialIntegrity(type.entity.name, value);
|
|
255
326
|
case NodeKind.IncludeIdentifierType:
|
|
256
|
-
return validateDeclReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, type.reference, type.args, value);
|
|
327
|
+
return validateDeclReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, type.reference, type.args, value);
|
|
257
328
|
case NodeKind.NestedEntityMapType: {
|
|
258
329
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
259
330
|
return [];
|
|
260
331
|
}
|
|
261
|
-
return parallelizeErrors(Object.keys(value).map(propName => wrapErrorsIfAny(`at nested entity map ${entity(`"${type.name}"`, helpers.useStyling)} at key ${key(`"${propName}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, type.type.value, value[propName]).concat(checkReferentialIntegrity(type.secondaryEntity.name, propName)))));
|
|
332
|
+
return parallelizeErrors(Object.keys(value).map(propName => wrapErrorsIfAny(`at nested entity map ${entity(`"${type.name}"`, helpers.useStyling)} at key ${key(`"${propName}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, type.type.value, value[propName]).concat(checkReferentialIntegrity(type.secondaryEntity.name, propName)))));
|
|
262
333
|
}
|
|
263
334
|
case NodeKind.EnumType: {
|
|
264
335
|
if (typeof value !== "object" ||
|
|
@@ -274,15 +345,16 @@ export const validateTypeReferentialIntegrity = (helpers, checkReferentialIntegr
|
|
|
274
345
|
type.values[enumCase].type !== null &&
|
|
275
346
|
enumCase in value
|
|
276
347
|
? parallelizeErrors([
|
|
277
|
-
wrapErrorsIfAny(`at enum case ${key(`"${enumCase}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkReferentialIntegrity, inDecls, type.values[enumCase].type, value[enumCase])),
|
|
348
|
+
wrapErrorsIfAny(`at enum case ${key(`"${enumCase}"`, helpers.useStyling)}`, validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, type.values[enumCase].type, value[enumCase])),
|
|
278
349
|
])
|
|
279
350
|
: [];
|
|
280
351
|
}
|
|
352
|
+
case NodeKind.StringType:
|
|
353
|
+
return validateMarkdownString(type, value, createReferentialAttributedStringValidator(checkEntityName, checkReferentialIntegrity, helpers.validationOptions));
|
|
281
354
|
case NodeKind.BooleanType:
|
|
282
355
|
case NodeKind.DateType:
|
|
283
356
|
case NodeKind.FloatType:
|
|
284
357
|
case NodeKind.IntegerType:
|
|
285
|
-
case NodeKind.StringType:
|
|
286
358
|
case NodeKind.ChildEntitiesType:
|
|
287
359
|
case NodeKind.TranslationObjectType:
|
|
288
360
|
return [];
|
|
@@ -35,7 +35,7 @@ export const createServer = (db, config) => {
|
|
|
35
35
|
defaultLocales,
|
|
36
36
|
locales: defaultLocales,
|
|
37
37
|
homeLayoutSections,
|
|
38
|
-
validationOptions: validationOptions ?? {},
|
|
38
|
+
validationOptions: { ...(validationOptions ?? {}), markdown: undefined },
|
|
39
39
|
};
|
|
40
40
|
app.use((req, _res, next) => {
|
|
41
41
|
debug("%s %s", req.method, req.originalUrl);
|
|
@@ -3,6 +3,7 @@ import type { FormatterOptions } from "../config.ts";
|
|
|
3
3
|
import { type EntityDecl } from "../schema/dsl/index.ts";
|
|
4
4
|
export declare const getFileNameForId: (id: string) => string;
|
|
5
5
|
export declare const getPathToInstance: (dataRoot: string, entityName: string, id: string) => string;
|
|
6
|
+
export declare const readInstance: (dataRoot: string, entity: EntityDecl, id: string) => Promise<string>;
|
|
6
7
|
export declare const writeInstance: (dataRoot: string, entity: EntityDecl, id: string, instance: InstanceContent, formatterOptions: Partial<FormatterOptions> | undefined) => Promise<void>;
|
|
7
8
|
export declare const deleteInstance: (dataRoot: string, entityName: string, id: string) => Promise<void>;
|
|
8
9
|
export declare const formatInstance: (entity: EntityDecl, instanceContent: InstanceContent, options: Partial<FormatterOptions> | undefined) => string;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { rm, writeFile } from "node:fs/promises";
|
|
1
|
+
import { readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import {} from "../schema/dsl/index.js";
|
|
4
4
|
import { formatValue } from "../schema/treeOperations/format.js";
|
|
5
5
|
export const getFileNameForId = (id) => `${id}.json`;
|
|
6
6
|
export const getPathToInstance = (dataRoot, entityName, id) => join(dataRoot, entityName, getFileNameForId(id));
|
|
7
|
+
export const readInstance = (dataRoot, entity, id) => readFile(getPathToInstance(dataRoot, entity.name, id), {
|
|
8
|
+
encoding: "utf-8",
|
|
9
|
+
});
|
|
7
10
|
export const writeInstance = (dataRoot, entity, id, instance, formatterOptions) => writeFile(getPathToInstance(dataRoot, entity.name, id), formatInstance(entity, instance, formatterOptions), {
|
|
8
11
|
encoding: "utf-8",
|
|
9
12
|
});
|
|
@@ -19,9 +19,9 @@ export const validateStringConstraints = (constraints, value) => parallelizeErro
|
|
|
19
19
|
? TypeError(`string does not match the pattern ${pattern.toString()}`)
|
|
20
20
|
: undefined;
|
|
21
21
|
})(),
|
|
22
|
-
(() => {
|
|
22
|
+
...(() => {
|
|
23
23
|
if (constraints.markdown === undefined) {
|
|
24
|
-
return
|
|
24
|
+
return [];
|
|
25
25
|
}
|
|
26
26
|
switch (constraints.markdown) {
|
|
27
27
|
case "inline":
|
package/dist/src/web/web.js
CHANGED
|
@@ -682,7 +682,7 @@ const request = async (method, url, options)=>{
|
|
|
682
682
|
if (!response.ok) throw new Error(await response.text());
|
|
683
683
|
return (options.getResult ?? ((response)=>{
|
|
684
684
|
if (response.headers.get("Content-Type")?.startsWith("application/json") === true) return response.json();
|
|
685
|
-
return Promise.resolve();
|
|
685
|
+
else return Promise.resolve();
|
|
686
686
|
}))(response);
|
|
687
687
|
};
|
|
688
688
|
const api_getResource = async (url, options)=>request("GET", url, options);
|
|
@@ -897,8 +897,7 @@ function signals_core_module_a(i) {
|
|
|
897
897
|
i.n = t;
|
|
898
898
|
if (32 & signals_core_module_o.f) i.S(t);
|
|
899
899
|
return t;
|
|
900
|
-
}
|
|
901
|
-
if (-1 === t.i) {
|
|
900
|
+
} else if (-1 === t.i) {
|
|
902
901
|
t.i = 0;
|
|
903
902
|
if (void 0 !== t.n) {
|
|
904
903
|
t.n.p = t.p;
|
|
@@ -2410,7 +2409,7 @@ const splitStringParts = (str)=>[
|
|
|
2410
2409
|
...acc.slice(0, -1),
|
|
2411
2410
|
lastPart + char
|
|
2412
2411
|
];
|
|
2413
|
-
return [
|
|
2412
|
+
else return [
|
|
2414
2413
|
...acc,
|
|
2415
2414
|
char
|
|
2416
2415
|
];
|
|
@@ -2420,7 +2419,7 @@ const splitStringParts = (str)=>[
|
|
|
2420
2419
|
lastPart + char
|
|
2421
2420
|
];
|
|
2422
2421
|
if ("" === lastPart) return acc;
|
|
2423
|
-
return [
|
|
2422
|
+
else return [
|
|
2424
2423
|
...acc,
|
|
2425
2424
|
""
|
|
2426
2425
|
];
|
|
@@ -2453,7 +2452,7 @@ const getSerializedDisplayNameFromEntityInstance = (entity, instance, defaultNam
|
|
|
2453
2452
|
name: getValueAtPath(instance, displayNamePath) ?? defaultName,
|
|
2454
2453
|
localeId: locales[0]
|
|
2455
2454
|
};
|
|
2456
|
-
{
|
|
2455
|
+
else {
|
|
2457
2456
|
const localeMapPath = displayNamePath.pathToLocaleMap ?? "translations";
|
|
2458
2457
|
const localeMap = getValueAtPath(instance, localeMapPath);
|
|
2459
2458
|
const pathInLocaleMap = displayNamePath.pathInLocaleMap ?? "name";
|
|
@@ -2467,6 +2466,7 @@ const getSerializedDisplayNameFromEntityInstance = (entity, instance, defaultNam
|
|
|
2467
2466
|
name: possibleName,
|
|
2468
2467
|
localeId: locale
|
|
2469
2468
|
};
|
|
2469
|
+
else return;
|
|
2470
2470
|
}, void 0) ?? {
|
|
2471
2471
|
name: getValueAtPath(localeMap[availableLocales[0]], pathInLocaleMap) ?? defaultName
|
|
2472
2472
|
};
|
|
@@ -3281,7 +3281,7 @@ const asText = (content)=>({
|
|
|
3281
3281
|
type: "text",
|
|
3282
3282
|
content
|
|
3283
3283
|
});
|
|
3284
|
-
const inline_text = (syntaxStartCharacters)=>anyStopOn(syntaxStartCharacters).then((result)=>
|
|
3284
|
+
const inline_text = (syntaxStartCharacters)=>anyStopOn(syntaxStartCharacters).then((result)=>StateTParser.getsT((state)=>state.keepSyntax || state.preserveEscapes).map((keepSyntax)=>asText(keepSyntax ? result : parseEscapedCharacters(result))));
|
|
3285
3285
|
const codeDelimiter = state_syntax(StateTParser.string("`"));
|
|
3286
3286
|
const codeText = anyStopOn([
|
|
3287
3287
|
"`"
|
|
@@ -3404,18 +3404,19 @@ const inlineNode = combineParsers([
|
|
|
3404
3404
|
leafParser(defaultInlineSyntaxStartSequences)
|
|
3405
3405
|
]);
|
|
3406
3406
|
const inlineMarkdown = inlineNode.many();
|
|
3407
|
-
const
|
|
3407
|
+
const inline_parseInlineMarkdown = (syntax, keepSyntax = false, preserveEscapes = false)=>{
|
|
3408
3408
|
const results = inlineMarkdown.evalT({
|
|
3409
3409
|
indentation: 0,
|
|
3410
|
-
keepSyntax
|
|
3410
|
+
keepSyntax,
|
|
3411
|
+
preserveEscapes
|
|
3411
3412
|
}).parse(syntax);
|
|
3412
3413
|
if (!isNotEmpty(results)) throw new Error("Failed to parse");
|
|
3413
3414
|
const [result, remaining] = results[0];
|
|
3414
3415
|
if (remaining.length > 0) throw new Error(`Failed to parse the entire string. Remaining: "${remaining}"`);
|
|
3415
3416
|
return result;
|
|
3416
3417
|
};
|
|
3417
|
-
const parseInlineMarkdown = (syntax)=>
|
|
3418
|
-
const parseInlineMarkdownForSyntaxHighlighting = (syntax)=>
|
|
3418
|
+
const parseInlineMarkdown = (syntax)=>inline_parseInlineMarkdown(syntax, false);
|
|
3419
|
+
const parseInlineMarkdownForSyntaxHighlighting = (syntax)=>inline_parseInlineMarkdown(syntax, true);
|
|
3419
3420
|
const isNullish = (value)=>null == value;
|
|
3420
3421
|
const isNotNullish = (value)=>!isNullish(value);
|
|
3421
3422
|
const sortObjectKeysByIndex = (obj, keys)=>Object.fromEntries([
|
|
@@ -3659,8 +3660,21 @@ const tableCaptionRowSyntax = sepByKeepFlat(StateTParser.string("|#").then((star
|
|
|
3659
3660
|
},
|
|
3660
3661
|
block_asText(endSpace + newline)
|
|
3661
3662
|
]))))))), block_indentation);
|
|
3662
|
-
const tableHeaderRow = tableRow(tableContentCellGuard.then(()=>inlineMarkdown)
|
|
3663
|
-
|
|
3663
|
+
const tableHeaderRow = tableRow(tableContentCellGuard.then(()=>inlineMarkdown).htoken().then((content)=>StateTParser.lookahead(StateTParser.string("||")).then(()=>StateTParser.string("|")).many().map((span)=>({
|
|
3664
|
+
content,
|
|
3665
|
+
span: span.length > 0 ? span.length + 1 : void 0
|
|
3666
|
+
}))), false);
|
|
3667
|
+
const tableHeaderRowSyntax = tableRowSyntax(tableContentCellGuard.then(()=>inlineMarkdown.then((content)=>anySpacesT.then((trailingSpace)=>StateTParser.lookahead(StateTParser.string("||")).then(()=>StateTParser.string("|")).many().map((span)=>[
|
|
3668
|
+
...content,
|
|
3669
|
+
block_asText(trailingSpace),
|
|
3670
|
+
...span.length > 0 ? [
|
|
3671
|
+
{
|
|
3672
|
+
type: "syntax",
|
|
3673
|
+
blockType: "table",
|
|
3674
|
+
content: "|".repeat(span.length)
|
|
3675
|
+
}
|
|
3676
|
+
] : []
|
|
3677
|
+
])))), false);
|
|
3664
3678
|
const tableSeparatorRow = tableRow(tableHeaderSeparatorCell.htoken());
|
|
3665
3679
|
const tableSeparatorRowSyntax = tableRowSyntax(tableHeaderSeparatorCell.then((separator)=>anySpacesT.map((trailingSpaces)=>[
|
|
3666
3680
|
{
|
|
@@ -3722,10 +3736,6 @@ const tableSectionPlainSeparatorRowSyntax = tableRowSyntax(tableSectionSeparator
|
|
|
3722
3736
|
])));
|
|
3723
3737
|
const tableBodyRow = tableSectionSubheaderWithSeparatorRow.orFirstW(tableSectionPlainSeparatorRow).orFirstW(tableNormalRow);
|
|
3724
3738
|
const tableBodyRowSyntax = tableSectionSubheaderWithSeparatorRowSyntax.orFirstW(tableSectionPlainSeparatorRowSyntax).orFirstW(tableNormalRowSyntax);
|
|
3725
|
-
const mapCell = (cell)=>({
|
|
3726
|
-
type: "tableCell",
|
|
3727
|
-
content: trimLastNodeEnd(cell)
|
|
3728
|
-
});
|
|
3729
3739
|
const mapCellObj = (cell)=>omitUndefinedKeys({
|
|
3730
3740
|
type: "tableCell",
|
|
3731
3741
|
content: trimLastNodeEnd(cell.content),
|
|
@@ -3750,7 +3760,7 @@ const sectionRows = (rows)=>{
|
|
|
3750
3760
|
}
|
|
3751
3761
|
return acc;
|
|
3752
3762
|
}, []);
|
|
3753
|
-
return rows.map((row)=>({
|
|
3763
|
+
else return rows.map((row)=>({
|
|
3754
3764
|
type: "tableRow",
|
|
3755
3765
|
cells: row.map(mapCellObj)
|
|
3756
3766
|
}));
|
|
@@ -3761,7 +3771,7 @@ const table = tableCaptionRow.then((caption)=>(0 === caption.length ? StateTPars
|
|
|
3761
3771
|
columns: separators.map((cell)=>omitUndefinedKeys({
|
|
3762
3772
|
alignment: getAlignmentFromSeparator(cell)
|
|
3763
3773
|
})),
|
|
3764
|
-
header: header.map(
|
|
3774
|
+
header: header.map(mapCellObj),
|
|
3765
3775
|
rows: sectionRows(rows)
|
|
3766
3776
|
}))))));
|
|
3767
3777
|
const tableSyntax = tableCaptionRowSyntax.then((caption)=>(0 === caption.length ? StateTParser.of([]) : block_indentation).then((indentBetweenCaptionAndHeader)=>tableHeaderRowSyntax.then((header)=>newlineT.then((headerNewline)=>tableSeparatorRowSyntax.then((separators)=>newlineT.then((separatorsNewline)=>sepBy1KeepFlat(tableBodyRowSyntax, newlineT.map(asSingleText)).map((rows)=>[
|
|
@@ -3789,10 +3799,11 @@ const finalBlockMarkdownSyntax = anyBlankLines.then((leadingsNewlines)=>blockMar
|
|
|
3789
3799
|
content: "\n"
|
|
3790
3800
|
} : node)
|
|
3791
3801
|
])));
|
|
3792
|
-
const
|
|
3802
|
+
const block_parseBlockMarkdown = (syntax, keepSyntax = false, preserveEscapes = false)=>{
|
|
3793
3803
|
const results = finalBlockMarkdown.evalT({
|
|
3794
3804
|
indentation: 0,
|
|
3795
|
-
keepSyntax
|
|
3805
|
+
keepSyntax,
|
|
3806
|
+
preserveEscapes
|
|
3796
3807
|
}).parse(syntax);
|
|
3797
3808
|
if (!isNotEmpty(results)) throw new Error("Failed to parse");
|
|
3798
3809
|
const [result = [], remaining] = results[0];
|
|
@@ -3810,10 +3821,12 @@ const parseBlockMarkdown = (syntax)=>{
|
|
|
3810
3821
|
];
|
|
3811
3822
|
return result;
|
|
3812
3823
|
};
|
|
3824
|
+
const parseBlockMarkdown = (syntax)=>block_parseBlockMarkdown(syntax);
|
|
3813
3825
|
const parseBlockMarkdownForSyntaxHighlighting = (syntax)=>{
|
|
3814
3826
|
const results = finalBlockMarkdownSyntax.evalT({
|
|
3815
3827
|
indentation: 0,
|
|
3816
|
-
keepSyntax: true
|
|
3828
|
+
keepSyntax: true,
|
|
3829
|
+
preserveEscapes: false
|
|
3817
3830
|
}).parse(syntax);
|
|
3818
3831
|
if (!isNotEmpty(results)) throw new Error("Failed to parse");
|
|
3819
3832
|
const [result, remaining] = results[0];
|
|
@@ -5440,6 +5453,17 @@ const ReferenceIdentifierTypeInput = ({ type, value, instanceNamesByEntity, disa
|
|
|
5440
5453
|
]
|
|
5441
5454
|
});
|
|
5442
5455
|
};
|
|
5456
|
+
const getBuilderForNode = (builder, node)=>builder[node.type];
|
|
5457
|
+
const renderInline = (node, builder, ...args)=>{
|
|
5458
|
+
const parseInner = (node, ...args)=>getBuilderForNode(builder, node)(node, parseInner, ...args);
|
|
5459
|
+
return parseInner(node, ...args);
|
|
5460
|
+
};
|
|
5461
|
+
const render = (node, builder, ...args)=>{
|
|
5462
|
+
const parseInnerInline = (node, ...args)=>getBuilderForNode(builder, node)(node, parseInnerInline, ...args);
|
|
5463
|
+
const parseInner = (node, ...args)=>getBuilderForNode(builder, node)(node, parseInner, parseInnerInline, ...args);
|
|
5464
|
+
return parseInner(node, ...args);
|
|
5465
|
+
};
|
|
5466
|
+
const passThroughInnerFlat = (node, validateInner, ...args)=>node.content.flatMap((content)=>validateInner(content, ...args));
|
|
5443
5467
|
class InternalMarkdownError extends Error {
|
|
5444
5468
|
constructor(message){
|
|
5445
5469
|
super(message);
|
|
@@ -5467,29 +5491,79 @@ const positionInStringToColumnAndRow = (position, string)=>{
|
|
|
5467
5491
|
column
|
|
5468
5492
|
};
|
|
5469
5493
|
};
|
|
5470
|
-
const
|
|
5494
|
+
const emptyErrors = ()=>[];
|
|
5495
|
+
const inlineValidationMap = {
|
|
5496
|
+
attributed: (node, validateInner, options)=>passThroughInnerFlat(node, validateInner, options).concat(options?.validateAttributes?.(node.attributes) ?? []),
|
|
5497
|
+
bold: passThroughInnerFlat,
|
|
5498
|
+
italic: passThroughInnerFlat,
|
|
5499
|
+
link: passThroughInnerFlat,
|
|
5500
|
+
superscript: passThroughInnerFlat,
|
|
5501
|
+
code: emptyErrors,
|
|
5502
|
+
footnoteRef: emptyErrors,
|
|
5503
|
+
text: emptyErrors
|
|
5504
|
+
};
|
|
5505
|
+
const collectInlineValidationErrors = (nodes, options)=>nodes.flatMap((node)=>renderInline(node, inlineValidationMap, options));
|
|
5506
|
+
const blockValidationMap = {
|
|
5507
|
+
container: (node, validateInner, _validateInnerInline, options)=>node.content.flatMap((content)=>validateInner(content, options)),
|
|
5508
|
+
definitionList: (node, validateInner, validateInnerInline, options)=>node.content.flatMap((itemGroup)=>[
|
|
5509
|
+
...itemGroup.terms.flatMap((term)=>term.flatMap((content)=>validateInnerInline(content, options))),
|
|
5510
|
+
...itemGroup.descriptions.flatMap((description)=>description.flatMap((content)=>validateInner(content, options)))
|
|
5511
|
+
]),
|
|
5512
|
+
footnote: (node, validateInner, _validateInnerInline, options)=>node.content.flatMap((content)=>validateInner(content, options)),
|
|
5513
|
+
heading: (node, _validateInner, validateInnerInline, options)=>node.content.flatMap((content)=>validateInnerInline(content, options)),
|
|
5514
|
+
list: (node, validateInner, _validateInnerInline, options)=>node.content.flatMap((item)=>item.content.flatMap((content)=>validateInner(content, options))),
|
|
5515
|
+
paragraph: (node, _validateInner, validateInnerInline, options)=>node.content.flatMap((content)=>"break" === content.type ? [] : validateInnerInline(content, options)),
|
|
5516
|
+
table: (node, _validateInner, validateInnerInline, options)=>[
|
|
5517
|
+
...node.caption?.flatMap((captionLine)=>captionLine.flatMap((content)=>validateInnerInline(content, options))) ?? [],
|
|
5518
|
+
...node.header.flatMap((cell)=>cell.content.flatMap((content)=>validateInnerInline(content, options))),
|
|
5519
|
+
...checkTableRowsAreSections(node.rows) ? node.rows.flatMap((section)=>[
|
|
5520
|
+
...section.header?.flatMap((cell)=>cell.content.flatMap((content)=>validateInnerInline(content, options))) ?? [],
|
|
5521
|
+
...section.rows.flatMap((row)=>row.cells.flatMap((cell)=>cell.content.flatMap((content)=>validateInnerInline(content, options))))
|
|
5522
|
+
]) : node.rows.flatMap((row)=>row.cells.flatMap((cell)=>cell.content.flatMap((content)=>validateInnerInline(content, options))))
|
|
5523
|
+
]
|
|
5524
|
+
};
|
|
5525
|
+
const validationMap = {
|
|
5526
|
+
...inlineValidationMap,
|
|
5527
|
+
...blockValidationMap
|
|
5528
|
+
};
|
|
5529
|
+
const collectBlockValidationErrors = (nodes, options)=>nodes.flatMap((node)=>render(node, validationMap, options));
|
|
5530
|
+
const validateInline = (markdown, options)=>{
|
|
5471
5531
|
const results = inlineMarkdown.evalT({
|
|
5472
5532
|
indentation: 0,
|
|
5473
|
-
keepSyntax: false
|
|
5533
|
+
keepSyntax: false,
|
|
5534
|
+
preserveEscapes: false
|
|
5474
5535
|
}).parse(markdown);
|
|
5475
|
-
if (!isNotEmpty(results)) return
|
|
5476
|
-
|
|
5536
|
+
if (!isNotEmpty(results)) return [
|
|
5537
|
+
new InternalMarkdownError("Failed to parse inline Markdown")
|
|
5538
|
+
];
|
|
5539
|
+
const [nodes, remaining] = results[0];
|
|
5477
5540
|
if (remaining.length > 0) {
|
|
5478
5541
|
const { row, column } = positionInStringToColumnAndRow(markdown.length - remaining.length, markdown);
|
|
5479
|
-
return
|
|
5542
|
+
return [
|
|
5543
|
+
new MarkdownSyntaxError(row, column, remaining)
|
|
5544
|
+
];
|
|
5480
5545
|
}
|
|
5546
|
+
if (options?.validateAttributes !== void 0) return collectInlineValidationErrors(nodes, options);
|
|
5547
|
+
return [];
|
|
5481
5548
|
};
|
|
5482
|
-
const validate = (markdown)=>{
|
|
5549
|
+
const validate = (markdown, options)=>{
|
|
5483
5550
|
const results = finalBlockMarkdown.evalT({
|
|
5484
5551
|
indentation: 0,
|
|
5485
|
-
keepSyntax: false
|
|
5552
|
+
keepSyntax: false,
|
|
5553
|
+
preserveEscapes: false
|
|
5486
5554
|
}).parse(markdown);
|
|
5487
|
-
if (!isNotEmpty(results)
|
|
5488
|
-
|
|
5555
|
+
if (!isNotEmpty(results) || void 0 === results[0][0] && markdown.length > 0) return [
|
|
5556
|
+
new InternalMarkdownError("Failed to parse Markdown")
|
|
5557
|
+
];
|
|
5558
|
+
const [nodes = [], remaining] = results[0];
|
|
5489
5559
|
if (remaining.length > 0) {
|
|
5490
5560
|
const { row, column } = positionInStringToColumnAndRow(markdown.length - remaining.length, markdown);
|
|
5491
|
-
return
|
|
5561
|
+
return [
|
|
5562
|
+
new MarkdownSyntaxError(row, column, remaining)
|
|
5563
|
+
];
|
|
5492
5564
|
}
|
|
5565
|
+
if (options?.validateAttributes !== void 0) return collectBlockValidationErrors(nodes, options);
|
|
5566
|
+
return [];
|
|
5493
5567
|
};
|
|
5494
5568
|
const validateStringConstraints = (constraints, value)=>parallelizeErrors([
|
|
5495
5569
|
void 0 !== constraints.minLength && value.length < constraints.minLength ? RangeError(`expected a string with at least ${constraints.minLength.toString()} character${1 === constraints.minLength ? "" : "s"}, but got ${value.length.toString()} character${1 === value.length ? "" : "s"}`) : void 0,
|
|
@@ -5499,8 +5573,8 @@ const validateStringConstraints = (constraints, value)=>parallelizeErrors([
|
|
|
5499
5573
|
const pattern = "string" == typeof constraints.pattern ? new RegExp(constraints.pattern) : constraints.pattern;
|
|
5500
5574
|
return pattern.test(value) ? void 0 : TypeError(`string does not match the pattern ${pattern.toString()}`);
|
|
5501
5575
|
})(),
|
|
5502
|
-
(()=>{
|
|
5503
|
-
if (void 0 === constraints.markdown) return;
|
|
5576
|
+
...(()=>{
|
|
5577
|
+
if (void 0 === constraints.markdown) return [];
|
|
5504
5578
|
switch(constraints.markdown){
|
|
5505
5579
|
case "inline":
|
|
5506
5580
|
return validateInline(value);
|
|
@@ -5515,7 +5589,7 @@ const BlockMarkdownHighlighting = ({ node })=>{
|
|
|
5515
5589
|
if ("syntax" !== node.type) return /*#__PURE__*/ jsxRuntime_module_u(InlineMarkdown, {
|
|
5516
5590
|
node: node
|
|
5517
5591
|
});
|
|
5518
|
-
switch(node.blockType){
|
|
5592
|
+
else switch(node.blockType){
|
|
5519
5593
|
case "heading":
|
|
5520
5594
|
return /*#__PURE__*/ jsxRuntime_module_u("span", {
|
|
5521
5595
|
class: "heading-marker",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsondb",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "Lukas Obermann",
|
|
@@ -37,23 +37,23 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@eslint/js": "^9.39.2",
|
|
39
39
|
"@rsbuild/plugin-preact": "^2.1.0",
|
|
40
|
-
"@rslib/core": "^1.0.
|
|
40
|
+
"@rslib/core": "^1.0.1",
|
|
41
41
|
"@types/debug": "^4.1.13",
|
|
42
42
|
"@types/express": "^5.0.6",
|
|
43
|
-
"@types/node": "^
|
|
43
|
+
"@types/node": "^26.6.2",
|
|
44
44
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
45
|
-
"commit-and-tag-version": "^13.2.
|
|
45
|
+
"commit-and-tag-version": "^13.2.1",
|
|
46
46
|
"eslint": "^9.39.4",
|
|
47
47
|
"eslint-plugin-react": "^7.37.5",
|
|
48
48
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
49
49
|
"globals": "^17.12.0",
|
|
50
|
-
"prettier": "^3.9.
|
|
51
|
-
"tsx": "^4.23.
|
|
50
|
+
"prettier": "^3.9.8",
|
|
51
|
+
"tsx": "^4.23.15",
|
|
52
52
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
53
|
-
"typescript-eslint": "^8.70.
|
|
53
|
+
"typescript-eslint": "^8.70.1"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@elyukai/markdown": "^0.
|
|
56
|
+
"@elyukai/markdown": "^0.4.0",
|
|
57
57
|
"@elyukai/utils": "^0.3.6",
|
|
58
58
|
"@preact/signals": "^2.11.2",
|
|
59
59
|
"debug": "^4.4.3",
|