conversation-replay 0.1.5 → 0.1.7

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 (3) hide show
  1. package/README.md +48 -11
  2. package/dist/cli.js +28 -28
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # Conversation Replay
2
2
 
3
- Conversation Replay is a "video" player for conversations.
3
+ Create animated replays of text conversations.
4
4
 
5
- After parsing the annotated conversation data you supply in a YAML file, this tool will generate a self-contained embeddable replay that uses HTML, JavaScript, and CSS. This can be help in security awareness, training, and web publishing situations.
5
+ After parsing the annotated conversation data you supply in a YAML file, this tool will generate a self-contained embeddable HTML file. The published conversation can help with security awareness training and other communications that involve presenting an annotated text conversation.
6
6
 
7
7
  - [Conversation Replay](#conversation-replay)
8
8
  - [How This Is Useful](#how-this-is-useful)
9
+ - [Installation](#installation)
10
+ - [Run Without Installing (Recommended)](#run-without-installing-recommended)
11
+ - [Global Install](#global-install)
12
+ - [Install from GitHub](#install-from-github)
9
13
  - [Quick Start](#quick-start)
10
14
  - [YAML Schema](#yaml-schema)
11
15
  - [Basic Structure](#basic-structure)
@@ -30,7 +34,7 @@ After parsing the annotated conversation data you supply in a YAML file, this to
30
34
 
31
35
  ## How This Is Useful
32
36
 
33
- Security training often involves showing how attacks unfold through conversation—phishing emails, social engineering calls, BEC attempts, scammer chat interactions. Static screenshots lose the temporal element. Video production is time-consuming and hard to update.
37
+ Security training often involves showing how attacks unfold through text conversations—phishing emails, social engineering calls, BEC attempts, scammer chat interactions. Static screenshots lose the temporal element. Video production is time-consuming and hard to update.
34
38
 
35
39
  Conversation Replay lets you:
36
40
 
@@ -39,20 +43,53 @@ Conversation Replay lets you:
39
43
  - **Slick Design:** Modern UI, nice typography, clean colors, and smooth animations
40
44
  - **Embed Anywhere:** Seamlessly integrates into blogs and LMS platforms
41
45
 
42
- Want to see it in action? Open the pre-generated demo replays [examples/london-scam.html](examples/london-scam.html) or [examples/ir-report.html](examples/ir-report.html) directly in your browser.
46
+ Want to see it in action? Open the pre-generated demo replays [examples/london-scam.html](examples/london-scam.html) or [examples/ir-report.html](examples/ir-report.html) in your browser.
43
47
 
44
- ## Quick Start
48
+ ## Installation
49
+
50
+ ### Run Without Installing (Recommended)
45
51
 
46
- To build your own conversation replay:
52
+ The easiest way to use Conversation Replay—no installation required—after you create the annotated conversation file demo.yaml:
47
53
 
48
54
  ```bash
49
- # Prerequisite: Bun (https://bun.sh) or Node.js 18+
55
+ # Using npx (comes with Node.js)
56
+ npx conversation-replay build demo.yaml -o demo.html
50
57
 
51
- # Install dependencies
52
- bun install
58
+ # Using bunx (comes with Bun)
59
+ bunx conversation-replay build demo.yaml -o demo.html
60
+ ```
53
61
 
54
- # Build a demo from YAML
55
- bun run src/cli.ts build examples/london-scam.yaml -o demo.html
62
+ ### Global Install
63
+
64
+ For frequent use, install globally:
65
+
66
+ ```bash
67
+ # Using npm
68
+ npm install -g conversation-replay
69
+
70
+ # Using Bun
71
+ bun add -g conversation-replay
72
+
73
+ # Then run directly
74
+ conversation-replay build demo.yaml -o demo.html
75
+ ```
76
+
77
+ ### Install from GitHub
78
+
79
+ To install the latest development version directly from GitHub:
80
+
81
+ ```bash
82
+ npm install -g github:lennyzeltser/conversation-replay
83
+ ```
84
+
85
+ Note: This requires [Bun](https://bun.sh) to be installed (for the build step).
86
+
87
+ ## Quick Start
88
+
89
+ Create a YAML file defining your conversation, then generate the HTML:
90
+
91
+ ```bash
92
+ conversation-replay build examples/london-scam.yaml -o demo.html
56
93
  ```
57
94
 
58
95
  Output:
package/dist/cli.js CHANGED
@@ -7361,6 +7361,12 @@ function generateColorOverrides(colors) {
7361
7361
  if (colors.tabInactiveColor) {
7362
7362
  overrides.push(`--tab-inactive-color: ${colors.tabInactiveColor};`);
7363
7363
  }
7364
+ if (colors.annotationText) {
7365
+ overrides.push(`--annotation-text: ${colors.annotationText};`);
7366
+ }
7367
+ if (colors.annotationBorder) {
7368
+ overrides.push(`--annotation-border: ${colors.annotationBorder};`);
7369
+ }
7364
7370
  if (overrides.length === 0)
7365
7371
  return "";
7366
7372
  return `
@@ -7370,10 +7376,11 @@ function generateColorOverrides(colors) {
7370
7376
  }
7371
7377
  `;
7372
7378
  }
7373
- function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7379
+ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle, initialBlur) {
7374
7380
  const colorOverrides = generateColorOverrides(colors);
7375
7381
  const radius = cornerStyle === "straight" ? "0" : "8px";
7376
7382
  const radiusLg = cornerStyle === "straight" ? "0" : "12px";
7383
+ const blurAmount = initialBlur ?? 1;
7377
7384
  const tabCss = hasMultipleScenarios ? `
7378
7385
  /* Tabs - browser-style integrated with canvas */
7379
7386
  .tabs {
@@ -7391,17 +7398,15 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7391
7398
  border: 1px solid transparent;
7392
7399
  border-bottom: none;
7393
7400
  background: transparent;
7394
- color: var(--tab-inactive-color, var(--text-muted));
7401
+ color: var(--tab-inactive-color, var(--text-secondary));
7395
7402
  border-radius: var(--radius) var(--radius) 0 0;
7396
7403
  cursor: pointer;
7397
7404
  font-size: 13px;
7398
7405
  font-weight: 500;
7399
7406
  transition: all 0.2s;
7400
- opacity: 0.75;
7401
7407
  }
7402
7408
 
7403
7409
  .tab:hover {
7404
- opacity: 0.9;
7405
7410
  color: var(--text-primary);
7406
7411
  }
7407
7412
 
@@ -7409,7 +7414,6 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7409
7414
  background: var(--bg-chat);
7410
7415
  color: var(--text-primary);
7411
7416
  border-color: var(--border-color);
7412
- opacity: 1;
7413
7417
  position: relative;
7414
7418
  }
7415
7419
 
@@ -7480,7 +7484,7 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7480
7484
 
7481
7485
  --annotation-bg: transparent;
7482
7486
  --annotation-border: var(--color-slate-300);
7483
- --annotation-text: var(--color-slate-500);
7487
+ --annotation-text: var(--color-slate-600);
7484
7488
 
7485
7489
  --transition-bg: var(--color-primary-50);
7486
7490
  --transition-border: var(--color-primary-300);
@@ -7518,7 +7522,7 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7518
7522
  --ai-text: #e2e8f0;
7519
7523
 
7520
7524
  --annotation-border: #475569;
7521
- --annotation-text: #94a3b8;
7525
+ --annotation-text: #cbd5e1;
7522
7526
 
7523
7527
  --border-color: #334155; /* Slate 700 */
7524
7528
 
@@ -7551,7 +7555,7 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7551
7555
  --ai-text: #e2e8f0;
7552
7556
 
7553
7557
  --annotation-border: #475569;
7554
- --annotation-text: #94a3b8;
7558
+ --annotation-text: #cbd5e1;
7555
7559
 
7556
7560
  --border-color: #334155; /* Slate 700 */
7557
7561
 
@@ -7730,16 +7734,15 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7730
7734
 
7731
7735
  body.in-iframe .chat-wrapper {
7732
7736
  box-shadow: none !important; /* Remove wrapper shadow */
7733
- background: transparent !important;
7734
7737
  }
7735
7738
 
7736
7739
  body.in-iframe .chat-container {
7737
7740
  flex: 1;
7738
7741
  min-height: 0;
7739
- box-shadow: none !important; /* Remove heavy shadow in iframe usually */
7740
- border: none !important;
7741
- background: transparent !important;
7742
- border-radius: 0 !important; /* Flatten corners for full bleed if needed, or keep them */
7742
+ max-height: none !important; /* Remove height constraint in iframe */
7743
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important; /* Subtle shadow in iframe */
7744
+ /* Keep border and background for visual definition */
7745
+ margin-bottom: clamp(70px, 15vh, 120px); /* Responsive space for fixed controls */
7743
7746
  }
7744
7747
 
7745
7748
  body.in-iframe .controls-wrapper {
@@ -7753,9 +7756,6 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7753
7756
  z-index: 20;
7754
7757
  }
7755
7758
 
7756
- body.in-iframe .play-overlay {
7757
- border-radius: 0 !important;
7758
- }
7759
7759
 
7760
7760
  .chat-messages {
7761
7761
  display: flex;
@@ -7774,8 +7774,8 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7774
7774
  align-items: center;
7775
7775
  justify-content: center;
7776
7776
  background: rgba(255, 255, 255, 0.1); /* Much more transparent */
7777
- backdrop-filter: blur(1.5px); /* Very subtle blur */
7778
- -webkit-backdrop-filter: blur(1.5px);
7777
+ backdrop-filter: blur(${blurAmount}px); /* Subtle blur - configurable via initialBlur */
7778
+ -webkit-backdrop-filter: blur(${blurAmount}px);
7779
7779
  border-radius: var(--radius-lg);
7780
7780
  cursor: pointer;
7781
7781
  transition: opacity 0.4s ease;
@@ -7800,9 +7800,9 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7800
7800
  }
7801
7801
 
7802
7802
  .play-overlay-icon svg {
7803
- margin-left: 4px; /* Optical center adjustment for play triangle */
7804
- width: 20px;
7805
- height: 20px;
7803
+ margin-left: 5px; /* Optical center adjustment for play triangle */
7804
+ width: 26px;
7805
+ height: 26px;
7806
7806
  fill: var(--accent);
7807
7807
  }
7808
7808
 
@@ -7923,7 +7923,7 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7923
7923
  width: 100%;
7924
7924
  margin: 24px 0;
7925
7925
  padding: 0 0 0 20px;
7926
- font-size: 13.5px;
7926
+ font-size: 15px;
7927
7927
  font-style: italic;
7928
7928
  color: var(--annotation-text);
7929
7929
  opacity: 0;
@@ -7953,12 +7953,13 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
7953
7953
  font-weight: 700;
7954
7954
  text-transform: uppercase;
7955
7955
  letter-spacing: 0.05em;
7956
- color: var(--annotation-border);
7956
+ color: var(--annotation-text);
7957
7957
  margin-bottom: 6px;
7958
7958
  font-style: normal;
7959
7959
  display: flex;
7960
7960
  align-items: center;
7961
7961
  gap: 6px;
7962
+ opacity: 0.8;
7962
7963
  }
7963
7964
 
7964
7965
  .annotation-content {
@@ -8057,11 +8058,10 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
8057
8058
  transition: opacity 0.3s, transform 0.3s;
8058
8059
  }
8059
8060
 
8060
- /* In iframe, add some breathing room safely away from edges */
8061
+ /* In iframe, match standalone appearance */
8061
8062
  body.in-iframe .controls {
8062
8063
  margin-bottom: 0;
8063
- background: rgba(255, 255, 255, 0.9);
8064
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
8064
+ /* Keep same shadow as standalone for consistency */
8065
8065
  }
8066
8066
 
8067
8067
  :root[data-theme="dark"] .controls {
@@ -8070,7 +8070,7 @@ function generateCss(theme, hasMultipleScenarios, colors, cornerStyle) {
8070
8070
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
8071
8071
  }
8072
8072
 
8073
- body.in-iframe :root[data-theme="dark"] .controls {
8073
+ :root[data-theme="dark"] body.in-iframe .controls {
8074
8074
  background: rgba(30, 41, 59, 0.9);
8075
8075
  }
8076
8076
 
@@ -9203,7 +9203,7 @@ function generateHtml(demo, options = { outputPath: "" }) {
9203
9203
  const hasMultipleScenarios = demo.scenarios.length > 1;
9204
9204
  const timerStyle = demo.meta.timerStyle ?? "circle";
9205
9205
  const cornerStyle = demo.meta.cornerStyle ?? "rounded";
9206
- const css = generateCss(theme, hasMultipleScenarios, demo.meta.colors, cornerStyle);
9206
+ const css = generateCss(theme, hasMultipleScenarios, demo.meta.colors, cornerStyle, demo.meta.initialBlur);
9207
9207
  const js = generateJs(demo, timerStyle);
9208
9208
  const titleHtml = demo.meta.articleUrl ? `<a href="${escapeHtml(demo.meta.articleUrl)}" class="demo-title-link">${escapeHtml(demo.meta.title)}</a>` : escapeHtml(demo.meta.title);
9209
9209
  const descriptionHtml = demo.meta.description ? `<p class="demo-description">${parseMarkdownLinks(demo.meta.description)}</p>` : "";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "conversation-replay",
3
- "version": "0.1.5",
4
- "description": "Create animated conversation demos from YAML for security awareness, IR training, and communication skills education",
3
+ "version": "0.1.7",
4
+ "description": "Create animated text conversation replays",
5
5
  "main": "dist/cli.js",
6
6
  "type": "module",
7
7
  "bin": {
@@ -16,6 +16,7 @@
16
16
  "validate": "bun run src/cli.ts validate",
17
17
  "example": "bun run src/cli.ts build examples/london-scam.yaml -o examples/london-scam.html",
18
18
  "build:dist": "bun build src/cli.ts --target=node --outfile=dist/cli.js --packages=bundle",
19
+ "prepare": "bun run build:dist",
19
20
  "prepublishOnly": "bun run build:dist"
20
21
  },
21
22
  "keywords": [