@faircopy/go 1.23.0
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 +41 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +238 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @faircopy/go
|
|
2
|
+
|
|
3
|
+
Go message adapter for [faircopy](https://github.com/omniaura/faircopy). It extracts static string arguments from configured Go function calls and maps every extracted character back to the source file.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm i -D faircopy @faircopy/config @faircopy/go
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// faircopy.config.ts
|
|
15
|
+
import { defineConfig } from '@faircopy/config'
|
|
16
|
+
import { go } from '@faircopy/go'
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
files: ['**/*.go'],
|
|
20
|
+
adapters: [
|
|
21
|
+
go({
|
|
22
|
+
calls: [
|
|
23
|
+
{ name: 'NewFactory', argumentIndex: 1 },
|
|
24
|
+
{ name: 'Errorf', argumentIndex: 0 },
|
|
25
|
+
],
|
|
26
|
+
}),
|
|
27
|
+
],
|
|
28
|
+
rules: {
|
|
29
|
+
'no-em-dash': 'error',
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`name` matches the called function's final identifier, so package aliases work. `argumentIndex` is zero-based. A configured argument can be a double-quoted or raw Go string, or a literal format string passed to `fmt.Sprintf` (or another configured `formatFunctions` entry). Dynamic values, concatenations, comments, and unrelated strings are skipped. Numeric status arguments are ignored unless explicitly selected as message arguments.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
go({
|
|
38
|
+
calls: [{ name: 'NewFactory', argumentIndex: 1 }],
|
|
39
|
+
formatFunctions: ['Sprintf'], // default
|
|
40
|
+
})
|
|
41
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Adapter } from '@faircopy/core';
|
|
2
|
+
|
|
3
|
+
interface GoMessageCall {
|
|
4
|
+
/** Function or method name whose argument contains user-facing copy. */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Zero-based argument index containing the message. */
|
|
7
|
+
argumentIndex: number;
|
|
8
|
+
}
|
|
9
|
+
interface GoAdapterOptions {
|
|
10
|
+
/** Calls to inspect. Match by the final identifier, so package aliases work. */
|
|
11
|
+
calls: GoMessageCall[];
|
|
12
|
+
/** Formatter function names whose first literal argument should be extracted. Default: Sprintf. */
|
|
13
|
+
formatFunctions?: string[];
|
|
14
|
+
}
|
|
15
|
+
declare function go(options: GoAdapterOptions): Adapter;
|
|
16
|
+
|
|
17
|
+
export { type GoAdapterOptions, type GoMessageCall, go };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var SIMPLE_ESCAPES = {
|
|
3
|
+
a: "\x07",
|
|
4
|
+
b: "\b",
|
|
5
|
+
f: "\f",
|
|
6
|
+
n: "\n",
|
|
7
|
+
r: "\r",
|
|
8
|
+
t: " ",
|
|
9
|
+
v: "\v",
|
|
10
|
+
"\\": "\\",
|
|
11
|
+
'"': '"',
|
|
12
|
+
"'": "'"
|
|
13
|
+
};
|
|
14
|
+
function skipComment(source, start) {
|
|
15
|
+
if (source.startsWith("//", start)) {
|
|
16
|
+
const newline = source.indexOf("\n", start + 2);
|
|
17
|
+
return newline === -1 ? source.length : newline + 1;
|
|
18
|
+
}
|
|
19
|
+
if (source.startsWith("/*", start)) {
|
|
20
|
+
const close = source.indexOf("*/", start + 2);
|
|
21
|
+
return close === -1 ? source.length : close + 2;
|
|
22
|
+
}
|
|
23
|
+
return start;
|
|
24
|
+
}
|
|
25
|
+
function quotedEnd(source, start) {
|
|
26
|
+
const quote = source[start];
|
|
27
|
+
if (quote !== '"' && quote !== "`" && quote !== "'") return start;
|
|
28
|
+
if (quote === "`") {
|
|
29
|
+
const close = source.indexOf("`", start + 1);
|
|
30
|
+
return close === -1 ? source.length : close + 1;
|
|
31
|
+
}
|
|
32
|
+
for (let index = start + 1; index < source.length; index++) {
|
|
33
|
+
if (source[index] === "\n" || source[index] === "\r") return index;
|
|
34
|
+
if (source[index] === "\\") {
|
|
35
|
+
index++;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (source[index] === quote) return index + 1;
|
|
39
|
+
}
|
|
40
|
+
return source.length;
|
|
41
|
+
}
|
|
42
|
+
function decodeString(source, start) {
|
|
43
|
+
const quote = source[start];
|
|
44
|
+
if (quote !== '"' && quote !== "`") return null;
|
|
45
|
+
let index = start + 1;
|
|
46
|
+
let text = "";
|
|
47
|
+
const sourceMap = [];
|
|
48
|
+
const append = (value, sourceOffset) => {
|
|
49
|
+
text += value;
|
|
50
|
+
for (let i = 0; i < value.length; i++) sourceMap.push(sourceOffset);
|
|
51
|
+
};
|
|
52
|
+
while (index < source.length) {
|
|
53
|
+
const char = source[index];
|
|
54
|
+
if (char === quote) return { end: index + 1, text, sourceMap };
|
|
55
|
+
if (quote === "`") {
|
|
56
|
+
if (char !== "\r") append(char, index);
|
|
57
|
+
index++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (char === "\n" || char === "\r") return null;
|
|
61
|
+
if (char !== "\\") {
|
|
62
|
+
append(char, index);
|
|
63
|
+
index++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const escapeStart = index;
|
|
67
|
+
const kind = source[index + 1];
|
|
68
|
+
if (kind === void 0) return null;
|
|
69
|
+
let decoded = SIMPLE_ESCAPES[kind];
|
|
70
|
+
let width = 2;
|
|
71
|
+
if (kind === "x") {
|
|
72
|
+
const hex = source.slice(index + 2, index + 4);
|
|
73
|
+
if (!/^[0-9a-fA-F]{2}$/.test(hex)) return null;
|
|
74
|
+
decoded = String.fromCodePoint(Number.parseInt(hex, 16));
|
|
75
|
+
width = 4;
|
|
76
|
+
} else if (kind === "u" || kind === "U") {
|
|
77
|
+
const digits = kind === "u" ? 4 : 8;
|
|
78
|
+
const hex = source.slice(index + 2, index + 2 + digits);
|
|
79
|
+
if (!new RegExp(`^[0-9a-fA-F]{${digits}}$`).test(hex)) return null;
|
|
80
|
+
const codePoint = Number.parseInt(hex, 16);
|
|
81
|
+
if (codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) return null;
|
|
82
|
+
decoded = String.fromCodePoint(codePoint);
|
|
83
|
+
width = 2 + digits;
|
|
84
|
+
} else if (/^[0-7]$/.test(kind)) {
|
|
85
|
+
const octal = source.slice(index + 1, index + 4);
|
|
86
|
+
if (!/^[0-7]{3}$/.test(octal)) return null;
|
|
87
|
+
const codePoint = Number.parseInt(octal, 8);
|
|
88
|
+
if (codePoint > 255) return null;
|
|
89
|
+
decoded = String.fromCodePoint(codePoint);
|
|
90
|
+
width = 4;
|
|
91
|
+
}
|
|
92
|
+
if (decoded === void 0) return null;
|
|
93
|
+
append(decoded, escapeStart);
|
|
94
|
+
index += width;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function skipTrivia(source, start) {
|
|
99
|
+
let index = start;
|
|
100
|
+
while (index < source.length) {
|
|
101
|
+
if (/\s/.test(source[index])) {
|
|
102
|
+
index++;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const afterComment = skipComment(source, index);
|
|
106
|
+
if (afterComment !== index) {
|
|
107
|
+
index = afterComment;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
return index;
|
|
113
|
+
}
|
|
114
|
+
function isIdentifierStart(char) {
|
|
115
|
+
return char === "_" || new RegExp("\\p{L}", "u").test(char ?? "");
|
|
116
|
+
}
|
|
117
|
+
function isIdentifierPart(char) {
|
|
118
|
+
return char === "_" || /[\p{L}\p{N}]/u.test(char ?? "");
|
|
119
|
+
}
|
|
120
|
+
function readCallee(source, start) {
|
|
121
|
+
if (!isIdentifierStart(source[start])) return null;
|
|
122
|
+
let index = start;
|
|
123
|
+
let finalName = "";
|
|
124
|
+
while (true) {
|
|
125
|
+
if (!isIdentifierStart(source[index])) break;
|
|
126
|
+
const segmentStart = index++;
|
|
127
|
+
while (isIdentifierPart(source[index])) index++;
|
|
128
|
+
finalName = source.slice(segmentStart, index);
|
|
129
|
+
if (source[index] !== "." || !isIdentifierStart(source[index + 1])) break;
|
|
130
|
+
index++;
|
|
131
|
+
}
|
|
132
|
+
return { name: finalName, end: index };
|
|
133
|
+
}
|
|
134
|
+
function callArguments(source, openParen) {
|
|
135
|
+
const args = [];
|
|
136
|
+
const depth = { paren: 0, bracket: 0, brace: 0 };
|
|
137
|
+
let argumentStart = openParen + 1;
|
|
138
|
+
for (let index = argumentStart; index < source.length; ) {
|
|
139
|
+
const afterComment = skipComment(source, index);
|
|
140
|
+
if (afterComment !== index) {
|
|
141
|
+
index = afterComment;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const char = source[index];
|
|
145
|
+
if (char === '"' || char === "`" || char === "'") {
|
|
146
|
+
index = quotedEnd(source, index);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (char === "(") depth.paren++;
|
|
150
|
+
else if (char === ")") {
|
|
151
|
+
if (depth.paren === 0 && depth.bracket === 0 && depth.brace === 0) {
|
|
152
|
+
if (argumentStart < index || args.length > 0) args.push({ start: argumentStart, end: index });
|
|
153
|
+
return { ranges: args, end: index + 1 };
|
|
154
|
+
}
|
|
155
|
+
depth.paren--;
|
|
156
|
+
} else if (char === "[") depth.bracket++;
|
|
157
|
+
else if (char === "]") depth.bracket--;
|
|
158
|
+
else if (char === "{") depth.brace++;
|
|
159
|
+
else if (char === "}") depth.brace--;
|
|
160
|
+
else if (char === "," && depth.paren === 0 && depth.bracket === 0 && depth.brace === 0) {
|
|
161
|
+
args.push({ start: argumentStart, end: index });
|
|
162
|
+
argumentStart = index + 1;
|
|
163
|
+
}
|
|
164
|
+
index++;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function literalArgument(source, range, formatFunctions) {
|
|
169
|
+
const start = skipTrivia(source, range.start);
|
|
170
|
+
if (source[start] === '"' || source[start] === "`") {
|
|
171
|
+
const literal2 = decodeString(source, start);
|
|
172
|
+
return literal2 && skipTrivia(source, literal2.end) === range.end ? literal2 : null;
|
|
173
|
+
}
|
|
174
|
+
const callee = readCallee(source, start);
|
|
175
|
+
if (!callee || !formatFunctions.has(callee.name)) return null;
|
|
176
|
+
const openParen = skipTrivia(source, callee.end);
|
|
177
|
+
if (source[openParen] !== "(") return null;
|
|
178
|
+
const call = callArguments(source, openParen);
|
|
179
|
+
if (!call?.ranges.length || skipTrivia(source, call.end) !== range.end) return null;
|
|
180
|
+
const formatRange = call.ranges[0];
|
|
181
|
+
const formatStart = skipTrivia(source, formatRange.start);
|
|
182
|
+
if (source[formatStart] !== '"' && source[formatStart] !== "`") return null;
|
|
183
|
+
const literal = decodeString(source, formatStart);
|
|
184
|
+
return literal && skipTrivia(source, literal.end) === formatRange.end ? literal : null;
|
|
185
|
+
}
|
|
186
|
+
function extractMessages(source, calls, formatFunctions) {
|
|
187
|
+
const extractions = [];
|
|
188
|
+
for (let index = 0; index < source.length; ) {
|
|
189
|
+
const afterComment = skipComment(source, index);
|
|
190
|
+
if (afterComment !== index) {
|
|
191
|
+
index = afterComment;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const char = source[index];
|
|
195
|
+
if (char === '"' || char === "`" || char === "'") {
|
|
196
|
+
index = quotedEnd(source, index);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const callee = readCallee(source, index);
|
|
200
|
+
if (!callee) {
|
|
201
|
+
index++;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const argumentIndex = calls.get(callee.name);
|
|
205
|
+
if (argumentIndex !== void 0) {
|
|
206
|
+
const openParen = skipTrivia(source, callee.end);
|
|
207
|
+
if (source[openParen] === "(") {
|
|
208
|
+
const call = callArguments(source, openParen);
|
|
209
|
+
const range = call?.ranges[argumentIndex];
|
|
210
|
+
const message = range ? literalArgument(source, range, formatFunctions) : null;
|
|
211
|
+
if (message?.text.trim()) {
|
|
212
|
+
extractions.push({
|
|
213
|
+
text: message.text,
|
|
214
|
+
sourceMap: message.sourceMap,
|
|
215
|
+
meta: { type: "go-message", function: callee.name, argumentIndex }
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
index = callee.end;
|
|
221
|
+
}
|
|
222
|
+
return extractions.sort((left, right) => (left.sourceMap[0] ?? 0) - (right.sourceMap[0] ?? 0));
|
|
223
|
+
}
|
|
224
|
+
function go(options) {
|
|
225
|
+
const calls = new Map(options.calls.map(({ name, argumentIndex }) => [name.split(".").at(-1), argumentIndex]));
|
|
226
|
+
const formatFunctions = new Set((options.formatFunctions ?? ["Sprintf"]).map((name) => name.split(".").at(-1)));
|
|
227
|
+
return {
|
|
228
|
+
name: "@faircopy/go",
|
|
229
|
+
extensions: [".go"],
|
|
230
|
+
async extract(_filePath, source) {
|
|
231
|
+
return extractMessages(source, calls, formatFunctions);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
export {
|
|
236
|
+
go
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Adapter, ExtractedText } from '@faircopy/core'\n\nexport interface GoMessageCall {\n /** Function or method name whose argument contains user-facing copy. */\n name: string\n /** Zero-based argument index containing the message. */\n argumentIndex: number\n}\n\nexport interface GoAdapterOptions {\n /** Calls to inspect. Match by the final identifier, so package aliases work. */\n calls: GoMessageCall[]\n /** Formatter function names whose first literal argument should be extracted. Default: Sprintf. */\n formatFunctions?: string[]\n}\n\ntype Literal = { end: number; text: string; sourceMap: number[] }\ntype Range = { start: number; end: number }\ntype CallArguments = { ranges: Range[]; end: number }\n\nconst SIMPLE_ESCAPES: Record<string, string> = {\n a: '\\x07',\n b: '\\b',\n f: '\\f',\n n: '\\n',\n r: '\\r',\n t: '\\t',\n v: '\\v',\n '\\\\': '\\\\',\n '\"': '\"',\n \"'\": \"'\",\n}\n\nfunction skipComment(source: string, start: number): number {\n if (source.startsWith('//', start)) {\n const newline = source.indexOf('\\n', start + 2)\n return newline === -1 ? source.length : newline + 1\n }\n if (source.startsWith('/*', start)) {\n const close = source.indexOf('*/', start + 2)\n return close === -1 ? source.length : close + 2\n }\n return start\n}\n\nfunction quotedEnd(source: string, start: number): number {\n const quote = source[start]\n if (quote !== '\"' && quote !== '`' && quote !== \"'\") return start\n\n if (quote === '`') {\n const close = source.indexOf('`', start + 1)\n return close === -1 ? source.length : close + 1\n }\n\n for (let index = start + 1; index < source.length; index++) {\n if (source[index] === '\\n' || source[index] === '\\r') return index\n if (source[index] === '\\\\') {\n index++\n continue\n }\n if (source[index] === quote) return index + 1\n }\n return source.length\n}\n\nfunction decodeString(source: string, start: number): Literal | null {\n const quote = source[start]\n if (quote !== '\"' && quote !== '`') return null\n\n let index = start + 1\n let text = ''\n const sourceMap: number[] = []\n const append = (value: string, sourceOffset: number) => {\n text += value\n for (let i = 0; i < value.length; i++) sourceMap.push(sourceOffset)\n }\n\n while (index < source.length) {\n const char = source[index]!\n if (char === quote) return { end: index + 1, text, sourceMap }\n\n if (quote === '`') {\n // Go discards carriage returns in raw string values.\n if (char !== '\\r') append(char, index)\n index++\n continue\n }\n\n if (char === '\\n' || char === '\\r') return null\n if (char !== '\\\\') {\n append(char, index)\n index++\n continue\n }\n\n const escapeStart = index\n const kind = source[index + 1]\n if (kind === undefined) return null\n let decoded = SIMPLE_ESCAPES[kind]\n let width = 2\n\n if (kind === 'x') {\n const hex = source.slice(index + 2, index + 4)\n if (!/^[0-9a-fA-F]{2}$/.test(hex)) return null\n decoded = String.fromCodePoint(Number.parseInt(hex, 16))\n width = 4\n } else if (kind === 'u' || kind === 'U') {\n const digits = kind === 'u' ? 4 : 8\n const hex = source.slice(index + 2, index + 2 + digits)\n if (!new RegExp(`^[0-9a-fA-F]{${digits}}$`).test(hex)) return null\n const codePoint = Number.parseInt(hex, 16)\n if (codePoint > 0x10ffff || (codePoint >= 0xd800 && codePoint <= 0xdfff)) return null\n decoded = String.fromCodePoint(codePoint)\n width = 2 + digits\n } else if (/^[0-7]$/.test(kind)) {\n const octal = source.slice(index + 1, index + 4)\n if (!/^[0-7]{3}$/.test(octal)) return null\n const codePoint = Number.parseInt(octal, 8)\n if (codePoint > 0xff) return null\n decoded = String.fromCodePoint(codePoint)\n width = 4\n }\n\n if (decoded === undefined) return null\n append(decoded, escapeStart)\n index += width\n }\n\n return null\n}\n\nfunction skipTrivia(source: string, start: number): number {\n let index = start\n while (index < source.length) {\n if (/\\s/.test(source[index]!)) {\n index++\n continue\n }\n const afterComment = skipComment(source, index)\n if (afterComment !== index) {\n index = afterComment\n continue\n }\n break\n }\n return index\n}\n\nfunction isIdentifierStart(char: string | undefined): boolean {\n return char === '_' || /\\p{L}/u.test(char ?? '')\n}\n\nfunction isIdentifierPart(char: string | undefined): boolean {\n return char === '_' || /[\\p{L}\\p{N}]/u.test(char ?? '')\n}\n\nfunction readCallee(source: string, start: number): { name: string; end: number } | null {\n if (!isIdentifierStart(source[start])) return null\n let index = start\n let finalName = ''\n\n while (true) {\n if (!isIdentifierStart(source[index])) break\n const segmentStart = index++\n while (isIdentifierPart(source[index])) index++\n finalName = source.slice(segmentStart, index)\n if (source[index] !== '.' || !isIdentifierStart(source[index + 1])) break\n index++\n }\n\n return { name: finalName, end: index }\n}\n\nfunction callArguments(source: string, openParen: number): CallArguments | null {\n const args: Range[] = []\n const depth = { paren: 0, bracket: 0, brace: 0 }\n let argumentStart = openParen + 1\n\n for (let index = argumentStart; index < source.length;) {\n const afterComment = skipComment(source, index)\n if (afterComment !== index) {\n index = afterComment\n continue\n }\n\n const char = source[index]!\n if (char === '\"' || char === '`' || char === \"'\") {\n index = quotedEnd(source, index)\n continue\n }\n\n if (char === '(') depth.paren++\n else if (char === ')') {\n if (depth.paren === 0 && depth.bracket === 0 && depth.brace === 0) {\n if (argumentStart < index || args.length > 0) args.push({ start: argumentStart, end: index })\n return { ranges: args, end: index + 1 }\n }\n depth.paren--\n } else if (char === '[') depth.bracket++\n else if (char === ']') depth.bracket--\n else if (char === '{') depth.brace++\n else if (char === '}') depth.brace--\n else if (char === ',' && depth.paren === 0 && depth.bracket === 0 && depth.brace === 0) {\n args.push({ start: argumentStart, end: index })\n argumentStart = index + 1\n }\n index++\n }\n\n return null\n}\n\nfunction literalArgument(source: string, range: Range, formatFunctions: Set<string>): Literal | null {\n const start = skipTrivia(source, range.start)\n if (source[start] === '\"' || source[start] === '`') {\n const literal = decodeString(source, start)\n return literal && skipTrivia(source, literal.end) === range.end ? literal : null\n }\n\n const callee = readCallee(source, start)\n if (!callee || !formatFunctions.has(callee.name)) return null\n const openParen = skipTrivia(source, callee.end)\n if (source[openParen] !== '(') return null\n const call = callArguments(source, openParen)\n if (!call?.ranges.length || skipTrivia(source, call.end) !== range.end) return null\n\n const formatRange = call.ranges[0]!\n const formatStart = skipTrivia(source, formatRange.start)\n if (source[formatStart] !== '\"' && source[formatStart] !== '`') return null\n const literal = decodeString(source, formatStart)\n return literal && skipTrivia(source, literal.end) === formatRange.end ? literal : null\n}\n\nfunction extractMessages(\n source: string,\n calls: Map<string, number>,\n formatFunctions: Set<string>,\n): ExtractedText[] {\n const extractions: ExtractedText[] = []\n\n for (let index = 0; index < source.length;) {\n const afterComment = skipComment(source, index)\n if (afterComment !== index) {\n index = afterComment\n continue\n }\n\n const char = source[index]!\n if (char === '\"' || char === '`' || char === \"'\") {\n index = quotedEnd(source, index)\n continue\n }\n\n const callee = readCallee(source, index)\n if (!callee) {\n index++\n continue\n }\n\n const argumentIndex = calls.get(callee.name)\n if (argumentIndex !== undefined) {\n const openParen = skipTrivia(source, callee.end)\n if (source[openParen] === '(') {\n const call = callArguments(source, openParen)\n const range = call?.ranges[argumentIndex]\n const message = range ? literalArgument(source, range, formatFunctions) : null\n if (message?.text.trim()) {\n extractions.push({\n text: message.text,\n sourceMap: message.sourceMap,\n meta: { type: 'go-message', function: callee.name, argumentIndex },\n })\n }\n }\n }\n\n index = callee.end\n }\n\n return extractions.sort((left, right) => (left.sourceMap[0] ?? 0) - (right.sourceMap[0] ?? 0))\n}\n\nexport function go(options: GoAdapterOptions): Adapter {\n const calls = new Map(options.calls.map(({ name, argumentIndex }) => [name.split('.').at(-1)!, argumentIndex]))\n const formatFunctions = new Set((options.formatFunctions ?? ['Sprintf']).map(name => name.split('.').at(-1)!))\n\n return {\n name: '@faircopy/go',\n extensions: ['.go'],\n async extract(_filePath, source) {\n return extractMessages(source, calls, formatFunctions)\n },\n }\n}\n"],"mappings":"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","names":["literal"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@faircopy/go",
|
|
3
|
+
"version": "1.23.0",
|
|
4
|
+
"description": "Configurable Go message adapter for faircopy with source maps",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@faircopy/core": "1.23.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^25.6.0",
|
|
21
|
+
"tsup": "^8.5.1",
|
|
22
|
+
"typescript": "^6.0.3"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/omniaura/faircopy",
|
|
30
|
+
"directory": "packages/go"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "omniaura",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"test": "pnpm run build && node --test test/*.test.mjs"
|
|
38
|
+
}
|
|
39
|
+
}
|