Skip to content

Commit b3378d4

Browse files
committed
tps v1.1.0
1 parent df4aef3 commit b3378d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+505
-276
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ Repo-specific design rules:
304304
- Keep UI flow logic, keyboard shortcuts, DOM ids/selectors, and reusable UI constants in C#/Blazor contracts whenever the platform allows it; use JS only for unavoidable browser API interop or DOM access that Blazor cannot own directly.
305305
- Prefer deleting JS files entirely when they only hold product UI behavior or duplicated constants; JS modules may exist only as thin bridges to browser APIs or external JS SDKs, with the owning workflow and state kept in C#/Blazor.
306306
- TPS front matter pasted or imported into the editor source MUST be parsed into the metadata rail automatically and removed from the visible body text instead of staying inline in the source editor.
307+
- TPS support MUST fully implement the current `design/TPS.md` contract end to end; legacy or partially compatible TPS syntax is not a supported mode, and any old incompatible behavior should be removed instead of kept behind compatibility shims.
307308
- For standalone cloud-storage integrations, persist provider keys, tokens, and connection metadata in browser `localStorage`; do not introduce server-side secret storage for runtime auth in this app shape.
308309
- Third-party runtime JavaScript SDKs MUST be sourced only from explicitly pinned GitHub Release tags and assets, copied into the repo, bundled locally with their runtime dependencies, and never loaded from CDNs, package registries, `latest` endpoints, or ad-hoc remote downloads at app runtime.
309310
- Repo-owned manifests, scripts, workflows, and project files that track third-party runtime JavaScript SDKs MUST point to concrete GitHub release versions and asset URLs, never floating references.

src/PrompterOne.Core/Editor/Services/TpsTextEditor.cs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,35 @@ namespace PrompterOne.Core.Services.Editor;
44

55
public sealed class TpsTextEditor
66
{
7-
private static readonly IReadOnlyList<(string OpeningToken, string ClosingToken)> ColorTokenPairs =
7+
private static readonly IReadOnlyList<(string OpeningToken, string ClosingToken)> InlineTokenPairs =
88
[
9-
("[red]", "[/red]"),
10-
("[green]", "[/green]"),
11-
("[blue]", "[/blue]"),
12-
("[yellow]", "[/yellow]"),
13-
("[orange]", "[/orange]"),
14-
("[purple]", "[/purple]"),
15-
("[cyan]", "[/cyan]"),
16-
("[magenta]", "[/magenta]"),
17-
("[pink]", "[/pink]"),
18-
("[teal]", "[/teal]"),
19-
("[gray]", "[/gray]")
9+
("[emphasis]", "[/emphasis]"),
10+
("[highlight]", "[/highlight]"),
11+
("[stress]", "[/stress]"),
12+
("[warm]", "[/warm]"),
13+
("[concerned]", "[/concerned]"),
14+
("[focused]", "[/focused]"),
15+
("[motivational]", "[/motivational]"),
16+
("[neutral]", "[/neutral]"),
17+
("[urgent]", "[/urgent]"),
18+
("[happy]", "[/happy]"),
19+
("[excited]", "[/excited]"),
20+
("[sad]", "[/sad]"),
21+
("[calm]", "[/calm]"),
22+
("[energetic]", "[/energetic]"),
23+
("[professional]", "[/professional]"),
24+
("[loud]", "[/loud]"),
25+
("[soft]", "[/soft]"),
26+
("[whisper]", "[/whisper]"),
27+
("[aside]", "[/aside]"),
28+
("[rhetorical]", "[/rhetorical]"),
29+
("[sarcasm]", "[/sarcasm]"),
30+
("[building]", "[/building]"),
31+
("[xslow]", "[/xslow]"),
32+
("[slow]", "[/slow]"),
33+
("[normal]", "[/normal]"),
34+
("[fast]", "[/fast]"),
35+
("[xfast]", "[/xfast]")
2036
];
2137

2238
public EditorTextMutationResult WrapSelection(
@@ -62,7 +78,7 @@ public EditorTextMutationResult ClearColorFormatting(string? text, EditorSelecti
6278
var safeText = text ?? string.Empty;
6379
var range = NormalizeSelection(selection, safeText.Length);
6480
var selectedText = safeText[range.OrderedStart..range.OrderedEnd];
65-
var cleanedSelection = RemoveColorTokens(selectedText);
81+
var cleanedSelection = RemoveInlineTokens(selectedText);
6682

6783
if (!string.Equals(cleanedSelection, selectedText, StringComparison.Ordinal))
6884
{
@@ -71,7 +87,7 @@ public EditorTextMutationResult ClearColorFormatting(string? text, EditorSelecti
7187
return new EditorTextMutationResult(updatedText, new EditorSelectionRange(range.OrderedStart, end));
7288
}
7389

74-
foreach (var (openingToken, closingToken) in ColorTokenPairs)
90+
foreach (var (openingToken, closingToken) in InlineTokenPairs)
7591
{
7692
if (!TryFindEnclosingTokenRange(safeText, range, openingToken, closingToken, out var tokenRange))
7793
{
@@ -96,15 +112,33 @@ private static EditorSelectionRange NormalizeSelection(EditorSelectionRange sele
96112
return new EditorSelectionRange(start, end);
97113
}
98114

99-
private static string RemoveColorTokens(string text)
115+
private static string RemoveInlineTokens(string text)
100116
{
101117
var cleaned = text;
102-
foreach (var (openingToken, closingToken) in ColorTokenPairs)
118+
foreach (var (openingToken, closingToken) in InlineTokenPairs)
103119
{
104120
cleaned = cleaned.Replace(openingToken, string.Empty, StringComparison.Ordinal);
105121
cleaned = cleaned.Replace(closingToken, string.Empty, StringComparison.Ordinal);
106122
}
107123

124+
cleaned = System.Text.RegularExpressions.Regex.Replace(
125+
cleaned,
126+
@"\[(?:pronunciation|phonetic|stress):[^\]]+\]",
127+
string.Empty,
128+
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
129+
130+
cleaned = System.Text.RegularExpressions.Regex.Replace(
131+
cleaned,
132+
@"\[/\d+WPM\]",
133+
string.Empty,
134+
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
135+
136+
cleaned = System.Text.RegularExpressions.Regex.Replace(
137+
cleaned,
138+
@"\[\d+WPM\]",
139+
string.Empty,
140+
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
141+
108142
return cleaned;
109143
}
110144

src/PrompterOne.Core/Tps/Services/ScriptCompiler.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -881,10 +881,14 @@ public void Apply(ActiveInlineState state, char character)
881881
_stressTextBuilder.Append(character);
882882
}
883883

884-
HasAbsoluteSpeed = state.HasAbsoluteSpeed;
885-
AbsoluteSpeed = state.AbsoluteSpeed;
886-
HasRelativeSpeed = state.HasRelativeSpeed;
887-
RelativeSpeedMultiplier = state.RelativeSpeedMultiplier;
884+
if (ShouldCaptureSpeedMetadata(character))
885+
{
886+
HasAbsoluteSpeed = state.HasAbsoluteSpeed;
887+
AbsoluteSpeed = state.AbsoluteSpeed;
888+
HasRelativeSpeed = state.HasRelativeSpeed;
889+
RelativeSpeedMultiplier = state.RelativeSpeedMultiplier;
890+
}
891+
888892
Speaker = state.Speaker;
889893
}
890894

@@ -924,5 +928,9 @@ public WordMetadata BuildWordMetadata(int inheritedWpm)
924928

925929
return metadata;
926930
}
931+
932+
private static bool ShouldCaptureSpeedMetadata(char character) =>
933+
!char.IsWhiteSpace(character) &&
934+
!TpsTokenTextRules.IsStandalonePunctuationToken(character.ToString());
927935
}
928936
}

src/PrompterOne.Shared/AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- Do not add server-only dependencies.
3535
- Keep keyboard shortcuts, screen ids/selectors, and reusable UI constants in Blazor/C# contracts when possible; leave JS only with unavoidable browser API interop and direct DOM work that Blazor cannot replace cleanly.
3636
- Prefer removing JS files that only orchestrate UI behavior, reader state, or shell interactions; keep those flows in Razor components or C# services and let JS expose only the minimal browser or SDK call surface.
37+
- TPS 1.1.0 removed legacy inline color tags, so editor, reader, menus, examples, and tests in this project must not expose or insert `[red]`, `[green]`, or other deprecated color-tag authoring paths.
3738

3839
## Project-Local Commands
3940

src/PrompterOne.Shared/Editor/Components/EditorSourcePanel.razor.css

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
.ed-source-stage{--ed-floatbar-edge:240px;--ed-floatbar-min-top:44px;position:relative;min-height:100%;height:100%;overflow:hidden;}
3737
.ed-source-highlight,.ed-source-input{box-sizing:border-box;font-family:var(--mono);font-size:16px;line-height:2;letter-spacing:normal;font-variant-ligatures:none;padding:40px 48px;tab-size:4;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;}
3838
.ed-source-highlight{position:relative;z-index:1;pointer-events:none;color:var(--t1);min-height:100%;height:100%;overflow:hidden;opacity:1;transition:opacity .12s ease;}
39+
.ed-source-highlight.ed-source-highlight-plain{opacity:0;}
3940
.ed-source-input{position:absolute;inset:0;z-index:2;width:100%;min-height:100%;border:0;outline:none;resize:none;background:transparent;color:transparent;-webkit-text-fill-color:transparent;caret-color:var(--t1);overflow:auto;}
41+
.ed-source-input.ed-source-input-plain{color:var(--t1);-webkit-text-fill-color:var(--t1);}
4042
.ed-source-input::selection{background:rgba(255,224,102,.18);}
4143
.ed-source-error{margin:0 48px 24px;padding:12px 16px;border-radius:10px;border:1px solid rgba(255,138,138,.22);background:rgba(255,96,96,.08);color:#FFB3B3;font-size:13px;line-height:1.5;}
4244
.ed-statusbar{display:flex;gap:24px;padding:8px 28px;background:transparent;border-top:1px solid var(--gold-06);font-size:13px;color:#7A8E88;flex-shrink:0;font-family:var(--mono);border-radius:0 0 var(--r2) var(--r2);}
@@ -81,22 +83,14 @@
8183
.ed-main ::deep .h-sep{color:#7A8E88;}
8284
.ed-main ::deep .h-wpm{color:#FFE066;}
8385
.ed-main ::deep .h-emo{color:#FFB86A;}
86+
.ed-main ::deep .h-speaker{color:#9ED6FF;}
87+
.ed-main ::deep .h-meta{color:#B8C0C8;}
8488
.ed-main ::deep .mk-pause{color:#E0C070;background-image:linear-gradient(180deg, transparent 62%, rgba(224,192,112,.18) 62%);text-shadow:0 0 10px rgba(224,192,112,.18);}
89+
.ed-main ::deep .mk-breath{color:#EEDB96;background-image:linear-gradient(180deg, transparent 62%, rgba(238,219,150,.14) 62%);box-shadow:inset 0 -1px 0 rgba(238,219,150,.24);}
8590
.ed-main ::deep .mk-tag{color:#8A9E98;opacity:.96;}
91+
.ed-main ::deep .mk-muted{color:#B8C0C8;}
8692
.ed-main ::deep .mk-em{font-weight:700;text-decoration:underline;text-decoration-color:var(--accent);text-underline-offset:4px;text-decoration-thickness:2px;}
8793
.ed-main ::deep .mk-hl{background-image:linear-gradient(180deg, transparent 58%, rgba(255,232,122,.15) 58%);box-shadow:inset 0 -2px 0 rgba(255,232,122,.35);color:#FFE87A;}
88-
.ed-main ::deep .mk-color-red{color:#FF8A8A;}
89-
.ed-main ::deep .mk-color-green{color:#6FE89A;}
90-
.ed-main ::deep .mk-color-blue{color:#8ECFFF;}
91-
.ed-main ::deep .mk-color-yellow{color:#FFE87A;}
92-
.ed-main ::deep .mk-color-orange{color:#FFB86A;}
93-
.ed-main ::deep .mk-color-purple{color:#D88AFF;}
94-
.ed-main ::deep .mk-color-cyan{color:#7DE8F0;}
95-
.ed-main ::deep .mk-color-magenta{color:#FF96C5;}
96-
.ed-main ::deep .mk-color-pink{color:#FFB3D1;}
97-
.ed-main ::deep .mk-color-teal{color:#5EECC2;}
98-
.ed-main ::deep .mk-color-white{color:#F8F9FA;}
99-
.ed-main ::deep .mk-color-gray{color:#B8C0C8;}
10094
.ed-main ::deep .mk-emo-warm{color:#FFB840;}
10195
.ed-main ::deep .mk-emo-concerned{color:#FF7A7A;}
10296
.ed-main ::deep .mk-emo-focused{color:#4AE0A0;}
@@ -109,6 +103,14 @@
109103
.ed-main ::deep .mk-emo-calm{color:#5EECC2;}
110104
.ed-main ::deep .mk-emo-energetic{color:#FFA050;}
111105
.ed-main ::deep .mk-emo-professional{color:#80B8FF;}
106+
.ed-main ::deep .mk-vol-loud{color:#FFB86A;font-weight:800;}
107+
.ed-main ::deep .mk-vol-soft{color:#C9DFFF;}
108+
.ed-main ::deep .mk-vol-whisper{color:#D7D1E2;font-style:italic;}
109+
.ed-main ::deep .mk-del-aside{color:#E2C89A;font-style:italic;}
110+
.ed-main ::deep .mk-del-rhetorical{color:#D7B8FF;}
111+
.ed-main ::deep .mk-del-sarcasm{color:#FFAACD;}
112+
.ed-main ::deep .mk-del-building{color:#FFD98A;font-weight:700;}
113+
.ed-main ::deep .mk-stress{text-decoration:underline;text-decoration-color:#FFD060;text-underline-offset:4px;text-decoration-thickness:2px;}
112114
.ed-main ::deep .mk-xslow{color:#FF8A8A;text-shadow:0 0 8px rgba(255,138,138,.16);}
113115
.ed-main ::deep .mk-slow{color:#FFB86A;text-shadow:0 0 8px rgba(255,184,106,.14);}
114116
.ed-main ::deep .mk-fast{color:#8ECFFF;text-shadow:0 0 8px rgba(142,207,255,.12);}

0 commit comments

Comments
 (0)