eslint-plugin-harlanzw 0.16.0 → 0.17.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/README.md +2 -0
- package/dist/index.mjs +119 -33
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@ The rules are organized into the following categories:
|
|
|
76
76
|
| [`ai-deslop-buzzwords`](./src/prompt/rules/deslop-buzzwords.ts) | replace AI-generated buzzword phrases with simpler alternatives (e.g. "leverage" → "use") |
|
|
77
77
|
| [`ai-deslop-casing`](./src/prompt/rules/deslop-casing.ts) | enforce correct casing for tech terms, brands, and abbreviations (e.g. "github" → "GitHub") |
|
|
78
78
|
| [`ai-deslop-false-dichotomy`](./src/prompt/rules/deslop-false-dichotomy.ts) | flag "it's not X, it's Y" contrast patterns common in AI writing |
|
|
79
|
+
| [`ai-deslop-false-sincerity`](./src/prompt/rules/deslop-false-sincerity.ts) | remove false-sincerity openers that pad sentences ("honestly", "frankly", "in all honesty") |
|
|
79
80
|
| [`ai-deslop-filler`](./src/prompt/rules/deslop-filler.ts) | remove AI-generated filler sentences and phrases (e.g. "it's worth noting that") |
|
|
80
81
|
| [`ai-deslop-hedging`](./src/prompt/rules/deslop-hedging.ts) | remove hedging/qualifying words that weaken copy (e.g. "very", "really", "quite", "just") |
|
|
81
82
|
| [`ai-deslop-no-em-dash`](./src/prompt/rules/deslop-no-em-dash.ts) | replace em dashes in content prose |
|
|
@@ -211,6 +212,7 @@ export default [
|
|
|
211
212
|
| `ai-deslop-casing` | Fixes tech term casing using a 300+ term dictionary ("github" → "GitHub", "typescript" → "TypeScript") |
|
|
212
213
|
| `ai-deslop-autolink` | Links first mention of tech terms to their canonical URLs ("Nuxt" → `[Nuxt](https://nuxt.com)`) |
|
|
213
214
|
| `ai-deslop-false-dichotomy` | Flags "it's not X, it's Y" false contrast patterns |
|
|
215
|
+
| `ai-deslop-false-sincerity` | Strips false-sincerity openers ("honestly", "frankly", "in all honesty", "let's be real") |
|
|
214
216
|
| `ai-deslop-hedging` | Strips hedging words that weaken copy ("very", "really", "quite", "just", "somewhat") |
|
|
215
217
|
| `ai-deslop-no-em-dash` | Replaces em dashes in content prose |
|
|
216
218
|
| `ai-deslop-no-exclamation` | Replaces exclamation marks with periods in content prose |
|
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.
|
|
7
|
+
const version = "0.17.0";
|
|
8
8
|
|
|
9
9
|
const STRENGTH_PATTERNS = {
|
|
10
10
|
strong: ["never", "must", "always", "under no circumstances", "absolutely", "required", "mandatory", "forbidden", "prohibited"],
|
|
@@ -356,6 +356,17 @@ const FILLER_PHRASES = [
|
|
|
356
356
|
"to summarize",
|
|
357
357
|
"to sum up"
|
|
358
358
|
];
|
|
359
|
+
const FALSE_SINCERITY_OPENERS = [
|
|
360
|
+
"honestly",
|
|
361
|
+
"frankly",
|
|
362
|
+
"in all honesty",
|
|
363
|
+
"in all fairness",
|
|
364
|
+
"to be frank",
|
|
365
|
+
"let's be real",
|
|
366
|
+
"if i'm honest",
|
|
367
|
+
"if i'm being honest",
|
|
368
|
+
"if we're being honest"
|
|
369
|
+
];
|
|
359
370
|
const UNNECESSARY_ADVERBS = [
|
|
360
371
|
"fundamentally",
|
|
361
372
|
"essentially",
|
|
@@ -718,7 +729,7 @@ function parseFrontmatter(lines) {
|
|
|
718
729
|
}
|
|
719
730
|
|
|
720
731
|
const REGEX_1$u = /[.*+?^${}()|[\]\\]/g;
|
|
721
|
-
const COMPILED$
|
|
732
|
+
const COMPILED$9 = AMBIGUOUS_QUANTIFIERS.map((quantifier) => {
|
|
722
733
|
const escaped = quantifier.replace(REGEX_1$u, "\\$&");
|
|
723
734
|
return new RegExp(`\\b${escaped}\\b`, "gi");
|
|
724
735
|
});
|
|
@@ -743,8 +754,8 @@ const promptAmbiguousQuantifier = {
|
|
|
743
754
|
if (shouldSkipLine(i, codeBlockLines, frontmatterEnd))
|
|
744
755
|
continue;
|
|
745
756
|
const line = lines[i];
|
|
746
|
-
for (let qi = 0; qi < COMPILED$
|
|
747
|
-
const regex = COMPILED$
|
|
757
|
+
for (let qi = 0; qi < COMPILED$9.length; qi++) {
|
|
758
|
+
const regex = COMPILED$9[qi];
|
|
748
759
|
regex.lastIndex = 0;
|
|
749
760
|
let match;
|
|
750
761
|
while ((match = regex.exec(line)) !== null) {
|
|
@@ -773,7 +784,7 @@ const promptAmbiguousQuantifier = {
|
|
|
773
784
|
|
|
774
785
|
const REGEX_2$d = /^[-*>\s#\d.]+$/;
|
|
775
786
|
const REGEX_1$t = /\.\s+$/;
|
|
776
|
-
const COMPILED$
|
|
787
|
+
const COMPILED$8 = UNNECESSARY_ADVERBS.map((adverb) => {
|
|
777
788
|
return { regex: new RegExp(`\\b${adverb}\\s+`, "gi"), adverb };
|
|
778
789
|
});
|
|
779
790
|
const aiDeslopAdverbs = {
|
|
@@ -799,7 +810,7 @@ const aiDeslopAdverbs = {
|
|
|
799
810
|
const line = lines[i];
|
|
800
811
|
const lineNode = node.children[i];
|
|
801
812
|
const scopes = parseLineScopes(line);
|
|
802
|
-
for (const { regex, adverb } of COMPILED$
|
|
813
|
+
for (const { regex, adverb } of COMPILED$8) {
|
|
803
814
|
regex.lastIndex = 0;
|
|
804
815
|
let match;
|
|
805
816
|
while ((match = regex.exec(line)) !== null) {
|
|
@@ -940,7 +951,7 @@ const DEDUPED_ENTRIES = SORTED_ENTRIES$1.filter(([name, url]) => {
|
|
|
940
951
|
SEEN_URLS.set(url, name);
|
|
941
952
|
return true;
|
|
942
953
|
});
|
|
943
|
-
const COMPILED$
|
|
954
|
+
const COMPILED$7 = DEDUPED_ENTRIES.map(([name, url]) => {
|
|
944
955
|
const escaped = name.replace(REGEX_3$7, "\\$&");
|
|
945
956
|
return { name, url, regex: new RegExp(`(?<=\\s|^)${escaped}(?=\\s|$|[.,;:!?)])`, "g") };
|
|
946
957
|
});
|
|
@@ -963,7 +974,7 @@ const aiDeslopAutolink = {
|
|
|
963
974
|
const codeBlockLines = getCodeBlockLines(lines);
|
|
964
975
|
const frontmatterEnd = getFrontmatterEnd(lines);
|
|
965
976
|
const linkedUrls = /* @__PURE__ */ new Set();
|
|
966
|
-
const allUrls = new Set(COMPILED$
|
|
977
|
+
const allUrls = new Set(COMPILED$7.map((c) => c.url));
|
|
967
978
|
for (const line of lines) {
|
|
968
979
|
LINK_URL_RE.lastIndex = 0;
|
|
969
980
|
let urlMatch;
|
|
@@ -982,7 +993,7 @@ const aiDeslopAutolink = {
|
|
|
982
993
|
continue;
|
|
983
994
|
const lineNode = node.children[i];
|
|
984
995
|
const scopes = parseLineScopes(line);
|
|
985
|
-
for (const { name, url, regex } of COMPILED$
|
|
996
|
+
for (const { name, url, regex } of COMPILED$7) {
|
|
986
997
|
if (linkedUrls.has(url))
|
|
987
998
|
continue;
|
|
988
999
|
regex.lastIndex = 0;
|
|
@@ -1028,7 +1039,7 @@ const REGEX_3$6 = /[.*+?^${}()|[\]\\]/g;
|
|
|
1028
1039
|
const REGEX_2$b = /^[-*>\s#\d.]+$/;
|
|
1029
1040
|
const REGEX_1$r = /\.\s+$/;
|
|
1030
1041
|
const SORTED_PHRASES = Object.entries(BUZZWORD_PHRASES).sort((a, b) => b[0].length - a[0].length);
|
|
1031
|
-
const COMPILED$
|
|
1042
|
+
const COMPILED$6 = SORTED_PHRASES.map(([phrase, replacement]) => {
|
|
1032
1043
|
const escaped = phrase.replace(REGEX_3$6, "\\$&");
|
|
1033
1044
|
return { regex: new RegExp(`\\b${escaped}\\b`, "gi"), phrase, replacement };
|
|
1034
1045
|
});
|
|
@@ -1056,7 +1067,7 @@ const aiDeslopBuzzwords = {
|
|
|
1056
1067
|
const lineNode = node.children[i];
|
|
1057
1068
|
const scopes = parseLineScopes(line);
|
|
1058
1069
|
const matched = [];
|
|
1059
|
-
for (const { regex, replacement } of COMPILED$
|
|
1070
|
+
for (const { regex, replacement } of COMPILED$6) {
|
|
1060
1071
|
regex.lastIndex = 0;
|
|
1061
1072
|
let match;
|
|
1062
1073
|
while ((match = regex.exec(line)) !== null) {
|
|
@@ -1433,7 +1444,7 @@ const CASING_DICTIONARY = {
|
|
|
1433
1444
|
|
|
1434
1445
|
const REGEX_1$q = /[.*+?^${}()|[\]\\]/g;
|
|
1435
1446
|
const SORTED_ENTRIES = Object.entries(CASING_DICTIONARY).sort((a, b) => b[0].length - a[0].length);
|
|
1436
|
-
const COMPILED$
|
|
1447
|
+
const COMPILED$5 = SORTED_ENTRIES.map(([key, correct]) => {
|
|
1437
1448
|
const escaped = key.replace(REGEX_1$q, "\\$&");
|
|
1438
1449
|
return { regex: new RegExp(`\\b${escaped}\\b`, "gi"), correct };
|
|
1439
1450
|
});
|
|
@@ -1461,7 +1472,7 @@ const aiDeslopCasing = {
|
|
|
1461
1472
|
const lineNode = node.children[i];
|
|
1462
1473
|
const scopes = parseLineScopes(line);
|
|
1463
1474
|
const matched = [];
|
|
1464
|
-
for (const { regex, correct } of COMPILED$
|
|
1475
|
+
for (const { regex, correct } of COMPILED$5) {
|
|
1465
1476
|
regex.lastIndex = 0;
|
|
1466
1477
|
let match;
|
|
1467
1478
|
while ((match = regex.exec(line)) !== null) {
|
|
@@ -1557,12 +1568,12 @@ const aiDeslopCodeLang = {
|
|
|
1557
1568
|
}
|
|
1558
1569
|
};
|
|
1559
1570
|
|
|
1560
|
-
const APOSTROPHE = `(?:'|\u2019)`;
|
|
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");
|
|
1571
|
+
const APOSTROPHE$1 = `(?:'|\u2019)`;
|
|
1572
|
+
const SUBJECT_NOT = `(?:it${APOSTROPHE$1}s|it is|they${APOSTROPHE$1}re|they are|we${APOSTROPHE$1}re|we are|you${APOSTROPHE$1}re|you are|this is|that is|is|are)`;
|
|
1573
|
+
const SUBJECT_IS = `(?:it${APOSTROPHE$1}s|it is|they${APOSTROPHE$1}re|they are|we${APOSTROPHE$1}re|we are|you${APOSTROPHE$1}re|you are|this is|that is|is|are)`;
|
|
1574
|
+
const CONTRACTION_NOT = `(?:isn${APOSTROPHE$1}t|aren${APOSTROPHE$1}t|wasn${APOSTROPHE$1}t|weren${APOSTROPHE$1}t)`;
|
|
1575
|
+
const NO_LONGER = `(?:is|it${APOSTROPHE$1}s|was)`;
|
|
1576
|
+
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$1}s|is)\\s+about\\b|\\b${NO_LONGER}\\s+no\\s+longer\\b.{1,60}?\\b(?:it${APOSTROPHE$1}s|is)\\b`, "i");
|
|
1566
1577
|
const aiDeslopFalseDichotomy = {
|
|
1567
1578
|
meta: {
|
|
1568
1579
|
type: "suggestion",
|
|
@@ -1604,6 +1615,78 @@ const aiDeslopFalseDichotomy = {
|
|
|
1604
1615
|
}
|
|
1605
1616
|
};
|
|
1606
1617
|
|
|
1618
|
+
const REGEX_ESCAPE = /[.*+?^${}()|[\]\\]/g;
|
|
1619
|
+
const APOSTROPHE = /\\'/g;
|
|
1620
|
+
const SENTENCE_START_PREFIX = /^[-*>\s#\d.]+$/;
|
|
1621
|
+
const SENTENCE_END = /[.:!?]\s+$/;
|
|
1622
|
+
const COMPILED$4 = FALSE_SINCERITY_OPENERS.map((opener) => {
|
|
1623
|
+
const escaped = opener.replace(REGEX_ESCAPE, "\\$&").replace(APOSTROPHE, `['\u2019]`);
|
|
1624
|
+
return { regex: new RegExp(`\\b${escaped}\\b\\s*,?\\s*`, "gi"), opener };
|
|
1625
|
+
});
|
|
1626
|
+
const aiDeslopFalseSincerity = {
|
|
1627
|
+
meta: {
|
|
1628
|
+
type: "suggestion",
|
|
1629
|
+
docs: { description: "Remove false-sincerity openers that pad the sentence without adding meaning" },
|
|
1630
|
+
fixable: "code",
|
|
1631
|
+
schema: [],
|
|
1632
|
+
messages: {
|
|
1633
|
+
falseSincerity: 'False-sincerity opener: "{{found}}". It signals nothing. State the point.'
|
|
1634
|
+
}
|
|
1635
|
+
},
|
|
1636
|
+
create(context) {
|
|
1637
|
+
return {
|
|
1638
|
+
document(node) {
|
|
1639
|
+
const sourceCode = context.sourceCode;
|
|
1640
|
+
const lines = sourceCode.lines;
|
|
1641
|
+
const codeBlockLines = getCodeBlockLines(lines);
|
|
1642
|
+
const frontmatterEnd = getFrontmatterEnd(lines);
|
|
1643
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1644
|
+
if (shouldSkipLine(i, codeBlockLines, frontmatterEnd))
|
|
1645
|
+
continue;
|
|
1646
|
+
const line = lines[i];
|
|
1647
|
+
const lineNode = node.children[i];
|
|
1648
|
+
const scopes = parseLineScopes(line);
|
|
1649
|
+
for (const { regex, opener } of COMPILED$4) {
|
|
1650
|
+
regex.lastIndex = 0;
|
|
1651
|
+
let match;
|
|
1652
|
+
while ((match = regex.exec(line)) !== null) {
|
|
1653
|
+
const textBefore = line.slice(0, match.index);
|
|
1654
|
+
const isAtSentenceStart = match.index === 0 || SENTENCE_START_PREFIX.test(textBefore) || SENTENCE_END.test(textBefore);
|
|
1655
|
+
if (!isAtSentenceStart)
|
|
1656
|
+
continue;
|
|
1657
|
+
if (isInsideCompoundIdentifier(line, match.index, match.index + match[0].length))
|
|
1658
|
+
continue;
|
|
1659
|
+
if (isInScope(scopes, match.index, match.index + match[0].length, ["code", "link-url"]))
|
|
1660
|
+
continue;
|
|
1661
|
+
const startOffset = lineNode.position.start.offset + match.index;
|
|
1662
|
+
const endOffset = startOffset + match[0].length;
|
|
1663
|
+
const afterMatch = line.slice(match.index + match[0].length);
|
|
1664
|
+
context.report({
|
|
1665
|
+
loc: {
|
|
1666
|
+
start: { line: i + 1, column: match.index + 1 },
|
|
1667
|
+
end: { line: i + 1, column: match.index + match[0].length + 1 }
|
|
1668
|
+
},
|
|
1669
|
+
messageId: "falseSincerity",
|
|
1670
|
+
data: { found: opener },
|
|
1671
|
+
fix(fixer) {
|
|
1672
|
+
const nextChar = afterMatch[0];
|
|
1673
|
+
if (nextChar >= "a" && nextChar <= "z") {
|
|
1674
|
+
return [
|
|
1675
|
+
fixer.replaceTextRange([startOffset, endOffset], ""),
|
|
1676
|
+
fixer.replaceTextRange([endOffset, endOffset + 1], nextChar.toUpperCase())
|
|
1677
|
+
];
|
|
1678
|
+
}
|
|
1679
|
+
return fixer.replaceTextRange([startOffset, endOffset], "");
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1607
1690
|
const REGEX_3$5 = /[.*+?^${}()|[\]\\]/g;
|
|
1608
1691
|
const REGEX_2$a = /^[-*>\s#\d.]+$/;
|
|
1609
1692
|
const REGEX_1$p = /\.\s+$/;
|
|
@@ -4963,18 +5046,18 @@ const SIDE_EFFECT_PATTERNS = /* @__PURE__ */ new Set([
|
|
|
4963
5046
|
"requestAnimationFrame",
|
|
4964
5047
|
"requestIdleCallback"
|
|
4965
5048
|
]);
|
|
4966
|
-
const RECEIVER_SCOPED_METHODS =
|
|
5049
|
+
const RECEIVER_SCOPED_METHODS = /* @__PURE__ */ new Map([
|
|
4967
5050
|
// Navigation — only on router instances
|
|
4968
|
-
push
|
|
4969
|
-
replace
|
|
4970
|
-
go
|
|
4971
|
-
back
|
|
4972
|
-
forward
|
|
5051
|
+
["push", /* @__PURE__ */ new Set(["router", "$router"])],
|
|
5052
|
+
["replace", /* @__PURE__ */ new Set(["router", "$router"])],
|
|
5053
|
+
["go", /* @__PURE__ */ new Set(["router", "$router"])],
|
|
5054
|
+
["back", /* @__PURE__ */ new Set(["router", "$router"])],
|
|
5055
|
+
["forward", /* @__PURE__ */ new Set(["router", "$router"])],
|
|
4973
5056
|
// Analytics — only on analytics/tracking objects
|
|
4974
|
-
track
|
|
4975
|
-
identify
|
|
4976
|
-
page
|
|
4977
|
-
|
|
5057
|
+
["track", /* @__PURE__ */ new Set(["analytics", "mixpanel", "segment"])],
|
|
5058
|
+
["identify", /* @__PURE__ */ new Set(["analytics", "mixpanel", "segment"])],
|
|
5059
|
+
["page", /* @__PURE__ */ new Set(["analytics", "mixpanel", "segment"])]
|
|
5060
|
+
]);
|
|
4978
5061
|
const SIDE_EFFECT_RECEIVERS = /* @__PURE__ */ new Set([
|
|
4979
5062
|
"console",
|
|
4980
5063
|
"gtag",
|
|
@@ -4999,7 +5082,7 @@ function isSideEffectInHandler(node) {
|
|
|
4999
5082
|
const method = node.callee.property.name;
|
|
5000
5083
|
if (SIDE_EFFECT_PATTERNS.has(method))
|
|
5001
5084
|
return true;
|
|
5002
|
-
const allowedReceivers = RECEIVER_SCOPED_METHODS
|
|
5085
|
+
const allowedReceivers = RECEIVER_SCOPED_METHODS.get(method);
|
|
5003
5086
|
if (allowedReceivers && node.callee.object.type === "Identifier" && allowedReceivers.has(node.callee.object.name))
|
|
5004
5087
|
return true;
|
|
5005
5088
|
if (node.callee.object.type === "Identifier" && SIDE_EFFECT_RECEIVERS.has(node.callee.object.name))
|
|
@@ -6993,6 +7076,7 @@ const plugin = {
|
|
|
6993
7076
|
"ai-deslop-casing": aiDeslopCasing,
|
|
6994
7077
|
"ai-deslop-code-lang": aiDeslopCodeLang,
|
|
6995
7078
|
"ai-deslop-false-dichotomy": aiDeslopFalseDichotomy,
|
|
7079
|
+
"ai-deslop-false-sincerity": aiDeslopFalseSincerity,
|
|
6996
7080
|
"ai-deslop-filler": aiDeslopFiller,
|
|
6997
7081
|
"ai-deslop-frontmatter-spacing": aiDeslopFrontmatterSpacing,
|
|
6998
7082
|
"ai-deslop-hedging": aiDeslopHedging,
|
|
@@ -7120,6 +7204,7 @@ const deslopRules = {
|
|
|
7120
7204
|
"harlanzw/ai-deslop-buzzwords": "error",
|
|
7121
7205
|
"harlanzw/ai-deslop-casing": "error",
|
|
7122
7206
|
"harlanzw/ai-deslop-false-dichotomy": "warn",
|
|
7207
|
+
"harlanzw/ai-deslop-false-sincerity": "error",
|
|
7123
7208
|
"harlanzw/ai-deslop-filler": "error",
|
|
7124
7209
|
"harlanzw/ai-deslop-adverbs": "error",
|
|
7125
7210
|
"harlanzw/ai-deslop-hedging": "warn",
|
|
@@ -7319,13 +7404,14 @@ function harlanzw(options = {}, ...extraConfigs) {
|
|
|
7319
7404
|
}
|
|
7320
7405
|
function detectFramework() {
|
|
7321
7406
|
const cwd = process.cwd();
|
|
7322
|
-
|
|
7407
|
+
let nuxt = existsSync(resolve(cwd, "nuxt.config.ts")) || existsSync(resolve(cwd, "nuxt.config.js"));
|
|
7323
7408
|
let vue = nuxt;
|
|
7324
|
-
if (!vue) {
|
|
7409
|
+
if (!vue || !nuxt) {
|
|
7325
7410
|
try {
|
|
7326
7411
|
const pkg = JSON.parse(readFileSync(resolve(cwd, "package.json"), "utf-8"));
|
|
7327
7412
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
7328
|
-
|
|
7413
|
+
nuxt = nuxt || !!deps.nuxt;
|
|
7414
|
+
vue = vue || !!(deps.vue || deps.nuxt);
|
|
7329
7415
|
} catch {
|
|
7330
7416
|
}
|
|
7331
7417
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-harlanzw",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0",
|
|
5
5
|
"description": "Harlan's opinionated ESLint rules",
|
|
6
6
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"funding": "https://github.
|
|
8
|
+
"funding": "https://github.comcla/sponsors/harlan-zw",
|
|
9
9
|
"homepage": "https://github.com/harlan-zw/eslint-plugin-harlanzw#readme",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|