@mathscan/math-exercise-engine 1.1.9 → 1.1.11
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.js +851 -826
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +851 -826
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +34 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3753,635 +3753,6 @@ function isProtractorWidget(widget) {
|
|
|
3753
3753
|
function isSetSquareWidget(widget) {
|
|
3754
3754
|
return widget.type === JSON_TYPES.SET_SQUARE;
|
|
3755
3755
|
}
|
|
3756
|
-
class LayoutIdGenerator {
|
|
3757
|
-
constructor() {
|
|
3758
|
-
this.counter = 0;
|
|
3759
|
-
}
|
|
3760
|
-
reset() {
|
|
3761
|
-
this.counter = 0;
|
|
3762
|
-
}
|
|
3763
|
-
generate(type) {
|
|
3764
|
-
return `${type}_${++this.counter}`;
|
|
3765
|
-
}
|
|
3766
|
-
}
|
|
3767
|
-
function toJSON(ast) {
|
|
3768
|
-
const idGenerator = new LayoutIdGenerator();
|
|
3769
|
-
const widgets = {};
|
|
3770
|
-
const answers = {};
|
|
3771
|
-
const allInlines = collectAllInlines(ast.lines);
|
|
3772
|
-
const inlineDragIds = /* @__PURE__ */ new Map();
|
|
3773
|
-
{
|
|
3774
|
-
let counter = 0;
|
|
3775
|
-
for (const inline of allInlines) {
|
|
3776
|
-
if (inline.type === AST_TYPES.INLINE_DRAG_OPTION) {
|
|
3777
|
-
inlineDragIds.set(inline, `${INLINE_DRAG_OPT_PREFIX}${counter++}`);
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
}
|
|
3781
|
-
const layout = [];
|
|
3782
|
-
if (ast.question) {
|
|
3783
|
-
layout.push({
|
|
3784
|
-
id: idGenerator.generate(JSON_TYPES.QUESTION_TEXT),
|
|
3785
|
-
type: JSON_TYPES.QUESTION_TEXT,
|
|
3786
|
-
value: ast.question.value
|
|
3787
|
-
});
|
|
3788
|
-
}
|
|
3789
|
-
for (const block of ast.lines) {
|
|
3790
|
-
if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
3791
|
-
layout.push(transformTable(block, idGenerator, inlineDragIds));
|
|
3792
|
-
} else if (block.type === AST_TYPES.NUMBER_LINE_BLOCK) {
|
|
3793
|
-
const nlItem = transformNumberLine(block, idGenerator, inlineDragIds);
|
|
3794
|
-
layout.push(nlItem);
|
|
3795
|
-
if (nlItem.counter?.answer !== void 0) {
|
|
3796
|
-
answers[nlItem.counter.id] = nlItem.counter.answer;
|
|
3797
|
-
}
|
|
3798
|
-
for (const cursor of nlItem.cursors ?? []) {
|
|
3799
|
-
answers[cursor.id] = cursor.answer;
|
|
3800
|
-
}
|
|
3801
|
-
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
3802
|
-
const matcherBlock = block;
|
|
3803
|
-
layout.push({
|
|
3804
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
3805
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
3806
|
-
widgetId: matcherBlock.name
|
|
3807
|
-
});
|
|
3808
|
-
layout.push({
|
|
3809
|
-
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
3810
|
-
type: JSON_TYPES.LINEBREAK
|
|
3811
|
-
});
|
|
3812
|
-
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
3813
|
-
const pmBlock = block;
|
|
3814
|
-
layout.push({
|
|
3815
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
3816
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
3817
|
-
widgetId: pmBlock.name
|
|
3818
|
-
});
|
|
3819
|
-
layout.push({
|
|
3820
|
-
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
3821
|
-
type: JSON_TYPES.LINEBREAK
|
|
3822
|
-
});
|
|
3823
|
-
} else if (block.type === AST_TYPES.VERTICAL_OPERATION_BLOCK) {
|
|
3824
|
-
layout.push(transformVerticalOperation(block, idGenerator));
|
|
3825
|
-
} else if (block.type === AST_TYPES.RADIO_OPTIONS) {
|
|
3826
|
-
const radioBlock = block;
|
|
3827
|
-
layout.push({
|
|
3828
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
3829
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
3830
|
-
widgetId: radioBlock.name
|
|
3831
|
-
});
|
|
3832
|
-
layout.push({
|
|
3833
|
-
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
3834
|
-
type: JSON_TYPES.LINEBREAK
|
|
3835
|
-
});
|
|
3836
|
-
} else {
|
|
3837
|
-
const lineItems = transformLine(block, idGenerator, inlineDragIds);
|
|
3838
|
-
layout.push(...lineItems);
|
|
3839
|
-
}
|
|
3840
|
-
}
|
|
3841
|
-
for (const inline of allInlines) {
|
|
3842
|
-
if (inline.type === AST_TYPES.INLINE_INPUT) {
|
|
3843
|
-
if (inline.inputType === INPUT_TYPES.STRING) {
|
|
3844
|
-
widgets[inline.name] = {
|
|
3845
|
-
type: JSON_TYPES.INLINE_INPUT,
|
|
3846
|
-
inputType: INPUT_TYPES.STRING,
|
|
3847
|
-
length: inline.length,
|
|
3848
|
-
placeholder: inline.placeholder
|
|
3849
|
-
};
|
|
3850
|
-
} else {
|
|
3851
|
-
widgets[inline.name] = {
|
|
3852
|
-
type: JSON_TYPES.INLINE_INPUT,
|
|
3853
|
-
inputType: INPUT_TYPES.NUMERIC,
|
|
3854
|
-
digits: inline.digits,
|
|
3855
|
-
placeholder: inline.placeholder
|
|
3856
|
-
};
|
|
3857
|
-
}
|
|
3858
|
-
if (inline.answer !== void 0) {
|
|
3859
|
-
answers[inline.name] = inline.answer;
|
|
3860
|
-
}
|
|
3861
|
-
} else if (inline.type === AST_TYPES.CLOCK && inline.mode === "interactive") {
|
|
3862
|
-
answers[inline.name] = inline.answer;
|
|
3863
|
-
}
|
|
3864
|
-
if (inline.type === AST_TYPES.FRACTION) {
|
|
3865
|
-
widgets[inline.name] = {
|
|
3866
|
-
type: JSON_TYPES.FRACTION,
|
|
3867
|
-
numerator: inline.numerator ?? null,
|
|
3868
|
-
denominator: inline.denominator ?? null,
|
|
3869
|
-
simplified: inline.simplified ?? true,
|
|
3870
|
-
placeholder: inline.placeholder
|
|
3871
|
-
};
|
|
3872
|
-
if (inline.answer !== void 0) {
|
|
3873
|
-
answers[inline.name] = inline.answer;
|
|
3874
|
-
}
|
|
3875
|
-
}
|
|
3876
|
-
if (inline.type === AST_TYPES.INLINE_DRAG_OPTION) {
|
|
3877
|
-
const widgetId = inlineDragIds.get(inline);
|
|
3878
|
-
widgets[widgetId] = {
|
|
3879
|
-
type: JSON_TYPES.INLINE_DRAG_OPTION,
|
|
3880
|
-
value: inline.value
|
|
3881
|
-
};
|
|
3882
|
-
}
|
|
3883
|
-
if (inline.type === AST_TYPES.VISUAL_FRACTION) {
|
|
3884
|
-
const answerArr = inline.answer ?? [];
|
|
3885
|
-
widgets[inline.name] = {
|
|
3886
|
-
type: JSON_TYPES.VISUAL_FRACTION,
|
|
3887
|
-
shape: inline.shape,
|
|
3888
|
-
divisions: inline.divisions,
|
|
3889
|
-
filled: inline.filled ?? [],
|
|
3890
|
-
answer: answerArr,
|
|
3891
|
-
...inline.orientation !== void 0 && { orientation: inline.orientation },
|
|
3892
|
-
...inline.label !== void 0 && { label: inline.label },
|
|
3893
|
-
...inline.size !== void 0 && { size: inline.size }
|
|
3894
|
-
};
|
|
3895
|
-
if (answerArr.length > 0) {
|
|
3896
|
-
answers[inline.name] = answerArr;
|
|
3897
|
-
}
|
|
3898
|
-
}
|
|
3899
|
-
}
|
|
3900
|
-
for (const block of ast.lines) {
|
|
3901
|
-
if (block.type !== AST_TYPES.VERTICAL_OPERATION_BLOCK) continue;
|
|
3902
|
-
const vop = block;
|
|
3903
|
-
for (const item of vop.items) {
|
|
3904
|
-
if (item.type !== AST_TYPES.VOP_ROW && item.type !== AST_TYPES.VOP_CARRY_ROW) continue;
|
|
3905
|
-
for (const cell of item.cells) {
|
|
3906
|
-
if (cell.kind !== "input") continue;
|
|
3907
|
-
if (widgets[cell.name]) {
|
|
3908
|
-
throw new Error(`VERTICAL_OPERATION: duplicate INPUT name "${cell.name}"`);
|
|
3909
|
-
}
|
|
3910
|
-
widgets[cell.name] = {
|
|
3911
|
-
type: JSON_TYPES.INLINE_INPUT,
|
|
3912
|
-
inputType: INPUT_TYPES.NUMERIC,
|
|
3913
|
-
digits: cell.digits
|
|
3914
|
-
};
|
|
3915
|
-
if (cell.answer !== void 0) {
|
|
3916
|
-
answers[cell.name] = cell.answer;
|
|
3917
|
-
}
|
|
3918
|
-
}
|
|
3919
|
-
}
|
|
3920
|
-
}
|
|
3921
|
-
for (const block of ast.lines) {
|
|
3922
|
-
if (block.type === AST_TYPES.RADIO_OPTIONS) {
|
|
3923
|
-
const radioBlock = block;
|
|
3924
|
-
widgets[radioBlock.name] = {
|
|
3925
|
-
type: JSON_TYPES.RADIO_OPTIONS,
|
|
3926
|
-
options: radioBlock.options
|
|
3927
|
-
};
|
|
3928
|
-
answers[radioBlock.name] = radioBlock.answer;
|
|
3929
|
-
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
3930
|
-
const matcherBlock = block;
|
|
3931
|
-
widgets[matcherBlock.name] = buildMatcherWidget(matcherBlock, idGenerator, inlineDragIds);
|
|
3932
|
-
answers[matcherBlock.name] = matcherBlock.answers;
|
|
3933
|
-
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
3934
|
-
const pmBlock = block;
|
|
3935
|
-
widgets[pmBlock.name] = buildPairMatcherWidget(pmBlock, idGenerator, inlineDragIds);
|
|
3936
|
-
answers[pmBlock.name] = pmBlock.answers;
|
|
3937
|
-
}
|
|
3938
|
-
}
|
|
3939
|
-
if (ast.tools) {
|
|
3940
|
-
for (const tool of ast.tools) {
|
|
3941
|
-
if (tool.type === AST_TYPES.DRAG_OPTIONS) {
|
|
3942
|
-
widgets["_drag_options"] = {
|
|
3943
|
-
type: JSON_TYPES.DRAG_OPTIONS,
|
|
3944
|
-
options: tool.options
|
|
3945
|
-
};
|
|
3946
|
-
} else if (tool.type === AST_TYPES.NUMERIC_KEYPAD) {
|
|
3947
|
-
widgets["_numeric_keypad"] = {
|
|
3948
|
-
type: JSON_TYPES.NUMERIC_KEYPAD,
|
|
3949
|
-
includeOperators: tool.includeOperators,
|
|
3950
|
-
includeDecimal: tool.includeDecimal,
|
|
3951
|
-
style: tool.style
|
|
3952
|
-
};
|
|
3953
|
-
} else if (tool.type === AST_TYPES.GEOMETRY_RULER) {
|
|
3954
|
-
widgets[RULER_WIDGET_ID] = {
|
|
3955
|
-
type: JSON_TYPES.RULER,
|
|
3956
|
-
size: tool.size
|
|
3957
|
-
};
|
|
3958
|
-
} else if (tool.type === AST_TYPES.GEOMETRY_PROTRACTOR) {
|
|
3959
|
-
widgets[PROTRACTOR_WIDGET_ID] = {
|
|
3960
|
-
type: JSON_TYPES.PROTRACTOR,
|
|
3961
|
-
size: tool.size
|
|
3962
|
-
};
|
|
3963
|
-
} else if (tool.type === AST_TYPES.GEOMETRY_SET_SQUARE) {
|
|
3964
|
-
widgets[SET_SQUARE_WIDGET_ID] = {
|
|
3965
|
-
type: JSON_TYPES.SET_SQUARE,
|
|
3966
|
-
size: tool.size
|
|
3967
|
-
};
|
|
3968
|
-
}
|
|
3969
|
-
}
|
|
3970
|
-
}
|
|
3971
|
-
return {
|
|
3972
|
-
version: "2.0",
|
|
3973
|
-
// Natural DSL version
|
|
3974
|
-
layout,
|
|
3975
|
-
widgets,
|
|
3976
|
-
...ast.validation ? { validation: transformValidation(ast.validation, answers, widgets) } : {}
|
|
3977
|
-
};
|
|
3978
|
-
}
|
|
3979
|
-
function collectAllInlines(blocks) {
|
|
3980
|
-
const result = [];
|
|
3981
|
-
for (const block of blocks) {
|
|
3982
|
-
if (block.type === AST_TYPES.LINE_BLOCK) {
|
|
3983
|
-
result.push(...block.inlines);
|
|
3984
|
-
} else if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
3985
|
-
for (const row of block.rows) {
|
|
3986
|
-
for (const cell of row.cells) {
|
|
3987
|
-
result.push(...cell.inlines);
|
|
3988
|
-
}
|
|
3989
|
-
}
|
|
3990
|
-
} else if (block.type === AST_TYPES.NUMBER_LINE_BLOCK) {
|
|
3991
|
-
const numberLine = block;
|
|
3992
|
-
for (const position of numberLine.positions) {
|
|
3993
|
-
result.push(...position.inlines);
|
|
3994
|
-
}
|
|
3995
|
-
for (const arrow of numberLine.arrows ?? []) {
|
|
3996
|
-
result.push(...arrow.inlines);
|
|
3997
|
-
}
|
|
3998
|
-
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
3999
|
-
for (const row of block.rows) {
|
|
4000
|
-
for (const item of row.items) {
|
|
4001
|
-
result.push(...item.inlines);
|
|
4002
|
-
}
|
|
4003
|
-
}
|
|
4004
|
-
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
4005
|
-
const pm = block;
|
|
4006
|
-
for (const item of [...pm.topItems, ...pm.bottomItems]) {
|
|
4007
|
-
result.push(...item.inlines);
|
|
4008
|
-
}
|
|
4009
|
-
}
|
|
4010
|
-
}
|
|
4011
|
-
return result;
|
|
4012
|
-
}
|
|
4013
|
-
function transformNumberLine(numberLine, idGenerator, inlineDragIds) {
|
|
4014
|
-
const positions = numberLine.positions.map((pos) => {
|
|
4015
|
-
const content = pos.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds));
|
|
4016
|
-
return {
|
|
4017
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_POSITION),
|
|
4018
|
-
type: JSON_TYPES.NUMBER_LINE_POSITION,
|
|
4019
|
-
value: pos.value,
|
|
4020
|
-
content
|
|
4021
|
-
};
|
|
4022
|
-
});
|
|
4023
|
-
let counterItem;
|
|
4024
|
-
if (numberLine.counter !== void 0) {
|
|
4025
|
-
const c = numberLine.counter;
|
|
4026
|
-
counterItem = {
|
|
4027
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_COUNTER),
|
|
4028
|
-
type: JSON_TYPES.NUMBER_LINE_COUNTER,
|
|
4029
|
-
min: c.min,
|
|
4030
|
-
max: c.max,
|
|
4031
|
-
...c.default !== void 0 && { default: c.default },
|
|
4032
|
-
...c.name !== void 0 && { name: c.name },
|
|
4033
|
-
...c.answer !== void 0 && { answer: c.answer }
|
|
4034
|
-
};
|
|
4035
|
-
}
|
|
4036
|
-
let highlights;
|
|
4037
|
-
if (numberLine.highlights !== void 0 && numberLine.highlights.length > 0) {
|
|
4038
|
-
highlights = numberLine.highlights.map((h) => ({
|
|
4039
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_HIGHLIGHT),
|
|
4040
|
-
type: JSON_TYPES.NUMBER_LINE_HIGHLIGHT,
|
|
4041
|
-
from: h.from,
|
|
4042
|
-
to: h.to,
|
|
4043
|
-
...h.color !== void 0 && { color: h.color },
|
|
4044
|
-
...h.label !== void 0 && { label: h.label }
|
|
4045
|
-
}));
|
|
4046
|
-
}
|
|
4047
|
-
let cursors;
|
|
4048
|
-
if (numberLine.cursors !== void 0 && numberLine.cursors.length > 0) {
|
|
4049
|
-
cursors = numberLine.cursors.map((c) => ({
|
|
4050
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_CURSOR),
|
|
4051
|
-
type: JSON_TYPES.NUMBER_LINE_CURSOR,
|
|
4052
|
-
value: c.value,
|
|
4053
|
-
answer: c.answer,
|
|
4054
|
-
fillRange: c.fillRange,
|
|
4055
|
-
...c.color !== void 0 && { color: c.color },
|
|
4056
|
-
...c.label !== void 0 && { label: c.label }
|
|
4057
|
-
}));
|
|
4058
|
-
}
|
|
4059
|
-
let arrows;
|
|
4060
|
-
if (numberLine.arrows !== void 0 && numberLine.arrows.length > 0) {
|
|
4061
|
-
arrows = numberLine.arrows.map((a) => ({
|
|
4062
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_ARROW),
|
|
4063
|
-
type: JSON_TYPES.NUMBER_LINE_ARROW,
|
|
4064
|
-
from: a.from,
|
|
4065
|
-
to: a.to,
|
|
4066
|
-
...a.color !== void 0 && { color: a.color },
|
|
4067
|
-
content: a.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds))
|
|
4068
|
-
}));
|
|
4069
|
-
}
|
|
4070
|
-
const item = {
|
|
4071
|
-
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE),
|
|
4072
|
-
type: JSON_TYPES.NUMBER_LINE,
|
|
4073
|
-
min: numberLine.min,
|
|
4074
|
-
max: numberLine.max,
|
|
4075
|
-
step: numberLine.step,
|
|
4076
|
-
...numberLine.minorTicks !== void 0 && { minorTicks: numberLine.minorTicks },
|
|
4077
|
-
...numberLine.style !== void 0 && { style: numberLine.style },
|
|
4078
|
-
...numberLine.labelVisibility !== void 0 && { labelVisibility: numberLine.labelVisibility },
|
|
4079
|
-
...counterItem !== void 0 && { counter: counterItem },
|
|
4080
|
-
...highlights !== void 0 && { highlights },
|
|
4081
|
-
...cursors !== void 0 && { cursors },
|
|
4082
|
-
...arrows !== void 0 && { arrows },
|
|
4083
|
-
...numberLine.dragMode !== void 0 && { dragMode: numberLine.dragMode },
|
|
4084
|
-
positions
|
|
4085
|
-
};
|
|
4086
|
-
return item;
|
|
4087
|
-
}
|
|
4088
|
-
function mapMatcherItemList(items, idGenerator, inlineDragIds) {
|
|
4089
|
-
return items.map((item) => ({
|
|
4090
|
-
id: idGenerator.generate(JSON_TYPES.MATCHER_ITEM),
|
|
4091
|
-
type: JSON_TYPES.MATCHER_ITEM,
|
|
4092
|
-
itemId: item.itemId,
|
|
4093
|
-
content: item.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds))
|
|
4094
|
-
}));
|
|
4095
|
-
}
|
|
4096
|
-
function buildMatcherWidget(matcher, idGenerator, inlineDragIds) {
|
|
4097
|
-
const rows = matcher.rows.map((row) => ({
|
|
4098
|
-
id: idGenerator.generate(JSON_TYPES.MATCHER_ROW),
|
|
4099
|
-
type: JSON_TYPES.MATCHER_ROW,
|
|
4100
|
-
items: mapMatcherItemList(row.items, idGenerator, inlineDragIds)
|
|
4101
|
-
}));
|
|
4102
|
-
const result = {
|
|
4103
|
-
type: JSON_TYPES.MATCHER,
|
|
4104
|
-
rows,
|
|
4105
|
-
groupCount: matcher.answers.length
|
|
4106
|
-
};
|
|
4107
|
-
if (matcher.colors !== void 0) {
|
|
4108
|
-
result.colors = matcher.colors;
|
|
4109
|
-
}
|
|
4110
|
-
return result;
|
|
4111
|
-
}
|
|
4112
|
-
function buildPairMatcherWidget(pm, idGenerator, inlineDragIds) {
|
|
4113
|
-
return {
|
|
4114
|
-
type: JSON_TYPES.PAIR_MATCHER,
|
|
4115
|
-
topItems: mapMatcherItemList(pm.topItems, idGenerator, inlineDragIds),
|
|
4116
|
-
bottomItems: mapMatcherItemList(pm.bottomItems, idGenerator, inlineDragIds)
|
|
4117
|
-
};
|
|
4118
|
-
}
|
|
4119
|
-
function transformVerticalOperation(vop, idGenerator) {
|
|
4120
|
-
const anyRowHasOp = vop.items.some(
|
|
4121
|
-
(item) => item.type === AST_TYPES.VOP_ROW && item.op !== void 0
|
|
4122
|
-
);
|
|
4123
|
-
if (!anyRowHasOp && vop.op === void 0) {
|
|
4124
|
-
throw new Error("VERTICAL_OPERATION: at least one op is required (set op on the block or on individual ROWs)");
|
|
4125
|
-
}
|
|
4126
|
-
let cols = 1;
|
|
4127
|
-
for (const item of vop.items) {
|
|
4128
|
-
if (item.type === AST_TYPES.VOP_ROW || item.type === AST_TYPES.VOP_CARRY_ROW) {
|
|
4129
|
-
cols = Math.max(cols, item.cells.length);
|
|
4130
|
-
}
|
|
4131
|
-
}
|
|
4132
|
-
function buildCells(row) {
|
|
4133
|
-
return row.cells.map((cell) => {
|
|
4134
|
-
const id = idGenerator.generate(JSON_TYPES.VOP_CELL);
|
|
4135
|
-
if (cell.kind === "digit") return { id, type: JSON_TYPES.VOP_CELL, kind: "digit", value: cell.value };
|
|
4136
|
-
if (cell.kind === "label") return { id, type: JSON_TYPES.VOP_CELL, kind: "label", value: cell.value };
|
|
4137
|
-
if (cell.kind === "color") return { id, type: JSON_TYPES.VOP_CELL, kind: "color", value: cell.value, color: cell.color };
|
|
4138
|
-
if (cell.kind === "bold") return { id, type: JSON_TYPES.VOP_CELL, kind: "bold", value: cell.value };
|
|
4139
|
-
if (cell.kind === "highlight") return { id, type: JSON_TYPES.VOP_CELL, kind: "highlight", value: cell.value };
|
|
4140
|
-
if (cell.kind === "input") return { id, type: JSON_TYPES.VOP_CELL, kind: "input", widgetId: cell.name };
|
|
4141
|
-
return { id, type: JSON_TYPES.VOP_CELL, kind: "empty" };
|
|
4142
|
-
});
|
|
4143
|
-
}
|
|
4144
|
-
const items = vop.items.map((item) => {
|
|
4145
|
-
if (item.type === AST_TYPES.VOP_SEPARATOR) {
|
|
4146
|
-
return {
|
|
4147
|
-
id: idGenerator.generate(JSON_TYPES.VOP_SEPARATOR),
|
|
4148
|
-
type: JSON_TYPES.VOP_SEPARATOR
|
|
4149
|
-
};
|
|
4150
|
-
}
|
|
4151
|
-
if (item.type === AST_TYPES.VOP_CARRY_ROW) {
|
|
4152
|
-
return {
|
|
4153
|
-
id: idGenerator.generate(JSON_TYPES.VOP_CARRY_ROW),
|
|
4154
|
-
type: JSON_TYPES.VOP_CARRY_ROW,
|
|
4155
|
-
cells: buildCells(item)
|
|
4156
|
-
};
|
|
4157
|
-
}
|
|
4158
|
-
const row = item;
|
|
4159
|
-
return {
|
|
4160
|
-
id: idGenerator.generate(JSON_TYPES.VOP_ROW),
|
|
4161
|
-
type: JSON_TYPES.VOP_ROW,
|
|
4162
|
-
cells: buildCells(row),
|
|
4163
|
-
...row.op !== void 0 && { op: row.op }
|
|
4164
|
-
};
|
|
4165
|
-
});
|
|
4166
|
-
return {
|
|
4167
|
-
id: idGenerator.generate(JSON_TYPES.VERTICAL_OPERATION),
|
|
4168
|
-
type: JSON_TYPES.VERTICAL_OPERATION,
|
|
4169
|
-
op: vop.op,
|
|
4170
|
-
cols,
|
|
4171
|
-
items
|
|
4172
|
-
};
|
|
4173
|
-
}
|
|
4174
|
-
function transformTable(table, idGenerator, inlineDragIds) {
|
|
4175
|
-
const rows = table.rows.map((row) => {
|
|
4176
|
-
const cells = row.cells.map((cell) => {
|
|
4177
|
-
const items = cell.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds));
|
|
4178
|
-
const cellItem = {
|
|
4179
|
-
id: idGenerator.generate(JSON_TYPES.TABLE_CELL),
|
|
4180
|
-
type: JSON_TYPES.TABLE_CELL,
|
|
4181
|
-
items
|
|
4182
|
-
};
|
|
4183
|
-
if (cell.colspan !== void 0) {
|
|
4184
|
-
cellItem.colspan = cell.colspan;
|
|
4185
|
-
}
|
|
4186
|
-
return cellItem;
|
|
4187
|
-
});
|
|
4188
|
-
return {
|
|
4189
|
-
id: idGenerator.generate(JSON_TYPES.TABLE_ROW),
|
|
4190
|
-
type: JSON_TYPES.TABLE_ROW,
|
|
4191
|
-
cells
|
|
4192
|
-
};
|
|
4193
|
-
});
|
|
4194
|
-
return {
|
|
4195
|
-
id: idGenerator.generate(JSON_TYPES.TABLE),
|
|
4196
|
-
type: JSON_TYPES.TABLE,
|
|
4197
|
-
cols: table.cols,
|
|
4198
|
-
rows
|
|
4199
|
-
};
|
|
4200
|
-
}
|
|
4201
|
-
function transformLine(line, idGenerator, inlineDragIds) {
|
|
4202
|
-
const items = [];
|
|
4203
|
-
for (const inline of line.inlines) {
|
|
4204
|
-
items.push(transformInline(inline, idGenerator, inlineDragIds));
|
|
4205
|
-
}
|
|
4206
|
-
items.push({
|
|
4207
|
-
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
4208
|
-
type: JSON_TYPES.LINEBREAK
|
|
4209
|
-
});
|
|
4210
|
-
return items;
|
|
4211
|
-
}
|
|
4212
|
-
function transformInline(inline, idGenerator, inlineDragIds) {
|
|
4213
|
-
switch (inline.type) {
|
|
4214
|
-
case AST_TYPES.FREE_TEXT: {
|
|
4215
|
-
const trimmed = inline.value.trim();
|
|
4216
|
-
const operators = ["+", "-", "×", "÷", "=", "<", ">", "?"];
|
|
4217
|
-
if (operators.includes(trimmed) && inline.value.trim() === inline.value) {
|
|
4218
|
-
return {
|
|
4219
|
-
id: idGenerator.generate("operator"),
|
|
4220
|
-
type: "operator",
|
|
4221
|
-
operator: trimmed
|
|
4222
|
-
};
|
|
4223
|
-
}
|
|
4224
|
-
return {
|
|
4225
|
-
id: idGenerator.generate(JSON_TYPES.TEXT),
|
|
4226
|
-
type: JSON_TYPES.TEXT,
|
|
4227
|
-
value: inline.value
|
|
4228
|
-
};
|
|
4229
|
-
}
|
|
4230
|
-
case AST_TYPES.SPACE:
|
|
4231
|
-
return {
|
|
4232
|
-
id: idGenerator.generate(JSON_TYPES.SPACE),
|
|
4233
|
-
type: JSON_TYPES.SPACE
|
|
4234
|
-
};
|
|
4235
|
-
case AST_TYPES.HIGHLIGHTED_TEXT:
|
|
4236
|
-
return {
|
|
4237
|
-
id: idGenerator.generate(JSON_TYPES.HIGHLIGHTED_TEXT),
|
|
4238
|
-
type: JSON_TYPES.HIGHLIGHTED_TEXT,
|
|
4239
|
-
value: inline.value,
|
|
4240
|
-
highlight: inline.highlight
|
|
4241
|
-
};
|
|
4242
|
-
case AST_TYPES.COLOR_TEXT:
|
|
4243
|
-
return {
|
|
4244
|
-
id: idGenerator.generate(JSON_TYPES.COLOR_TEXT),
|
|
4245
|
-
type: JSON_TYPES.COLOR_TEXT,
|
|
4246
|
-
value: inline.value,
|
|
4247
|
-
color: inline.color,
|
|
4248
|
-
highlight: inline.highlight
|
|
4249
|
-
};
|
|
4250
|
-
case AST_TYPES.BOLD_TEXT:
|
|
4251
|
-
return {
|
|
4252
|
-
id: idGenerator.generate(JSON_TYPES.BOLD_TEXT),
|
|
4253
|
-
type: JSON_TYPES.BOLD_TEXT,
|
|
4254
|
-
value: inline.value,
|
|
4255
|
-
highlight: inline.highlight
|
|
4256
|
-
};
|
|
4257
|
-
case AST_TYPES.INLINE_INPUT:
|
|
4258
|
-
return {
|
|
4259
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
4260
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
4261
|
-
widgetId: inline.name
|
|
4262
|
-
};
|
|
4263
|
-
case AST_TYPES.FRACTION:
|
|
4264
|
-
return {
|
|
4265
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
4266
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
4267
|
-
widgetId: inline.name
|
|
4268
|
-
};
|
|
4269
|
-
case AST_TYPES.IMAGE:
|
|
4270
|
-
return {
|
|
4271
|
-
id: idGenerator.generate(JSON_TYPES.IMAGE),
|
|
4272
|
-
type: JSON_TYPES.IMAGE,
|
|
4273
|
-
name: inline.name,
|
|
4274
|
-
src: inline.src,
|
|
4275
|
-
alt: inline.alt,
|
|
4276
|
-
...inline.width !== void 0 && { width: inline.width },
|
|
4277
|
-
...inline.height !== void 0 && { height: inline.height }
|
|
4278
|
-
};
|
|
4279
|
-
case AST_TYPES.VISUAL_FRACTION:
|
|
4280
|
-
return {
|
|
4281
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
4282
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
4283
|
-
widgetId: inline.name
|
|
4284
|
-
};
|
|
4285
|
-
case AST_TYPES.INLINE_DRAG_OPTION:
|
|
4286
|
-
return {
|
|
4287
|
-
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
4288
|
-
type: JSON_TYPES.WIDGET_REF,
|
|
4289
|
-
widgetId: inlineDragIds.get(inline)
|
|
4290
|
-
};
|
|
4291
|
-
case AST_TYPES.CLOCK: {
|
|
4292
|
-
const base = {
|
|
4293
|
-
id: idGenerator.generate(JSON_TYPES.CLOCK),
|
|
4294
|
-
type: JSON_TYPES.CLOCK,
|
|
4295
|
-
mode: inline.mode,
|
|
4296
|
-
clockType: inline.clockType,
|
|
4297
|
-
value: inline.value,
|
|
4298
|
-
...inline.format !== void 0 && { format: inline.format },
|
|
4299
|
-
...inline.name !== void 0 && { name: inline.name }
|
|
4300
|
-
};
|
|
4301
|
-
if (inline.mode === "interactive") {
|
|
4302
|
-
return { ...base, ...inline.snap !== void 0 && { snap: inline.snap } };
|
|
4303
|
-
}
|
|
4304
|
-
return base;
|
|
4305
|
-
}
|
|
4306
|
-
default:
|
|
4307
|
-
throw new Error(`Unknown inline type: ${inline.type}`);
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
function transformValidation(validation, answers, widgets) {
|
|
4311
|
-
if (validation.type === AST_TYPES.SIMPLE_VALIDATION) {
|
|
4312
|
-
return {
|
|
4313
|
-
mode: VALIDATION_MODES.SIMPLE,
|
|
4314
|
-
answers
|
|
4315
|
-
};
|
|
4316
|
-
} else if (validation.type === AST_TYPES.EXPRESSION_VALIDATION) {
|
|
4317
|
-
const validVariableNames = Object.keys(widgets);
|
|
4318
|
-
const variables = extractVariables$1(validation.expression, validVariableNames);
|
|
4319
|
-
return {
|
|
4320
|
-
mode: VALIDATION_MODES.EXPRESSION,
|
|
4321
|
-
expression: validation.expression,
|
|
4322
|
-
variables
|
|
4323
|
-
};
|
|
4324
|
-
} else if (validation.type === AST_TYPES.MIXED_VALIDATION) {
|
|
4325
|
-
const validVariableNames = Object.keys(widgets);
|
|
4326
|
-
const variables = extractVariables$1(validation.expression, validVariableNames);
|
|
4327
|
-
const inExpression = new Set(variables);
|
|
4328
|
-
for (const [name, widget] of Object.entries(widgets)) {
|
|
4329
|
-
if (name.startsWith("_")) continue;
|
|
4330
|
-
if (name in answers) continue;
|
|
4331
|
-
if (inExpression.has(name)) continue;
|
|
4332
|
-
if (widget.type === JSON_TYPES.FRACTION) {
|
|
4333
|
-
const w = widget;
|
|
4334
|
-
if (w.numerator !== null && w.denominator !== null) continue;
|
|
4335
|
-
}
|
|
4336
|
-
if (widget.type === JSON_TYPES.VISUAL_FRACTION) {
|
|
4337
|
-
const w = widget;
|
|
4338
|
-
if (Array.isArray(w.filled) && w.filled.length > 0) continue;
|
|
4339
|
-
}
|
|
4340
|
-
throw new Error(
|
|
4341
|
-
`Mixed validation: widget "${name}" has no \`answer\` and is not referenced in expression "${validation.expression}"`
|
|
4342
|
-
);
|
|
4343
|
-
}
|
|
4344
|
-
return {
|
|
4345
|
-
mode: VALIDATION_MODES.MIXED,
|
|
4346
|
-
expression: validation.expression,
|
|
4347
|
-
answers,
|
|
4348
|
-
variables
|
|
4349
|
-
};
|
|
4350
|
-
}
|
|
4351
|
-
throw new Error(`Unknown validation type: ${validation.type}`);
|
|
4352
|
-
}
|
|
4353
|
-
function extractVariables$1(expression, validVariables) {
|
|
4354
|
-
const matches = expression.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g) || [];
|
|
4355
|
-
const variables = matches.filter(
|
|
4356
|
-
(v) => v !== "true" && v !== "false" && v !== "null" && v !== "undefined"
|
|
4357
|
-
);
|
|
4358
|
-
const uniqueVars = Array.from(new Set(variables));
|
|
4359
|
-
if (validVariables && validVariables.length > 0) {
|
|
4360
|
-
return uniqueVars.filter((v) => validVariables.includes(v));
|
|
4361
|
-
}
|
|
4362
|
-
return uniqueVars;
|
|
4363
|
-
}
|
|
4364
|
-
function normalize(value) {
|
|
4365
|
-
if (typeof value === "number") {
|
|
4366
|
-
return String(Math.round(value * 10 ** INTERNAL_PRECISION) / 10 ** INTERNAL_PRECISION);
|
|
4367
|
-
}
|
|
4368
|
-
const trimmed = String(value).trim().toLowerCase().replace(/^["']|["']$/g, "");
|
|
4369
|
-
const asNum = Number(trimmed);
|
|
4370
|
-
if (trimmed !== "" && !isNaN(asNum)) {
|
|
4371
|
-
return String(Math.round(asNum * 10 ** INTERNAL_PRECISION) / 10 ** INTERNAL_PRECISION);
|
|
4372
|
-
}
|
|
4373
|
-
return trimmed;
|
|
4374
|
-
}
|
|
4375
|
-
const NL_DRAG_PREFIX = "\0nl-drag\0";
|
|
4376
|
-
const isNLDragEncoded = (v) => v.startsWith(NL_DRAG_PREFIX);
|
|
4377
|
-
const encodeNLDragValue = (label, position) => `${NL_DRAG_PREFIX}${label}@${String(position)}`;
|
|
4378
|
-
function isNLDragCorrect(encoded, expectedLabel, expectedPosition) {
|
|
4379
|
-
const payload = encoded.slice(NL_DRAG_PREFIX.length);
|
|
4380
|
-
const atIdx = payload.lastIndexOf("@");
|
|
4381
|
-
const label = normalize(payload.slice(0, atIdx));
|
|
4382
|
-
const position = normalize(payload.slice(atIdx + 1));
|
|
4383
|
-
return label === normalize(expectedLabel) && position === normalize(expectedPosition);
|
|
4384
|
-
}
|
|
4385
3756
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
4386
3757
|
var lodash = { exports: {} };
|
|
4387
3758
|
/**
|
|
@@ -9699,172 +9070,803 @@ lodash.exports;
|
|
|
9699
9070
|
arrayEach(["bind", "bindKey", "curry", "curryRight", "partial", "partialRight"], function(methodName) {
|
|
9700
9071
|
lodash2[methodName].placeholder = lodash2;
|
|
9701
9072
|
});
|
|
9702
|
-
arrayEach(["drop", "take"], function(methodName, index) {
|
|
9703
|
-
LazyWrapper.prototype[methodName] = function(n) {
|
|
9704
|
-
n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
|
|
9705
|
-
var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
|
|
9706
|
-
if (result2.__filtered__) {
|
|
9707
|
-
result2.__takeCount__ = nativeMin(n, result2.__takeCount__);
|
|
9708
|
-
} else {
|
|
9709
|
-
result2.__views__.push({
|
|
9710
|
-
"size": nativeMin(n, MAX_ARRAY_LENGTH),
|
|
9711
|
-
"type": methodName + (result2.__dir__ < 0 ? "Right" : "")
|
|
9712
|
-
});
|
|
9713
|
-
}
|
|
9714
|
-
return result2;
|
|
9073
|
+
arrayEach(["drop", "take"], function(methodName, index) {
|
|
9074
|
+
LazyWrapper.prototype[methodName] = function(n) {
|
|
9075
|
+
n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
|
|
9076
|
+
var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
|
|
9077
|
+
if (result2.__filtered__) {
|
|
9078
|
+
result2.__takeCount__ = nativeMin(n, result2.__takeCount__);
|
|
9079
|
+
} else {
|
|
9080
|
+
result2.__views__.push({
|
|
9081
|
+
"size": nativeMin(n, MAX_ARRAY_LENGTH),
|
|
9082
|
+
"type": methodName + (result2.__dir__ < 0 ? "Right" : "")
|
|
9083
|
+
});
|
|
9084
|
+
}
|
|
9085
|
+
return result2;
|
|
9086
|
+
};
|
|
9087
|
+
LazyWrapper.prototype[methodName + "Right"] = function(n) {
|
|
9088
|
+
return this.reverse()[methodName](n).reverse();
|
|
9089
|
+
};
|
|
9090
|
+
});
|
|
9091
|
+
arrayEach(["filter", "map", "takeWhile"], function(methodName, index) {
|
|
9092
|
+
var type = index + 1, isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
|
|
9093
|
+
LazyWrapper.prototype[methodName] = function(iteratee2) {
|
|
9094
|
+
var result2 = this.clone();
|
|
9095
|
+
result2.__iteratees__.push({
|
|
9096
|
+
"iteratee": getIteratee(iteratee2, 3),
|
|
9097
|
+
"type": type
|
|
9098
|
+
});
|
|
9099
|
+
result2.__filtered__ = result2.__filtered__ || isFilter;
|
|
9100
|
+
return result2;
|
|
9101
|
+
};
|
|
9102
|
+
});
|
|
9103
|
+
arrayEach(["head", "last"], function(methodName, index) {
|
|
9104
|
+
var takeName = "take" + (index ? "Right" : "");
|
|
9105
|
+
LazyWrapper.prototype[methodName] = function() {
|
|
9106
|
+
return this[takeName](1).value()[0];
|
|
9107
|
+
};
|
|
9108
|
+
});
|
|
9109
|
+
arrayEach(["initial", "tail"], function(methodName, index) {
|
|
9110
|
+
var dropName = "drop" + (index ? "" : "Right");
|
|
9111
|
+
LazyWrapper.prototype[methodName] = function() {
|
|
9112
|
+
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
|
|
9113
|
+
};
|
|
9114
|
+
});
|
|
9115
|
+
LazyWrapper.prototype.compact = function() {
|
|
9116
|
+
return this.filter(identity);
|
|
9117
|
+
};
|
|
9118
|
+
LazyWrapper.prototype.find = function(predicate) {
|
|
9119
|
+
return this.filter(predicate).head();
|
|
9120
|
+
};
|
|
9121
|
+
LazyWrapper.prototype.findLast = function(predicate) {
|
|
9122
|
+
return this.reverse().find(predicate);
|
|
9123
|
+
};
|
|
9124
|
+
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
|
|
9125
|
+
if (typeof path == "function") {
|
|
9126
|
+
return new LazyWrapper(this);
|
|
9127
|
+
}
|
|
9128
|
+
return this.map(function(value) {
|
|
9129
|
+
return baseInvoke(value, path, args);
|
|
9130
|
+
});
|
|
9131
|
+
});
|
|
9132
|
+
LazyWrapper.prototype.reject = function(predicate) {
|
|
9133
|
+
return this.filter(negate(getIteratee(predicate)));
|
|
9134
|
+
};
|
|
9135
|
+
LazyWrapper.prototype.slice = function(start, end) {
|
|
9136
|
+
start = toInteger(start);
|
|
9137
|
+
var result2 = this;
|
|
9138
|
+
if (result2.__filtered__ && (start > 0 || end < 0)) {
|
|
9139
|
+
return new LazyWrapper(result2);
|
|
9140
|
+
}
|
|
9141
|
+
if (start < 0) {
|
|
9142
|
+
result2 = result2.takeRight(-start);
|
|
9143
|
+
} else if (start) {
|
|
9144
|
+
result2 = result2.drop(start);
|
|
9145
|
+
}
|
|
9146
|
+
if (end !== undefined$1) {
|
|
9147
|
+
end = toInteger(end);
|
|
9148
|
+
result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start);
|
|
9149
|
+
}
|
|
9150
|
+
return result2;
|
|
9151
|
+
};
|
|
9152
|
+
LazyWrapper.prototype.takeRightWhile = function(predicate) {
|
|
9153
|
+
return this.reverse().takeWhile(predicate).reverse();
|
|
9154
|
+
};
|
|
9155
|
+
LazyWrapper.prototype.toArray = function() {
|
|
9156
|
+
return this.take(MAX_ARRAY_LENGTH);
|
|
9157
|
+
};
|
|
9158
|
+
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
9159
|
+
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash2[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName);
|
|
9160
|
+
if (!lodashFunc) {
|
|
9161
|
+
return;
|
|
9162
|
+
}
|
|
9163
|
+
lodash2.prototype[methodName] = function() {
|
|
9164
|
+
var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray(value);
|
|
9165
|
+
var interceptor = function(value2) {
|
|
9166
|
+
var result3 = lodashFunc.apply(lodash2, arrayPush([value2], args));
|
|
9167
|
+
return isTaker && chainAll ? result3[0] : result3;
|
|
9168
|
+
};
|
|
9169
|
+
if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) {
|
|
9170
|
+
isLazy = useLazy = false;
|
|
9171
|
+
}
|
|
9172
|
+
var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid;
|
|
9173
|
+
if (!retUnwrapped && useLazy) {
|
|
9174
|
+
value = onlyLazy ? value : new LazyWrapper(this);
|
|
9175
|
+
var result2 = func.apply(value, args);
|
|
9176
|
+
result2.__actions__.push({ "func": thru, "args": [interceptor], "thisArg": undefined$1 });
|
|
9177
|
+
return new LodashWrapper(result2, chainAll);
|
|
9178
|
+
}
|
|
9179
|
+
if (isUnwrapped && onlyLazy) {
|
|
9180
|
+
return func.apply(this, args);
|
|
9181
|
+
}
|
|
9182
|
+
result2 = this.thru(interceptor);
|
|
9183
|
+
return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2;
|
|
9184
|
+
};
|
|
9185
|
+
});
|
|
9186
|
+
arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) {
|
|
9187
|
+
var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
|
|
9188
|
+
lodash2.prototype[methodName] = function() {
|
|
9189
|
+
var args = arguments;
|
|
9190
|
+
if (retUnwrapped && !this.__chain__) {
|
|
9191
|
+
var value = this.value();
|
|
9192
|
+
return func.apply(isArray(value) ? value : [], args);
|
|
9193
|
+
}
|
|
9194
|
+
return this[chainName](function(value2) {
|
|
9195
|
+
return func.apply(isArray(value2) ? value2 : [], args);
|
|
9196
|
+
});
|
|
9197
|
+
};
|
|
9198
|
+
});
|
|
9199
|
+
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
9200
|
+
var lodashFunc = lodash2[methodName];
|
|
9201
|
+
if (lodashFunc) {
|
|
9202
|
+
var key2 = lodashFunc.name + "";
|
|
9203
|
+
if (!hasOwnProperty.call(realNames, key2)) {
|
|
9204
|
+
realNames[key2] = [];
|
|
9205
|
+
}
|
|
9206
|
+
realNames[key2].push({ "name": methodName, "func": lodashFunc });
|
|
9207
|
+
}
|
|
9208
|
+
});
|
|
9209
|
+
realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
|
|
9210
|
+
"name": "wrapper",
|
|
9211
|
+
"func": undefined$1
|
|
9212
|
+
}];
|
|
9213
|
+
LazyWrapper.prototype.clone = lazyClone;
|
|
9214
|
+
LazyWrapper.prototype.reverse = lazyReverse;
|
|
9215
|
+
LazyWrapper.prototype.value = lazyValue;
|
|
9216
|
+
lodash2.prototype.at = wrapperAt;
|
|
9217
|
+
lodash2.prototype.chain = wrapperChain;
|
|
9218
|
+
lodash2.prototype.commit = wrapperCommit;
|
|
9219
|
+
lodash2.prototype.next = wrapperNext;
|
|
9220
|
+
lodash2.prototype.plant = wrapperPlant;
|
|
9221
|
+
lodash2.prototype.reverse = wrapperReverse;
|
|
9222
|
+
lodash2.prototype.toJSON = lodash2.prototype.valueOf = lodash2.prototype.value = wrapperValue;
|
|
9223
|
+
lodash2.prototype.first = lodash2.prototype.head;
|
|
9224
|
+
if (symIterator) {
|
|
9225
|
+
lodash2.prototype[symIterator] = wrapperToIterator;
|
|
9226
|
+
}
|
|
9227
|
+
return lodash2;
|
|
9228
|
+
};
|
|
9229
|
+
var _ = runInContext();
|
|
9230
|
+
if (freeModule) {
|
|
9231
|
+
(freeModule.exports = _)._ = _;
|
|
9232
|
+
freeExports._ = _;
|
|
9233
|
+
} else {
|
|
9234
|
+
root._ = _;
|
|
9235
|
+
}
|
|
9236
|
+
}).call(commonjsGlobal);
|
|
9237
|
+
})(lodash, lodash.exports);
|
|
9238
|
+
var lodashExports = lodash.exports;
|
|
9239
|
+
class LayoutIdGenerator {
|
|
9240
|
+
constructor() {
|
|
9241
|
+
this.counter = 0;
|
|
9242
|
+
}
|
|
9243
|
+
reset() {
|
|
9244
|
+
this.counter = 0;
|
|
9245
|
+
}
|
|
9246
|
+
generate(type) {
|
|
9247
|
+
return `${type}_${++this.counter}`;
|
|
9248
|
+
}
|
|
9249
|
+
}
|
|
9250
|
+
function toJSON(ast) {
|
|
9251
|
+
const idGenerator = new LayoutIdGenerator();
|
|
9252
|
+
const widgets = {};
|
|
9253
|
+
const answers = {};
|
|
9254
|
+
const allInlines = collectAllInlines(ast.lines);
|
|
9255
|
+
const inlineDragIds = /* @__PURE__ */ new Map();
|
|
9256
|
+
{
|
|
9257
|
+
let counter = 0;
|
|
9258
|
+
for (const inline of allInlines) {
|
|
9259
|
+
if (inline.type === AST_TYPES.INLINE_DRAG_OPTION) {
|
|
9260
|
+
inlineDragIds.set(inline, `${INLINE_DRAG_OPT_PREFIX}${counter++}`);
|
|
9261
|
+
}
|
|
9262
|
+
}
|
|
9263
|
+
}
|
|
9264
|
+
const layout = [];
|
|
9265
|
+
if (ast.question) {
|
|
9266
|
+
layout.push({
|
|
9267
|
+
id: idGenerator.generate(JSON_TYPES.QUESTION_TEXT),
|
|
9268
|
+
type: JSON_TYPES.QUESTION_TEXT,
|
|
9269
|
+
value: ast.question.value
|
|
9270
|
+
});
|
|
9271
|
+
}
|
|
9272
|
+
for (const block of ast.lines) {
|
|
9273
|
+
if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
9274
|
+
layout.push(transformTable(block, idGenerator, inlineDragIds));
|
|
9275
|
+
} else if (block.type === AST_TYPES.NUMBER_LINE_BLOCK) {
|
|
9276
|
+
const nlItem = transformNumberLine(block, idGenerator, inlineDragIds);
|
|
9277
|
+
layout.push(nlItem);
|
|
9278
|
+
if (nlItem.counter?.answer !== void 0) {
|
|
9279
|
+
answers[nlItem.counter.id] = nlItem.counter.answer;
|
|
9280
|
+
}
|
|
9281
|
+
for (const cursor of nlItem.cursors ?? []) {
|
|
9282
|
+
answers[cursor.id] = cursor.answer;
|
|
9283
|
+
}
|
|
9284
|
+
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
9285
|
+
const matcherBlock = block;
|
|
9286
|
+
layout.push({
|
|
9287
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9288
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9289
|
+
widgetId: matcherBlock.name
|
|
9290
|
+
});
|
|
9291
|
+
layout.push({
|
|
9292
|
+
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
9293
|
+
type: JSON_TYPES.LINEBREAK
|
|
9294
|
+
});
|
|
9295
|
+
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
9296
|
+
const pmBlock = block;
|
|
9297
|
+
layout.push({
|
|
9298
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9299
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9300
|
+
widgetId: pmBlock.name
|
|
9301
|
+
});
|
|
9302
|
+
layout.push({
|
|
9303
|
+
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
9304
|
+
type: JSON_TYPES.LINEBREAK
|
|
9305
|
+
});
|
|
9306
|
+
} else if (block.type === AST_TYPES.VERTICAL_OPERATION_BLOCK) {
|
|
9307
|
+
layout.push(transformVerticalOperation(block, idGenerator));
|
|
9308
|
+
} else if (block.type === AST_TYPES.RADIO_OPTIONS) {
|
|
9309
|
+
const radioBlock = block;
|
|
9310
|
+
layout.push({
|
|
9311
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9312
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9313
|
+
widgetId: radioBlock.name
|
|
9314
|
+
});
|
|
9315
|
+
layout.push({
|
|
9316
|
+
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
9317
|
+
type: JSON_TYPES.LINEBREAK
|
|
9318
|
+
});
|
|
9319
|
+
} else {
|
|
9320
|
+
const lineItems = transformLine(block, idGenerator, inlineDragIds);
|
|
9321
|
+
layout.push(...lineItems);
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9324
|
+
for (const inline of allInlines) {
|
|
9325
|
+
if (inline.type === AST_TYPES.INLINE_INPUT) {
|
|
9326
|
+
if (inline.inputType === INPUT_TYPES.STRING) {
|
|
9327
|
+
widgets[inline.name] = {
|
|
9328
|
+
type: JSON_TYPES.INLINE_INPUT,
|
|
9329
|
+
inputType: INPUT_TYPES.STRING,
|
|
9330
|
+
length: inline.length,
|
|
9331
|
+
placeholder: inline.placeholder
|
|
9715
9332
|
};
|
|
9716
|
-
|
|
9717
|
-
|
|
9333
|
+
} else {
|
|
9334
|
+
widgets[inline.name] = {
|
|
9335
|
+
type: JSON_TYPES.INLINE_INPUT,
|
|
9336
|
+
inputType: INPUT_TYPES.NUMERIC,
|
|
9337
|
+
digits: inline.digits,
|
|
9338
|
+
placeholder: inline.placeholder
|
|
9718
9339
|
};
|
|
9719
|
-
}
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9340
|
+
}
|
|
9341
|
+
if (inline.answer !== void 0) {
|
|
9342
|
+
answers[inline.name] = inline.answer;
|
|
9343
|
+
}
|
|
9344
|
+
} else if (inline.type === AST_TYPES.CLOCK && inline.mode === "interactive") {
|
|
9345
|
+
answers[inline.name] = inline.answer;
|
|
9346
|
+
}
|
|
9347
|
+
if (inline.type === AST_TYPES.FRACTION) {
|
|
9348
|
+
widgets[inline.name] = {
|
|
9349
|
+
type: JSON_TYPES.FRACTION,
|
|
9350
|
+
numerator: inline.numerator ?? null,
|
|
9351
|
+
denominator: inline.denominator ?? null,
|
|
9352
|
+
simplified: inline.simplified ?? true,
|
|
9353
|
+
placeholder: inline.placeholder
|
|
9354
|
+
};
|
|
9355
|
+
if (inline.answer !== void 0) {
|
|
9356
|
+
answers[inline.name] = inline.answer;
|
|
9357
|
+
}
|
|
9358
|
+
}
|
|
9359
|
+
if (inline.type === AST_TYPES.INLINE_DRAG_OPTION) {
|
|
9360
|
+
const widgetId = inlineDragIds.get(inline);
|
|
9361
|
+
widgets[widgetId] = {
|
|
9362
|
+
type: JSON_TYPES.INLINE_DRAG_OPTION,
|
|
9363
|
+
value: inline.value
|
|
9364
|
+
};
|
|
9365
|
+
}
|
|
9366
|
+
if (inline.type === AST_TYPES.VISUAL_FRACTION) {
|
|
9367
|
+
const answerArr = inline.answer ?? [];
|
|
9368
|
+
widgets[inline.name] = {
|
|
9369
|
+
type: JSON_TYPES.VISUAL_FRACTION,
|
|
9370
|
+
shape: inline.shape,
|
|
9371
|
+
divisions: inline.divisions,
|
|
9372
|
+
filled: inline.filled ?? [],
|
|
9373
|
+
answer: answerArr,
|
|
9374
|
+
...inline.orientation !== void 0 && { orientation: inline.orientation },
|
|
9375
|
+
...inline.label !== void 0 && { label: inline.label },
|
|
9376
|
+
...inline.size !== void 0 && { size: inline.size }
|
|
9377
|
+
};
|
|
9378
|
+
if (answerArr.length > 0) {
|
|
9379
|
+
answers[inline.name] = answerArr;
|
|
9380
|
+
}
|
|
9381
|
+
}
|
|
9382
|
+
}
|
|
9383
|
+
for (const block of ast.lines) {
|
|
9384
|
+
if (block.type !== AST_TYPES.VERTICAL_OPERATION_BLOCK) continue;
|
|
9385
|
+
const vop = block;
|
|
9386
|
+
for (const item of vop.items) {
|
|
9387
|
+
if (item.type !== AST_TYPES.VOP_ROW && item.type !== AST_TYPES.VOP_CARRY_ROW) continue;
|
|
9388
|
+
for (const cell of item.cells) {
|
|
9389
|
+
if (cell.kind !== "input") continue;
|
|
9390
|
+
if (widgets[cell.name]) {
|
|
9391
|
+
throw new Error(`VERTICAL_OPERATION: duplicate INPUT name "${cell.name}"`);
|
|
9392
|
+
}
|
|
9393
|
+
widgets[cell.name] = {
|
|
9394
|
+
type: JSON_TYPES.INLINE_INPUT,
|
|
9395
|
+
inputType: INPUT_TYPES.NUMERIC,
|
|
9396
|
+
digits: cell.digits
|
|
9730
9397
|
};
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9398
|
+
if (cell.answer !== void 0) {
|
|
9399
|
+
answers[cell.name] = cell.answer;
|
|
9400
|
+
}
|
|
9401
|
+
}
|
|
9402
|
+
}
|
|
9403
|
+
}
|
|
9404
|
+
for (const block of ast.lines) {
|
|
9405
|
+
if (block.type === AST_TYPES.RADIO_OPTIONS) {
|
|
9406
|
+
const radioBlock = block;
|
|
9407
|
+
widgets[radioBlock.name] = {
|
|
9408
|
+
type: JSON_TYPES.RADIO_OPTIONS,
|
|
9409
|
+
// Randomise option order per compile so the answer position isn't fixed.
|
|
9410
|
+
options: lodashExports.shuffle(radioBlock.options)
|
|
9411
|
+
};
|
|
9412
|
+
answers[radioBlock.name] = radioBlock.answer;
|
|
9413
|
+
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
9414
|
+
const matcherBlock = block;
|
|
9415
|
+
widgets[matcherBlock.name] = buildMatcherWidget(matcherBlock, idGenerator, inlineDragIds);
|
|
9416
|
+
answers[matcherBlock.name] = matcherBlock.answers;
|
|
9417
|
+
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
9418
|
+
const pmBlock = block;
|
|
9419
|
+
widgets[pmBlock.name] = buildPairMatcherWidget(pmBlock, idGenerator, inlineDragIds);
|
|
9420
|
+
answers[pmBlock.name] = pmBlock.answers;
|
|
9421
|
+
}
|
|
9422
|
+
}
|
|
9423
|
+
if (ast.tools) {
|
|
9424
|
+
for (const tool of ast.tools) {
|
|
9425
|
+
if (tool.type === AST_TYPES.DRAG_OPTIONS) {
|
|
9426
|
+
widgets["_drag_options"] = {
|
|
9427
|
+
type: JSON_TYPES.DRAG_OPTIONS,
|
|
9428
|
+
// Randomise chip order per compile so the answer position isn't fixed.
|
|
9429
|
+
options: lodashExports.shuffle(tool.options)
|
|
9736
9430
|
};
|
|
9737
|
-
})
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9431
|
+
} else if (tool.type === AST_TYPES.NUMERIC_KEYPAD) {
|
|
9432
|
+
widgets["_numeric_keypad"] = {
|
|
9433
|
+
type: JSON_TYPES.NUMERIC_KEYPAD,
|
|
9434
|
+
includeOperators: tool.includeOperators,
|
|
9435
|
+
includeDecimal: tool.includeDecimal,
|
|
9436
|
+
style: tool.style
|
|
9437
|
+
};
|
|
9438
|
+
} else if (tool.type === AST_TYPES.GEOMETRY_RULER) {
|
|
9439
|
+
widgets[RULER_WIDGET_ID] = {
|
|
9440
|
+
type: JSON_TYPES.RULER,
|
|
9441
|
+
size: tool.size
|
|
9442
|
+
};
|
|
9443
|
+
} else if (tool.type === AST_TYPES.GEOMETRY_PROTRACTOR) {
|
|
9444
|
+
widgets[PROTRACTOR_WIDGET_ID] = {
|
|
9445
|
+
type: JSON_TYPES.PROTRACTOR,
|
|
9446
|
+
size: tool.size
|
|
9447
|
+
};
|
|
9448
|
+
} else if (tool.type === AST_TYPES.GEOMETRY_SET_SQUARE) {
|
|
9449
|
+
widgets[SET_SQUARE_WIDGET_ID] = {
|
|
9450
|
+
type: JSON_TYPES.SET_SQUARE,
|
|
9451
|
+
size: tool.size
|
|
9452
|
+
};
|
|
9453
|
+
}
|
|
9454
|
+
}
|
|
9455
|
+
}
|
|
9456
|
+
return {
|
|
9457
|
+
version: "2.0",
|
|
9458
|
+
// Natural DSL version
|
|
9459
|
+
layout,
|
|
9460
|
+
widgets,
|
|
9461
|
+
...ast.validation ? { validation: transformValidation(ast.validation, answers, widgets) } : {}
|
|
9462
|
+
};
|
|
9463
|
+
}
|
|
9464
|
+
function collectAllInlines(blocks) {
|
|
9465
|
+
const result = [];
|
|
9466
|
+
for (const block of blocks) {
|
|
9467
|
+
if (block.type === AST_TYPES.LINE_BLOCK) {
|
|
9468
|
+
result.push(...block.inlines);
|
|
9469
|
+
} else if (block.type === AST_TYPES.TABLE_BLOCK) {
|
|
9470
|
+
for (const row of block.rows) {
|
|
9471
|
+
for (const cell of row.cells) {
|
|
9472
|
+
result.push(...cell.inlines);
|
|
9473
|
+
}
|
|
9474
|
+
}
|
|
9475
|
+
} else if (block.type === AST_TYPES.NUMBER_LINE_BLOCK) {
|
|
9476
|
+
const numberLine = block;
|
|
9477
|
+
for (const position of numberLine.positions) {
|
|
9478
|
+
result.push(...position.inlines);
|
|
9479
|
+
}
|
|
9480
|
+
for (const arrow of numberLine.arrows ?? []) {
|
|
9481
|
+
result.push(...arrow.inlines);
|
|
9482
|
+
}
|
|
9483
|
+
} else if (block.type === AST_TYPES.MATCHER_BLOCK) {
|
|
9484
|
+
for (const row of block.rows) {
|
|
9485
|
+
for (const item of row.items) {
|
|
9486
|
+
result.push(...item.inlines);
|
|
9487
|
+
}
|
|
9488
|
+
}
|
|
9489
|
+
} else if (block.type === AST_TYPES.PAIR_MATCHER_BLOCK) {
|
|
9490
|
+
const pm = block;
|
|
9491
|
+
for (const item of [...pm.topItems, ...pm.bottomItems]) {
|
|
9492
|
+
result.push(...item.inlines);
|
|
9493
|
+
}
|
|
9494
|
+
}
|
|
9495
|
+
}
|
|
9496
|
+
return result;
|
|
9497
|
+
}
|
|
9498
|
+
function transformNumberLine(numberLine, idGenerator, inlineDragIds) {
|
|
9499
|
+
const positions = numberLine.positions.map((pos) => {
|
|
9500
|
+
const content = pos.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds));
|
|
9501
|
+
return {
|
|
9502
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_POSITION),
|
|
9503
|
+
type: JSON_TYPES.NUMBER_LINE_POSITION,
|
|
9504
|
+
value: pos.value,
|
|
9505
|
+
content
|
|
9506
|
+
};
|
|
9507
|
+
});
|
|
9508
|
+
let counterItem;
|
|
9509
|
+
if (numberLine.counter !== void 0) {
|
|
9510
|
+
const c = numberLine.counter;
|
|
9511
|
+
counterItem = {
|
|
9512
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_COUNTER),
|
|
9513
|
+
type: JSON_TYPES.NUMBER_LINE_COUNTER,
|
|
9514
|
+
min: c.min,
|
|
9515
|
+
max: c.max,
|
|
9516
|
+
...c.default !== void 0 && { default: c.default },
|
|
9517
|
+
...c.name !== void 0 && { name: c.name },
|
|
9518
|
+
...c.answer !== void 0 && { answer: c.answer }
|
|
9519
|
+
};
|
|
9520
|
+
}
|
|
9521
|
+
let highlights;
|
|
9522
|
+
if (numberLine.highlights !== void 0 && numberLine.highlights.length > 0) {
|
|
9523
|
+
highlights = numberLine.highlights.map((h) => ({
|
|
9524
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_HIGHLIGHT),
|
|
9525
|
+
type: JSON_TYPES.NUMBER_LINE_HIGHLIGHT,
|
|
9526
|
+
from: h.from,
|
|
9527
|
+
to: h.to,
|
|
9528
|
+
...h.color !== void 0 && { color: h.color },
|
|
9529
|
+
...h.label !== void 0 && { label: h.label }
|
|
9530
|
+
}));
|
|
9531
|
+
}
|
|
9532
|
+
let cursors;
|
|
9533
|
+
if (numberLine.cursors !== void 0 && numberLine.cursors.length > 0) {
|
|
9534
|
+
cursors = numberLine.cursors.map((c) => ({
|
|
9535
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_CURSOR),
|
|
9536
|
+
type: JSON_TYPES.NUMBER_LINE_CURSOR,
|
|
9537
|
+
value: c.value,
|
|
9538
|
+
answer: c.answer,
|
|
9539
|
+
fillRange: c.fillRange,
|
|
9540
|
+
...c.color !== void 0 && { color: c.color },
|
|
9541
|
+
...c.label !== void 0 && { label: c.label }
|
|
9542
|
+
}));
|
|
9543
|
+
}
|
|
9544
|
+
let arrows;
|
|
9545
|
+
if (numberLine.arrows !== void 0 && numberLine.arrows.length > 0) {
|
|
9546
|
+
arrows = numberLine.arrows.map((a) => ({
|
|
9547
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE_ARROW),
|
|
9548
|
+
type: JSON_TYPES.NUMBER_LINE_ARROW,
|
|
9549
|
+
from: a.from,
|
|
9550
|
+
to: a.to,
|
|
9551
|
+
...a.color !== void 0 && { color: a.color },
|
|
9552
|
+
content: a.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds))
|
|
9553
|
+
}));
|
|
9554
|
+
}
|
|
9555
|
+
const item = {
|
|
9556
|
+
id: idGenerator.generate(JSON_TYPES.NUMBER_LINE),
|
|
9557
|
+
type: JSON_TYPES.NUMBER_LINE,
|
|
9558
|
+
min: numberLine.min,
|
|
9559
|
+
max: numberLine.max,
|
|
9560
|
+
step: numberLine.step,
|
|
9561
|
+
...numberLine.minorTicks !== void 0 && { minorTicks: numberLine.minorTicks },
|
|
9562
|
+
...numberLine.style !== void 0 && { style: numberLine.style },
|
|
9563
|
+
...numberLine.labelVisibility !== void 0 && { labelVisibility: numberLine.labelVisibility },
|
|
9564
|
+
...counterItem !== void 0 && { counter: counterItem },
|
|
9565
|
+
...highlights !== void 0 && { highlights },
|
|
9566
|
+
...cursors !== void 0 && { cursors },
|
|
9567
|
+
...arrows !== void 0 && { arrows },
|
|
9568
|
+
...numberLine.dragMode !== void 0 && { dragMode: numberLine.dragMode },
|
|
9569
|
+
positions
|
|
9570
|
+
};
|
|
9571
|
+
return item;
|
|
9572
|
+
}
|
|
9573
|
+
function mapMatcherItemList(items, idGenerator, inlineDragIds) {
|
|
9574
|
+
return items.map((item) => ({
|
|
9575
|
+
id: idGenerator.generate(JSON_TYPES.MATCHER_ITEM),
|
|
9576
|
+
type: JSON_TYPES.MATCHER_ITEM,
|
|
9577
|
+
itemId: item.itemId,
|
|
9578
|
+
content: item.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds))
|
|
9579
|
+
}));
|
|
9580
|
+
}
|
|
9581
|
+
function buildMatcherWidget(matcher, idGenerator, inlineDragIds) {
|
|
9582
|
+
const rows = matcher.rows.map((row) => ({
|
|
9583
|
+
id: idGenerator.generate(JSON_TYPES.MATCHER_ROW),
|
|
9584
|
+
type: JSON_TYPES.MATCHER_ROW,
|
|
9585
|
+
items: mapMatcherItemList(row.items, idGenerator, inlineDragIds)
|
|
9586
|
+
}));
|
|
9587
|
+
const result = {
|
|
9588
|
+
type: JSON_TYPES.MATCHER,
|
|
9589
|
+
rows,
|
|
9590
|
+
groupCount: matcher.answers.length
|
|
9591
|
+
};
|
|
9592
|
+
if (matcher.colors !== void 0) {
|
|
9593
|
+
result.colors = matcher.colors;
|
|
9594
|
+
}
|
|
9595
|
+
return result;
|
|
9596
|
+
}
|
|
9597
|
+
function buildPairMatcherWidget(pm, idGenerator, inlineDragIds) {
|
|
9598
|
+
return {
|
|
9599
|
+
type: JSON_TYPES.PAIR_MATCHER,
|
|
9600
|
+
topItems: mapMatcherItemList(pm.topItems, idGenerator, inlineDragIds),
|
|
9601
|
+
bottomItems: mapMatcherItemList(pm.bottomItems, idGenerator, inlineDragIds)
|
|
9602
|
+
};
|
|
9603
|
+
}
|
|
9604
|
+
function transformVerticalOperation(vop, idGenerator) {
|
|
9605
|
+
const anyRowHasOp = vop.items.some(
|
|
9606
|
+
(item) => item.type === AST_TYPES.VOP_ROW && item.op !== void 0
|
|
9607
|
+
);
|
|
9608
|
+
if (!anyRowHasOp && vop.op === void 0) {
|
|
9609
|
+
throw new Error("VERTICAL_OPERATION: at least one op is required (set op on the block or on individual ROWs)");
|
|
9610
|
+
}
|
|
9611
|
+
let cols = 1;
|
|
9612
|
+
for (const item of vop.items) {
|
|
9613
|
+
if (item.type === AST_TYPES.VOP_ROW || item.type === AST_TYPES.VOP_CARRY_ROW) {
|
|
9614
|
+
cols = Math.max(cols, item.cells.length);
|
|
9615
|
+
}
|
|
9616
|
+
}
|
|
9617
|
+
function buildCells(row) {
|
|
9618
|
+
return row.cells.map((cell) => {
|
|
9619
|
+
const id = idGenerator.generate(JSON_TYPES.VOP_CELL);
|
|
9620
|
+
if (cell.kind === "digit") return { id, type: JSON_TYPES.VOP_CELL, kind: "digit", value: cell.value };
|
|
9621
|
+
if (cell.kind === "label") return { id, type: JSON_TYPES.VOP_CELL, kind: "label", value: cell.value };
|
|
9622
|
+
if (cell.kind === "color") return { id, type: JSON_TYPES.VOP_CELL, kind: "color", value: cell.value, color: cell.color };
|
|
9623
|
+
if (cell.kind === "bold") return { id, type: JSON_TYPES.VOP_CELL, kind: "bold", value: cell.value };
|
|
9624
|
+
if (cell.kind === "highlight") return { id, type: JSON_TYPES.VOP_CELL, kind: "highlight", value: cell.value };
|
|
9625
|
+
if (cell.kind === "input") return { id, type: JSON_TYPES.VOP_CELL, kind: "input", widgetId: cell.name };
|
|
9626
|
+
return { id, type: JSON_TYPES.VOP_CELL, kind: "empty" };
|
|
9627
|
+
});
|
|
9628
|
+
}
|
|
9629
|
+
const items = vop.items.map((item) => {
|
|
9630
|
+
if (item.type === AST_TYPES.VOP_SEPARATOR) {
|
|
9631
|
+
return {
|
|
9632
|
+
id: idGenerator.generate(JSON_TYPES.VOP_SEPARATOR),
|
|
9633
|
+
type: JSON_TYPES.VOP_SEPARATOR
|
|
9634
|
+
};
|
|
9635
|
+
}
|
|
9636
|
+
if (item.type === AST_TYPES.VOP_CARRY_ROW) {
|
|
9637
|
+
return {
|
|
9638
|
+
id: idGenerator.generate(JSON_TYPES.VOP_CARRY_ROW),
|
|
9639
|
+
type: JSON_TYPES.VOP_CARRY_ROW,
|
|
9640
|
+
cells: buildCells(item)
|
|
9641
|
+
};
|
|
9642
|
+
}
|
|
9643
|
+
const row = item;
|
|
9644
|
+
return {
|
|
9645
|
+
id: idGenerator.generate(JSON_TYPES.VOP_ROW),
|
|
9646
|
+
type: JSON_TYPES.VOP_ROW,
|
|
9647
|
+
cells: buildCells(row),
|
|
9648
|
+
...row.op !== void 0 && { op: row.op }
|
|
9649
|
+
};
|
|
9650
|
+
});
|
|
9651
|
+
return {
|
|
9652
|
+
id: idGenerator.generate(JSON_TYPES.VERTICAL_OPERATION),
|
|
9653
|
+
type: JSON_TYPES.VERTICAL_OPERATION,
|
|
9654
|
+
op: vop.op,
|
|
9655
|
+
cols,
|
|
9656
|
+
items
|
|
9657
|
+
};
|
|
9658
|
+
}
|
|
9659
|
+
function transformTable(table, idGenerator, inlineDragIds) {
|
|
9660
|
+
const rows = table.rows.map((row) => {
|
|
9661
|
+
const cells = row.cells.map((cell) => {
|
|
9662
|
+
const items = cell.inlines.map((inline) => transformInline(inline, idGenerator, inlineDragIds));
|
|
9663
|
+
const cellItem = {
|
|
9664
|
+
id: idGenerator.generate(JSON_TYPES.TABLE_CELL),
|
|
9665
|
+
type: JSON_TYPES.TABLE_CELL,
|
|
9666
|
+
items
|
|
9667
|
+
};
|
|
9668
|
+
if (cell.colspan !== void 0) {
|
|
9669
|
+
cellItem.colspan = cell.colspan;
|
|
9670
|
+
}
|
|
9671
|
+
return cellItem;
|
|
9672
|
+
});
|
|
9673
|
+
return {
|
|
9674
|
+
id: idGenerator.generate(JSON_TYPES.TABLE_ROW),
|
|
9675
|
+
type: JSON_TYPES.TABLE_ROW,
|
|
9676
|
+
cells
|
|
9677
|
+
};
|
|
9678
|
+
});
|
|
9679
|
+
return {
|
|
9680
|
+
id: idGenerator.generate(JSON_TYPES.TABLE),
|
|
9681
|
+
type: JSON_TYPES.TABLE,
|
|
9682
|
+
cols: table.cols,
|
|
9683
|
+
rows
|
|
9684
|
+
};
|
|
9685
|
+
}
|
|
9686
|
+
function transformLine(line, idGenerator, inlineDragIds) {
|
|
9687
|
+
const items = [];
|
|
9688
|
+
for (const inline of line.inlines) {
|
|
9689
|
+
items.push(transformInline(inline, idGenerator, inlineDragIds));
|
|
9690
|
+
}
|
|
9691
|
+
items.push({
|
|
9692
|
+
id: idGenerator.generate(JSON_TYPES.LINEBREAK),
|
|
9693
|
+
type: JSON_TYPES.LINEBREAK
|
|
9694
|
+
});
|
|
9695
|
+
return items;
|
|
9696
|
+
}
|
|
9697
|
+
function transformInline(inline, idGenerator, inlineDragIds) {
|
|
9698
|
+
switch (inline.type) {
|
|
9699
|
+
case AST_TYPES.FREE_TEXT: {
|
|
9700
|
+
const trimmed = inline.value.trim();
|
|
9701
|
+
const operators = ["+", "-", "×", "÷", "=", "<", ">", "?"];
|
|
9702
|
+
if (operators.includes(trimmed) && inline.value.trim() === inline.value) {
|
|
9703
|
+
return {
|
|
9704
|
+
id: idGenerator.generate("operator"),
|
|
9705
|
+
type: "operator",
|
|
9706
|
+
operator: trimmed
|
|
9742
9707
|
};
|
|
9743
|
-
}
|
|
9744
|
-
|
|
9745
|
-
|
|
9708
|
+
}
|
|
9709
|
+
return {
|
|
9710
|
+
id: idGenerator.generate(JSON_TYPES.TEXT),
|
|
9711
|
+
type: JSON_TYPES.TEXT,
|
|
9712
|
+
value: inline.value
|
|
9746
9713
|
};
|
|
9747
|
-
|
|
9748
|
-
|
|
9714
|
+
}
|
|
9715
|
+
case AST_TYPES.SPACE:
|
|
9716
|
+
return {
|
|
9717
|
+
id: idGenerator.generate(JSON_TYPES.SPACE),
|
|
9718
|
+
type: JSON_TYPES.SPACE
|
|
9749
9719
|
};
|
|
9750
|
-
|
|
9751
|
-
|
|
9720
|
+
case AST_TYPES.HIGHLIGHTED_TEXT:
|
|
9721
|
+
return {
|
|
9722
|
+
id: idGenerator.generate(JSON_TYPES.HIGHLIGHTED_TEXT),
|
|
9723
|
+
type: JSON_TYPES.HIGHLIGHTED_TEXT,
|
|
9724
|
+
value: inline.value,
|
|
9725
|
+
highlight: inline.highlight
|
|
9752
9726
|
};
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
}
|
|
9761
|
-
|
|
9762
|
-
|
|
9727
|
+
case AST_TYPES.COLOR_TEXT:
|
|
9728
|
+
return {
|
|
9729
|
+
id: idGenerator.generate(JSON_TYPES.COLOR_TEXT),
|
|
9730
|
+
type: JSON_TYPES.COLOR_TEXT,
|
|
9731
|
+
value: inline.value,
|
|
9732
|
+
color: inline.color,
|
|
9733
|
+
highlight: inline.highlight
|
|
9734
|
+
};
|
|
9735
|
+
case AST_TYPES.BOLD_TEXT:
|
|
9736
|
+
return {
|
|
9737
|
+
id: idGenerator.generate(JSON_TYPES.BOLD_TEXT),
|
|
9738
|
+
type: JSON_TYPES.BOLD_TEXT,
|
|
9739
|
+
value: inline.value,
|
|
9740
|
+
highlight: inline.highlight
|
|
9741
|
+
};
|
|
9742
|
+
case AST_TYPES.INLINE_INPUT:
|
|
9743
|
+
return {
|
|
9744
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9745
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9746
|
+
widgetId: inline.name
|
|
9747
|
+
};
|
|
9748
|
+
case AST_TYPES.FRACTION:
|
|
9749
|
+
return {
|
|
9750
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9751
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9752
|
+
widgetId: inline.name
|
|
9763
9753
|
};
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
result2 = result2.drop(start);
|
|
9774
|
-
}
|
|
9775
|
-
if (end !== undefined$1) {
|
|
9776
|
-
end = toInteger(end);
|
|
9777
|
-
result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start);
|
|
9778
|
-
}
|
|
9779
|
-
return result2;
|
|
9754
|
+
case AST_TYPES.IMAGE:
|
|
9755
|
+
return {
|
|
9756
|
+
id: idGenerator.generate(JSON_TYPES.IMAGE),
|
|
9757
|
+
type: JSON_TYPES.IMAGE,
|
|
9758
|
+
name: inline.name,
|
|
9759
|
+
src: inline.src,
|
|
9760
|
+
alt: inline.alt,
|
|
9761
|
+
...inline.width !== void 0 && { width: inline.width },
|
|
9762
|
+
...inline.height !== void 0 && { height: inline.height }
|
|
9780
9763
|
};
|
|
9781
|
-
|
|
9782
|
-
|
|
9764
|
+
case AST_TYPES.VISUAL_FRACTION:
|
|
9765
|
+
return {
|
|
9766
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9767
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9768
|
+
widgetId: inline.name
|
|
9783
9769
|
};
|
|
9784
|
-
|
|
9785
|
-
|
|
9770
|
+
case AST_TYPES.INLINE_DRAG_OPTION:
|
|
9771
|
+
return {
|
|
9772
|
+
id: idGenerator.generate(JSON_TYPES.WIDGET_REF),
|
|
9773
|
+
type: JSON_TYPES.WIDGET_REF,
|
|
9774
|
+
widgetId: inlineDragIds.get(inline)
|
|
9786
9775
|
};
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
isLazy = useLazy = false;
|
|
9800
|
-
}
|
|
9801
|
-
var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid;
|
|
9802
|
-
if (!retUnwrapped && useLazy) {
|
|
9803
|
-
value = onlyLazy ? value : new LazyWrapper(this);
|
|
9804
|
-
var result2 = func.apply(value, args);
|
|
9805
|
-
result2.__actions__.push({ "func": thru, "args": [interceptor], "thisArg": undefined$1 });
|
|
9806
|
-
return new LodashWrapper(result2, chainAll);
|
|
9807
|
-
}
|
|
9808
|
-
if (isUnwrapped && onlyLazy) {
|
|
9809
|
-
return func.apply(this, args);
|
|
9810
|
-
}
|
|
9811
|
-
result2 = this.thru(interceptor);
|
|
9812
|
-
return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2;
|
|
9813
|
-
};
|
|
9814
|
-
});
|
|
9815
|
-
arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) {
|
|
9816
|
-
var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
|
|
9817
|
-
lodash2.prototype[methodName] = function() {
|
|
9818
|
-
var args = arguments;
|
|
9819
|
-
if (retUnwrapped && !this.__chain__) {
|
|
9820
|
-
var value = this.value();
|
|
9821
|
-
return func.apply(isArray(value) ? value : [], args);
|
|
9822
|
-
}
|
|
9823
|
-
return this[chainName](function(value2) {
|
|
9824
|
-
return func.apply(isArray(value2) ? value2 : [], args);
|
|
9825
|
-
});
|
|
9826
|
-
};
|
|
9827
|
-
});
|
|
9828
|
-
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
9829
|
-
var lodashFunc = lodash2[methodName];
|
|
9830
|
-
if (lodashFunc) {
|
|
9831
|
-
var key2 = lodashFunc.name + "";
|
|
9832
|
-
if (!hasOwnProperty.call(realNames, key2)) {
|
|
9833
|
-
realNames[key2] = [];
|
|
9834
|
-
}
|
|
9835
|
-
realNames[key2].push({ "name": methodName, "func": lodashFunc });
|
|
9836
|
-
}
|
|
9837
|
-
});
|
|
9838
|
-
realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
|
|
9839
|
-
"name": "wrapper",
|
|
9840
|
-
"func": undefined$1
|
|
9841
|
-
}];
|
|
9842
|
-
LazyWrapper.prototype.clone = lazyClone;
|
|
9843
|
-
LazyWrapper.prototype.reverse = lazyReverse;
|
|
9844
|
-
LazyWrapper.prototype.value = lazyValue;
|
|
9845
|
-
lodash2.prototype.at = wrapperAt;
|
|
9846
|
-
lodash2.prototype.chain = wrapperChain;
|
|
9847
|
-
lodash2.prototype.commit = wrapperCommit;
|
|
9848
|
-
lodash2.prototype.next = wrapperNext;
|
|
9849
|
-
lodash2.prototype.plant = wrapperPlant;
|
|
9850
|
-
lodash2.prototype.reverse = wrapperReverse;
|
|
9851
|
-
lodash2.prototype.toJSON = lodash2.prototype.valueOf = lodash2.prototype.value = wrapperValue;
|
|
9852
|
-
lodash2.prototype.first = lodash2.prototype.head;
|
|
9853
|
-
if (symIterator) {
|
|
9854
|
-
lodash2.prototype[symIterator] = wrapperToIterator;
|
|
9776
|
+
case AST_TYPES.CLOCK: {
|
|
9777
|
+
const base = {
|
|
9778
|
+
id: idGenerator.generate(JSON_TYPES.CLOCK),
|
|
9779
|
+
type: JSON_TYPES.CLOCK,
|
|
9780
|
+
mode: inline.mode,
|
|
9781
|
+
clockType: inline.clockType,
|
|
9782
|
+
value: inline.value,
|
|
9783
|
+
...inline.format !== void 0 && { format: inline.format },
|
|
9784
|
+
...inline.name !== void 0 && { name: inline.name }
|
|
9785
|
+
};
|
|
9786
|
+
if (inline.mode === "interactive") {
|
|
9787
|
+
return { ...base, ...inline.snap !== void 0 && { snap: inline.snap } };
|
|
9855
9788
|
}
|
|
9856
|
-
return
|
|
9789
|
+
return base;
|
|
9790
|
+
}
|
|
9791
|
+
default:
|
|
9792
|
+
throw new Error(`Unknown inline type: ${inline.type}`);
|
|
9793
|
+
}
|
|
9794
|
+
}
|
|
9795
|
+
function transformValidation(validation, answers, widgets) {
|
|
9796
|
+
if (validation.type === AST_TYPES.SIMPLE_VALIDATION) {
|
|
9797
|
+
return {
|
|
9798
|
+
mode: VALIDATION_MODES.SIMPLE,
|
|
9799
|
+
answers
|
|
9857
9800
|
};
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9801
|
+
} else if (validation.type === AST_TYPES.EXPRESSION_VALIDATION) {
|
|
9802
|
+
const validVariableNames = Object.keys(widgets);
|
|
9803
|
+
const variables = extractVariables$1(validation.expression, validVariableNames);
|
|
9804
|
+
return {
|
|
9805
|
+
mode: VALIDATION_MODES.EXPRESSION,
|
|
9806
|
+
expression: validation.expression,
|
|
9807
|
+
variables
|
|
9808
|
+
};
|
|
9809
|
+
} else if (validation.type === AST_TYPES.MIXED_VALIDATION) {
|
|
9810
|
+
const validVariableNames = Object.keys(widgets);
|
|
9811
|
+
const variables = extractVariables$1(validation.expression, validVariableNames);
|
|
9812
|
+
const inExpression = new Set(variables);
|
|
9813
|
+
for (const [name, widget] of Object.entries(widgets)) {
|
|
9814
|
+
if (name.startsWith("_")) continue;
|
|
9815
|
+
if (name in answers) continue;
|
|
9816
|
+
if (inExpression.has(name)) continue;
|
|
9817
|
+
if (widget.type === JSON_TYPES.FRACTION) {
|
|
9818
|
+
const w = widget;
|
|
9819
|
+
if (w.numerator !== null && w.denominator !== null) continue;
|
|
9820
|
+
}
|
|
9821
|
+
if (widget.type === JSON_TYPES.VISUAL_FRACTION) {
|
|
9822
|
+
const w = widget;
|
|
9823
|
+
if (Array.isArray(w.filled) && w.filled.length > 0) continue;
|
|
9824
|
+
}
|
|
9825
|
+
throw new Error(
|
|
9826
|
+
`Mixed validation: widget "${name}" has no \`answer\` and is not referenced in expression "${validation.expression}"`
|
|
9827
|
+
);
|
|
9864
9828
|
}
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9829
|
+
return {
|
|
9830
|
+
mode: VALIDATION_MODES.MIXED,
|
|
9831
|
+
expression: validation.expression,
|
|
9832
|
+
answers,
|
|
9833
|
+
variables
|
|
9834
|
+
};
|
|
9835
|
+
}
|
|
9836
|
+
throw new Error(`Unknown validation type: ${validation.type}`);
|
|
9837
|
+
}
|
|
9838
|
+
function extractVariables$1(expression, validVariables) {
|
|
9839
|
+
const matches = expression.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g) || [];
|
|
9840
|
+
const variables = matches.filter(
|
|
9841
|
+
(v) => v !== "true" && v !== "false" && v !== "null" && v !== "undefined"
|
|
9842
|
+
);
|
|
9843
|
+
const uniqueVars = Array.from(new Set(variables));
|
|
9844
|
+
if (validVariables && validVariables.length > 0) {
|
|
9845
|
+
return uniqueVars.filter((v) => validVariables.includes(v));
|
|
9846
|
+
}
|
|
9847
|
+
return uniqueVars;
|
|
9848
|
+
}
|
|
9849
|
+
function normalize(value) {
|
|
9850
|
+
if (typeof value === "number") {
|
|
9851
|
+
return String(Math.round(value * 10 ** INTERNAL_PRECISION) / 10 ** INTERNAL_PRECISION);
|
|
9852
|
+
}
|
|
9853
|
+
const trimmed = String(value).trim().toLowerCase().replace(/^["']|["']$/g, "");
|
|
9854
|
+
const asNum = Number(trimmed);
|
|
9855
|
+
if (trimmed !== "" && !isNaN(asNum)) {
|
|
9856
|
+
return String(Math.round(asNum * 10 ** INTERNAL_PRECISION) / 10 ** INTERNAL_PRECISION);
|
|
9857
|
+
}
|
|
9858
|
+
return trimmed;
|
|
9859
|
+
}
|
|
9860
|
+
const NL_DRAG_PREFIX = "\0nl-drag\0";
|
|
9861
|
+
const isNLDragEncoded = (v) => v.startsWith(NL_DRAG_PREFIX);
|
|
9862
|
+
const encodeNLDragValue = (label, position) => `${NL_DRAG_PREFIX}${label}@${String(position)}`;
|
|
9863
|
+
function isNLDragCorrect(encoded, expectedLabel, expectedPosition) {
|
|
9864
|
+
const payload = encoded.slice(NL_DRAG_PREFIX.length);
|
|
9865
|
+
const atIdx = payload.lastIndexOf("@");
|
|
9866
|
+
const label = normalize(payload.slice(0, atIdx));
|
|
9867
|
+
const position = normalize(payload.slice(atIdx + 1));
|
|
9868
|
+
return label === normalize(expectedLabel) && position === normalize(expectedPosition);
|
|
9869
|
+
}
|
|
9868
9870
|
function areMatcherEqual(expected, result) {
|
|
9869
9871
|
if (!Array.isArray(result)) return false;
|
|
9870
9872
|
if (expected.length !== result.length) return false;
|
|
@@ -17418,6 +17420,11 @@ function getArrowArcLayouts(arrows, min, max) {
|
|
|
17418
17420
|
}
|
|
17419
17421
|
return sorted.sort((a, b) => a.index - b.index);
|
|
17420
17422
|
}
|
|
17423
|
+
function getArrowArcsRowHeight(layouts) {
|
|
17424
|
+
if (layouts.length === 0) return 0;
|
|
17425
|
+
const levelCount = Math.max(...layouts.map((layout) => layout.level)) + 1;
|
|
17426
|
+
return levelCount * ARROW_ARC_LEVEL_HEIGHT;
|
|
17427
|
+
}
|
|
17421
17428
|
function useElementWidth() {
|
|
17422
17429
|
const ref = useRef(null);
|
|
17423
17430
|
const [width, setWidth] = useState(0);
|
|
@@ -17518,9 +17525,8 @@ const ArrowArc = ({
|
|
|
17518
17525
|
);
|
|
17519
17526
|
};
|
|
17520
17527
|
const ArrowArcsRow = ({
|
|
17521
|
-
|
|
17522
|
-
|
|
17523
|
-
max,
|
|
17528
|
+
layouts,
|
|
17529
|
+
rowHeight,
|
|
17524
17530
|
widgets,
|
|
17525
17531
|
values,
|
|
17526
17532
|
droppedInputs,
|
|
@@ -17528,14 +17534,12 @@ const ArrowArcsRow = ({
|
|
|
17528
17534
|
onChange,
|
|
17529
17535
|
onInputFocus
|
|
17530
17536
|
}) => {
|
|
17531
|
-
const layouts = useMemo(() => getArrowArcLayouts(arrows, min, max), [arrows, min, max]);
|
|
17532
17537
|
if (layouts.length === 0) return null;
|
|
17533
|
-
const levelCount = Math.max(...layouts.map((layout) => layout.level)) + 1;
|
|
17534
17538
|
return /* @__PURE__ */ jsx(
|
|
17535
17539
|
"div",
|
|
17536
17540
|
{
|
|
17537
17541
|
className: "number-line-arrow-arcs-row",
|
|
17538
|
-
style: { height: `${
|
|
17542
|
+
style: { height: `${rowHeight}px` },
|
|
17539
17543
|
children: layouts.map((layout) => /* @__PURE__ */ jsx(
|
|
17540
17544
|
ArrowArc,
|
|
17541
17545
|
{
|
|
@@ -17726,6 +17730,15 @@ const NumberLineRenderer = ({
|
|
|
17726
17730
|
[visiblePositions]
|
|
17727
17731
|
);
|
|
17728
17732
|
const { positionContentHeight, getPositionContentRef } = useMeasuredPositionContentHeight(visiblePositionIds);
|
|
17733
|
+
const arrowArcLayouts = useMemo(
|
|
17734
|
+
() => getArrowArcLayouts(arrows, min, max),
|
|
17735
|
+
[arrows, min, max]
|
|
17736
|
+
);
|
|
17737
|
+
const arrowArcsRowHeight = useMemo(
|
|
17738
|
+
() => getArrowArcsRowHeight(arrowArcLayouts),
|
|
17739
|
+
[arrowArcLayouts]
|
|
17740
|
+
);
|
|
17741
|
+
const hasOverlayRow = arrowArcsRowHeight > 0 || visiblePositions.length > 0;
|
|
17729
17742
|
const nlValidationStatus = useMemo(() => {
|
|
17730
17743
|
if (!validationDetails || counter === void 0) return null;
|
|
17731
17744
|
if (counter.answer === void 0) return null;
|
|
@@ -17755,40 +17768,48 @@ const NumberLineRenderer = ({
|
|
|
17755
17768
|
role: "group",
|
|
17756
17769
|
"aria-label": `Number line from ${min} to ${max}`,
|
|
17757
17770
|
children: [
|
|
17758
|
-
|
|
17771
|
+
hasOverlayRow && /* @__PURE__ */ jsxs(
|
|
17759
17772
|
"div",
|
|
17760
17773
|
{
|
|
17761
|
-
|
|
17762
|
-
|
|
17763
|
-
|
|
17764
|
-
|
|
17765
|
-
|
|
17766
|
-
|
|
17767
|
-
|
|
17768
|
-
|
|
17769
|
-
|
|
17770
|
-
|
|
17771
|
-
|
|
17772
|
-
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17777
|
-
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17788
|
-
|
|
17789
|
-
|
|
17790
|
-
|
|
17791
|
-
|
|
17774
|
+
className: "number-line-overlays-row",
|
|
17775
|
+
style: { "--nl-arrow-arcs-row-height": `${arrowArcsRowHeight}px` },
|
|
17776
|
+
children: [
|
|
17777
|
+
/* @__PURE__ */ jsx(
|
|
17778
|
+
ArrowArcsRow,
|
|
17779
|
+
{
|
|
17780
|
+
layouts: arrowArcLayouts,
|
|
17781
|
+
rowHeight: arrowArcsRowHeight,
|
|
17782
|
+
widgets,
|
|
17783
|
+
values,
|
|
17784
|
+
droppedInputs,
|
|
17785
|
+
validationDetails,
|
|
17786
|
+
onChange,
|
|
17787
|
+
onInputFocus
|
|
17788
|
+
}
|
|
17789
|
+
),
|
|
17790
|
+
visiblePositions.length > 0 && /* @__PURE__ */ jsx("div", { className: "number-line-content-row", children: visiblePositions.map((pos) => /* @__PURE__ */ jsx(
|
|
17791
|
+
"div",
|
|
17792
|
+
{
|
|
17793
|
+
ref: getPositionContentRef(pos.id),
|
|
17794
|
+
className: "number-line-position-content",
|
|
17795
|
+
style: { left: `${toPercent(pos.value, min, max)}%` },
|
|
17796
|
+
children: pos.content.map((subItem) => /* @__PURE__ */ jsx(
|
|
17797
|
+
LayoutRenderer,
|
|
17798
|
+
{
|
|
17799
|
+
item: subItem,
|
|
17800
|
+
widgets,
|
|
17801
|
+
values,
|
|
17802
|
+
droppedInputs,
|
|
17803
|
+
validationDetails,
|
|
17804
|
+
onChange,
|
|
17805
|
+
onInputFocus
|
|
17806
|
+
},
|
|
17807
|
+
subItem.id
|
|
17808
|
+
))
|
|
17809
|
+
},
|
|
17810
|
+
pos.id
|
|
17811
|
+
)) })
|
|
17812
|
+
]
|
|
17792
17813
|
}
|
|
17793
17814
|
),
|
|
17794
17815
|
isAxisDragMode ? /* @__PURE__ */ jsx(
|
|
@@ -18112,6 +18133,8 @@ function groupLineItems(items) {
|
|
|
18112
18133
|
return groups;
|
|
18113
18134
|
}
|
|
18114
18135
|
const toValidationStatus = (v) => v === true ? "correct" : v === false ? "incorrect" : null;
|
|
18136
|
+
const isNumericText = (value) => /^[\d.,\s]+$/.test(value);
|
|
18137
|
+
const numberClass = (value) => isNumericText(value) ? "text-item-number" : "";
|
|
18115
18138
|
const LayoutRenderer = ({
|
|
18116
18139
|
item,
|
|
18117
18140
|
widgets,
|
|
@@ -18128,47 +18151,49 @@ const LayoutRenderer = ({
|
|
|
18128
18151
|
return /* @__PURE__ */ jsx("span", { className: `question-text ${hasArabic ? "question-text-arabic" : ""}`, children: item.value });
|
|
18129
18152
|
}
|
|
18130
18153
|
case JSON_TYPES.TEXT: {
|
|
18131
|
-
|
|
18132
|
-
return /* @__PURE__ */ jsx("span", { className: `text-item ${isNum ? "text-item-number" : ""} ${isArabic(item.value) ? "text-item-arabic" : "text-item-not-arabic"}`, children: item.value });
|
|
18154
|
+
return /* @__PURE__ */ jsx("span", { className: `text-item ${numberClass(item.value)} ${isArabic(item.value) ? "text-item-arabic" : "text-item-not-arabic"}`, children: item.value });
|
|
18133
18155
|
}
|
|
18134
18156
|
case JSON_TYPES.HIGHLIGHTED_TEXT: {
|
|
18135
18157
|
const hasArabic = isArabic(item.value);
|
|
18136
18158
|
const dirAttr = !hasArabic ? "ltr" : void 0;
|
|
18159
|
+
const numClass = numberClass(item.value);
|
|
18137
18160
|
if (item.highlight) {
|
|
18138
18161
|
const [start, end] = item.highlight;
|
|
18139
|
-
return /* @__PURE__ */ jsxs("span", { className:
|
|
18162
|
+
return /* @__PURE__ */ jsxs("span", { className: `highlighted-text text-item ${numClass}`, dir: dirAttr, children: [
|
|
18140
18163
|
item.value.slice(0, start),
|
|
18141
18164
|
/* @__PURE__ */ jsx("mark", { className: "highlight text-item", children: item.value.slice(start, end) }),
|
|
18142
18165
|
item.value.slice(end)
|
|
18143
18166
|
] });
|
|
18144
18167
|
}
|
|
18145
|
-
return /* @__PURE__ */ jsx("mark", { className:
|
|
18168
|
+
return /* @__PURE__ */ jsx("mark", { className: `highlighted-text text-item ${numClass}`, dir: dirAttr, children: item.value });
|
|
18146
18169
|
}
|
|
18147
18170
|
case JSON_TYPES.COLOR_TEXT: {
|
|
18148
18171
|
const hasArabic = isArabic(item.value);
|
|
18149
18172
|
const dirAttr = !hasArabic ? "ltr" : void 0;
|
|
18173
|
+
const numClass = numberClass(item.value);
|
|
18150
18174
|
if (item.highlight) {
|
|
18151
18175
|
const [start, end] = item.highlight;
|
|
18152
|
-
return /* @__PURE__ */ jsxs("span", { className:
|
|
18176
|
+
return /* @__PURE__ */ jsxs("span", { className: `color-text text-item ${numClass}`, dir: dirAttr, children: [
|
|
18153
18177
|
item.value.slice(0, start),
|
|
18154
18178
|
/* @__PURE__ */ jsx("span", { className: "color-text-colored", style: { color: item.color }, children: item.value.slice(start, end) }),
|
|
18155
18179
|
item.value.slice(end)
|
|
18156
18180
|
] });
|
|
18157
18181
|
}
|
|
18158
|
-
return /* @__PURE__ */ jsx("span", { className:
|
|
18182
|
+
return /* @__PURE__ */ jsx("span", { className: `color-text text-item ${numClass}`, style: { color: item.color }, dir: dirAttr, children: item.value });
|
|
18159
18183
|
}
|
|
18160
18184
|
case JSON_TYPES.BOLD_TEXT: {
|
|
18161
18185
|
const hasArabic = isArabic(item.value);
|
|
18162
18186
|
const dirAttr = !hasArabic ? "ltr" : void 0;
|
|
18187
|
+
const numClass = numberClass(item.value);
|
|
18163
18188
|
if (item.highlight) {
|
|
18164
18189
|
const [start, end] = item.highlight;
|
|
18165
|
-
return /* @__PURE__ */ jsxs("span", { className:
|
|
18190
|
+
return /* @__PURE__ */ jsxs("span", { className: `bold-text text-item ${numClass}`, dir: dirAttr, children: [
|
|
18166
18191
|
item.value.slice(0, start),
|
|
18167
18192
|
/* @__PURE__ */ jsx("strong", { className: "bold-text-strong text-item", children: item.value.slice(start, end) }),
|
|
18168
18193
|
item.value.slice(end)
|
|
18169
18194
|
] });
|
|
18170
18195
|
}
|
|
18171
|
-
return /* @__PURE__ */ jsx("strong", { className:
|
|
18196
|
+
return /* @__PURE__ */ jsx("strong", { className: `bold-text text-item ${numClass}`, dir: dirAttr, children: item.value });
|
|
18172
18197
|
}
|
|
18173
18198
|
case JSON_TYPES.IMAGE:
|
|
18174
18199
|
return /* @__PURE__ */ jsx(
|