@khanacademy/perseus-linter 0.0.0-PR862-20231207182125 → 0.0.0-PR875-20240813215114
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/README.md +7 -0
- package/dist/es/index.js +23 -10
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +50 -24
- package/dist/index.js.map +1 -1
- package/package.json +8 -6
- package/.eslintrc.js +0 -12
- package/CHANGELOG.md +0 -148
- package/src/README.md +0 -41
- package/src/__tests__/matcher.test.ts +0 -498
- package/src/__tests__/rule.test.ts +0 -110
- package/src/__tests__/rules.test.ts +0 -548
- package/src/__tests__/selector-parser.test.ts +0 -51
- package/src/__tests__/tree-transformer.test.ts +0 -444
- package/src/index.ts +0 -281
- package/src/proptypes.ts +0 -19
- package/src/rule.ts +0 -419
- package/src/rules/absolute-url.ts +0 -23
- package/src/rules/all-rules.ts +0 -71
- package/src/rules/blockquoted-math.ts +0 -9
- package/src/rules/blockquoted-widget.ts +0 -9
- package/src/rules/double-spacing-after-terminal.ts +0 -11
- package/src/rules/extra-content-spacing.ts +0 -11
- package/src/rules/heading-level-1.ts +0 -13
- package/src/rules/heading-level-skip.ts +0 -19
- package/src/rules/heading-sentence-case.ts +0 -10
- package/src/rules/heading-title-case.ts +0 -68
- package/src/rules/image-alt-text.ts +0 -20
- package/src/rules/image-in-table.ts +0 -9
- package/src/rules/image-spaces-around-urls.ts +0 -34
- package/src/rules/image-widget.ts +0 -49
- package/src/rules/link-click-here.ts +0 -10
- package/src/rules/lint-utils.ts +0 -47
- package/src/rules/long-paragraph.ts +0 -13
- package/src/rules/math-adjacent.ts +0 -9
- package/src/rules/math-align-extra-break.ts +0 -10
- package/src/rules/math-align-linebreaks.ts +0 -42
- package/src/rules/math-empty.ts +0 -9
- package/src/rules/math-font-size.ts +0 -11
- package/src/rules/math-frac.ts +0 -9
- package/src/rules/math-nested.ts +0 -10
- package/src/rules/math-starts-with-space.ts +0 -11
- package/src/rules/math-text-empty.ts +0 -9
- package/src/rules/math-without-dollars.ts +0 -13
- package/src/rules/nested-lists.ts +0 -10
- package/src/rules/profanity.ts +0 -9
- package/src/rules/table-missing-cells.ts +0 -19
- package/src/rules/unbalanced-code-delimiters.ts +0 -13
- package/src/rules/unescaped-dollar.ts +0 -9
- package/src/rules/widget-in-table.ts +0 -9
- package/src/selector.ts +0 -504
- package/src/tree-transformer.ts +0 -583
- package/src/types.ts +0 -7
- package/src/version.ts +0 -10
- package/tsconfig-build.json +0 -12
- package/tsconfig-build.tsbuildinfo +0 -1
- /package/dist/rules/{profanity.d.ts → static-widget-in-question-stem.d.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var perseusError = require('@khanacademy/perseus-error');
|
|
6
5
|
var perseusCore = require('@khanacademy/perseus-core');
|
|
7
6
|
var PropTypes = require('prop-types');
|
|
8
7
|
|
|
@@ -29,7 +28,7 @@ class Selector {
|
|
|
29
28
|
* subclasses must provide an implementation of this method.
|
|
30
29
|
*/
|
|
31
30
|
match(state) {
|
|
32
|
-
throw new
|
|
31
|
+
throw new perseusCore.PerseusError("Selector subclasses must implement match()", perseusCore.Errors.NotAllowed);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/**
|
|
@@ -51,9 +50,9 @@ class Selector {
|
|
|
51
50
|
* Instead call the static Selector.parse() method.
|
|
52
51
|
*/
|
|
53
52
|
class Parser {
|
|
54
|
-
// We do lexing with a simple regular expression
|
|
55
|
-
// The array of tokens
|
|
56
|
-
// Which token in the array we're looking at now
|
|
53
|
+
static TOKENS; // We do lexing with a simple regular expression
|
|
54
|
+
tokens; // The array of tokens
|
|
55
|
+
tokenIndex; // Which token in the array we're looking at now
|
|
57
56
|
|
|
58
57
|
constructor(s) {
|
|
59
58
|
// Normalize whitespace:
|
|
@@ -212,6 +211,7 @@ class ParseError extends Error {
|
|
|
212
211
|
* first.
|
|
213
212
|
*/
|
|
214
213
|
class SelectorList extends Selector {
|
|
214
|
+
selectors;
|
|
215
215
|
constructor(selectors) {
|
|
216
216
|
super();
|
|
217
217
|
this.selectors = selectors;
|
|
@@ -254,6 +254,7 @@ class AnyNode extends Selector {
|
|
|
254
254
|
* it matches any node whose `type` property is a specified string
|
|
255
255
|
*/
|
|
256
256
|
class TypeSelector extends Selector {
|
|
257
|
+
type;
|
|
257
258
|
constructor(type) {
|
|
258
259
|
super();
|
|
259
260
|
this.type = type;
|
|
@@ -277,6 +278,8 @@ class TypeSelector extends Selector {
|
|
|
277
278
|
* method.
|
|
278
279
|
*/
|
|
279
280
|
class SelectorCombinator extends Selector {
|
|
281
|
+
left;
|
|
282
|
+
right;
|
|
280
283
|
constructor(left, right) {
|
|
281
284
|
super();
|
|
282
285
|
this.left = left;
|
|
@@ -543,20 +546,21 @@ class SiblingCombinator extends SelectorCombinator {
|
|
|
543
546
|
* this file for detailed description.
|
|
544
547
|
*/
|
|
545
548
|
class Rule {
|
|
546
|
-
// The name of the rule
|
|
547
|
-
// The severity of the rule
|
|
548
|
-
// The specified selector or the DEFAULT_SELECTOR
|
|
549
|
-
// A regular expression if one was specified
|
|
550
|
-
// The lint-testing function or a default
|
|
551
|
-
// Checks to see if we should apply a rule or not
|
|
552
|
-
// The error message for use with the default function
|
|
549
|
+
name; // The name of the rule
|
|
550
|
+
severity; // The severity of the rule
|
|
551
|
+
selector; // The specified selector or the DEFAULT_SELECTOR
|
|
552
|
+
pattern; // A regular expression if one was specified
|
|
553
|
+
lint; // The lint-testing function or a default
|
|
554
|
+
applies; // Checks to see if we should apply a rule or not
|
|
555
|
+
message; // The error message for use with the default function
|
|
556
|
+
static DEFAULT_SELECTOR;
|
|
553
557
|
|
|
554
558
|
// The comment at the top of this file has detailed docs for
|
|
555
559
|
// this constructor and its arguments
|
|
556
560
|
constructor(name, severity, selector, pattern, lint, applies) {
|
|
557
561
|
var _this = this;
|
|
558
562
|
if (!selector && !pattern) {
|
|
559
|
-
throw new
|
|
563
|
+
throw new perseusCore.PerseusError("Lint rules must have a selector or pattern", perseusCore.Errors.InvalidInput, {
|
|
560
564
|
metadata: {
|
|
561
565
|
name
|
|
562
566
|
}
|
|
@@ -1154,12 +1158,25 @@ nested lists are hard to read on mobile devices;
|
|
|
1154
1158
|
do not use additional indentation.`
|
|
1155
1159
|
});
|
|
1156
1160
|
|
|
1157
|
-
var
|
|
1158
|
-
name: "
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1161
|
+
var StaticWidgetInQuestionStem = Rule.makeRule({
|
|
1162
|
+
name: "static-widget-in-question-stem",
|
|
1163
|
+
severity: Rule.Severity.WARNING,
|
|
1164
|
+
selector: "widget",
|
|
1165
|
+
lint: (state, content, nodes, match, context) => {
|
|
1166
|
+
if (context.contentType !== "exercise") {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
if (context.stack.includes("hint")) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
const widget = context?.widgets?.[state.currentNode().id];
|
|
1173
|
+
if (!widget) {
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (widget.static) {
|
|
1177
|
+
return `Widget in question stem is static (non-interactive).`;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1163
1180
|
});
|
|
1164
1181
|
|
|
1165
1182
|
var TableMissingCells = Rule.makeRule({
|
|
@@ -1209,7 +1226,7 @@ do not put widgets inside of tables.`
|
|
|
1209
1226
|
});
|
|
1210
1227
|
|
|
1211
1228
|
// TODO(davidflanagan):
|
|
1212
|
-
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,
|
|
1229
|
+
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, StaticWidgetInQuestionStem, TableMissingCells, UnescapedDollar, WidgetInTable, MathWithoutDollars, UnbalancedCodeDelimiters, ImageSpacesAroundUrls, ImageWidget];
|
|
1213
1230
|
|
|
1214
1231
|
/**
|
|
1215
1232
|
* TreeTransformer is a class for traversing and transforming trees. Create a
|
|
@@ -1277,6 +1294,8 @@ var AllRules = [AbsoluteUrl, BlockquotedMath, BlockquotedWidget, DoubleSpacingAf
|
|
|
1277
1294
|
// This is the TreeTransformer class described in detail at the
|
|
1278
1295
|
// top of this file.
|
|
1279
1296
|
class TreeTransformer {
|
|
1297
|
+
root;
|
|
1298
|
+
|
|
1280
1299
|
// To create a tree transformer, just pass the root node of the tree
|
|
1281
1300
|
constructor(root) {
|
|
1282
1301
|
this.root = root;
|
|
@@ -1424,6 +1443,7 @@ class TreeTransformer {
|
|
|
1424
1443
|
**/
|
|
1425
1444
|
class TraversalState {
|
|
1426
1445
|
// The root node of the tree being traversed
|
|
1446
|
+
root;
|
|
1427
1447
|
|
|
1428
1448
|
// These are internal state properties. Use the accessor methods defined
|
|
1429
1449
|
// below instead of using these properties directly. Note that the
|
|
@@ -1431,6 +1451,11 @@ class TraversalState {
|
|
|
1431
1451
|
// elements, depending on whether we just recursed on an array or on a
|
|
1432
1452
|
// node. This is hard for TypeScript to deal with, so you'll see a number of
|
|
1433
1453
|
// type casts through the any type when working with these two properties.
|
|
1454
|
+
_currentNode;
|
|
1455
|
+
_containers;
|
|
1456
|
+
_indexes;
|
|
1457
|
+
_ancestors;
|
|
1458
|
+
|
|
1434
1459
|
// The constructor just stores the root node and creates empty stacks.
|
|
1435
1460
|
constructor(root) {
|
|
1436
1461
|
this.root = root;
|
|
@@ -1558,7 +1583,7 @@ class TraversalState {
|
|
|
1558
1583
|
replace() {
|
|
1559
1584
|
const parent = this._containers.top();
|
|
1560
1585
|
if (!parent) {
|
|
1561
|
-
throw new
|
|
1586
|
+
throw new perseusCore.PerseusError("Can't replace the root of the tree", perseusCore.Errors.Internal);
|
|
1562
1587
|
}
|
|
1563
1588
|
|
|
1564
1589
|
// The top of the container stack is either an array or an object
|
|
@@ -1611,7 +1636,7 @@ class TraversalState {
|
|
|
1611
1636
|
*/
|
|
1612
1637
|
goToPreviousSibling() {
|
|
1613
1638
|
if (!this.hasPreviousSibling()) {
|
|
1614
|
-
throw new
|
|
1639
|
+
throw new perseusCore.PerseusError("goToPreviousSibling(): node has no previous sibling", perseusCore.Errors.Internal);
|
|
1615
1640
|
}
|
|
1616
1641
|
this._currentNode = this.previousSibling();
|
|
1617
1642
|
// Since we know that we have a previous sibling, we know that
|
|
@@ -1641,7 +1666,7 @@ class TraversalState {
|
|
|
1641
1666
|
*/
|
|
1642
1667
|
goToParent() {
|
|
1643
1668
|
if (!this.hasParent()) {
|
|
1644
|
-
throw new
|
|
1669
|
+
throw new perseusCore.PerseusError("goToParent(): node has no ancestor", perseusCore.Errors.NotAllowed);
|
|
1645
1670
|
}
|
|
1646
1671
|
this._currentNode = this._ancestors.pop();
|
|
1647
1672
|
|
|
@@ -1688,6 +1713,7 @@ class TraversalState {
|
|
|
1688
1713
|
* the TraversalState class simpler in a number of places.
|
|
1689
1714
|
*/
|
|
1690
1715
|
class Stack {
|
|
1716
|
+
stack;
|
|
1691
1717
|
constructor(array) {
|
|
1692
1718
|
this.stack = array ? array.slice(0) : [];
|
|
1693
1719
|
}
|
|
@@ -1747,7 +1773,7 @@ class Stack {
|
|
|
1747
1773
|
|
|
1748
1774
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
1749
1775
|
const libName = "@khanacademy/perseus-linter";
|
|
1750
|
-
const libVersion = "0.
|
|
1776
|
+
const libVersion = "1.0.0";
|
|
1751
1777
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
1752
1778
|
|
|
1753
1779
|
// Define the shape of the linter context object that is passed through the
|