@khanacademy/perseus-linter 0.0.0-PR862-20231207182234 → 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.
Files changed (57) hide show
  1. package/README.md +7 -0
  2. package/dist/es/index.js +23 -10
  3. package/dist/es/index.js.map +1 -1
  4. package/dist/index.js +50 -24
  5. package/dist/index.js.map +1 -1
  6. package/package.json +8 -6
  7. package/.eslintrc.js +0 -12
  8. package/CHANGELOG.md +0 -148
  9. package/src/README.md +0 -41
  10. package/src/__tests__/matcher.test.ts +0 -498
  11. package/src/__tests__/rule.test.ts +0 -110
  12. package/src/__tests__/rules.test.ts +0 -548
  13. package/src/__tests__/selector-parser.test.ts +0 -51
  14. package/src/__tests__/tree-transformer.test.ts +0 -444
  15. package/src/index.ts +0 -281
  16. package/src/proptypes.ts +0 -19
  17. package/src/rule.ts +0 -419
  18. package/src/rules/absolute-url.ts +0 -23
  19. package/src/rules/all-rules.ts +0 -71
  20. package/src/rules/blockquoted-math.ts +0 -9
  21. package/src/rules/blockquoted-widget.ts +0 -9
  22. package/src/rules/double-spacing-after-terminal.ts +0 -11
  23. package/src/rules/extra-content-spacing.ts +0 -11
  24. package/src/rules/heading-level-1.ts +0 -13
  25. package/src/rules/heading-level-skip.ts +0 -19
  26. package/src/rules/heading-sentence-case.ts +0 -10
  27. package/src/rules/heading-title-case.ts +0 -68
  28. package/src/rules/image-alt-text.ts +0 -20
  29. package/src/rules/image-in-table.ts +0 -9
  30. package/src/rules/image-spaces-around-urls.ts +0 -34
  31. package/src/rules/image-widget.ts +0 -49
  32. package/src/rules/link-click-here.ts +0 -10
  33. package/src/rules/lint-utils.ts +0 -47
  34. package/src/rules/long-paragraph.ts +0 -13
  35. package/src/rules/math-adjacent.ts +0 -9
  36. package/src/rules/math-align-extra-break.ts +0 -10
  37. package/src/rules/math-align-linebreaks.ts +0 -42
  38. package/src/rules/math-empty.ts +0 -9
  39. package/src/rules/math-font-size.ts +0 -11
  40. package/src/rules/math-frac.ts +0 -9
  41. package/src/rules/math-nested.ts +0 -10
  42. package/src/rules/math-starts-with-space.ts +0 -11
  43. package/src/rules/math-text-empty.ts +0 -9
  44. package/src/rules/math-without-dollars.ts +0 -13
  45. package/src/rules/nested-lists.ts +0 -10
  46. package/src/rules/profanity.ts +0 -9
  47. package/src/rules/table-missing-cells.ts +0 -19
  48. package/src/rules/unbalanced-code-delimiters.ts +0 -13
  49. package/src/rules/unescaped-dollar.ts +0 -9
  50. package/src/rules/widget-in-table.ts +0 -9
  51. package/src/selector.ts +0 -504
  52. package/src/tree-transformer.ts +0 -583
  53. package/src/types.ts +0 -7
  54. package/src/version.ts +0 -10
  55. package/tsconfig-build.json +0 -12
  56. package/tsconfig-build.tsbuildinfo +0 -1
  57. /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 perseusError.PerseusError("Selector subclasses must implement match()", perseusError.Errors.NotAllowed);
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 perseusError.PerseusError("Lint rules must have a selector or pattern", perseusError.Errors.InvalidInput, {
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 Profanity = Rule.makeRule({
1158
- name: "profanity",
1159
- // This list could obviously be expanded a lot, but I figured we
1160
- // could start with https://en.wikipedia.org/wiki/Seven_dirty_words
1161
- pattern: /\b(shit|piss|fuck|cunt|cocksucker|motherfucker|tits)\b/i,
1162
- message: "Avoid profanity"
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, Profanity, MathWithoutDollars, UnbalancedCodeDelimiters, ImageSpacesAroundUrls, ImageWidget];
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 perseusError.PerseusError("Can't replace the root of the tree", perseusError.Errors.Internal);
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 perseusError.PerseusError("goToPreviousSibling(): node has no previous sibling", perseusError.Errors.Internal);
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 perseusError.PerseusError("goToParent(): node has no ancestor", perseusError.Errors.NotAllowed);
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.3.9";
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