@sharpee/text-service 0.9.60-beta

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli-renderer.d.ts +43 -0
  3. package/dist/cli-renderer.d.ts.map +1 -0
  4. package/dist/cli-renderer.js +208 -0
  5. package/dist/cli-renderer.js.map +1 -0
  6. package/dist/decoration-parser.d.ts +31 -0
  7. package/dist/decoration-parser.d.ts.map +1 -0
  8. package/dist/decoration-parser.js +176 -0
  9. package/dist/decoration-parser.js.map +1 -0
  10. package/dist/handlers/action.d.ts +19 -0
  11. package/dist/handlers/action.d.ts.map +1 -0
  12. package/dist/handlers/action.js +68 -0
  13. package/dist/handlers/action.js.map +1 -0
  14. package/dist/handlers/game.d.ts +29 -0
  15. package/dist/handlers/game.d.ts.map +1 -0
  16. package/dist/handlers/game.js +56 -0
  17. package/dist/handlers/game.js.map +1 -0
  18. package/dist/handlers/generic.d.ts +23 -0
  19. package/dist/handlers/generic.d.ts.map +1 -0
  20. package/dist/handlers/generic.js +70 -0
  21. package/dist/handlers/generic.js.map +1 -0
  22. package/dist/handlers/index.d.ts +12 -0
  23. package/dist/handlers/index.d.ts.map +1 -0
  24. package/dist/handlers/index.js +22 -0
  25. package/dist/handlers/index.js.map +1 -0
  26. package/dist/handlers/revealed.d.ts +16 -0
  27. package/dist/handlers/revealed.d.ts.map +1 -0
  28. package/dist/handlers/revealed.js +50 -0
  29. package/dist/handlers/revealed.js.map +1 -0
  30. package/dist/handlers/room.d.ts +22 -0
  31. package/dist/handlers/room.d.ts.map +1 -0
  32. package/dist/handlers/room.js +70 -0
  33. package/dist/handlers/room.js.map +1 -0
  34. package/dist/handlers/types.d.ts +40 -0
  35. package/dist/handlers/types.d.ts.map +1 -0
  36. package/dist/handlers/types.js +8 -0
  37. package/dist/handlers/types.js.map +1 -0
  38. package/dist/index.d.ts +31 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +58 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/stages/assemble.d.ts +18 -0
  43. package/dist/stages/assemble.d.ts.map +1 -0
  44. package/dist/stages/assemble.js +38 -0
  45. package/dist/stages/assemble.js.map +1 -0
  46. package/dist/stages/filter.d.ts +14 -0
  47. package/dist/stages/filter.d.ts.map +1 -0
  48. package/dist/stages/filter.js +28 -0
  49. package/dist/stages/filter.js.map +1 -0
  50. package/dist/stages/index.d.ts +9 -0
  51. package/dist/stages/index.d.ts.map +1 -0
  52. package/dist/stages/index.js +17 -0
  53. package/dist/stages/index.js.map +1 -0
  54. package/dist/stages/sort.d.ts +36 -0
  55. package/dist/stages/sort.d.ts.map +1 -0
  56. package/dist/stages/sort.js +84 -0
  57. package/dist/stages/sort.js.map +1 -0
  58. package/dist/text-service.d.ts +85 -0
  59. package/dist/text-service.d.ts.map +1 -0
  60. package/dist/text-service.js +233 -0
  61. package/dist/text-service.js.map +1 -0
  62. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Cornelson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,43 @@
1
+ /**
2
+ * CLI Renderer
3
+ *
4
+ * Renders ITextBlock[] to string output for CLI clients.
5
+ * Supports optional ANSI color codes.
6
+ *
7
+ * @see ADR-096 Text Service Architecture
8
+ */
9
+ import type { ITextBlock } from '@sharpee/text-blocks';
10
+ /**
11
+ * CLI render options
12
+ */
13
+ export interface CLIRenderOptions {
14
+ /** Enable ANSI color codes (default: false) */
15
+ ansi?: boolean;
16
+ /** Separator between blocks (default: '\n\n') */
17
+ blockSeparator?: string;
18
+ /** Story-defined color mappings */
19
+ colors?: Record<string, string>;
20
+ /** Include status blocks in output (default: false) */
21
+ includeStatus?: boolean;
22
+ }
23
+ /**
24
+ * Render ITextBlock[] to string for CLI output.
25
+ *
26
+ * Uses smart joining: single newline between consecutive blocks of the same type,
27
+ * double newline between different block types. This keeps related output together
28
+ * (e.g., multiple "Taken" messages) while separating distinct sections.
29
+ *
30
+ * @example
31
+ * const output = renderToString(blocks, { ansi: true });
32
+ * console.log(output);
33
+ */
34
+ export declare function renderToString(blocks: ITextBlock[], options?: CLIRenderOptions): string;
35
+ /**
36
+ * Render status blocks to a single line (for status bar display).
37
+ *
38
+ * @example
39
+ * const status = renderStatusLine(blocks);
40
+ * // "West of House | Score: 0 | Turns: 1"
41
+ */
42
+ export declare function renderStatusLine(blocks: ITextBlock[], options?: CLIRenderOptions): string;
43
+ //# sourceMappingURL=cli-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-renderer.d.ts","sourceRoot":"","sources":["../src/cli-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,sBAAsB,CAAC;AAGjF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC,uDAAuD;IACvD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA0ID;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CA+BR;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CA6BR"}
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Renderer
4
+ *
5
+ * Renders ITextBlock[] to string output for CLI clients.
6
+ * Supports optional ANSI color codes.
7
+ *
8
+ * @see ADR-096 Text Service Architecture
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.renderToString = renderToString;
12
+ exports.renderStatusLine = renderStatusLine;
13
+ const text_blocks_1 = require("@sharpee/text-blocks");
14
+ /**
15
+ * ANSI escape codes
16
+ */
17
+ const ANSI = {
18
+ RESET: '\x1b[0m',
19
+ BOLD: '\x1b[1m',
20
+ ITALIC: '\x1b[3m',
21
+ UNDERLINE: '\x1b[4m',
22
+ STRIKETHROUGH: '\x1b[9m',
23
+ // Colors
24
+ BLACK: '\x1b[30m',
25
+ RED: '\x1b[31m',
26
+ GREEN: '\x1b[32m',
27
+ YELLOW: '\x1b[33m',
28
+ BLUE: '\x1b[34m',
29
+ MAGENTA: '\x1b[35m',
30
+ CYAN: '\x1b[36m',
31
+ WHITE: '\x1b[37m',
32
+ // Bright colors
33
+ BRIGHT_RED: '\x1b[91m',
34
+ BRIGHT_GREEN: '\x1b[92m',
35
+ BRIGHT_YELLOW: '\x1b[93m',
36
+ BRIGHT_BLUE: '\x1b[94m',
37
+ BRIGHT_MAGENTA: '\x1b[95m',
38
+ BRIGHT_CYAN: '\x1b[96m',
39
+ BRIGHT_WHITE: '\x1b[97m',
40
+ };
41
+ /**
42
+ * Map decoration types to ANSI codes
43
+ */
44
+ const DECORATION_ANSI = {
45
+ em: ANSI.ITALIC,
46
+ strong: ANSI.BOLD,
47
+ item: ANSI.CYAN,
48
+ room: ANSI.YELLOW,
49
+ npc: ANSI.MAGENTA,
50
+ command: ANSI.GREEN,
51
+ direction: ANSI.WHITE,
52
+ underline: ANSI.UNDERLINE,
53
+ strikethrough: ANSI.STRIKETHROUGH,
54
+ };
55
+ /**
56
+ * Approximate hex colors to ANSI
57
+ */
58
+ function hexToAnsi(hex) {
59
+ // Simple approximation - extract dominant color
60
+ const r = parseInt(hex.slice(1, 3), 16);
61
+ const g = parseInt(hex.slice(3, 5), 16);
62
+ const b = parseInt(hex.slice(5, 7), 16);
63
+ // Find closest ANSI color
64
+ if (r > g && r > b)
65
+ return r > 180 ? ANSI.BRIGHT_RED : ANSI.RED;
66
+ if (g > r && g > b)
67
+ return g > 180 ? ANSI.BRIGHT_GREEN : ANSI.GREEN;
68
+ if (b > r && b > g)
69
+ return b > 180 ? ANSI.BRIGHT_BLUE : ANSI.BLUE;
70
+ if (r > 200 && g > 200)
71
+ return ANSI.BRIGHT_YELLOW;
72
+ if (r > 200 && b > 200)
73
+ return ANSI.BRIGHT_MAGENTA;
74
+ if (g > 200 && b > 200)
75
+ return ANSI.BRIGHT_CYAN;
76
+ if (r > 180 && g > 180 && b > 180)
77
+ return ANSI.BRIGHT_WHITE;
78
+ return ANSI.WHITE;
79
+ }
80
+ /**
81
+ * Render TextContent to string
82
+ */
83
+ function renderContent(content, options) {
84
+ return content
85
+ .map((item) => {
86
+ if (typeof item === 'string') {
87
+ return item;
88
+ }
89
+ // IDecoration
90
+ return renderDecoration(item, options);
91
+ })
92
+ .join('');
93
+ }
94
+ /**
95
+ * Render a decoration to string
96
+ */
97
+ function renderDecoration(decoration, options) {
98
+ const innerText = renderContent(decoration.content, options);
99
+ if (!options.ansi) {
100
+ // Plain text fallback
101
+ if (decoration.type === 'em')
102
+ return `*${innerText}*`;
103
+ if (decoration.type === 'strong')
104
+ return `**${innerText}**`;
105
+ return innerText;
106
+ }
107
+ // ANSI rendering
108
+ let ansiCode = DECORATION_ANSI[decoration.type];
109
+ // Check for story-defined color
110
+ if (!ansiCode && options.colors?.[decoration.type]) {
111
+ const hex = options.colors[decoration.type];
112
+ if (hex.startsWith('#')) {
113
+ ansiCode = hexToAnsi(hex);
114
+ }
115
+ }
116
+ if (ansiCode) {
117
+ return `${ansiCode}${innerText}${ANSI.RESET}`;
118
+ }
119
+ // Unknown decoration type - render without styling
120
+ return innerText;
121
+ }
122
+ /**
123
+ * Render a single block to string
124
+ */
125
+ function renderBlock(block, options) {
126
+ const text = renderContent(block.content, options);
127
+ // Apply block-level styling
128
+ if (options.ansi) {
129
+ if (block.key === 'room.name') {
130
+ return `${ANSI.BOLD}${ANSI.YELLOW}${text}${ANSI.RESET}`;
131
+ }
132
+ if (block.key === 'action.blocked' || block.key === 'error') {
133
+ return `${ANSI.RED}${text}${ANSI.RESET}`;
134
+ }
135
+ }
136
+ return text;
137
+ }
138
+ /**
139
+ * Render ITextBlock[] to string for CLI output.
140
+ *
141
+ * Uses smart joining: single newline between consecutive blocks of the same type,
142
+ * double newline between different block types. This keeps related output together
143
+ * (e.g., multiple "Taken" messages) while separating distinct sections.
144
+ *
145
+ * @example
146
+ * const output = renderToString(blocks, { ansi: true });
147
+ * console.log(output);
148
+ */
149
+ function renderToString(blocks, options = {}) {
150
+ const opts = {
151
+ ansi: false,
152
+ blockSeparator: '\n\n',
153
+ includeStatus: false,
154
+ ...options,
155
+ };
156
+ // Filter out status blocks unless explicitly included
157
+ const filteredBlocks = opts.includeStatus
158
+ ? blocks
159
+ : blocks.filter((b) => !(0, text_blocks_1.isStatusBlock)(b));
160
+ // Render each block and pair with its key for smart joining
161
+ const rendered = filteredBlocks
162
+ .map((block) => ({ key: block.key, text: renderBlock(block, opts) }))
163
+ .filter((item) => item.text.trim());
164
+ if (rendered.length === 0)
165
+ return '';
166
+ // Smart join: \n between same block types, \n\n between different types
167
+ const parts = [rendered[0].text];
168
+ for (let i = 1; i < rendered.length; i++) {
169
+ const prev = rendered[i - 1];
170
+ const curr = rendered[i];
171
+ // Use single newline for consecutive same-type blocks, double for different
172
+ const separator = prev.key === curr.key ? '\n' : opts.blockSeparator;
173
+ parts.push(separator + curr.text);
174
+ }
175
+ return parts.join('');
176
+ }
177
+ /**
178
+ * Render status blocks to a single line (for status bar display).
179
+ *
180
+ * @example
181
+ * const status = renderStatusLine(blocks);
182
+ * // "West of House | Score: 0 | Turns: 1"
183
+ */
184
+ function renderStatusLine(blocks, options = {}) {
185
+ const statusBlocks = blocks.filter(text_blocks_1.isStatusBlock);
186
+ const parts = [];
187
+ // Render in specific order
188
+ const roomBlock = statusBlocks.find((b) => b.key === 'status.room');
189
+ if (roomBlock) {
190
+ parts.push(renderContent(roomBlock.content, options));
191
+ }
192
+ const scoreBlock = statusBlocks.find((b) => b.key === 'status.score');
193
+ if (scoreBlock) {
194
+ parts.push(`Score: ${renderContent(scoreBlock.content, options)}`);
195
+ }
196
+ const turnsBlock = statusBlocks.find((b) => b.key === 'status.turns');
197
+ if (turnsBlock) {
198
+ parts.push(`Turns: ${renderContent(turnsBlock.content, options)}`);
199
+ }
200
+ // Add any custom status blocks
201
+ const knownKeys = ['status.room', 'status.score', 'status.turns'];
202
+ const customBlocks = statusBlocks.filter((b) => !knownKeys.includes(b.key));
203
+ for (const block of customBlocks) {
204
+ parts.push(renderContent(block.content, options));
205
+ }
206
+ return parts.join(' | ');
207
+ }
208
+ //# sourceMappingURL=cli-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-renderer.js","sourceRoot":"","sources":["../src/cli-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Decoration Parser
3
+ *
4
+ * Parses decoration syntax from resolved templates into IDecoration structures.
5
+ *
6
+ * Supports:
7
+ * - [type:content] - semantic decorations
8
+ * - *emphasis* - emphasis
9
+ * - **strong** - strong emphasis
10
+ * - Nested decorations
11
+ * - Escaped characters: \*, \[, \]
12
+ *
13
+ * @see ADR-091 Text Decorations
14
+ */
15
+ import type { TextContent } from '@sharpee/text-blocks';
16
+ /**
17
+ * Parse decorated text into TextContent array.
18
+ *
19
+ * @example
20
+ * parseDecorations('You take [item:the sword].')
21
+ * // Returns: ['You take ', { type: 'item', content: ['the sword'] }, '.']
22
+ *
23
+ * parseDecorations('The lantern glows *brightly*.')
24
+ * // Returns: ['The lantern glows ', { type: 'em', content: ['brightly'] }, '.']
25
+ */
26
+ export declare function parseDecorations(text: string): TextContent[];
27
+ /**
28
+ * Check if text contains any decoration markers.
29
+ */
30
+ export declare function hasDecorations(text: string): boolean;
31
+ //# sourceMappingURL=decoration-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decoration-parser.d.ts","sourceRoot":"","sources":["../src/decoration-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,sBAAsB,CAAC;AAErE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CA4G5D;AA4DD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD"}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ /**
3
+ * Decoration Parser
4
+ *
5
+ * Parses decoration syntax from resolved templates into IDecoration structures.
6
+ *
7
+ * Supports:
8
+ * - [type:content] - semantic decorations
9
+ * - *emphasis* - emphasis
10
+ * - **strong** - strong emphasis
11
+ * - Nested decorations
12
+ * - Escaped characters: \*, \[, \]
13
+ *
14
+ * @see ADR-091 Text Decorations
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.parseDecorations = parseDecorations;
18
+ exports.hasDecorations = hasDecorations;
19
+ /**
20
+ * Parse decorated text into TextContent array.
21
+ *
22
+ * @example
23
+ * parseDecorations('You take [item:the sword].')
24
+ * // Returns: ['You take ', { type: 'item', content: ['the sword'] }, '.']
25
+ *
26
+ * parseDecorations('The lantern glows *brightly*.')
27
+ * // Returns: ['The lantern glows ', { type: 'em', content: ['brightly'] }, '.']
28
+ */
29
+ function parseDecorations(text) {
30
+ if (!text)
31
+ return [];
32
+ const result = [];
33
+ let current = '';
34
+ let i = 0;
35
+ while (i < text.length) {
36
+ const char = text[i];
37
+ // Handle escape sequences
38
+ if (char === '\\' && i + 1 < text.length) {
39
+ const nextChar = text[i + 1];
40
+ if (nextChar === '*' || nextChar === '[' || nextChar === ']' || nextChar === '\\') {
41
+ current += nextChar;
42
+ i += 2;
43
+ continue;
44
+ }
45
+ }
46
+ // Handle [type:content] decorations
47
+ if (char === '[') {
48
+ const closeIndex = findMatchingBracket(text, i);
49
+ if (closeIndex !== -1) {
50
+ // Flush current text
51
+ if (current) {
52
+ result.push(current);
53
+ current = '';
54
+ }
55
+ const inner = text.slice(i + 1, closeIndex);
56
+ const colonIndex = inner.indexOf(':');
57
+ if (colonIndex !== -1) {
58
+ const type = inner.slice(0, colonIndex);
59
+ const content = inner.slice(colonIndex + 1);
60
+ // Recursively parse content for nested decorations
61
+ const decoration = {
62
+ type,
63
+ content: parseDecorations(content),
64
+ };
65
+ result.push(decoration);
66
+ }
67
+ else {
68
+ // No colon - treat as literal text
69
+ current += text.slice(i, closeIndex + 1);
70
+ }
71
+ i = closeIndex + 1;
72
+ continue;
73
+ }
74
+ }
75
+ // Handle **strong** (check before single *)
76
+ if (char === '*' && text[i + 1] === '*') {
77
+ const closeIndex = text.indexOf('**', i + 2);
78
+ if (closeIndex !== -1) {
79
+ // Flush current text
80
+ if (current) {
81
+ result.push(current);
82
+ current = '';
83
+ }
84
+ const content = text.slice(i + 2, closeIndex);
85
+ const decoration = {
86
+ type: 'strong',
87
+ content: parseDecorations(content),
88
+ };
89
+ result.push(decoration);
90
+ i = closeIndex + 2;
91
+ continue;
92
+ }
93
+ }
94
+ // Handle *emphasis*
95
+ if (char === '*') {
96
+ const closeIndex = findSingleAsterisk(text, i + 1);
97
+ if (closeIndex !== -1) {
98
+ // Flush current text
99
+ if (current) {
100
+ result.push(current);
101
+ current = '';
102
+ }
103
+ const content = text.slice(i + 1, closeIndex);
104
+ const decoration = {
105
+ type: 'em',
106
+ content: parseDecorations(content),
107
+ };
108
+ result.push(decoration);
109
+ i = closeIndex + 1;
110
+ continue;
111
+ }
112
+ }
113
+ // Regular character
114
+ current += char;
115
+ i++;
116
+ }
117
+ // Flush remaining text
118
+ if (current) {
119
+ result.push(current);
120
+ }
121
+ return result;
122
+ }
123
+ /**
124
+ * Find matching closing bracket, handling nesting.
125
+ */
126
+ function findMatchingBracket(text, openIndex) {
127
+ let depth = 1;
128
+ let i = openIndex + 1;
129
+ while (i < text.length && depth > 0) {
130
+ const char = text[i];
131
+ // Handle escapes
132
+ if (char === '\\' && i + 1 < text.length) {
133
+ i += 2;
134
+ continue;
135
+ }
136
+ if (char === '[') {
137
+ depth++;
138
+ }
139
+ else if (char === ']') {
140
+ depth--;
141
+ }
142
+ if (depth === 0) {
143
+ return i;
144
+ }
145
+ i++;
146
+ }
147
+ return -1; // No matching bracket
148
+ }
149
+ /**
150
+ * Find closing single asterisk (not part of **).
151
+ */
152
+ function findSingleAsterisk(text, startIndex) {
153
+ let i = startIndex;
154
+ while (i < text.length) {
155
+ const char = text[i];
156
+ // Handle escapes
157
+ if (char === '\\' && i + 1 < text.length) {
158
+ i += 2;
159
+ continue;
160
+ }
161
+ // Found single asterisk (not part of **)
162
+ if (char === '*' && text[i + 1] !== '*' && (i === startIndex || text[i - 1] !== '*')) {
163
+ return i;
164
+ }
165
+ i++;
166
+ }
167
+ return -1;
168
+ }
169
+ /**
170
+ * Check if text contains any decoration markers.
171
+ */
172
+ function hasDecorations(text) {
173
+ // Quick check for decoration markers
174
+ return /[*\[]/.test(text);
175
+ }
176
+ //# sourceMappingURL=decoration-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decoration-parser.js","sourceRoot":"","sources":["../src/decoration-parser.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AAcH,4CA4GC;AA+DD,wCAGC;AAxLD;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErB,0BAA0B;QAC1B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAClF,OAAO,IAAI,QAAQ,CAAC;gBACpB,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAChD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtB,qBAAqB;gBACrB,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACrB,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAEtC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;oBACtB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;oBACxC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;oBAE5C,mDAAmD;oBACnD,MAAM,UAAU,GAAgB;wBAC9B,IAAI;wBACJ,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;qBACnC,CAAC;oBACF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,mCAAmC;oBACnC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;gBAC3C,CAAC;gBAED,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;gBACnB,SAAS;YACX,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtB,qBAAqB;gBACrB,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACrB,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC9C,MAAM,UAAU,GAAgB;oBAC9B,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;iBACnC,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAExB,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;gBACnB,SAAS;YACX,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACnD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtB,qBAAqB;gBACrB,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACrB,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC9C,MAAM,UAAU,GAAgB;oBAC9B,IAAI,EAAE,IAAI;oBACV,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;iBACnC,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAExB,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;gBACnB,SAAS;YACX,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,OAAO,IAAI,IAAI,CAAC;QAChB,CAAC,EAAE,CAAC;IACN,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,IAAY,EAAE,SAAiB;IAC1D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;IAEtB,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErB,iBAAiB;QACjB,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,KAAK,EAAE,CAAC;QACV,CAAC;QAED,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,CAAC,EAAE,CAAC;IACN,CAAC;IAED,OAAO,CAAC,CAAC,CAAC,CAAC,sBAAsB;AACnC,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAY,EAAE,UAAkB;IAC1D,IAAI,CAAC,GAAG,UAAU,CAAC;IAEnB,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErB,iBAAiB;QACjB,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,yCAAyC;QACzC,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACrF,OAAO,CAAC,CAAC;QACX,CAAC;QAED,CAAC,EAAE,CAAC;IACN,CAAC;IAED,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAY;IACzC,qCAAqC;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Action event handlers
3
+ *
4
+ * Handles: action.success, action.failure, action.blocked
5
+ *
6
+ * @see ADR-096 Text Service Architecture
7
+ */
8
+ import type { ITextBlock } from '@sharpee/text-blocks';
9
+ import type { ISemanticEvent } from '@sharpee/core';
10
+ import type { HandlerContext } from './types.js';
11
+ /**
12
+ * Handle action.success events
13
+ */
14
+ export declare function handleActionSuccess(event: ISemanticEvent, context: HandlerContext): ITextBlock[];
15
+ /**
16
+ * Handle action.failure and action.blocked events
17
+ */
18
+ export declare function handleActionFailure(event: ISemanticEvent, context: HandlerContext): ITextBlock[];
19
+ //# sourceMappingURL=action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/handlers/action.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBjD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,cAAc,GACtB,UAAU,EAAE,CA4Bd;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,cAAc,GACtB,UAAU,EAAE,CA8Bd"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * Action event handlers
4
+ *
5
+ * Handles: action.success, action.failure, action.blocked
6
+ *
7
+ * @see ADR-096 Text Service Architecture
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.handleActionSuccess = handleActionSuccess;
11
+ exports.handleActionFailure = handleActionFailure;
12
+ const text_blocks_1 = require("@sharpee/text-blocks");
13
+ const assemble_js_1 = require("../stages/assemble.js");
14
+ /**
15
+ * Handle action.success events
16
+ */
17
+ function handleActionSuccess(event, context) {
18
+ const data = event.data;
19
+ // Try to get message from language provider
20
+ if (data.messageId && context.languageProvider) {
21
+ const fullMessageId = data.actionId
22
+ ? `${data.actionId}.${data.messageId}`
23
+ : data.messageId;
24
+ let message = context.languageProvider.getMessage(fullMessageId, data.params);
25
+ // Fallback to just messageId
26
+ if (message === fullMessageId && data.messageId) {
27
+ message = context.languageProvider.getMessage(data.messageId, data.params);
28
+ }
29
+ if (message !== data.messageId && message !== fullMessageId) {
30
+ return [(0, assemble_js_1.createBlock)(text_blocks_1.BLOCK_KEYS.ACTION_RESULT, message)];
31
+ }
32
+ }
33
+ // Fallback to data in event
34
+ const text = data.message ?? data.text;
35
+ if (text) {
36
+ return [(0, assemble_js_1.createBlock)(text_blocks_1.BLOCK_KEYS.ACTION_RESULT, text)];
37
+ }
38
+ return [];
39
+ }
40
+ /**
41
+ * Handle action.failure and action.blocked events
42
+ */
43
+ function handleActionFailure(event, context) {
44
+ const data = event.data;
45
+ // Try language provider
46
+ if (data.messageId && context.languageProvider) {
47
+ const fullMessageId = data.actionId
48
+ ? `${data.actionId}.${data.messageId}`
49
+ : data.messageId;
50
+ let message = context.languageProvider.getMessage(fullMessageId, data.params);
51
+ // Fallback to just messageId (matches handleActionSuccess behavior)
52
+ // This allows capability behaviors to use story-specific messageIds like
53
+ // 'dungeo.troll.spits_at_player' without needing the action prefix
54
+ if (message === fullMessageId && data.messageId) {
55
+ message = context.languageProvider.getMessage(data.messageId, data.params);
56
+ }
57
+ if (message !== data.messageId && message !== fullMessageId) {
58
+ return [(0, assemble_js_1.createBlock)(text_blocks_1.BLOCK_KEYS.ACTION_BLOCKED, message)];
59
+ }
60
+ }
61
+ // Fallback
62
+ const text = data.params?.reason ??
63
+ data.reason ??
64
+ data.message ??
65
+ "You can't do that.";
66
+ return [(0, assemble_js_1.createBlock)(text_blocks_1.BLOCK_KEYS.ACTION_BLOCKED, text)];
67
+ }
68
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.js","sourceRoot":"","sources":["../../src/handlers/action.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAiCH,kDA+BC;AAKD,kDAiCC;AAnGD,sDAAkD;AAGlD,uDAAoD;AAwBpD;;GAEG;AACH,SAAgB,mBAAmB,CACjC,KAAqB,EACrB,OAAuB;IAEvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAyB,CAAC;IAE7C,4CAA4C;IAC5C,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ;YACjC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;YACtC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAEnB,IAAI,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAE9E,6BAA6B;QAC7B,IAAI,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChD,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,OAAO,KAAK,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5D,OAAO,CAAC,IAAA,yBAAW,EAAC,wBAAU,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC;IACvC,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAA,yBAAW,EAAC,wBAAU,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CACjC,KAAqB,EACrB,OAAuB;IAEvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAyB,CAAC;IAE7C,wBAAwB;IACxB,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ;YACjC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;YACtC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAEnB,IAAI,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAE9E,oEAAoE;QACpE,yEAAyE;QACzE,mEAAmE;QACnE,IAAI,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChD,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,OAAO,KAAK,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5D,OAAO,CAAC,IAAA,yBAAW,EAAC,wBAAU,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,WAAW;IACX,MAAM,IAAI,GACP,IAAI,CAAC,MAA8B,EAAE,MAAM;QAC5C,IAAI,CAAC,MAAM;QACX,IAAI,CAAC,OAAO;QACZ,oBAAoB,CAAC;IACvB,OAAO,CAAC,IAAA,yBAAW,EAAC,wBAAU,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Game Event Handler
3
+ *
4
+ * Handles game lifecycle events like game.started to produce
5
+ * text output (e.g., opening banner).
6
+ *
7
+ * @see ADR-096 Text Service Architecture
8
+ * @see ADR-097 IGameEvent Deprecation (now uses ISemanticEvent with typed data)
9
+ * @see ISSUE-028 Opening banner hardcoded in browser-entry.ts
10
+ */
11
+ import type { ITextBlock } from '@sharpee/text-blocks';
12
+ import type { ISemanticEvent } from '@sharpee/core';
13
+ import type { HandlerContext } from './types.js';
14
+ /**
15
+ * Handle game.started event to produce the opening banner.
16
+ *
17
+ * The event data (GameStartedData) contains:
18
+ * - story.title: Game title
19
+ * - story.author: Author name(s)
20
+ * - story.version: Game version
21
+ * - story.id: Story identifier
22
+ * - gameState: 'running'
23
+ * - session: { startTime, turns, moves }
24
+ *
25
+ * The language provider supplies the banner template via 'game.started.banner'.
26
+ * Stories can customize by overriding this message in extendLanguage().
27
+ */
28
+ export declare function handleGameStarted(event: ISemanticEvent, context: HandlerContext): ITextBlock[];
29
+ //# sourceMappingURL=game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/handlers/game.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAA4B,MAAM,eAAe,CAAC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,cAAc,GACtB,UAAU,EAAE,CAgCd"}