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