eslint-plugin-harlanzw 0.10.2 → 0.10.4

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 (2) hide show
  1. package/dist/index.mjs +27 -66
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import process from 'node:process';
4
4
  import { TextSourceCodeBase, ConfigCommentParser, Directive, VisitNodeStep } from '@eslint/plugin-kit';
5
5
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
6
6
 
7
- const version = "0.10.2";
7
+ const version = "0.10.4";
8
8
 
9
9
  const STRENGTH_PATTERNS = {
10
10
  strong: ["never", "must", "always", "under no circumstances", "absolutely", "required", "mandatory", "forbidden", "prohibited"],
@@ -404,6 +404,7 @@ const HEDGING_WORDS = [
404
404
  "practically"
405
405
  ];
406
406
  const CONTENT_FILES = ["**/content/**/*.md", "**/docs/**/*.md", "**/README.md"];
407
+ const NUXT_CONTENT_FILES = ["**/content/**/*.md", "**/docs/**/*.md"];
407
408
 
408
409
  const REGEX_1$x = /\r?\n/;
409
410
  const configCommentStart = /<!--\s*eslint(?:-enable|-disable(?:(?:-next)?-line)?)?(?:\s|-->)/u;
@@ -1557,9 +1558,11 @@ const aiDeslopCodeLang = {
1557
1558
  };
1558
1559
 
1559
1560
  const APOSTROPHE = `(?:'|\u2019)`;
1560
- const SUBJECT_NOT = `(?:it${APOSTROPHE}s|it is|they${APOSTROPHE}re|they are|this is|that is|is|are)`;
1561
- const SUBJECT_IS = `(?:it${APOSTROPHE}s|it is|they${APOSTROPHE}re|they are|this is|that is|is|are)`;
1562
- const PATTERN = new RegExp(`\\b${SUBJECT_NOT}\\s+not\\b.{1,80}?\\b${SUBJECT_IS}\\b|\\bis\\s+no\\s+longer\\s+just\\s+about\\b.{1,80}?\\bit${APOSTROPHE}s\\s+about\\b`, "i");
1561
+ const SUBJECT_NOT = `(?:it${APOSTROPHE}s|it is|they${APOSTROPHE}re|they are|we${APOSTROPHE}re|we are|you${APOSTROPHE}re|you are|this is|that is|is|are)`;
1562
+ const SUBJECT_IS = `(?:it${APOSTROPHE}s|it is|they${APOSTROPHE}re|they are|we${APOSTROPHE}re|we are|you${APOSTROPHE}re|you are|this is|that is|is|are)`;
1563
+ const CONTRACTION_NOT = `(?:isn${APOSTROPHE}t|aren${APOSTROPHE}t|wasn${APOSTROPHE}t|weren${APOSTROPHE}t)`;
1564
+ const NO_LONGER = `(?:is|it${APOSTROPHE}s|was)`;
1565
+ const PATTERN = new RegExp(`\\b${SUBJECT_NOT}\\s+not\\b.{1,80}?\\b${SUBJECT_IS}\\b|\\b${CONTRACTION_NOT}\\s+(?:just\\s+)?about\\b.{1,80}?\\b(?:it${APOSTROPHE}s|is)\\s+about\\b|\\b${NO_LONGER}\\s+no\\s+longer\\b.{1,60}?\\b(?:it${APOSTROPHE}s|is)\\b`, "i");
1563
1566
  const aiDeslopFalseDichotomy = {
1564
1567
  meta: {
1565
1568
  type: "suggestion",
@@ -1800,17 +1803,13 @@ function findEmDashes(line, scopes) {
1800
1803
  }
1801
1804
  return positions;
1802
1805
  }
1803
- const LABEL_BEFORE = /(?:\*\*[^*]+\*\*|#{1,6}\s+\S(?:.*\S)?)\s*$/;
1804
1806
  const aiDeslopNoEmDash = {
1805
1807
  meta: {
1806
1808
  type: "suggestion",
1807
- docs: { description: "Replace em dashes with plain dashes, commas, or colons" },
1808
- fixable: "code",
1809
+ docs: { description: "Flag em dashes so sentences can be rewritten without them" },
1809
1810
  schema: [],
1810
1811
  messages: {
1811
- emDash: "Avoid em dashes in content. Use a plain dash instead.",
1812
- emDashParen: "Avoid em dashes for parentheticals. Use commas instead.",
1813
- emDashColon: "Avoid em dashes after labels. Use a colon instead."
1812
+ emDash: "Rewrite this sentence to avoid using an em dash as a separator. Use two sentences, a semicolon, or restructure with commas."
1814
1813
  }
1815
1814
  },
1816
1815
  create(context) {
@@ -1824,70 +1823,22 @@ const aiDeslopNoEmDash = {
1824
1823
  if (shouldSkipLine(i, codeBlockLines, frontmatterEnd))
1825
1824
  continue;
1826
1825
  const line = lines[i];
1827
- const lineNode = node.children[i];
1828
1826
  const scopes = parseLineScopes(line);
1829
1827
  const positions = findEmDashes(line, scopes);
1830
- if (positions.length === 0)
1831
- continue;
1832
- const isPair = positions.length === 2 && positions[0] > 0 && positions[1] < line.length - 1;
1833
1828
  for (const pos of positions) {
1834
- const startOffset = lineNode.position.start.offset + pos;
1835
- const endOffset = startOffset + 1;
1836
- const before = line[pos - 1];
1837
- const after = line[pos + 1];
1838
- const spaceBefore = before === " ";
1839
- const spaceAfter = after === " ";
1840
- let fixStart = startOffset;
1841
- let fixEnd = endOffset;
1842
- const textBefore = line.slice(0, pos);
1843
- const isLabel = positions.length === 1 && LABEL_BEFORE.test(textBefore);
1844
- if (isPair) {
1845
- const replacement = ",";
1846
- if (spaceBefore && spaceAfter) {
1847
- fixStart -= 1;
1848
- } else if (!spaceAfter) {
1849
- report(context, i, pos, "emDashParen", fixStart, fixEnd, ", ");
1850
- continue;
1851
- }
1852
- report(context, i, pos, "emDashParen", fixStart, fixEnd, replacement);
1853
- } else if (isLabel) {
1854
- if (spaceBefore && spaceAfter) {
1855
- fixStart -= 1;
1856
- } else if (spaceBefore) {
1857
- fixStart -= 1;
1858
- }
1859
- const replacement = spaceAfter ? ":" : ": ";
1860
- report(context, i, pos, "emDashColon", fixStart, fixEnd, replacement);
1861
- } else {
1862
- const replacement = " - ";
1863
- if (spaceBefore && spaceAfter) {
1864
- fixStart -= 1;
1865
- fixEnd += 1;
1866
- } else if (spaceBefore) {
1867
- fixStart -= 1;
1868
- } else if (spaceAfter) {
1869
- fixEnd += 1;
1870
- }
1871
- report(context, i, pos, "emDash", fixStart, fixEnd, replacement);
1872
- }
1829
+ context.report({
1830
+ loc: {
1831
+ start: { line: i + 1, column: pos + 1 },
1832
+ end: { line: i + 1, column: pos + 2 }
1833
+ },
1834
+ messageId: "emDash"
1835
+ });
1873
1836
  }
1874
1837
  }
1875
1838
  }
1876
1839
  };
1877
1840
  }
1878
1841
  };
1879
- function report(context, lineIdx, col, messageId, fixStart, fixEnd, replacement) {
1880
- context.report({
1881
- loc: {
1882
- start: { line: lineIdx + 1, column: col + 1 },
1883
- end: { line: lineIdx + 1, column: col + 2 }
1884
- },
1885
- messageId,
1886
- fix(fixer) {
1887
- return fixer.replaceTextRange([fixStart, fixEnd], replacement);
1888
- }
1889
- });
1890
- }
1891
1842
 
1892
1843
  const REGEX_2$9 = /!(?!\[)/g;
1893
1844
  const REGEX_1$n = /\w/;
@@ -6802,8 +6753,10 @@ const deslopRules = {
6802
6753
  "harlanzw/ai-deslop-passive-voice": "warn",
6803
6754
  "harlanzw/ai-deslop-weak-opener": "warn",
6804
6755
  "harlanzw/ai-deslop-autolink": "warn",
6756
+ "harlanzw/ai-deslop-frontmatter-spacing": "error"
6757
+ };
6758
+ const nuxtContentDeslopRules = {
6805
6759
  "harlanzw/ai-deslop-code-lang": "warn",
6806
- "harlanzw/ai-deslop-frontmatter-spacing": "error",
6807
6760
  "harlanzw/ai-deslop-vue-ts-lang": "error"
6808
6761
  };
6809
6762
  plugin.configs.content = [
@@ -6814,6 +6767,14 @@ plugin.configs.content = [
6814
6767
  language: "harlanzw/prompt",
6815
6768
  plugins: { harlanzw: plugin },
6816
6769
  rules: deslopRules
6770
+ },
6771
+ {
6772
+ name: "harlanzw/content/nuxt-content",
6773
+ files: NUXT_CONTENT_FILES,
6774
+ ignores: CODE_IGNORES,
6775
+ language: "harlanzw/prompt",
6776
+ plugins: { harlanzw: plugin },
6777
+ rules: nuxtContentDeslopRules
6817
6778
  }
6818
6779
  ];
6819
6780
  const LINK_RULES_WITH_OPTIONS = [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-harlanzw",
3
3
  "type": "module",
4
- "version": "0.10.2",
4
+ "version": "0.10.4",
5
5
  "description": "Harlan's opinionated ESLint rules",
6
6
  "author": "Harlan Wilton <harlan@harlanzw.com>",
7
7
  "license": "MIT",