opencode-ascii 0.1.3 → 0.1.4
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/README.md +22 -19
- package/dist/substitutions.js +60 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# opencode-ascii
|
|
2
2
|
|
|
3
|
-
An [OpenCode](https://opencode.ai) plugin that automatically substitutes unicode characters with ASCII equivalents in AI responses and file edits.
|
|
3
|
+
An [OpenCode](https://opencode.ai) plugin that automatically substitutes unicode characters with ASCII-safe equivalents in AI responses and file edits.
|
|
4
4
|
|
|
5
5
|
## Why?
|
|
6
6
|
|
|
7
7
|
LLMs love to reach for typographic characters — em-dashes, curly quotes, arrows, emoji — that look great in a browser but cause friction in terminals, code, config files, and plain-text tooling. This plugin intercepts output at two points:
|
|
8
8
|
|
|
9
9
|
- **AI text responses** (`experimental.text.complete`) — rewrites text parts before they are stored.
|
|
10
|
-
- **File write/edit tool calls** (`tool.execute.before`) — rewrites `write`, `edit`, and `
|
|
10
|
+
- **File write/edit tool calls** (`tool.execute.before`) — rewrites `write`, `edit`, `multiedit`, and `apply_patch` tool arguments before execution.
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -45,7 +45,7 @@ All four substitution categories are **enabled by default**. Disable any categor
|
|
|
45
45
|
| `punctuation` | boolean | `true` | Em/en dashes, ellipsis, curly/smart quotes |
|
|
46
46
|
| `arrows` | boolean | `true` | `→` → `->`, `←` → `<-`, `⇒` → `=>`, etc. |
|
|
47
47
|
| `math` | boolean | `true` | `≠` → `!=`, `≤` → `<=`, `×` → `*`, etc. |
|
|
48
|
-
| `emojis` | boolean | `true` | Common emoji
|
|
48
|
+
| `emojis` | boolean | `true` | Common emoji -> `:shortcode:` labels |
|
|
49
49
|
|
|
50
50
|
## Substitution reference
|
|
51
51
|
|
|
@@ -96,21 +96,23 @@ All four substitution categories are **enabled by default**. Disable any categor
|
|
|
96
96
|
|
|
97
97
|
| Unicode | Character | ASCII |
|
|
98
98
|
|---------|-----------|-------|
|
|
99
|
-
| U+2713 | ✓ |
|
|
100
|
-
| U+274C |
|
|
101
|
-
| U+26A0 |
|
|
102
|
-
| U+2139 |
|
|
103
|
-
| U+2B50 |
|
|
104
|
-
| U+1F525 |
|
|
105
|
-
| U+1F680 |
|
|
106
|
-
| U+1F41B |
|
|
107
|
-
| U+1F4DD |
|
|
108
|
-
| U+1F512 |
|
|
109
|
-
| U+1F513 |
|
|
110
|
-
| U+1F4C1 |
|
|
111
|
-
| U+1F4C4 |
|
|
112
|
-
| U+1F44D |
|
|
113
|
-
| U+1F44E |
|
|
99
|
+
| U+2713 | ✓ | `:white_check_mark:` |
|
|
100
|
+
| U+274C | ❌ | `:x:` |
|
|
101
|
+
| U+26A0 | ⚠ | `:warning:` |
|
|
102
|
+
| U+2139 | ℹ | `:information_source:` |
|
|
103
|
+
| U+2B50 | ⭐ | `:star:` |
|
|
104
|
+
| U+1F525 | 🔥 | `:fire:` |
|
|
105
|
+
| U+1F680 | 🚀 | `:rocket:` |
|
|
106
|
+
| U+1F41B | 🐛 | `:bug:` |
|
|
107
|
+
| U+1F4DD | 📝 | `:memo:` |
|
|
108
|
+
| U+1F512 | 🔒 | `:lock:` |
|
|
109
|
+
| U+1F513 | 🔓 | `:unlock:` |
|
|
110
|
+
| U+1F4C1 | 📁 | `:file_folder:` |
|
|
111
|
+
| U+1F4C4 | 📄 | `:page_facing_up:` |
|
|
112
|
+
| U+1F44D | 👍 | `:+1:` |
|
|
113
|
+
| U+1F44E | 👎 | `:-1:` |
|
|
114
|
+
|
|
115
|
+
and many more!
|
|
114
116
|
|
|
115
117
|
See [`src/substitutions.ts`](src/substitutions.ts) for the full list.
|
|
116
118
|
|
|
@@ -123,7 +125,8 @@ The plugin uses two hooks:
|
|
|
123
125
|
2. **`tool.execute.before`** — fired before any tool executes. The plugin rewrites:
|
|
124
126
|
- `output.args.content` for the `write` tool
|
|
125
127
|
- `output.args.newString` for the `edit` tool (never `oldString` — it must match existing file content exactly)
|
|
126
|
-
- `output.args.
|
|
128
|
+
- each `output.args.edits[].newString` for the `multiedit` tool
|
|
129
|
+
- `output.args.patchText` for the `apply_patch` tool
|
|
127
130
|
|
|
128
131
|
Substitution uses a single compiled regex built from all active mappings, so there is no O(n) string-replace loop per character.
|
|
129
132
|
|
package/dist/substitutions.js
CHANGED
|
@@ -82,71 +82,70 @@ export const MATH = [
|
|
|
82
82
|
];
|
|
83
83
|
export const EMOJIS = [
|
|
84
84
|
// Checkmarks / cross marks
|
|
85
|
-
["\u2713", "
|
|
86
|
-
["\u2714", "
|
|
87
|
-
["\u2611", "
|
|
88
|
-
["\u2705", "
|
|
89
|
-
["\u2717", "
|
|
90
|
-
["\u2718", "
|
|
91
|
-
["\u274C", "
|
|
92
|
-
["\u274E", "
|
|
85
|
+
["\u2713", ":white_check_mark:"], // check mark ([x])
|
|
86
|
+
["\u2714", ":white_check_mark:"], // heavy check mark ([x])
|
|
87
|
+
["\u2611", ":ballot_box_with_check:"], // ballot box with check ([x])
|
|
88
|
+
["\u2705", ":white_check_mark:"], // white heavy check mark ([done])
|
|
89
|
+
["\u2717", ":x:"], // ballot x ([!])
|
|
90
|
+
["\u2718", ":x:"], // heavy ballot x ([!])
|
|
91
|
+
["\u274C", ":x:"], // cross mark ([!])
|
|
92
|
+
["\u274E", ":x:"], // cross mark button ([!])
|
|
93
93
|
// Warnings / alerts
|
|
94
|
-
["\u26A0", "
|
|
95
|
-
["\u2757", "
|
|
96
|
-
["\u2755", "
|
|
97
|
-
["\u26A1", "
|
|
94
|
+
["\u26A0", ":warning:"], // warning sign ([!])
|
|
95
|
+
["\u2757", ":exclamation:"], // heavy exclamation mark ornament ([!])
|
|
96
|
+
["\u2755", ":grey_exclamation:"], // white exclamation mark ornament ([!])
|
|
97
|
+
["\u26A1", ":zap:"], // high voltage sign ([!])
|
|
98
98
|
// Info / ideas
|
|
99
|
-
["\u2139", "
|
|
100
|
-
["\u{1F4A1}", "
|
|
99
|
+
["\u2139", ":information_source:"], // information source ([i])
|
|
100
|
+
["\u{1F4A1}", ":bulb:"], // light bulb ([i])
|
|
101
101
|
// Stars / rating
|
|
102
|
-
["\u2B50", "
|
|
103
|
-
["\u{1F31F}", "
|
|
104
|
-
["\u2605", "
|
|
105
|
-
["\u2606", "
|
|
102
|
+
["\u2B50", ":star:"], // white medium star ([*])
|
|
103
|
+
["\u{1F31F}", ":star2:"], // glowing star ([*])
|
|
104
|
+
["\u2605", ":star:"], // black star ([*])
|
|
105
|
+
["\u2606", ":star:"], // white star ([*])
|
|
106
106
|
// Common emoji sequences
|
|
107
|
-
["\u{1F525}", "
|
|
108
|
-
["\u{1F680}", "
|
|
109
|
-
["\u{1F41B}", "
|
|
110
|
-
["\u{1F41E}", "
|
|
111
|
-
["\u{1F4DD}", "
|
|
112
|
-
["\u270F", "
|
|
113
|
-
["\u{1F512}", "
|
|
114
|
-
["\u{1F513}", "
|
|
115
|
-
["\u{1F4C1}", "
|
|
116
|
-
["\u{1F4C2}", "
|
|
117
|
-
["\u{1F4C4}", "
|
|
118
|
-
["\u{1F4C3}", "
|
|
119
|
-
["\u{1F44D}", "
|
|
120
|
-
["\u{1F44E}", "
|
|
121
|
-
["\u{1F4AC}", "
|
|
122
|
-
["\u{1F4E6}", "
|
|
123
|
-
["\u{1F517}", "
|
|
124
|
-
["\u{1F6A7}", "
|
|
125
|
-
["\u2699", "
|
|
126
|
-
["\u{1F527}", "
|
|
127
|
-
["\u{1F5D1}", "
|
|
128
|
-
["\u{1F310}", "
|
|
129
|
-
["\u{1F4BB}", "
|
|
130
|
-
["\u{1F4F1}", "
|
|
131
|
-
["\u{1F4E7}", "
|
|
132
|
-
["\u{1F4CA}", "
|
|
133
|
-
["\u{1F4C8}", "
|
|
134
|
-
["\u{1F4C9}", "
|
|
135
|
-
["\u2764", "
|
|
136
|
-
["\u{1F4AF}", "
|
|
137
|
-
["\u{1F44B}", "
|
|
138
|
-
["\u{1F91D}", "
|
|
139
|
-
["\u{1F4AA}", "
|
|
140
|
-
["\u{1F914}", "
|
|
141
|
-
["\u{1F644}", "
|
|
142
|
-
["\u{1F4A5}", "
|
|
143
|
-
["\u{1F389}", "
|
|
144
|
-
["\u{1F3C6}", "
|
|
145
|
-
["\u{1F4B0}", "
|
|
146
|
-
["\u231B", "
|
|
147
|
-
["\u23F3", "
|
|
148
|
-
["\u{1F504}", "
|
|
149
|
-
["\u2705", "[done]"], // white heavy check mark ([done]) -- already above, kept for completeness
|
|
107
|
+
["\u{1F525}", ":fire:"], // fire ([fire])
|
|
108
|
+
["\u{1F680}", ":rocket:"], // rocket ([>>])
|
|
109
|
+
["\u{1F41B}", ":bug:"], // bug ([bug])
|
|
110
|
+
["\u{1F41E}", ":beetle:"], // lady beetle ([bug])
|
|
111
|
+
["\u{1F4DD}", ":memo:"], // memo ([note])
|
|
112
|
+
["\u270F", ":pencil2:"], // pencil ([note])
|
|
113
|
+
["\u{1F512}", ":lock:"], // lock ([lock])
|
|
114
|
+
["\u{1F513}", ":unlock:"], // open lock ([open])
|
|
115
|
+
["\u{1F4C1}", ":file_folder:"], // file folder ([dir])
|
|
116
|
+
["\u{1F4C2}", ":open_file_folder:"], // open file folder ([dir])
|
|
117
|
+
["\u{1F4C4}", ":page_facing_up:"], // page facing up ([file])
|
|
118
|
+
["\u{1F4C3}", ":page_with_curl:"], // page with curl ([file])
|
|
119
|
+
["\u{1F44D}", ":+1:"], // thumbs up ([+1])
|
|
120
|
+
["\u{1F44E}", ":-1:"], // thumbs down ([-1])
|
|
121
|
+
["\u{1F4AC}", ":speech_balloon:"], // speech balloon ([comment])
|
|
122
|
+
["\u{1F4E6}", ":package:"], // package ([pkg])
|
|
123
|
+
["\u{1F517}", ":link:"], // link ([link])
|
|
124
|
+
["\u{1F6A7}", ":construction:"], // construction sign ([wip])
|
|
125
|
+
["\u2699", ":gear:"], // gear ([config])
|
|
126
|
+
["\u{1F527}", ":wrench:"], // wrench ([fix])
|
|
127
|
+
["\u{1F5D1}", ":wastebasket:"], // wastebasket ([del])
|
|
128
|
+
["\u{1F310}", ":globe_with_meridians:"], // globe with meridians ([web])
|
|
129
|
+
["\u{1F4BB}", ":computer:"], // personal computer ([pc])
|
|
130
|
+
["\u{1F4F1}", ":iphone:"], // mobile phone ([phone])
|
|
131
|
+
["\u{1F4E7}", ":e-mail:"], // e-mail ([email])
|
|
132
|
+
["\u{1F4CA}", ":bar_chart:"], // bar chart ([chart])
|
|
133
|
+
["\u{1F4C8}", ":chart_with_upwards_trend:"], // chart with upwards trend ([up])
|
|
134
|
+
["\u{1F4C9}", ":chart_with_downwards_trend:"], // chart with downwards trend ([down])
|
|
135
|
+
["\u2764", ":heart:"], // heavy black heart ([<3])
|
|
136
|
+
["\u{1F4AF}", ":100:"], // hundred points ([100])
|
|
137
|
+
["\u{1F44B}", ":wave:"], // waving hand ([wave])
|
|
138
|
+
["\u{1F91D}", ":handshake:"], // handshake ([deal])
|
|
139
|
+
["\u{1F4AA}", ":muscle:"], // flexed biceps ([strong])
|
|
140
|
+
["\u{1F914}", ":thinking:"], // thinking face ([?])
|
|
141
|
+
["\u{1F644}", ":roll_eyes:"], // face with rolling eyes ([eye-roll])
|
|
142
|
+
["\u{1F4A5}", ":boom:"], // collision ([boom])
|
|
143
|
+
["\u{1F389}", ":tada:"], // party popper ([party])
|
|
144
|
+
["\u{1F3C6}", ":trophy:"], // trophy ([trophy])
|
|
145
|
+
["\u{1F4B0}", ":moneybag:"], // money bag ([money])
|
|
146
|
+
["\u231B", ":hourglass:"], // hourglass ([wait])
|
|
147
|
+
["\u23F3", ":hourglass_flowing_sand:"], // hourglass with flowing sand ([wait])
|
|
148
|
+
["\u{1F504}", ":arrows_counterclockwise:"], // counterclockwise arrows button ([refresh])
|
|
150
149
|
];
|
|
151
150
|
const DEFAULT_CONFIG = {
|
|
152
151
|
punctuation: true,
|
package/package.json
CHANGED