refactor: rename 'user' target to 'source' in slay-the-spire-like

Updates the card effect and intent target types from 'user' to 'source'
within the desert data files and combat effect system to maintain
consistency. Also reformat command tests to use 2-space indentation.
This commit is contained in:
2026-04-23 00:35:28 +08:00
parent f4c96a4a72
commit 8ec95cbf81
6 changed files with 193 additions and 191 deletions
@@ -1,5 +1,5 @@
# type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard'
# type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'
# type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'
# type CardEffectList = [effect: @effect; stacks: number][]
id,card,trigger,target,effects
@@ -9,28 +9,28 @@ greataxe,greataxe,onPlay,eachTarget,[attack;5]
spear,spear,onPlay,eachTarget,[attack;2];[attack;2];[attack;2]
dagger,dagger,onPlay,eachTarget,[attack;3];[attack;3]
dart,dart,onPlay,eachTarget,[attack;1]
dart-draw,dart,onPlay,user,[draw;1]
dart-draw,dart,onPlay,source,[draw;1]
crossbow,crossbow,onPlay,eachTarget,[attack;6]
crossbow-combo,crossbow,onPlay,user,[crossbow;0]
shield,shield,onPlay,user,[defend;3]
hat,hat,onPlay,user,[defend;8]
cape,cape,onPlay,user,[defend;2];[defendNext;2]
bracer,bracer,onPlay,user,[defend;1];[draw;1]
greatshield,greatshield,onPlay,user,[defend;5]
chainmail,chainmail,onPlay,user,[damageReduce;3]
bandage,bandage,onPlay,user,[removeWound;1]
poisonPotion,poisonPotion,onPlay,user,[attackBuff;2]
fortifyPotion,fortifyPotion,onPlay,user,[defendBuff;2]
vitalityPotion,vitalityPotion,onPlay,user,[gainEnergy;1]
focusPotion,focusPotion,onPlay,user,[draw;2]
healingPotion,healingPotion,onPlay,user,[removeWound;3]
waterBag,waterBag,onPlay,user,[energyNext;1];[drawNext;2]
rope,rope,onPlay,user,[defendBuffUntilPlay;2]
belt,belt,onPlay,user,[drawChoice;1]
torch,torch,onPlay,user,[burnForEnergy;1]
whetstone,whetstone,onPlay,user,[attackBuffUntilPlay;3]
blacksmithHammer,blacksmithHammer,onPlay,user,[transformRandom;1]
venom,venom,onDiscard,user,[attack;3]
curse,curse,onDraw,user,[curse;1]
static,static,onDraw,user,[static;1]
vultureEye,vultureEye,onDraw,user,[expose;3]
crossbow-combo,crossbow,onPlay,source,[crossbow;0]
shield,shield,onPlay,source,[defend;3]
hat,hat,onPlay,source,[defend;8]
cape,cape,onPlay,source,[defend;2];[defendNext;2]
bracer,bracer,onPlay,source,[defend;1];[draw;1]
greatshield,greatshield,onPlay,source,[defend;5]
chainmail,chainmail,onPlay,source,[damageReduce;3]
bandage,bandage,onPlay,source,[removeWound;1]
poisonPotion,poisonPotion,onPlay,source,[attackBuff;2]
fortifyPotion,fortifyPotion,onPlay,source,[defendBuff;2]
vitalityPotion,vitalityPotion,onPlay,source,[gainEnergy;1]
focusPotion,focusPotion,onPlay,source,[draw;2]
healingPotion,healingPotion,onPlay,source,[removeWound;3]
waterBag,waterBag,onPlay,source,[energyNext;1];[drawNext;2]
rope,rope,onPlay,source,[defendBuffUntilPlay;2]
belt,belt,onPlay,source,[drawChoice;1]
torch,torch,onPlay,source,[burnForEnergy;1]
whetstone,whetstone,onPlay,source,[attackBuffUntilPlay;3]
blacksmithHammer,blacksmithHammer,onPlay,source,[transformRandom;1]
venom,venom,onDiscard,source,[attack;3]
curse,curse,onDraw,source,[curse;1]
static,static,onDraw,source,[static;1]
vultureEye,vultureEye,onDraw,source,[expose;3]
1 # type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard'
2 # type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player' # type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'
3 # type CardEffectList = [effect: @effect; stacks: number][]
4 id,card,trigger,target,effects
5 string,@card,CardEffectTrigger,CardEffectTarget,CardEffectList
9 dagger,dagger,onPlay,eachTarget,[attack;3];[attack;3]
10 dart,dart,onPlay,eachTarget,[attack;1]
11 dart-draw,dart,onPlay,user,[draw;1] dart-draw,dart,onPlay,source,[draw;1]
12 crossbow,crossbow,onPlay,eachTarget,[attack;6]
13 crossbow-combo,crossbow,onPlay,user,[crossbow;0] crossbow-combo,crossbow,onPlay,source,[crossbow;0]
14 shield,shield,onPlay,user,[defend;3] shield,shield,onPlay,source,[defend;3]
15 hat,hat,onPlay,user,[defend;8] hat,hat,onPlay,source,[defend;8]
16 cape,cape,onPlay,user,[defend;2];[defendNext;2] cape,cape,onPlay,source,[defend;2];[defendNext;2]
17 bracer,bracer,onPlay,user,[defend;1];[draw;1] bracer,bracer,onPlay,source,[defend;1];[draw;1]
18 greatshield,greatshield,onPlay,user,[defend;5] greatshield,greatshield,onPlay,source,[defend;5]
19 chainmail,chainmail,onPlay,user,[damageReduce;3] chainmail,chainmail,onPlay,source,[damageReduce;3]
20 bandage,bandage,onPlay,user,[removeWound;1] bandage,bandage,onPlay,source,[removeWound;1]
21 poisonPotion,poisonPotion,onPlay,user,[attackBuff;2] poisonPotion,poisonPotion,onPlay,source,[attackBuff;2]
22 fortifyPotion,fortifyPotion,onPlay,user,[defendBuff;2] fortifyPotion,fortifyPotion,onPlay,source,[defendBuff;2]
23 vitalityPotion,vitalityPotion,onPlay,user,[gainEnergy;1] vitalityPotion,vitalityPotion,onPlay,source,[gainEnergy;1]
24 focusPotion,focusPotion,onPlay,user,[draw;2] focusPotion,focusPotion,onPlay,source,[draw;2]
25 healingPotion,healingPotion,onPlay,user,[removeWound;3] healingPotion,healingPotion,onPlay,source,[removeWound;3]
26 waterBag,waterBag,onPlay,user,[energyNext;1];[drawNext;2] waterBag,waterBag,onPlay,source,[energyNext;1];[drawNext;2]
27 rope,rope,onPlay,user,[defendBuffUntilPlay;2] rope,rope,onPlay,source,[defendBuffUntilPlay;2]
28 belt,belt,onPlay,user,[drawChoice;1] belt,belt,onPlay,source,[drawChoice;1]
29 torch,torch,onPlay,user,[burnForEnergy;1] torch,torch,onPlay,source,[burnForEnergy;1]
30 whetstone,whetstone,onPlay,user,[attackBuffUntilPlay;3] whetstone,whetstone,onPlay,source,[attackBuffUntilPlay;3]
31 blacksmithHammer,blacksmithHammer,onPlay,user,[transformRandom;1] blacksmithHammer,blacksmithHammer,onPlay,source,[transformRandom;1]
32 venom,venom,onDiscard,user,[attack;3] venom,venom,onDiscard,source,[attack;3]
33 curse,curse,onDraw,user,[curse;1] curse,curse,onDraw,source,[curse;1]
34 static,static,onDraw,user,[static;1] static,static,onDraw,source,[static;1]
35 vultureEye,vultureEye,onDraw,user,[expose;3] vultureEye,vultureEye,onDraw,source,[expose;3]
36
@@ -2,7 +2,7 @@ import type { Card } from './card.csv';
import type { Effect } from './effect.csv';
export type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard';
export type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player';
export type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player';
export type CardEffectList = [effect: Effect, stacks: number][];
type CardEffectTable = readonly {
@@ -6,50 +6,50 @@
# initBuffs: initial buffs for this intent (applied when intent becomes active)
# effects: effects executed when this intent is active
# type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player'
# type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player'
# type IntentEffect = [IntentEffectTarget;@effect;number]
# type IntentEffectList = IntentEffect[]
id,enemy,initialIntent,nextIntents,brokenIntent,effects
string,@enemy,boolean,@intent[],@intent[],IntentEffectList
仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[user;spike;1];[user;defend;4]
仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[user;defend;8]
仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[source;spike;1];[source;defend;4]
仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[source;defend;8]
仙人掌怪-attack,仙人掌怪,false,仙人掌怪-boost,,[player;attack;5]
蛇-poison,,true,蛇-attack;蛇-attack,,[player;venom;1];[player;attack;4]
蛇-attack,,false,蛇-poison;蛇-boost,,[player;attack;6]
蛇-boost,,false,蛇-poison;蛇-attack,,[user;defend;3];[player;venom;1]
蛇-boost,,false,蛇-poison;蛇-attack,,[source;defend;3];[player;venom;1]
木乃伊-attack,木乃伊,true,木乃伊-defend;木乃伊-curse,,[player;attack;6]
木乃伊-defend,木乃伊,false,木乃伊-attack,,[user;defend;6]
木乃伊-defend,木乃伊,false,木乃伊-attack,,[source;defend;6]
木乃伊-curse,木乃伊,false,木乃伊-defend;木乃伊-attack,木乃伊-attack,[player;curse;1]
枪手-aim,枪手,true,枪手-attack,,[user;aim;2]
枪手-aim,枪手,true,枪手-attack,,[source;aim;2]
枪手-attack,枪手,false,枪手-aim;枪手-defend,枪手-aim,[player;attack;8]
枪手-defend,枪手,false,枪手-aim,枪手-aim,[user;defend;5]
风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[user;roll;5];[user;defend;4]
风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[user;defend;8]
枪手-defend,枪手,false,枪手-aim,枪手-aim,[source;defend;5]
风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[source;roll;5];[source;defend;4]
风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[source;defend;8]
风卷草-attack,风卷草,false,风卷草-boost,,[player;rollDamage;0]
秃鹫-attack,秃鹫,true,秃鹫-defend;秃鹫-defend,,[player;attack;6];[player;vultureEye;1]
秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[user;defend;5]
沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[user;tailSting;2]
秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[source;defend;5]
沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[source;tailSting;2]
沙蝎-attack,沙蝎,false,沙蝎-boost;沙蝎-attack,,[player;attack;6]
幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[user;defend;6]
幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[user;energyDrain;1];[user;defend;4]
幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[source;defend;6]
幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[source;energyDrain;1];[source;defend;4]
幼沙虫-attack,幼沙虫,false,幼沙虫-defend;幼沙虫-defend,,[player;attack;5]
蜥蜴-attack,蜥蜴,true,蜥蜴-defend;蜥蜴-molt,,[player;attack;5]
蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[user;defend;6]
蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[user;molt;3]
蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[source;defend;6]
蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[source;molt;3]
沙匪-attack,沙匪,true,沙匪-attack;沙匪-heavyAttack,,[player;attack;6]
沙匪-heavyAttack,沙匪,false,沙匪-attack;沙匪-attack;沙匪-debuff,,[player;attack;10]
沙匪-debuff,沙匪,false,沙匪-attack;沙匪-attack,,[player;discard;1]
风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[user;storm;2];[user;defend;3]
风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[source;storm;2];[source;defend;3]
风暴之灵-attack,风暴之灵,false,风暴之灵-storm;风暴之灵-defend,,[player;attack;8];[player;static;1]
风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[user;defend;8]
骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[user;charge;2]
风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[source;defend;8]
骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[source;charge;2]
骑马枪手-attack,骑马枪手,false,骑马枪手-charge;骑马枪手-defend,骑马枪手-charge,[player;attack;6]
骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[user;defend;5]
沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[user;summonSandwormLarva;18]
骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[source;defend;5]
沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[source;summonSandwormLarva;18]
沙虫王-attack,沙虫王,false,沙虫王-summon;沙虫王-defend,,[player;attack;9]
沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[user;defend;6]
沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[user;summonMummy;14]
沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[source;defend;6]
沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[source;summonMummy;14]
沙漠守卫-attack,沙漠守卫,false,沙漠守卫-defend;沙漠守卫-summon,,[player;attack;8]
沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[user;defend;8]
沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[user;reviveMummy;1]
沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[source;defend;8]
沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[source;reviveMummy;1]
1 # intentId: unique intent state ID (e.g. '仙人掌怪-boost')
6 # initBuffs: initial buffs for this intent (applied when intent becomes active)
7 # effects: effects executed when this intent is active
8 # type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player' # type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player'
9 # type IntentEffect = [IntentEffectTarget;@effect;number]
10 # type IntentEffectList = IntentEffect[]
11 id
12 string
13 仙人掌怪-boost
14 仙人掌怪-defend
15 仙人掌怪-attack
16 蛇-poison
17 蛇-attack
18 蛇-boost
19 木乃伊-attack
20 木乃伊-defend
21 木乃伊-curse
22 枪手-aim
23 枪手-attack
24 枪手-defend
25 风卷草-boost
26 风卷草-defend
27 风卷草-attack
28 秃鹫-attack
29 秃鹫-defend
30 沙蝎-boost
31 沙蝎-attack
32 幼沙虫-defend
33 幼沙虫-boost
34 幼沙虫-attack
35 蜥蜴-attack
36 蜥蜴-defend
37 蜥蜴-molt
38 沙匪-attack
39 沙匪-heavyAttack
40 沙匪-debuff
41 风暴之灵-storm
42 风暴之灵-attack
43 风暴之灵-defend
44 骑马枪手-charge
45 骑马枪手-attack
46 骑马枪手-defend
47 沙虫王-summon
48 沙虫王-attack
49 沙虫王-defend
50 沙漠守卫-summon
51 沙漠守卫-attack
52 沙漠守卫-defend
53 沙漠守卫-revive
54
55
@@ -1,7 +1,7 @@
import type { Enemy } from './enemy.csv';
import type { Effect } from './effect.csv';
export type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player';
export type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player';
export type IntentEffect = [IntentEffectTarget, Effect, number];
export type IntentEffectList = IntentEffect[];
@@ -112,7 +112,7 @@ export function* getEffectTargets(
for (const enemy of getAliveEnemies(game.value)) {
yield enemy;
}
} else if (target === "user") {
} else if (target === "source") {
const entity = getCombatEntity(game.value, sourceEntityKey);
if (entity) yield entity;
} else if (target === "player") {
+75 -73
View File
@@ -1,174 +1,176 @@
import { describe, it, expect } from 'vitest';
import { parseCommand, type Command } from '@/utils/command';
import { describe, it, expect } from "vitest";
import { parseCommand, type Command } from "@/utils/command";
describe('parseCommand', () => {
it('should parse empty string', () => {
const result = parseCommand('');
describe("parseCommand", () => {
it("should parse empty string", () => {
const result = parseCommand("");
expect(result).toEqual({
name: '',
name: "",
flags: {},
options: {},
params: []
params: [],
});
});
it('should parse command name only', () => {
const result = parseCommand('move');
it("should parse command name only", () => {
const result = parseCommand("move");
expect(result).toEqual({
name: 'move',
name: "move",
flags: {},
options: {},
params: []
params: [],
});
});
it('should parse command with params', () => {
const result = parseCommand('move meeple1 region1');
it("should parse command with params", () => {
const result = parseCommand("move meeple1 region1");
expect(result).toEqual({
name: 'move',
name: "move",
flags: {},
options: {},
params: ['meeple1', 'region1']
params: ["meeple1", "region1"],
});
});
it('should parse command with long flags', () => {
const result = parseCommand('move meeple1 --force --quiet');
it("should parse command with long flags", () => {
const result = parseCommand("move meeple1 --force --quiet");
expect(result).toEqual({
name: 'move',
name: "move",
flags: { force: true, quiet: true },
options: {},
params: ['meeple1']
params: ["meeple1"],
});
});
it('should parse command with short flags', () => {
const result = parseCommand('move meeple1 -f -q');
it("should parse command with short flags", () => {
const result = parseCommand("move meeple1 -f -q");
expect(result).toEqual({
name: 'move',
name: "move",
flags: { f: true, q: true },
options: {},
params: ['meeple1']
params: ["meeple1"],
});
});
it('should parse command with long options', () => {
const result = parseCommand('move meeple1 --x 10 --y 20');
it("should parse command with long options", () => {
const result = parseCommand("move meeple1 --x 10 --y 20");
expect(result).toEqual({
name: 'move',
name: "move",
flags: {},
options: { x: '10', y: '20' },
params: ['meeple1']
options: { x: "10", y: "20" },
params: ["meeple1"],
});
});
it('should parse command with short options', () => {
const result = parseCommand('move meeple1 -x 10 -y 20');
it("should parse command with short options", () => {
const result = parseCommand("move meeple1 -x 10 -y 20");
expect(result).toEqual({
name: 'move',
name: "move",
flags: {},
options: { x: '10', y: '20' },
params: ['meeple1']
options: { x: "10", y: "20" },
params: ["meeple1"],
});
});
it('should parse command with mixed flags和选项', () => {
const result = parseCommand('move meeple1 region1 --force -x 10 -q');
it("should parse command with mixed flags和选项", () => {
const result = parseCommand("move meeple1 region1 --force -x 10 -q");
expect(result).toEqual({
name: 'move',
name: "move",
flags: { force: true, q: true },
options: { x: '10' },
params: ['meeple1', 'region1']
options: { x: "10" },
params: ["meeple1", "region1"],
});
});
it('should handle extra whitespace', () => {
const result = parseCommand(' move meeple1 --force ');
it("should handle extra whitespace", () => {
const result = parseCommand(" move meeple1 --force ");
expect(result).toEqual({
name: 'move',
name: "move",
flags: { force: true },
options: {},
params: ['meeple1']
params: ["meeple1"],
});
});
it('should parse complex command', () => {
const result = parseCommand('place meeple1 board --x 5 --y 3 --rotate 90 --force');
it("should parse complex command", () => {
const result = parseCommand(
"place meeple1 board --x 5 --y 3 --rotate 90 --force",
);
expect(result).toEqual({
name: 'place',
name: "place",
flags: { force: true },
options: { x: '5', y: '3', rotate: '90' },
params: ['meeple1', 'board']
options: { x: "5", y: "3", rotate: "90" },
params: ["meeple1", "board"],
});
});
it('should treat negative number as option value', () => {
const result = parseCommand('set --value -10');
it("should treat negative number as option value", () => {
const result = parseCommand("set --value -10");
expect(result).toEqual({
name: 'set',
name: "set",
flags: {},
options: { value: '-10' },
params: []
options: { value: "-10" },
params: [],
});
});
it('should parse quoted string with double quotes', () => {
it("should parse quoted string with double quotes", () => {
const result = parseCommand('place tile "large castle" --x 5');
expect(result).toEqual({
name: 'place',
name: "place",
flags: {},
options: { x: '5' },
params: ['tile', 'large castle']
options: { x: "5" },
params: ["tile", "large castle"],
});
});
it('should parse quoted string with single quotes', () => {
it("should parse quoted string with single quotes", () => {
const result = parseCommand("place tile 'large castle' --x 5");
expect(result).toEqual({
name: 'place',
name: "place",
flags: {},
options: { x: '5' },
params: ['tile', 'large castle']
options: { x: "5" },
params: ["tile", "large castle"],
});
});
it('should handle escaped quotes', () => {
it("should handle escaped quotes", () => {
const result = parseCommand('say "hello \\"world\\""');
expect(result).toEqual({
name: 'say',
name: "say",
flags: {},
options: {},
params: ['hello "world"']
params: ['hello "world"'],
});
});
it('should handle escaped backslash', () => {
it("should handle escaped backslash", () => {
const result = parseCommand('set path "C:\\\\Users"');
expect(result).toEqual({
name: 'set',
name: "set",
flags: {},
options: {},
params: ['path', 'C:\\Users']
params: ["path", "C:\\Users"],
});
});
it('should handle mixed quotes', () => {
const result = parseCommand('cmd "hello world" \'foo bar\' --flag');
it("should handle mixed quotes", () => {
const result = parseCommand("cmd \"hello world\" 'foo bar' --flag");
expect(result).toEqual({
name: 'cmd',
name: "cmd",
flags: { flag: true },
options: {},
params: ['hello world', 'foo bar']
params: ["hello world", "foo bar"],
});
});
it('should handle quote in middle of argument', () => {
it("should handle quote in middle of argument", () => {
const result = parseCommand('cmd "hello\'s world"');
expect(result).toEqual({
name: 'cmd',
name: "cmd",
flags: {},
options: {},
params: ["hello's world"]
params: ["hello's world"],
});
});
});