@mathscan/math-exercise-engine 1.0.5 → 1.0.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/dist/index.d.ts +2860 -999
- package/dist/index.js +362 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +362 -29
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +34 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29,6 +29,12 @@ const AST_TYPES = {
|
|
|
29
29
|
TEXT_BLOCK: "TextBlock",
|
|
30
30
|
/** Line containing inline elements */
|
|
31
31
|
LINE_BLOCK: "LineBlock",
|
|
32
|
+
/** Table layout block */
|
|
33
|
+
TABLE_BLOCK: "TableBlock",
|
|
34
|
+
/** Row within a table */
|
|
35
|
+
TABLE_ROW: "TableRow",
|
|
36
|
+
/** Cell within a table row */
|
|
37
|
+
TABLE_CELL: "TableCell",
|
|
32
38
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
33
39
|
// Tools
|
|
34
40
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -73,6 +79,12 @@ const JSON_TYPES = {
|
|
|
73
79
|
GROUP: "group",
|
|
74
80
|
/** Operator symbol */
|
|
75
81
|
OPERATOR: "operator",
|
|
82
|
+
/** Table layout block */
|
|
83
|
+
TABLE: "table",
|
|
84
|
+
/** Row within a table */
|
|
85
|
+
TABLE_ROW: "table-row",
|
|
86
|
+
/** Cell within a table */
|
|
87
|
+
TABLE_CELL: "table-cell",
|
|
76
88
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
77
89
|
// Widget Types
|
|
78
90
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -164,6 +176,18 @@ const NUMERIC_INPUT = chevrotain.createToken({
|
|
|
164
176
|
name: "NUMERIC_INPUT",
|
|
165
177
|
pattern: /NUMERIC_INPUT/
|
|
166
178
|
});
|
|
179
|
+
const TABLE = chevrotain.createToken({
|
|
180
|
+
name: "TABLE",
|
|
181
|
+
pattern: /TABLE/
|
|
182
|
+
});
|
|
183
|
+
const ROW = chevrotain.createToken({
|
|
184
|
+
name: "ROW",
|
|
185
|
+
pattern: /ROW/
|
|
186
|
+
});
|
|
187
|
+
const CELL = chevrotain.createToken({
|
|
188
|
+
name: "CELL",
|
|
189
|
+
pattern: /CELL/
|
|
190
|
+
});
|
|
167
191
|
const NumberLiteral = chevrotain.createToken({
|
|
168
192
|
name: "NumberLiteral",
|
|
169
193
|
pattern: /-?\d+(\.\d+)?/
|
|
@@ -231,9 +255,17 @@ const Comma = chevrotain.createToken({
|
|
|
231
255
|
name: "Comma",
|
|
232
256
|
pattern: /,/
|
|
233
257
|
});
|
|
258
|
+
const LBrace = chevrotain.createToken({
|
|
259
|
+
name: "LBrace",
|
|
260
|
+
pattern: /\{/
|
|
261
|
+
});
|
|
262
|
+
const RBrace = chevrotain.createToken({
|
|
263
|
+
name: "RBrace",
|
|
264
|
+
pattern: /\}/
|
|
265
|
+
});
|
|
234
266
|
const FreeText = chevrotain.createToken({
|
|
235
267
|
name: "FreeText",
|
|
236
|
-
pattern: /(?:[^A-Z\n\r \t+\-−×*÷/=<>?()\[\],]|(?![A-Z_]
|
|
268
|
+
pattern: /(?:[^A-Z\n\r \t+\-−×*÷/=<>?()\[\],{}]|(?![A-Z_]+[\[{])[A-Z])+/,
|
|
237
269
|
line_breaks: false
|
|
238
270
|
});
|
|
239
271
|
const allTokens = [
|
|
@@ -257,6 +289,9 @@ const allTokens = [
|
|
|
257
289
|
WIDGET_ANSWER,
|
|
258
290
|
W_N_I,
|
|
259
291
|
NUMERIC_INPUT,
|
|
292
|
+
TABLE,
|
|
293
|
+
ROW,
|
|
294
|
+
CELL,
|
|
260
295
|
// Literals
|
|
261
296
|
NumberLiteral,
|
|
262
297
|
StringLiteral,
|
|
@@ -277,6 +312,8 @@ const allTokens = [
|
|
|
277
312
|
LBracket,
|
|
278
313
|
RBracket,
|
|
279
314
|
Comma,
|
|
315
|
+
LBrace,
|
|
316
|
+
RBrace,
|
|
280
317
|
// FreeText - LAST (fallback for natural text)
|
|
281
318
|
FreeText
|
|
282
319
|
];
|
|
@@ -371,7 +408,7 @@ class MathExerciseParser extends chevrotain.CstParser {
|
|
|
371
408
|
this.SUBRULE(this.question);
|
|
372
409
|
});
|
|
373
410
|
this.MANY2(() => {
|
|
374
|
-
this.SUBRULE(this.
|
|
411
|
+
this.SUBRULE(this.contentBlock);
|
|
375
412
|
});
|
|
376
413
|
this.MANY3(() => {
|
|
377
414
|
this.SUBRULE(this.tool);
|
|
@@ -396,6 +433,116 @@ class MathExerciseParser extends chevrotain.CstParser {
|
|
|
396
433
|
]);
|
|
397
434
|
});
|
|
398
435
|
});
|
|
436
|
+
this.contentBlock = this.RULE("contentBlock", () => {
|
|
437
|
+
this.OR([
|
|
438
|
+
{
|
|
439
|
+
GATE: this.BACKTRACK(this.table),
|
|
440
|
+
ALT: () => this.SUBRULE(this.table)
|
|
441
|
+
},
|
|
442
|
+
{ ALT: () => this.SUBRULE(this.line) }
|
|
443
|
+
]);
|
|
444
|
+
});
|
|
445
|
+
this.table = this.RULE("table", () => {
|
|
446
|
+
this.MANY(() => {
|
|
447
|
+
this.OR2([
|
|
448
|
+
{ ALT: () => this.CONSUME(Space) },
|
|
449
|
+
{ ALT: () => this.CONSUME(Newline) }
|
|
450
|
+
]);
|
|
451
|
+
});
|
|
452
|
+
this.CONSUME(TABLE);
|
|
453
|
+
this.CONSUME(LBracket);
|
|
454
|
+
this.SUBRULE(this.parameterList);
|
|
455
|
+
this.CONSUME(RBracket);
|
|
456
|
+
this.MANY2(() => {
|
|
457
|
+
this.OR3([
|
|
458
|
+
{ ALT: () => this.CONSUME2(Space) },
|
|
459
|
+
{ ALT: () => this.CONSUME2(Newline) }
|
|
460
|
+
]);
|
|
461
|
+
});
|
|
462
|
+
this.CONSUME(LBrace);
|
|
463
|
+
this.MANY3(() => {
|
|
464
|
+
this.OR4([
|
|
465
|
+
{ ALT: () => this.CONSUME3(Space) },
|
|
466
|
+
{ ALT: () => this.CONSUME3(Newline) }
|
|
467
|
+
]);
|
|
468
|
+
});
|
|
469
|
+
this.AT_LEAST_ONE(() => {
|
|
470
|
+
this.SUBRULE(this.row);
|
|
471
|
+
});
|
|
472
|
+
this.CONSUME(RBrace);
|
|
473
|
+
this.MANY4(() => {
|
|
474
|
+
this.OR5([
|
|
475
|
+
{ ALT: () => this.CONSUME4(Newline) },
|
|
476
|
+
{ ALT: () => this.CONSUME4(Space) }
|
|
477
|
+
]);
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
this.row = this.RULE("row", () => {
|
|
481
|
+
this.MANY(() => {
|
|
482
|
+
this.OR([
|
|
483
|
+
{ ALT: () => this.CONSUME(Space) },
|
|
484
|
+
{ ALT: () => this.CONSUME(Newline) }
|
|
485
|
+
]);
|
|
486
|
+
});
|
|
487
|
+
this.CONSUME(ROW);
|
|
488
|
+
this.MANY2(() => {
|
|
489
|
+
this.OR2([
|
|
490
|
+
{ ALT: () => this.CONSUME2(Space) },
|
|
491
|
+
{ ALT: () => this.CONSUME2(Newline) }
|
|
492
|
+
]);
|
|
493
|
+
});
|
|
494
|
+
this.CONSUME(LBrace);
|
|
495
|
+
this.MANY3(() => {
|
|
496
|
+
this.OR3([
|
|
497
|
+
{ ALT: () => this.CONSUME3(Space) },
|
|
498
|
+
{ ALT: () => this.CONSUME3(Newline) }
|
|
499
|
+
]);
|
|
500
|
+
});
|
|
501
|
+
this.AT_LEAST_ONE(() => {
|
|
502
|
+
this.SUBRULE(this.cell);
|
|
503
|
+
});
|
|
504
|
+
this.CONSUME(RBrace);
|
|
505
|
+
this.MANY4(() => {
|
|
506
|
+
this.OR4([
|
|
507
|
+
{ ALT: () => this.CONSUME4(Space) },
|
|
508
|
+
{ ALT: () => this.CONSUME4(Newline) }
|
|
509
|
+
]);
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
this.cell = this.RULE("cell", () => {
|
|
513
|
+
this.MANY(() => {
|
|
514
|
+
this.OR([
|
|
515
|
+
{ ALT: () => this.CONSUME(Space) },
|
|
516
|
+
{ ALT: () => this.CONSUME(Newline) }
|
|
517
|
+
]);
|
|
518
|
+
});
|
|
519
|
+
this.CONSUME(CELL);
|
|
520
|
+
this.OPTION(() => {
|
|
521
|
+
this.CONSUME(LBracket);
|
|
522
|
+
this.SUBRULE(this.parameterList);
|
|
523
|
+
this.CONSUME(RBracket);
|
|
524
|
+
});
|
|
525
|
+
this.MANY2(() => {
|
|
526
|
+
this.OR2([
|
|
527
|
+
{ ALT: () => this.CONSUME2(Space) },
|
|
528
|
+
{ ALT: () => this.CONSUME2(Newline) }
|
|
529
|
+
]);
|
|
530
|
+
});
|
|
531
|
+
this.CONSUME(LBrace);
|
|
532
|
+
this.MANY3(() => {
|
|
533
|
+
this.OR3([
|
|
534
|
+
{ ALT: () => this.SUBRULE(this.inlineElement) },
|
|
535
|
+
{ ALT: () => this.CONSUME3(Newline) }
|
|
536
|
+
]);
|
|
537
|
+
});
|
|
538
|
+
this.CONSUME(RBrace);
|
|
539
|
+
this.MANY4(() => {
|
|
540
|
+
this.OR4([
|
|
541
|
+
{ ALT: () => this.CONSUME4(Space) },
|
|
542
|
+
{ ALT: () => this.CONSUME4(Newline) }
|
|
543
|
+
]);
|
|
544
|
+
});
|
|
545
|
+
});
|
|
399
546
|
this.line = this.RULE("line", () => {
|
|
400
547
|
this.MANY(() => {
|
|
401
548
|
this.CONSUME(Space);
|
|
@@ -733,6 +880,40 @@ function isTextBlock(value) {
|
|
|
733
880
|
function isLineBlock(value) {
|
|
734
881
|
return LineBlockSchema.safeParse(value).success;
|
|
735
882
|
}
|
|
883
|
+
const TableCellSchema = zod.z.object({
|
|
884
|
+
type: zod.z.literal(AST_TYPES.TABLE_CELL),
|
|
885
|
+
colspan: zod.z.number().int().positive().optional(),
|
|
886
|
+
inlines: zod.z.array(InlineNodeSchema)
|
|
887
|
+
});
|
|
888
|
+
function createTableCell(inlines, colspan) {
|
|
889
|
+
return TableCellSchema.parse({
|
|
890
|
+
type: AST_TYPES.TABLE_CELL,
|
|
891
|
+
colspan,
|
|
892
|
+
inlines
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
const TableRowSchema = zod.z.object({
|
|
896
|
+
type: zod.z.literal(AST_TYPES.TABLE_ROW),
|
|
897
|
+
cells: zod.z.array(TableCellSchema).min(1)
|
|
898
|
+
});
|
|
899
|
+
function createTableRow(cells) {
|
|
900
|
+
return TableRowSchema.parse({
|
|
901
|
+
type: AST_TYPES.TABLE_ROW,
|
|
902
|
+
cells
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
const TableBlockSchema = zod.z.object({
|
|
906
|
+
type: zod.z.literal(AST_TYPES.TABLE_BLOCK),
|
|
907
|
+
cols: zod.z.number().int().positive(),
|
|
908
|
+
rows: zod.z.array(TableRowSchema).min(1)
|
|
909
|
+
});
|
|
910
|
+
function createTableBlock(cols, rows) {
|
|
911
|
+
return TableBlockSchema.parse({
|
|
912
|
+
type: AST_TYPES.TABLE_BLOCK,
|
|
913
|
+
cols,
|
|
914
|
+
rows
|
|
915
|
+
});
|
|
916
|
+
}
|
|
736
917
|
const DragOptionsToolSchema = zod.z.object({
|
|
737
918
|
type: zod.z.literal(AST_TYPES.DRAG_OPTIONS),
|
|
738
919
|
options: zod.z.array(zod.z.string()).min(1)
|
|
@@ -799,10 +980,11 @@ function isExpressionValidation(value) {
|
|
|
799
980
|
function isValidationNode(value) {
|
|
800
981
|
return ValidationNodeSchema.safeParse(value).success;
|
|
801
982
|
}
|
|
983
|
+
const ContentBlockSchema = zod.z.union([LineBlockSchema, TableBlockSchema]);
|
|
802
984
|
const ExerciseDocumentSchema = zod.z.object({
|
|
803
985
|
type: zod.z.literal(AST_TYPES.EXERCISE_DOCUMENT),
|
|
804
986
|
question: TextBlockSchema.optional(),
|
|
805
|
-
lines: zod.z.array(
|
|
987
|
+
lines: zod.z.array(ContentBlockSchema),
|
|
806
988
|
tools: zod.z.array(ToolNodeSchema).optional(),
|
|
807
989
|
validation: ValidationNodeSchema
|
|
808
990
|
});
|
|
@@ -829,10 +1011,10 @@ class NaturalDSLVisitor extends BaseCstVisitor {
|
|
|
829
1011
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
830
1012
|
exerciseDocument(ctx) {
|
|
831
1013
|
const question = ctx.question ? this.visit(ctx.question) : void 0;
|
|
832
|
-
const
|
|
1014
|
+
const contentBlocks = ctx.contentBlock ? ctx.contentBlock.map((cb) => this.visit(cb)) : [];
|
|
833
1015
|
const tools = ctx.tool ? ctx.tool.map((t) => this.visit(t)) : [];
|
|
834
1016
|
const validation = this.visit(ctx.validation);
|
|
835
|
-
return createExerciseDocument(question,
|
|
1017
|
+
return createExerciseDocument(question, contentBlocks, validation, tools);
|
|
836
1018
|
}
|
|
837
1019
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
838
1020
|
// Question Block
|
|
@@ -843,6 +1025,33 @@ class NaturalDSLVisitor extends BaseCstVisitor {
|
|
|
843
1025
|
return createTextBlock(value);
|
|
844
1026
|
}
|
|
845
1027
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1028
|
+
// Content Block
|
|
1029
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1030
|
+
contentBlock(ctx) {
|
|
1031
|
+
if (ctx.table) return this.visit(ctx.table);
|
|
1032
|
+
if (ctx.line) return this.visit(ctx.line);
|
|
1033
|
+
throw new Error("Unknown content block");
|
|
1034
|
+
}
|
|
1035
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1036
|
+
// Table Block
|
|
1037
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1038
|
+
table(ctx) {
|
|
1039
|
+
const params = this.visit(ctx.parameterList);
|
|
1040
|
+
const cols = params.cols;
|
|
1041
|
+
const rows = ctx.row.map((r) => this.visit(r));
|
|
1042
|
+
return createTableBlock(cols, rows);
|
|
1043
|
+
}
|
|
1044
|
+
row(ctx) {
|
|
1045
|
+
const cells = ctx.cell.map((c) => this.visit(c));
|
|
1046
|
+
return createTableRow(cells);
|
|
1047
|
+
}
|
|
1048
|
+
cell(ctx) {
|
|
1049
|
+
const params = ctx.parameterList ? this.visit(ctx.parameterList) : {};
|
|
1050
|
+
const colspan = params.colspan;
|
|
1051
|
+
const inlines = ctx.inlineElement ? ctx.inlineElement.map((elem) => this.visit(elem)) : [];
|
|
1052
|
+
return createTableCell(inlines, colspan);
|
|
1053
|
+
}
|
|
1054
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
846
1055
|
// Line Block
|
|
847
1056
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
848
1057
|
line(ctx) {
|
|
@@ -1114,6 +1323,10 @@ const BoldTextSchema = zod.z.object({
|
|
|
1114
1323
|
value: zod.z.string(),
|
|
1115
1324
|
highlight: zod.z.tuple([zod.z.number(), zod.z.number()]).optional()
|
|
1116
1325
|
});
|
|
1326
|
+
const SpaceItemSchema = zod.z.object({
|
|
1327
|
+
id: zod.z.string(),
|
|
1328
|
+
type: zod.z.literal(JSON_TYPES.SPACE)
|
|
1329
|
+
});
|
|
1117
1330
|
const LinebreakSchema = zod.z.object({
|
|
1118
1331
|
id: zod.z.string(),
|
|
1119
1332
|
type: zod.z.literal(JSON_TYPES.LINEBREAK)
|
|
@@ -1132,9 +1345,11 @@ const LayoutItemSchema = zod.z.lazy(
|
|
|
1132
1345
|
HighlightedTextSchema,
|
|
1133
1346
|
ColorTextSchema,
|
|
1134
1347
|
BoldTextSchema,
|
|
1348
|
+
SpaceItemSchema,
|
|
1135
1349
|
LinebreakSchema,
|
|
1136
1350
|
GroupItemSchema,
|
|
1137
|
-
OperatorItemSchema
|
|
1351
|
+
OperatorItemSchema,
|
|
1352
|
+
TableItemSchema
|
|
1138
1353
|
])
|
|
1139
1354
|
);
|
|
1140
1355
|
const GroupItemSchema = zod.z.object({
|
|
@@ -1142,6 +1357,23 @@ const GroupItemSchema = zod.z.object({
|
|
|
1142
1357
|
type: zod.z.literal(JSON_TYPES.GROUP),
|
|
1143
1358
|
items: zod.z.array(LayoutItemSchema)
|
|
1144
1359
|
});
|
|
1360
|
+
const TableCellItemSchema = zod.z.object({
|
|
1361
|
+
id: zod.z.string(),
|
|
1362
|
+
type: zod.z.literal(JSON_TYPES.TABLE_CELL),
|
|
1363
|
+
colspan: zod.z.number().int().positive().optional(),
|
|
1364
|
+
items: zod.z.array(LayoutItemSchema)
|
|
1365
|
+
});
|
|
1366
|
+
const TableRowItemSchema = zod.z.object({
|
|
1367
|
+
id: zod.z.string(),
|
|
1368
|
+
type: zod.z.literal(JSON_TYPES.TABLE_ROW),
|
|
1369
|
+
cells: zod.z.array(TableCellItemSchema)
|
|
1370
|
+
});
|
|
1371
|
+
const TableItemSchema = zod.z.object({
|
|
1372
|
+
id: zod.z.string(),
|
|
1373
|
+
type: zod.z.literal(JSON_TYPES.TABLE),
|
|
1374
|
+
cols: zod.z.number().int().positive(),
|
|
1375
|
+
rows: zod.z.array(TableRowItemSchema)
|
|
1376
|
+
});
|
|
1145
1377
|
const StringInputJSONSchema = zod.z.object({
|
|
1146
1378
|
type: zod.z.literal(JSON_TYPES.INLINE_INPUT),
|
|
1147
1379
|
inputType: zod.z.literal(INPUT_TYPES.STRING),
|
|
@@ -1220,6 +1452,9 @@ function isColorText(item) {
|
|
|
1220
1452
|
function isBoldText(item) {
|
|
1221
1453
|
return item.type === JSON_TYPES.BOLD_TEXT;
|
|
1222
1454
|
}
|
|
1455
|
+
function isSpaceItem(item) {
|
|
1456
|
+
return item.type === JSON_TYPES.SPACE;
|
|
1457
|
+
}
|
|
1223
1458
|
function isLinebreak(item) {
|
|
1224
1459
|
return item.type === JSON_TYPES.LINEBREAK;
|
|
1225
1460
|
}
|
|
@@ -1229,6 +1464,15 @@ function isGroupItem(item) {
|
|
|
1229
1464
|
function isOperatorItem(item) {
|
|
1230
1465
|
return item.type === JSON_TYPES.OPERATOR;
|
|
1231
1466
|
}
|
|
1467
|
+
function isTableItem(item) {
|
|
1468
|
+
return item.type === JSON_TYPES.TABLE;
|
|
1469
|
+
}
|
|
1470
|
+
function isTableRowItem(item) {
|
|
1471
|
+
return item.type === JSON_TYPES.TABLE_ROW;
|
|
1472
|
+
}
|
|
1473
|
+
function isTableCellItem(item) {
|
|
1474
|
+
return item.type === JSON_TYPES.TABLE_CELL;
|
|
1475
|
+
}
|
|
1232
1476
|
function isInlineInputJSON(widget) {
|
|
1233
1477
|
return widget.type === JSON_TYPES.INLINE_INPUT;
|
|
1234
1478
|
}
|
|
@@ -1259,31 +1503,34 @@ function toJSON(ast) {
|
|
|
1259
1503
|
value: ast.question.value
|
|
1260
1504
|
});
|
|
1261
1505
|
}
|
|
1262
|
-
for (const
|
|
1263
|
-
|
|
1264
|
-
|
|
1506
|
+
for (const block of ast.lines) {
|
|
1507
|
+
if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
1508
|
+
layout.push(transformTable(block, idGenerator));
|
|
1509
|
+
} else {
|
|
1510
|
+
const lineItems = transformLine(block, idGenerator);
|
|
1511
|
+
layout.push(...lineItems);
|
|
1512
|
+
}
|
|
1265
1513
|
}
|
|
1266
1514
|
const widgets = {};
|
|
1267
1515
|
const answers = {};
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
}
|
|
1516
|
+
const allInlines = collectAllInlines(ast.lines);
|
|
1517
|
+
for (const inline of allInlines) {
|
|
1518
|
+
if (inline.type === AST_TYPES.INLINE_INPUT) {
|
|
1519
|
+
if (inline.inputType === INPUT_TYPES.STRING) {
|
|
1520
|
+
widgets[inline.name] = {
|
|
1521
|
+
type: JSON_TYPES.INLINE_INPUT,
|
|
1522
|
+
inputType: INPUT_TYPES.STRING,
|
|
1523
|
+
length: inline.length
|
|
1524
|
+
};
|
|
1525
|
+
} else {
|
|
1526
|
+
widgets[inline.name] = {
|
|
1527
|
+
type: JSON_TYPES.INLINE_INPUT,
|
|
1528
|
+
inputType: INPUT_TYPES.NUMERIC,
|
|
1529
|
+
digits: inline.digits
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
if (inline.answer !== void 0) {
|
|
1533
|
+
answers[inline.name] = inline.answer;
|
|
1287
1534
|
}
|
|
1288
1535
|
}
|
|
1289
1536
|
}
|
|
@@ -1312,6 +1559,48 @@ function toJSON(ast) {
|
|
|
1312
1559
|
validation
|
|
1313
1560
|
};
|
|
1314
1561
|
}
|
|
1562
|
+
function collectAllInlines(blocks) {
|
|
1563
|
+
const result = [];
|
|
1564
|
+
for (const block of blocks) {
|
|
1565
|
+
if (block.type === AST_TYPES.LINE_BLOCK) {
|
|
1566
|
+
result.push(...block.inlines);
|
|
1567
|
+
} else if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
1568
|
+
for (const row of block.rows) {
|
|
1569
|
+
for (const cell of row.cells) {
|
|
1570
|
+
result.push(...cell.inlines);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return result;
|
|
1576
|
+
}
|
|
1577
|
+
function transformTable(table, idGenerator) {
|
|
1578
|
+
const rows = table.rows.map((row) => {
|
|
1579
|
+
const cells = row.cells.map((cell) => {
|
|
1580
|
+
const items = cell.inlines.map((inline) => transformInline(inline, idGenerator));
|
|
1581
|
+
const cellItem = {
|
|
1582
|
+
id: idGenerator.generate(JSON_TYPES.TABLE_CELL),
|
|
1583
|
+
type: JSON_TYPES.TABLE_CELL,
|
|
1584
|
+
items
|
|
1585
|
+
};
|
|
1586
|
+
if (cell.colspan !== void 0) {
|
|
1587
|
+
cellItem.colspan = cell.colspan;
|
|
1588
|
+
}
|
|
1589
|
+
return cellItem;
|
|
1590
|
+
});
|
|
1591
|
+
return {
|
|
1592
|
+
id: idGenerator.generate(JSON_TYPES.TABLE_ROW),
|
|
1593
|
+
type: JSON_TYPES.TABLE_ROW,
|
|
1594
|
+
cells
|
|
1595
|
+
};
|
|
1596
|
+
});
|
|
1597
|
+
return {
|
|
1598
|
+
id: idGenerator.generate(JSON_TYPES.TABLE),
|
|
1599
|
+
type: JSON_TYPES.TABLE,
|
|
1600
|
+
cols: table.cols,
|
|
1601
|
+
rows
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1315
1604
|
function transformLine(line, idGenerator) {
|
|
1316
1605
|
const items = [];
|
|
1317
1606
|
for (const inline of line.inlines) {
|
|
@@ -5983,7 +6272,7 @@ function itemContainsLatin(item) {
|
|
|
5983
6272
|
return false;
|
|
5984
6273
|
}
|
|
5985
6274
|
function isTextItem(item) {
|
|
5986
|
-
return item.type === JSON_TYPES.TEXT || item.type === JSON_TYPES.HIGHLIGHTED_TEXT || item.type === JSON_TYPES.OPERATOR || item.type === JSON_TYPES.SPACE || item.type === JSON_TYPES.GROUP;
|
|
6275
|
+
return item.type === JSON_TYPES.TEXT || item.type === JSON_TYPES.HIGHLIGHTED_TEXT || item.type === JSON_TYPES.BOLD_TEXT || item.type === JSON_TYPES.COLOR_TEXT || item.type === JSON_TYPES.OPERATOR || item.type === JSON_TYPES.SPACE || item.type === JSON_TYPES.GROUP;
|
|
5987
6276
|
}
|
|
5988
6277
|
function groupLineItems(items) {
|
|
5989
6278
|
const groups = [];
|
|
@@ -6098,6 +6387,27 @@ const LayoutRenderer = ({
|
|
|
6098
6387
|
},
|
|
6099
6388
|
subItem.id
|
|
6100
6389
|
)) });
|
|
6390
|
+
case JSON_TYPES.TABLE:
|
|
6391
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "exercise-table-container", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "exercise-table", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: item.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "exercise-table-row", children: row.cells.map((cell) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6392
|
+
"td",
|
|
6393
|
+
{
|
|
6394
|
+
className: "exercise-table-cell",
|
|
6395
|
+
colSpan: cell.colspan || 1,
|
|
6396
|
+
children: cell.items.map((subItem) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6397
|
+
LayoutRenderer,
|
|
6398
|
+
{
|
|
6399
|
+
item: subItem,
|
|
6400
|
+
widgets,
|
|
6401
|
+
values,
|
|
6402
|
+
droppedInputs,
|
|
6403
|
+
onChange,
|
|
6404
|
+
onInputFocus
|
|
6405
|
+
},
|
|
6406
|
+
subItem.id
|
|
6407
|
+
))
|
|
6408
|
+
},
|
|
6409
|
+
cell.id
|
|
6410
|
+
)) }, row.id)) }) }) });
|
|
6101
6411
|
default:
|
|
6102
6412
|
return null;
|
|
6103
6413
|
}
|
|
@@ -6171,6 +6481,20 @@ const ExerciseRenderer = React.forwardRef(({
|
|
|
6171
6481
|
});
|
|
6172
6482
|
continue;
|
|
6173
6483
|
}
|
|
6484
|
+
if (item.type === JSON_TYPES.TABLE) {
|
|
6485
|
+
if (currentGroup.length > 0) {
|
|
6486
|
+
const hasArabic = currentGroup.some((item2) => itemContainsArabic(item2));
|
|
6487
|
+
const subGroups = groupLineItems(currentGroup);
|
|
6488
|
+
groups.push({ items: currentGroup, hasArabic, subGroups });
|
|
6489
|
+
currentGroup = [];
|
|
6490
|
+
}
|
|
6491
|
+
groups.push({
|
|
6492
|
+
items: [item],
|
|
6493
|
+
hasArabic: false,
|
|
6494
|
+
subGroups: []
|
|
6495
|
+
});
|
|
6496
|
+
continue;
|
|
6497
|
+
}
|
|
6174
6498
|
if (item.type === JSON_TYPES.LINEBREAK) {
|
|
6175
6499
|
if (currentGroup.length > 0) {
|
|
6176
6500
|
const hasArabic = currentGroup.some((item2) => itemContainsArabic(item2));
|
|
@@ -38293,6 +38617,7 @@ exports.BoldTextInlineSchema = BoldTextInlineSchema;
|
|
|
38293
38617
|
exports.BoldTextSchema = BoldTextSchema;
|
|
38294
38618
|
exports.ColorTextInlineSchema = ColorTextInlineSchema;
|
|
38295
38619
|
exports.ColorTextSchema = ColorTextSchema;
|
|
38620
|
+
exports.ContentBlockSchema = ContentBlockSchema;
|
|
38296
38621
|
exports.DragOptionsJSONSchema = DragOptionsJSONSchema;
|
|
38297
38622
|
exports.DragOptionsToolSchema = DragOptionsToolSchema;
|
|
38298
38623
|
exports.EngineError = EngineError;
|
|
@@ -38322,6 +38647,10 @@ exports.ParseError = ParseError;
|
|
|
38322
38647
|
exports.QuestionTextSchema = QuestionTextSchema;
|
|
38323
38648
|
exports.SimpleValidationSchema = SimpleValidationSchema;
|
|
38324
38649
|
exports.SpaceInlineSchema = SpaceInlineSchema;
|
|
38650
|
+
exports.SpaceItemSchema = SpaceItemSchema;
|
|
38651
|
+
exports.TableCellItemSchema = TableCellItemSchema;
|
|
38652
|
+
exports.TableItemSchema = TableItemSchema;
|
|
38653
|
+
exports.TableRowItemSchema = TableRowItemSchema;
|
|
38325
38654
|
exports.TextBlockSchema = TextBlockSchema;
|
|
38326
38655
|
exports.TextItemSchema = TextItemSchema;
|
|
38327
38656
|
exports.ToolNodeSchema = ToolNodeSchema;
|
|
@@ -38372,6 +38701,10 @@ exports.isOperatorItem = isOperatorItem;
|
|
|
38372
38701
|
exports.isQuestionText = isQuestionText;
|
|
38373
38702
|
exports.isSimpleValidation = isSimpleValidation;
|
|
38374
38703
|
exports.isSpace = isSpace;
|
|
38704
|
+
exports.isSpaceItem = isSpaceItem;
|
|
38705
|
+
exports.isTableCellItem = isTableCellItem;
|
|
38706
|
+
exports.isTableItem = isTableItem;
|
|
38707
|
+
exports.isTableRowItem = isTableRowItem;
|
|
38375
38708
|
exports.isTextBlock = isTextBlock;
|
|
38376
38709
|
exports.isTextItem = isTextItem$1;
|
|
38377
38710
|
exports.isToolNode = isToolNode;
|