@phuc1403/musketeer 0.9.0 → 0.10.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.
Files changed (163) hide show
  1. package/INSTALLATION.md +52 -52
  2. package/bin/musketeer.js +168 -168
  3. package/package.json +48 -48
  4. package/src/dotnet-scaffold-copier.js +79 -79
  5. package/src/provisioner/detect.js +93 -93
  6. package/src/self-update.js +77 -77
  7. package/template/.claude/agents/git-manager.md +18 -18
  8. package/template/.claude/agents/hallmark-auditor.md +78 -78
  9. package/template/.claude/agents/researcher.md +33 -33
  10. package/template/.claude/hooks/block-unsafe-adr-title.cjs +85 -85
  11. package/template/.claude/hooks/init-adr-dir.cjs +173 -173
  12. package/template/.claude/hooks/inject-adr-flags.cjs +94 -94
  13. package/template/.claude/hooks/lib/adr/command-scan.cjs +115 -115
  14. package/template/.claude/hooks/lib/characteristics/checker.cjs +357 -357
  15. package/template/.claude/hooks/lib/git-info-cache.cjs +191 -191
  16. package/template/.claude/hooks/sync-adr-toc.cjs +146 -146
  17. package/template/.claude/hooks/usage-quota-cache-refresh.cjs +166 -166
  18. package/template/.claude/hooks/validate-characteristics-hook.cjs +66 -66
  19. package/template/.claude/hooks/validate-cml-hook.js +145 -145
  20. package/template/.claude/skills/adr-writer/SKILL.md +48 -48
  21. package/template/.claude/skills/adr-writer/references/adr-example.md +35 -35
  22. package/template/.claude/skills/architecture-characteristic-writer/SKILL.md +215 -215
  23. package/template/.claude/skills/architecture-characteristic-writer/assets/worksheet-template.md +29 -29
  24. package/template/.claude/skills/architecture-characteristic-writer/references/characteristics-catalog.md +40 -40
  25. package/template/.claude/skills/architecture-characteristic-writer/scripts/ranking-table.cjs +171 -171
  26. package/template/.claude/skills/context-map/SKILL.md +80 -80
  27. package/template/.claude/skills/context-map/example.cml +106 -106
  28. package/template/.claude/skills/context-map/reference/Bounded Context/Bounded Context.md +40 -40
  29. package/template/.claude/skills/context-map/reference/Bounded Context/businessModel.md +5 -5
  30. package/template/.claude/skills/context-map/reference/Bounded Context/domainVisionStatement.md +2 -2
  31. package/template/.claude/skills/context-map/reference/Bounded Context/evolution.md +5 -5
  32. package/template/.claude/skills/context-map/reference/Bounded Context/implementationTechnology.md +1 -1
  33. package/template/.claude/skills/context-map/reference/Bounded Context/implements.md +1 -1
  34. package/template/.claude/skills/context-map/reference/Bounded Context/knowledgeLevel.md +4 -4
  35. package/template/.claude/skills/context-map/reference/Bounded Context/realizes.md +9 -9
  36. package/template/.claude/skills/context-map/reference/Bounded Context/refines.md +10 -10
  37. package/template/.claude/skills/context-map/reference/Bounded Context/responsibilities.md +26 -26
  38. package/template/.claude/skills/context-map/reference/Bounded Context/type.md +23 -23
  39. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Anticorruption Layer.md +5 -5
  40. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Bounded Context Relationship.md +12 -12
  41. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Conformist.md +5 -5
  42. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Customer-Supplier (C-S).md +22 -22
  43. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Open Host Service.md +4 -4
  44. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Partnership (P).md +13 -13
  45. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Published Language.md +4 -4
  46. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Shared Kernel (SK).md +12 -12
  47. package/template/.claude/skills/context-map/reference/Context Map.md +62 -62
  48. package/template/.claude/skills/context-map/reference/Domain/Domain.md +30 -30
  49. package/template/.claude/skills/context-map/reference/Domain/supports.md +33 -33
  50. package/template/.claude/skills/context-map/reference/Domain/type.md +3 -3
  51. package/template/.claude/skills/context-map/reference/Semantic Rules.md +32 -32
  52. package/template/.claude/skills/hallmark/SKILL.md +552 -552
  53. package/template/.claude/skills/hallmark/references/anti-patterns.md +412 -412
  54. package/template/.claude/skills/hallmark/references/assets.md +406 -406
  55. package/template/.claude/skills/hallmark/references/color.md +95 -95
  56. package/template/.claude/skills/hallmark/references/component-cookbook.md +256 -256
  57. package/template/.claude/skills/hallmark/references/components/c1-outlined-chip.md +12 -12
  58. package/template/.claude/skills/hallmark/references/components/c2-inline-form-as-cta.md +16 -16
  59. package/template/.claude/skills/hallmark/references/components/c3-typographic-link.md +8 -8
  60. package/template/.claude/skills/hallmark/references/components/c4-sticky-bottom-bar.md +16 -16
  61. package/template/.claude/skills/hallmark/references/components/f1-bento-grid.md +20 -20
  62. package/template/.claude/skills/hallmark/references/components/f2-sticky-scroll-stack.md +20 -20
  63. package/template/.claude/skills/hallmark/references/components/f3-tabular-spec-sheet.md +11 -11
  64. package/template/.claude/skills/hallmark/references/components/f4-step-sequence.md +11 -11
  65. package/template/.claude/skills/hallmark/references/components/f5-annotated-screenshot.md +11 -11
  66. package/template/.claude/skills/hallmark/references/components/f6-product-card-grid.md +41 -41
  67. package/template/.claude/skills/hallmark/references/components/ft1-mast-headed.md +13 -13
  68. package/template/.claude/skills/hallmark/references/components/ft2-inline-rule-single-line.md +10 -10
  69. package/template/.claude/skills/hallmark/references/components/ft3-index-style-category-list.md +12 -12
  70. package/template/.claude/skills/hallmark/references/components/ft4-dense-typographic.md +10 -10
  71. package/template/.claude/skills/hallmark/references/components/ft5-statement.md +21 -21
  72. package/template/.claude/skills/hallmark/references/components/ft6-letter-close.md +19 -19
  73. package/template/.claude/skills/hallmark/references/components/ft7-newsletter-first.md +27 -27
  74. package/template/.claude/skills/hallmark/references/components/ft8-marquee-scroll.md +25 -25
  75. package/template/.claude/skills/hallmark/references/components/h1-marquee.md +15 -15
  76. package/template/.claude/skills/hallmark/references/components/h2-split-diptych.md +15 -15
  77. package/template/.claude/skills/hallmark/references/components/h3-quote-led.md +11 -11
  78. package/template/.claude/skills/hallmark/references/components/h4-stat-led.md +14 -14
  79. package/template/.claude/skills/hallmark/references/components/h5-letter-hero.md +11 -11
  80. package/template/.claude/skills/hallmark/references/components/h6-photographic-fold.md +16 -16
  81. package/template/.claude/skills/hallmark/references/components/h7-demo-video-clipped-by-viewport-edge.md +27 -27
  82. package/template/.claude/skills/hallmark/references/components/h8-mockup-split-browser-framed.md +23 -23
  83. package/template/.claude/skills/hallmark/references/components/h9-custom-illustration-centerpiece.md +27 -27
  84. package/template/.claude/skills/hallmark/references/components/n1-wordmark-2-links.md +12 -12
  85. package/template/.claude/skills/hallmark/references/components/n10-floating-on-scroll-morph.md +19 -19
  86. package/template/.claude/skills/hallmark/references/components/n2-floating-chip.md +14 -14
  87. package/template/.claude/skills/hallmark/references/components/n3-side-rail.md +14 -14
  88. package/template/.claude/skills/hallmark/references/components/n4-hidden-behind-k.md +9 -9
  89. package/template/.claude/skills/hallmark/references/components/n5-floating-pill.md +28 -28
  90. package/template/.claude/skills/hallmark/references/components/n6-newspaper-masthead.md +24 -24
  91. package/template/.claude/skills/hallmark/references/components/n7-brutal-slab.md +22 -22
  92. package/template/.claude/skills/hallmark/references/components/n8-terminal-command.md +21 -21
  93. package/template/.claude/skills/hallmark/references/components/n9-edge-aligned-minimal.md +17 -17
  94. package/template/.claude/skills/hallmark/references/components/s1-left-margin-numbered.md +15 -15
  95. package/template/.claude/skills/hallmark/references/components/s2-hanging.md +13 -13
  96. package/template/.claude/skills/hallmark/references/components/s3-sticky-pinned.md +19 -19
  97. package/template/.claude/skills/hallmark/references/components/s4-inline-no-break.md +11 -11
  98. package/template/.claude/skills/hallmark/references/components/s5-bottom-anchored.md +13 -13
  99. package/template/.claude/skills/hallmark/references/components/t1-pull-quote-with-marginalia.md +12 -12
  100. package/template/.claude/skills/hallmark/references/components/t2-logo-wall-hairline.md +19 -19
  101. package/template/.claude/skills/hallmark/references/components/t3-single-huge-quote.md +11 -11
  102. package/template/.claude/skills/hallmark/references/components/t4-numbered-stat-strip.md +14 -14
  103. package/template/.claude/skills/hallmark/references/contract.md +24 -24
  104. package/template/.claude/skills/hallmark/references/copy.md +182 -182
  105. package/template/.claude/skills/hallmark/references/custom-craft.md +626 -626
  106. package/template/.claude/skills/hallmark/references/custom-theme.md +329 -329
  107. package/template/.claude/skills/hallmark/references/design-md.md +116 -116
  108. package/template/.claude/skills/hallmark/references/export-formats.md +328 -328
  109. package/template/.claude/skills/hallmark/references/floating-nav.md +89 -89
  110. package/template/.claude/skills/hallmark/references/genres/atmospheric.md +65 -65
  111. package/template/.claude/skills/hallmark/references/genres/editorial.md +70 -70
  112. package/template/.claude/skills/hallmark/references/genres/modern-minimal.md +67 -67
  113. package/template/.claude/skills/hallmark/references/genres/playful.md +65 -65
  114. package/template/.claude/skills/hallmark/references/hero-enrichment.md +474 -474
  115. package/template/.claude/skills/hallmark/references/imagery-kit.md +170 -170
  116. package/template/.claude/skills/hallmark/references/interaction-and-states.md +207 -207
  117. package/template/.claude/skills/hallmark/references/layout-and-space.md +111 -111
  118. package/template/.claude/skills/hallmark/references/macrostructures/01-bento-grid.md +35 -35
  119. package/template/.claude/skills/hallmark/references/macrostructures/02-long-document.md +34 -34
  120. package/template/.claude/skills/hallmark/references/macrostructures/03-marquee-hero.md +31 -31
  121. package/template/.claude/skills/hallmark/references/macrostructures/04-stat-led.md +32 -32
  122. package/template/.claude/skills/hallmark/references/macrostructures/05-workbench.md +32 -32
  123. package/template/.claude/skills/hallmark/references/macrostructures/06-conversational-faq.md +33 -33
  124. package/template/.claude/skills/hallmark/references/macrostructures/07-manifesto.md +32 -32
  125. package/template/.claude/skills/hallmark/references/macrostructures/08-photographic.md +34 -34
  126. package/template/.claude/skills/hallmark/references/macrostructures/09-quote-led.md +32 -32
  127. package/template/.claude/skills/hallmark/references/macrostructures/10-specimen.md +32 -32
  128. package/template/.claude/skills/hallmark/references/macrostructures/11-catalogue.md +23 -23
  129. package/template/.claude/skills/hallmark/references/macrostructures/12-letter.md +23 -23
  130. package/template/.claude/skills/hallmark/references/macrostructures/13-index-first.md +23 -23
  131. package/template/.claude/skills/hallmark/references/macrostructures/14-narrative-workflow.md +23 -23
  132. package/template/.claude/skills/hallmark/references/macrostructures/15-split-studio.md +23 -23
  133. package/template/.claude/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -23
  134. package/template/.claude/skills/hallmark/references/macrostructures/17-type-specimen.md +23 -23
  135. package/template/.claude/skills/hallmark/references/macrostructures/18-portfolio-grid.md +23 -23
  136. package/template/.claude/skills/hallmark/references/macrostructures/19-map-diagram.md +23 -23
  137. package/template/.claude/skills/hallmark/references/macrostructures/20-ecosystem-index.md +23 -23
  138. package/template/.claude/skills/hallmark/references/macrostructures/21-component-playground.md +23 -23
  139. package/template/.claude/skills/hallmark/references/macrostructures.md +89 -89
  140. package/template/.claude/skills/hallmark/references/microinteractions.md +260 -260
  141. package/template/.claude/skills/hallmark/references/motion.md +109 -109
  142. package/template/.claude/skills/hallmark/references/preview-examples.md +49 -49
  143. package/template/.claude/skills/hallmark/references/responsive.md +138 -138
  144. package/template/.claude/skills/hallmark/references/slop-test.md +205 -205
  145. package/template/.claude/skills/hallmark/references/structure.md +164 -164
  146. package/template/.claude/skills/hallmark/references/study.md +511 -511
  147. package/template/.claude/skills/hallmark/references/typography.md +243 -243
  148. package/template/.claude/skills/hallmark/references/verbs/audit.md +25 -25
  149. package/template/.claude/skills/hallmark/references/verbs/redesign.md +269 -269
  150. package/template/.claude/skills/hallmark-loop/SKILL.md +105 -105
  151. package/template/.claude/skills/hallmark-loop/references/auditor-call.md +60 -60
  152. package/template/.claude/skills/hallmark-loop/references/capture.md +78 -78
  153. package/template/.claude/skills/hallmark-loop/references/loop-control.md +79 -79
  154. package/template/.claude/skills/handoff/SKILL.md +15 -15
  155. package/template/.claude/skills/knowledge-crunching/SKILL.md +94 -94
  156. package/template/.claude/skills/research/SKILL.md +69 -69
  157. package/template/.claude/skills/tdd/SKILL.md +142 -142
  158. package/template/.claude/skills/tdd/deep-modules.md +15 -15
  159. package/template/.claude/skills/tdd/interface-design.md +31 -31
  160. package/template/.claude/skills/tdd/mocking.md +59 -59
  161. package/template/.claude/skills/tdd/refactoring.md +10 -10
  162. package/template/.claude/skills/tdd/tests.md +61 -61
  163. package/template/.claude/statusline.cjs +100 -37
@@ -1,115 +1,115 @@
1
- 'use strict';
2
-
3
- // Tells a real `adr` invocation apart from a command that merely mentions one.
4
- //
5
- // Three PreToolUse hooks key off `adr new` and `adr init`. Matching those words
6
- // anywhere in the command string is too loose: a commit message explaining ADR
7
- // work, a grep for the phrase, or a heredoc of documentation all contain them
8
- // and none of them run the tool. Denying those commands leaves the user staring
9
- // at an error about a command they never wrote.
10
- //
11
- // Three tests must all pass before an occurrence counts:
12
- //
13
- // 1. It sits at a command position — the start of the string, or just after a
14
- // separator such as `;` `&&` `||` `|` `(` or a newline — allowing for any
15
- // KEY=value assignments in front of it.
16
- // 2. It is not inside an open quote.
17
- // 3. It is not inside a heredoc body, which is data being written rather than
18
- // a command being run.
19
- //
20
- // Where the two disagree with each other, the answer is "not an invocation".
21
- // A missed invocation makes a hook skip work the user will notice at once; a
22
- // false one blocks an unrelated command for a reason nobody can guess.
23
-
24
- // boundary/start, whitespace, any existing KEY=value prefix, then `adr <sub>`.
25
- //
26
- // The subcommand must not run straight into a word character or a hyphen. `\b`
27
- // alone is not enough: it sits happily between the `w` of `new` and the `-` of
28
- // `adr new-thing`, so that string would count as an `adr new` invocation. A hook
29
- // that only reads the command could shrug that off, but inject-adr-flags writes
30
- // the flag directly after the subcommand and would turn it into `adr new -q-thing`.
31
- // A trailing `;` or `|` still has to count, so this is a negated class rather
32
- // than a required space.
33
- function invocationRe(sub) {
34
- return new RegExp(
35
- `(^|[;&|\\n(){}])([ \\t]*)((?:[A-Za-z_][A-Za-z0-9_]*=(?:'[^']*'|"[^"]*"|\\S*)[ \\t]+)*)(adr[ \\t]+${sub})(?![\\w-])`,
36
- 'g'
37
- );
38
- }
39
-
40
- // An odd number of quote characters before this point means the point is inside
41
- // a string that is still open.
42
- function isInsideQuotes(command, index) {
43
- const before = command.slice(0, index);
44
- const dq = (before.match(/"/g) || []).length;
45
- const sq = (before.match(/'/g) || []).length;
46
- return dq % 2 === 1 || sq % 2 === 1;
47
- }
48
-
49
- const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
50
-
51
- // `<<TAG`, `<<-TAG`, `<<'TAG'`, `<<"TAG"`. `<<<` is a herestring, not a heredoc,
52
- // and does not match here because `<` is neither a quote nor a word character.
53
- const HEREDOC_OPEN = /<<(-?)[ \t]*(?:'([^']+)'|"([^"]+)"|([A-Za-z_][A-Za-z0-9_]*))/g;
54
-
55
- // Offset ranges covering heredoc bodies.
56
- //
57
- // A heredoc body is data being written, not commands being run. Writing install
58
- // docs that show `adr new -- "Use X"` is an ordinary thing to do in this repo,
59
- // and the line sits at the start of its own line with balanced quotes in front
60
- // of it, so both of the other tests would wave it through.
61
- //
62
- // Known limit: several heredocs opened on one line share the first body start,
63
- // so the ranges merge. That errs toward treating more text as data, which only
64
- // ever makes this scanner quieter.
65
- function heredocRanges(command) {
66
- const ranges = [];
67
- const re = new RegExp(HEREDOC_OPEN.source, 'g');
68
- let m;
69
-
70
- while ((m = re.exec(command))) {
71
- const tag = m[2] || m[3] || m[4];
72
- const newline = command.indexOf('\n', m.index);
73
- if (newline === -1) continue; // an opener with no body on this command
74
-
75
- const start = newline + 1;
76
- // `<<-` lets the terminator be indented with tabs.
77
- const terminator = new RegExp(`^${m[1] === '-' ? '[ \\t]*' : ''}${escapeRe(tag)}[ \\t]*$`, 'm');
78
- const hit = command.slice(start).match(terminator);
79
- ranges.push([start, hit ? start + hit.index : command.length]);
80
- }
81
-
82
- return ranges;
83
- }
84
-
85
- function isInsideHeredoc(command, index) {
86
- return heredocRanges(command).some(([start, end]) => index >= start && index < end);
87
- }
88
-
89
- // Where the word `adr` itself starts. The match begins at the boundary
90
- // character before it, which is close enough for counting quotes but one
91
- // position short of the heredoc body it may sit in.
92
- function adrOffsetOf(match) {
93
- return match.index + match[1].length + match[2].length + match[3].length;
94
- }
95
-
96
- // True when the command really runs `adr <sub>` at least once.
97
- function invokesAdr(command, sub) {
98
- const re = invocationRe(sub);
99
- const bodies = heredocRanges(command);
100
- const inBody = (i) => bodies.some(([start, end]) => i >= start && i < end);
101
- let m;
102
- while ((m = re.exec(command))) {
103
- const at = adrOffsetOf(m);
104
- if (!isInsideQuotes(command, at) && !inBody(at)) return true;
105
- }
106
- return false;
107
- }
108
-
109
- module.exports = {
110
- invokesAdr,
111
- isInsideQuotes,
112
- isInsideHeredoc,
113
- heredocRanges,
114
- invocationRe,
115
- };
1
+ 'use strict';
2
+
3
+ // Tells a real `adr` invocation apart from a command that merely mentions one.
4
+ //
5
+ // Three PreToolUse hooks key off `adr new` and `adr init`. Matching those words
6
+ // anywhere in the command string is too loose: a commit message explaining ADR
7
+ // work, a grep for the phrase, or a heredoc of documentation all contain them
8
+ // and none of them run the tool. Denying those commands leaves the user staring
9
+ // at an error about a command they never wrote.
10
+ //
11
+ // Three tests must all pass before an occurrence counts:
12
+ //
13
+ // 1. It sits at a command position — the start of the string, or just after a
14
+ // separator such as `;` `&&` `||` `|` `(` or a newline — allowing for any
15
+ // KEY=value assignments in front of it.
16
+ // 2. It is not inside an open quote.
17
+ // 3. It is not inside a heredoc body, which is data being written rather than
18
+ // a command being run.
19
+ //
20
+ // Where the two disagree with each other, the answer is "not an invocation".
21
+ // A missed invocation makes a hook skip work the user will notice at once; a
22
+ // false one blocks an unrelated command for a reason nobody can guess.
23
+
24
+ // boundary/start, whitespace, any existing KEY=value prefix, then `adr <sub>`.
25
+ //
26
+ // The subcommand must not run straight into a word character or a hyphen. `\b`
27
+ // alone is not enough: it sits happily between the `w` of `new` and the `-` of
28
+ // `adr new-thing`, so that string would count as an `adr new` invocation. A hook
29
+ // that only reads the command could shrug that off, but inject-adr-flags writes
30
+ // the flag directly after the subcommand and would turn it into `adr new -q-thing`.
31
+ // A trailing `;` or `|` still has to count, so this is a negated class rather
32
+ // than a required space.
33
+ function invocationRe(sub) {
34
+ return new RegExp(
35
+ `(^|[;&|\\n(){}])([ \\t]*)((?:[A-Za-z_][A-Za-z0-9_]*=(?:'[^']*'|"[^"]*"|\\S*)[ \\t]+)*)(adr[ \\t]+${sub})(?![\\w-])`,
36
+ 'g'
37
+ );
38
+ }
39
+
40
+ // An odd number of quote characters before this point means the point is inside
41
+ // a string that is still open.
42
+ function isInsideQuotes(command, index) {
43
+ const before = command.slice(0, index);
44
+ const dq = (before.match(/"/g) || []).length;
45
+ const sq = (before.match(/'/g) || []).length;
46
+ return dq % 2 === 1 || sq % 2 === 1;
47
+ }
48
+
49
+ const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
50
+
51
+ // `<<TAG`, `<<-TAG`, `<<'TAG'`, `<<"TAG"`. `<<<` is a herestring, not a heredoc,
52
+ // and does not match here because `<` is neither a quote nor a word character.
53
+ const HEREDOC_OPEN = /<<(-?)[ \t]*(?:'([^']+)'|"([^"]+)"|([A-Za-z_][A-Za-z0-9_]*))/g;
54
+
55
+ // Offset ranges covering heredoc bodies.
56
+ //
57
+ // A heredoc body is data being written, not commands being run. Writing install
58
+ // docs that show `adr new -- "Use X"` is an ordinary thing to do in this repo,
59
+ // and the line sits at the start of its own line with balanced quotes in front
60
+ // of it, so both of the other tests would wave it through.
61
+ //
62
+ // Known limit: several heredocs opened on one line share the first body start,
63
+ // so the ranges merge. That errs toward treating more text as data, which only
64
+ // ever makes this scanner quieter.
65
+ function heredocRanges(command) {
66
+ const ranges = [];
67
+ const re = new RegExp(HEREDOC_OPEN.source, 'g');
68
+ let m;
69
+
70
+ while ((m = re.exec(command))) {
71
+ const tag = m[2] || m[3] || m[4];
72
+ const newline = command.indexOf('\n', m.index);
73
+ if (newline === -1) continue; // an opener with no body on this command
74
+
75
+ const start = newline + 1;
76
+ // `<<-` lets the terminator be indented with tabs.
77
+ const terminator = new RegExp(`^${m[1] === '-' ? '[ \\t]*' : ''}${escapeRe(tag)}[ \\t]*$`, 'm');
78
+ const hit = command.slice(start).match(terminator);
79
+ ranges.push([start, hit ? start + hit.index : command.length]);
80
+ }
81
+
82
+ return ranges;
83
+ }
84
+
85
+ function isInsideHeredoc(command, index) {
86
+ return heredocRanges(command).some(([start, end]) => index >= start && index < end);
87
+ }
88
+
89
+ // Where the word `adr` itself starts. The match begins at the boundary
90
+ // character before it, which is close enough for counting quotes but one
91
+ // position short of the heredoc body it may sit in.
92
+ function adrOffsetOf(match) {
93
+ return match.index + match[1].length + match[2].length + match[3].length;
94
+ }
95
+
96
+ // True when the command really runs `adr <sub>` at least once.
97
+ function invokesAdr(command, sub) {
98
+ const re = invocationRe(sub);
99
+ const bodies = heredocRanges(command);
100
+ const inBody = (i) => bodies.some(([start, end]) => i >= start && i < end);
101
+ let m;
102
+ while ((m = re.exec(command))) {
103
+ const at = adrOffsetOf(m);
104
+ if (!isInsideQuotes(command, at) && !inBody(at)) return true;
105
+ }
106
+ return false;
107
+ }
108
+
109
+ module.exports = {
110
+ invokesAdr,
111
+ isInsideQuotes,
112
+ isInsideHeredoc,
113
+ heredocRanges,
114
+ invocationRe,
115
+ };