@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.
- package/INSTALLATION.md +52 -52
- package/bin/musketeer.js +168 -168
- package/package.json +48 -48
- package/src/dotnet-scaffold-copier.js +79 -79
- package/src/provisioner/detect.js +93 -93
- package/src/self-update.js +77 -77
- package/template/.claude/agents/git-manager.md +18 -18
- package/template/.claude/agents/hallmark-auditor.md +78 -78
- package/template/.claude/agents/researcher.md +33 -33
- package/template/.claude/hooks/block-unsafe-adr-title.cjs +85 -85
- package/template/.claude/hooks/init-adr-dir.cjs +173 -173
- package/template/.claude/hooks/inject-adr-flags.cjs +94 -94
- package/template/.claude/hooks/lib/adr/command-scan.cjs +115 -115
- package/template/.claude/hooks/lib/characteristics/checker.cjs +357 -357
- package/template/.claude/hooks/lib/git-info-cache.cjs +191 -191
- package/template/.claude/hooks/sync-adr-toc.cjs +146 -146
- package/template/.claude/hooks/usage-quota-cache-refresh.cjs +166 -166
- package/template/.claude/hooks/validate-characteristics-hook.cjs +66 -66
- package/template/.claude/hooks/validate-cml-hook.js +145 -145
- package/template/.claude/skills/adr-writer/SKILL.md +48 -48
- package/template/.claude/skills/adr-writer/references/adr-example.md +35 -35
- package/template/.claude/skills/architecture-characteristic-writer/SKILL.md +215 -215
- package/template/.claude/skills/architecture-characteristic-writer/assets/worksheet-template.md +29 -29
- package/template/.claude/skills/architecture-characteristic-writer/references/characteristics-catalog.md +40 -40
- package/template/.claude/skills/architecture-characteristic-writer/scripts/ranking-table.cjs +171 -171
- package/template/.claude/skills/context-map/SKILL.md +80 -80
- package/template/.claude/skills/context-map/example.cml +106 -106
- package/template/.claude/skills/context-map/reference/Bounded Context/Bounded Context.md +40 -40
- package/template/.claude/skills/context-map/reference/Bounded Context/businessModel.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context/domainVisionStatement.md +2 -2
- package/template/.claude/skills/context-map/reference/Bounded Context/evolution.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context/implementationTechnology.md +1 -1
- package/template/.claude/skills/context-map/reference/Bounded Context/implements.md +1 -1
- package/template/.claude/skills/context-map/reference/Bounded Context/knowledgeLevel.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context/realizes.md +9 -9
- package/template/.claude/skills/context-map/reference/Bounded Context/refines.md +10 -10
- package/template/.claude/skills/context-map/reference/Bounded Context/responsibilities.md +26 -26
- package/template/.claude/skills/context-map/reference/Bounded Context/type.md +23 -23
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Anticorruption Layer.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Bounded Context Relationship.md +12 -12
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Conformist.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Customer-Supplier (C-S).md +22 -22
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Open Host Service.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Partnership (P).md +13 -13
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Published Language.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Shared Kernel (SK).md +12 -12
- package/template/.claude/skills/context-map/reference/Context Map.md +62 -62
- package/template/.claude/skills/context-map/reference/Domain/Domain.md +30 -30
- package/template/.claude/skills/context-map/reference/Domain/supports.md +33 -33
- package/template/.claude/skills/context-map/reference/Domain/type.md +3 -3
- package/template/.claude/skills/context-map/reference/Semantic Rules.md +32 -32
- package/template/.claude/skills/hallmark/SKILL.md +552 -552
- package/template/.claude/skills/hallmark/references/anti-patterns.md +412 -412
- package/template/.claude/skills/hallmark/references/assets.md +406 -406
- package/template/.claude/skills/hallmark/references/color.md +95 -95
- package/template/.claude/skills/hallmark/references/component-cookbook.md +256 -256
- package/template/.claude/skills/hallmark/references/components/c1-outlined-chip.md +12 -12
- package/template/.claude/skills/hallmark/references/components/c2-inline-form-as-cta.md +16 -16
- package/template/.claude/skills/hallmark/references/components/c3-typographic-link.md +8 -8
- package/template/.claude/skills/hallmark/references/components/c4-sticky-bottom-bar.md +16 -16
- package/template/.claude/skills/hallmark/references/components/f1-bento-grid.md +20 -20
- package/template/.claude/skills/hallmark/references/components/f2-sticky-scroll-stack.md +20 -20
- package/template/.claude/skills/hallmark/references/components/f3-tabular-spec-sheet.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f4-step-sequence.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f5-annotated-screenshot.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f6-product-card-grid.md +41 -41
- package/template/.claude/skills/hallmark/references/components/ft1-mast-headed.md +13 -13
- package/template/.claude/skills/hallmark/references/components/ft2-inline-rule-single-line.md +10 -10
- package/template/.claude/skills/hallmark/references/components/ft3-index-style-category-list.md +12 -12
- package/template/.claude/skills/hallmark/references/components/ft4-dense-typographic.md +10 -10
- package/template/.claude/skills/hallmark/references/components/ft5-statement.md +21 -21
- package/template/.claude/skills/hallmark/references/components/ft6-letter-close.md +19 -19
- package/template/.claude/skills/hallmark/references/components/ft7-newsletter-first.md +27 -27
- package/template/.claude/skills/hallmark/references/components/ft8-marquee-scroll.md +25 -25
- package/template/.claude/skills/hallmark/references/components/h1-marquee.md +15 -15
- package/template/.claude/skills/hallmark/references/components/h2-split-diptych.md +15 -15
- package/template/.claude/skills/hallmark/references/components/h3-quote-led.md +11 -11
- package/template/.claude/skills/hallmark/references/components/h4-stat-led.md +14 -14
- package/template/.claude/skills/hallmark/references/components/h5-letter-hero.md +11 -11
- package/template/.claude/skills/hallmark/references/components/h6-photographic-fold.md +16 -16
- package/template/.claude/skills/hallmark/references/components/h7-demo-video-clipped-by-viewport-edge.md +27 -27
- package/template/.claude/skills/hallmark/references/components/h8-mockup-split-browser-framed.md +23 -23
- package/template/.claude/skills/hallmark/references/components/h9-custom-illustration-centerpiece.md +27 -27
- package/template/.claude/skills/hallmark/references/components/n1-wordmark-2-links.md +12 -12
- package/template/.claude/skills/hallmark/references/components/n10-floating-on-scroll-morph.md +19 -19
- package/template/.claude/skills/hallmark/references/components/n2-floating-chip.md +14 -14
- package/template/.claude/skills/hallmark/references/components/n3-side-rail.md +14 -14
- package/template/.claude/skills/hallmark/references/components/n4-hidden-behind-k.md +9 -9
- package/template/.claude/skills/hallmark/references/components/n5-floating-pill.md +28 -28
- package/template/.claude/skills/hallmark/references/components/n6-newspaper-masthead.md +24 -24
- package/template/.claude/skills/hallmark/references/components/n7-brutal-slab.md +22 -22
- package/template/.claude/skills/hallmark/references/components/n8-terminal-command.md +21 -21
- package/template/.claude/skills/hallmark/references/components/n9-edge-aligned-minimal.md +17 -17
- package/template/.claude/skills/hallmark/references/components/s1-left-margin-numbered.md +15 -15
- package/template/.claude/skills/hallmark/references/components/s2-hanging.md +13 -13
- package/template/.claude/skills/hallmark/references/components/s3-sticky-pinned.md +19 -19
- package/template/.claude/skills/hallmark/references/components/s4-inline-no-break.md +11 -11
- package/template/.claude/skills/hallmark/references/components/s5-bottom-anchored.md +13 -13
- package/template/.claude/skills/hallmark/references/components/t1-pull-quote-with-marginalia.md +12 -12
- package/template/.claude/skills/hallmark/references/components/t2-logo-wall-hairline.md +19 -19
- package/template/.claude/skills/hallmark/references/components/t3-single-huge-quote.md +11 -11
- package/template/.claude/skills/hallmark/references/components/t4-numbered-stat-strip.md +14 -14
- package/template/.claude/skills/hallmark/references/contract.md +24 -24
- package/template/.claude/skills/hallmark/references/copy.md +182 -182
- package/template/.claude/skills/hallmark/references/custom-craft.md +626 -626
- package/template/.claude/skills/hallmark/references/custom-theme.md +329 -329
- package/template/.claude/skills/hallmark/references/design-md.md +116 -116
- package/template/.claude/skills/hallmark/references/export-formats.md +328 -328
- package/template/.claude/skills/hallmark/references/floating-nav.md +89 -89
- package/template/.claude/skills/hallmark/references/genres/atmospheric.md +65 -65
- package/template/.claude/skills/hallmark/references/genres/editorial.md +70 -70
- package/template/.claude/skills/hallmark/references/genres/modern-minimal.md +67 -67
- package/template/.claude/skills/hallmark/references/genres/playful.md +65 -65
- package/template/.claude/skills/hallmark/references/hero-enrichment.md +474 -474
- package/template/.claude/skills/hallmark/references/imagery-kit.md +170 -170
- package/template/.claude/skills/hallmark/references/interaction-and-states.md +207 -207
- package/template/.claude/skills/hallmark/references/layout-and-space.md +111 -111
- package/template/.claude/skills/hallmark/references/macrostructures/01-bento-grid.md +35 -35
- package/template/.claude/skills/hallmark/references/macrostructures/02-long-document.md +34 -34
- package/template/.claude/skills/hallmark/references/macrostructures/03-marquee-hero.md +31 -31
- package/template/.claude/skills/hallmark/references/macrostructures/04-stat-led.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/05-workbench.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/06-conversational-faq.md +33 -33
- package/template/.claude/skills/hallmark/references/macrostructures/07-manifesto.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/08-photographic.md +34 -34
- package/template/.claude/skills/hallmark/references/macrostructures/09-quote-led.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/10-specimen.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/11-catalogue.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/12-letter.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/13-index-first.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/14-narrative-workflow.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/15-split-studio.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/17-type-specimen.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/18-portfolio-grid.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/19-map-diagram.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/20-ecosystem-index.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/21-component-playground.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures.md +89 -89
- package/template/.claude/skills/hallmark/references/microinteractions.md +260 -260
- package/template/.claude/skills/hallmark/references/motion.md +109 -109
- package/template/.claude/skills/hallmark/references/preview-examples.md +49 -49
- package/template/.claude/skills/hallmark/references/responsive.md +138 -138
- package/template/.claude/skills/hallmark/references/slop-test.md +205 -205
- package/template/.claude/skills/hallmark/references/structure.md +164 -164
- package/template/.claude/skills/hallmark/references/study.md +511 -511
- package/template/.claude/skills/hallmark/references/typography.md +243 -243
- package/template/.claude/skills/hallmark/references/verbs/audit.md +25 -25
- package/template/.claude/skills/hallmark/references/verbs/redesign.md +269 -269
- package/template/.claude/skills/hallmark-loop/SKILL.md +105 -105
- package/template/.claude/skills/hallmark-loop/references/auditor-call.md +60 -60
- package/template/.claude/skills/hallmark-loop/references/capture.md +78 -78
- package/template/.claude/skills/hallmark-loop/references/loop-control.md +79 -79
- package/template/.claude/skills/handoff/SKILL.md +15 -15
- package/template/.claude/skills/knowledge-crunching/SKILL.md +94 -94
- package/template/.claude/skills/research/SKILL.md +69 -69
- package/template/.claude/skills/tdd/SKILL.md +142 -142
- package/template/.claude/skills/tdd/deep-modules.md +15 -15
- package/template/.claude/skills/tdd/interface-design.md +31 -31
- package/template/.claude/skills/tdd/mocking.md +59 -59
- package/template/.claude/skills/tdd/refactoring.md +10 -10
- package/template/.claude/skills/tdd/tests.md +61 -61
- 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
|
+
};
|