@khanacademy/perseus-linter 1.0.0 → 1.2.0
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/es/index.js +85 -5
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +83 -5
- package/dist/index.js.map +1 -1
- package/dist/rule.d.ts +24 -8
- package/dist/rules/expression-widget.d.ts +9 -0
- package/dist/rules/static-widget-in-question-stem.d.ts +3 -0
- package/dist/tree-transformer.d.ts +2 -0
- package/package.json +2 -2
package/dist/es/index.js
CHANGED
|
@@ -804,12 +804,62 @@ var DoubleSpacingAfterTerminal = Rule.makeRule({
|
|
|
804
804
|
any other kind of terminal punctuation.`
|
|
805
805
|
});
|
|
806
806
|
|
|
807
|
+
function buttonNotInButtonSet(name, set) {
|
|
808
|
+
return `Answer requires a button not found in the button sets: ${name} (in ${set})`;
|
|
809
|
+
}
|
|
810
|
+
const stringToButtonSet = {
|
|
811
|
+
"\\sqrt": "prealgebra",
|
|
812
|
+
"\\sin": "trig",
|
|
813
|
+
"\\cos": "trig",
|
|
814
|
+
"\\tan": "trig",
|
|
815
|
+
"\\log": "logarithms",
|
|
816
|
+
"\\ln": "logarithms"
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Rule to make sure that Expression questions that require
|
|
821
|
+
* a specific math symbol to answer have that math symbol
|
|
822
|
+
* available in the keypad (desktop learners can use a keyboard,
|
|
823
|
+
* but mobile learners must use the MathInput keypad)
|
|
824
|
+
*/
|
|
825
|
+
var ExpressionWidget = Rule.makeRule({
|
|
826
|
+
name: "expression-widget",
|
|
827
|
+
severity: Rule.Severity.WARNING,
|
|
828
|
+
selector: "widget",
|
|
829
|
+
lint: function (state, content, nodes, match, context) {
|
|
830
|
+
var _context$widgets;
|
|
831
|
+
// This rule only looks at image widgets
|
|
832
|
+
if (state.currentNode().widgetType !== "expression") {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const nodeId = state.currentNode().id;
|
|
836
|
+
if (!nodeId) {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// If it can't find a definition for the widget it does nothing
|
|
841
|
+
const widget = context == null || (_context$widgets = context.widgets) == null ? void 0 : _context$widgets[nodeId];
|
|
842
|
+
if (!widget) {
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const answers = widget.options.answerForms;
|
|
846
|
+
const buttons = widget.options.buttonSets;
|
|
847
|
+
for (const answer of answers) {
|
|
848
|
+
for (const [str, set] of Object.entries(stringToButtonSet)) {
|
|
849
|
+
if (answer.value.includes(str) && !buttons.includes(set)) {
|
|
850
|
+
return buttonNotInButtonSet(str, set);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
|
|
807
857
|
var ExtraContentSpacing = Rule.makeRule({
|
|
808
858
|
name: "extra-content-spacing",
|
|
809
859
|
selector: "paragraph",
|
|
810
860
|
pattern: /\s+$/,
|
|
811
861
|
applies: function (context) {
|
|
812
|
-
return context.contentType === "article";
|
|
862
|
+
return (context == null ? void 0 : context.contentType) === "article";
|
|
813
863
|
},
|
|
814
864
|
message: `No extra whitespace at the end of content blocks.`
|
|
815
865
|
});
|
|
@@ -989,9 +1039,13 @@ var ImageWidget = Rule.makeRule({
|
|
|
989
1039
|
if (state.currentNode().widgetType !== "image") {
|
|
990
1040
|
return;
|
|
991
1041
|
}
|
|
1042
|
+
const nodeId = state.currentNode().id;
|
|
1043
|
+
if (!nodeId) {
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
992
1046
|
|
|
993
1047
|
// If it can't find a definition for the widget it does nothing
|
|
994
|
-
const widget = context && context.widgets && context.widgets[
|
|
1048
|
+
const widget = context && context.widgets && context.widgets[nodeId];
|
|
995
1049
|
if (!widget) {
|
|
996
1050
|
return;
|
|
997
1051
|
}
|
|
@@ -1075,7 +1129,7 @@ var MathAlignLinebreaks = Rule.makeRule({
|
|
|
1075
1129
|
const index = text.indexOf("\\\\");
|
|
1076
1130
|
if (index === -1) {
|
|
1077
1131
|
// No more backslash pairs, so we found no lint
|
|
1078
|
-
return
|
|
1132
|
+
return;
|
|
1079
1133
|
}
|
|
1080
1134
|
text = text.substring(index + 2);
|
|
1081
1135
|
|
|
@@ -1171,6 +1225,32 @@ nested lists are hard to read on mobile devices;
|
|
|
1171
1225
|
do not use additional indentation.`
|
|
1172
1226
|
});
|
|
1173
1227
|
|
|
1228
|
+
var StaticWidgetInQuestionStem = Rule.makeRule({
|
|
1229
|
+
name: "static-widget-in-question-stem",
|
|
1230
|
+
severity: Rule.Severity.WARNING,
|
|
1231
|
+
selector: "widget",
|
|
1232
|
+
lint: (state, content, nodes, match, context) => {
|
|
1233
|
+
var _context$widgets;
|
|
1234
|
+
if ((context == null ? void 0 : context.contentType) !== "exercise") {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (context.stack.includes("hint")) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
const nodeId = state.currentNode().id;
|
|
1241
|
+
if (!nodeId) {
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
const widget = context == null || (_context$widgets = context.widgets) == null ? void 0 : _context$widgets[nodeId];
|
|
1245
|
+
if (!widget) {
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
if (widget.static) {
|
|
1249
|
+
return `Widget in question stem is static (non-interactive).`;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1174
1254
|
var TableMissingCells = Rule.makeRule({
|
|
1175
1255
|
name: "table-missing-cells",
|
|
1176
1256
|
severity: Rule.Severity.WARNING,
|
|
@@ -1218,7 +1298,7 @@ do not put widgets inside of tables.`
|
|
|
1218
1298
|
});
|
|
1219
1299
|
|
|
1220
1300
|
// TODO(davidflanagan):
|
|
1221
|
-
var AllRules = [AbsoluteUrl, BlockquotedMath, BlockquotedWidget, DoubleSpacingAfterTerminal, ExtraContentSpacing, HeadingLevel1, HeadingLevelSkip, HeadingSentenceCase, HeadingTitleCase, ImageAltText, ImageInTable, LinkClickHere, LongParagraph, MathAdjacent, MathAlignExtraBreak, MathAlignLinebreaks, MathEmpty, MathFontSize, MathFrac, MathNested, MathStartsWithSpace, MathTextEmpty, NestedLists, TableMissingCells, UnescapedDollar, WidgetInTable, MathWithoutDollars, UnbalancedCodeDelimiters, ImageSpacesAroundUrls, ImageWidget];
|
|
1301
|
+
var AllRules = [AbsoluteUrl, BlockquotedMath, BlockquotedWidget, DoubleSpacingAfterTerminal, ExpressionWidget, ExtraContentSpacing, HeadingLevel1, HeadingLevelSkip, HeadingSentenceCase, HeadingTitleCase, ImageAltText, ImageInTable, LinkClickHere, LongParagraph, MathAdjacent, MathAlignExtraBreak, MathAlignLinebreaks, MathEmpty, MathFontSize, MathFrac, MathNested, MathStartsWithSpace, MathTextEmpty, NestedLists, StaticWidgetInQuestionStem, TableMissingCells, UnescapedDollar, WidgetInTable, MathWithoutDollars, UnbalancedCodeDelimiters, ImageSpacesAroundUrls, ImageWidget];
|
|
1222
1302
|
|
|
1223
1303
|
/**
|
|
1224
1304
|
* TreeTransformer is a class for traversing and transforming trees. Create a
|
|
@@ -1759,7 +1839,7 @@ class Stack {
|
|
|
1759
1839
|
|
|
1760
1840
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
1761
1841
|
const libName = "@khanacademy/perseus-linter";
|
|
1762
|
-
const libVersion = "1.
|
|
1842
|
+
const libVersion = "1.2.0";
|
|
1763
1843
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
1764
1844
|
|
|
1765
1845
|
// Define the shape of the linter context object that is passed through the
|