@gringow/gringow 0.1.2 → 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 +313 -35
- package/dist/browser.d.mts +2 -1
- package/dist/browser.mjs +61 -4
- package/dist/config.d.mts +1 -0
- package/dist/config.mjs +5 -3
- package/dist/config.test.mjs +52 -67
- package/dist/constants/default-config.mjs +1 -0
- package/dist/{data/create-cache-id.d.mts → create-cache-id.d.mts} +2 -2
- package/dist/create-cache-id.mjs +54 -0
- package/dist/create-cache-id.test.d.mts +2 -0
- package/dist/create-cache-id.test.mjs +18464 -0
- package/dist/data/check-cache.d.mts +1 -1
- package/dist/data/check-cache.mjs +14 -7
- package/dist/data/clear-cache.mjs +14 -7
- package/dist/data/create-cache-dir.mjs +5 -3
- package/dist/data/delete-cache-item.d.mts +1 -1
- package/dist/data/delete-cache-item.mjs +14 -7
- package/dist/data/get-cache.mjs +5 -3
- package/dist/data/get-or-create-cache.d.mts +1 -1
- package/dist/data/get-or-create-cache.mjs +14 -7
- package/dist/data/md5.d.mts +13 -0
- package/dist/data/md5.mjs +47 -0
- package/dist/data/md5.test.d.mts +2 -0
- package/dist/data/md5.test.mjs +18457 -0
- package/dist/data/save-cache.d.mts +2 -2
- package/dist/data/save-cache.mjs +14 -7
- package/dist/data/write-cache-to-disk.d.mts +1 -1
- package/dist/data/write-cache-to-disk.mjs +14 -7
- package/dist/flat-template-string.test.mjs +10 -10
- package/dist/gringow.d.mts +1 -1
- package/dist/gringow.mjs +100 -35
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +100 -35
- package/dist/interpolate-template.d.mts +3 -0
- package/dist/interpolate-template.mjs +14 -0
- package/dist/io/anthropic/ask.mjs +5 -3
- package/dist/io/anthropic/commit-response.d.mts +1 -1
- package/dist/io/anthropic/index.d.mts +1 -1
- package/dist/io/anthropic/index.mjs +5 -3
- package/dist/io/anthropic/parse.d.mts +1 -1
- package/dist/io/ask-llm.d.mts +1 -1
- package/dist/io/ask-llm.mjs +38 -25
- package/dist/io/gemini/ask.mjs +38 -25
- package/dist/io/gemini/index.d.mts +1 -1
- package/dist/io/gemini/index.mjs +38 -25
- package/dist/io/gemini/parse.d.mts +1 -1
- package/dist/io/huggingface/ask.d.mts +1 -1
- package/dist/io/huggingface/ask.mjs +5 -3
- package/dist/io/huggingface/commit-response.d.mts +1 -1
- package/dist/io/huggingface/index.d.mts +1 -1
- package/dist/io/huggingface/index.mjs +5 -3
- package/dist/io/huggingface/parse.d.mts +1 -1
- package/dist/logger.test.mjs +10 -10
- package/dist/schemas/config.shcema.d.mts +5 -0
- package/dist/schemas/config.shcema.mjs +1 -0
- package/dist/types/index.d.mts +1 -1
- package/package.json +10 -10
- package/dist/data/create-cache-id.mjs +0 -10
|
@@ -3,7 +3,7 @@ import '../config.mjs';
|
|
|
3
3
|
import '../constants/default-config.mjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../schemas/config.shcema.mjs';
|
|
6
|
+
import '../create-cache-id.mjs';
|
|
6
7
|
import './clear-cache.mjs';
|
|
7
|
-
import './create-cache-id.mjs';
|
|
8
8
|
import './get-cache.mjs';
|
|
9
9
|
import '../flat-template-string.mjs';
|
|
@@ -21,6 +21,7 @@ var defaultConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
keys: {},
|
|
23
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
24
25
|
languages: ["pt-BR", "fr-CA"],
|
|
25
26
|
llm: {
|
|
26
27
|
choice: "huggingface",
|
|
@@ -48,6 +49,7 @@ var configSchema = z.object({
|
|
|
48
49
|
geminiApiKey: z.string().optional()
|
|
49
50
|
}),
|
|
50
51
|
sourceLanguage: languageSchema,
|
|
52
|
+
defaultLanguage: languageSchema,
|
|
51
53
|
languages: z.array(languageSchema),
|
|
52
54
|
llm: z.object({
|
|
53
55
|
choice: llmOptionsSchema,
|
|
@@ -104,9 +106,9 @@ async function loadUserConfig() {
|
|
|
104
106
|
var awaitedConfig = loadUserConfig();
|
|
105
107
|
function defaultPrePrompt(config, extraInstructions) {
|
|
106
108
|
return `
|
|
107
|
-
You are a translation generator.
|
|
109
|
+
You are a ultimate translation generator server api.
|
|
108
110
|
|
|
109
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
111
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
110
112
|
|
|
111
113
|
Follow these rules strictly:
|
|
112
114
|
|
|
@@ -116,7 +118,7 @@ Follow these rules strictly:
|
|
|
116
118
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
117
119
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
118
120
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
119
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
121
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
120
122
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
121
123
|
|
|
122
124
|
{
|
|
@@ -378,12 +380,17 @@ async function getCache() {
|
|
|
378
380
|
throw error;
|
|
379
381
|
}
|
|
380
382
|
}
|
|
383
|
+
var savingQueue = Promise.resolve();
|
|
381
384
|
async function saveCache(cache) {
|
|
382
385
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
386
|
+
savingQueue = savingQueue.then(async () => {
|
|
387
|
+
const config = await awaitedConfig;
|
|
388
|
+
await createCacheDir();
|
|
389
|
+
const contents = JSON.stringify(cache, null, 2);
|
|
390
|
+
await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
|
|
391
|
+
});
|
|
392
|
+
await savingQueue;
|
|
393
|
+
return cache;
|
|
387
394
|
} catch (error) {
|
|
388
395
|
throw error;
|
|
389
396
|
}
|
|
@@ -21,6 +21,7 @@ var defaultConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
keys: {},
|
|
23
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
24
25
|
languages: ["pt-BR", "fr-CA"],
|
|
25
26
|
llm: {
|
|
26
27
|
choice: "huggingface",
|
|
@@ -48,6 +49,7 @@ var configSchema = z.object({
|
|
|
48
49
|
geminiApiKey: z.string().optional()
|
|
49
50
|
}),
|
|
50
51
|
sourceLanguage: languageSchema,
|
|
52
|
+
defaultLanguage: languageSchema,
|
|
51
53
|
languages: z.array(languageSchema),
|
|
52
54
|
llm: z.object({
|
|
53
55
|
choice: llmOptionsSchema,
|
|
@@ -104,9 +106,9 @@ async function loadUserConfig() {
|
|
|
104
106
|
var awaitedConfig = loadUserConfig();
|
|
105
107
|
function defaultPrePrompt(config, extraInstructions) {
|
|
106
108
|
return `
|
|
107
|
-
You are a translation generator.
|
|
109
|
+
You are a ultimate translation generator server api.
|
|
108
110
|
|
|
109
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
111
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
110
112
|
|
|
111
113
|
Follow these rules strictly:
|
|
112
114
|
|
|
@@ -116,7 +118,7 @@ Follow these rules strictly:
|
|
|
116
118
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
117
119
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
118
120
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
119
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
121
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
120
122
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
121
123
|
|
|
122
124
|
{
|
|
@@ -368,12 +370,17 @@ async function createCacheDir() {
|
|
|
368
370
|
}
|
|
369
371
|
|
|
370
372
|
// src/data/save-cache.ts
|
|
373
|
+
var savingQueue = Promise.resolve();
|
|
371
374
|
async function saveCache(cache) {
|
|
372
375
|
try {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
savingQueue = savingQueue.then(async () => {
|
|
377
|
+
const config = await awaitedConfig;
|
|
378
|
+
await createCacheDir();
|
|
379
|
+
const contents = JSON.stringify(cache, null, 2);
|
|
380
|
+
await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
|
|
381
|
+
});
|
|
382
|
+
await savingQueue;
|
|
383
|
+
return cache;
|
|
377
384
|
} catch (error) {
|
|
378
385
|
throw error;
|
|
379
386
|
}
|
|
@@ -225,6 +225,7 @@ var defaultConfig = {
|
|
|
225
225
|
},
|
|
226
226
|
keys: {},
|
|
227
227
|
sourceLanguage: "en-US",
|
|
228
|
+
defaultLanguage: "pt-BR",
|
|
228
229
|
languages: ["pt-BR", "fr-CA"],
|
|
229
230
|
llm: {
|
|
230
231
|
choice: "huggingface",
|
|
@@ -252,6 +253,7 @@ var configSchema = z.object({
|
|
|
252
253
|
geminiApiKey: z.string().optional()
|
|
253
254
|
}),
|
|
254
255
|
sourceLanguage: languageSchema,
|
|
256
|
+
defaultLanguage: languageSchema,
|
|
255
257
|
languages: z.array(languageSchema),
|
|
256
258
|
llm: z.object({
|
|
257
259
|
choice: llmOptionsSchema,
|
|
@@ -308,9 +310,9 @@ async function loadUserConfig() {
|
|
|
308
310
|
var awaitedConfig = loadUserConfig();
|
|
309
311
|
function defaultPrePrompt(config, extraInstructions) {
|
|
310
312
|
return `
|
|
311
|
-
You are a translation generator.
|
|
313
|
+
You are a ultimate translation generator server api.
|
|
312
314
|
|
|
313
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
315
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
314
316
|
|
|
315
317
|
Follow these rules strictly:
|
|
316
318
|
|
|
@@ -320,7 +322,7 @@ Follow these rules strictly:
|
|
|
320
322
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
321
323
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
322
324
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
323
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
325
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
324
326
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
325
327
|
|
|
326
328
|
{
|
|
@@ -3,7 +3,7 @@ import '../config.mjs';
|
|
|
3
3
|
import '../constants/default-config.mjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../schemas/config.shcema.mjs';
|
|
6
|
+
import '../create-cache-id.mjs';
|
|
6
7
|
import './clear-cache.mjs';
|
|
7
|
-
import './create-cache-id.mjs';
|
|
8
8
|
import './get-cache.mjs';
|
|
9
9
|
import '../flat-template-string.mjs';
|
|
@@ -21,6 +21,7 @@ var defaultConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
keys: {},
|
|
23
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
24
25
|
languages: ["pt-BR", "fr-CA"],
|
|
25
26
|
llm: {
|
|
26
27
|
choice: "huggingface",
|
|
@@ -48,6 +49,7 @@ var configSchema = z.object({
|
|
|
48
49
|
geminiApiKey: z.string().optional()
|
|
49
50
|
}),
|
|
50
51
|
sourceLanguage: languageSchema,
|
|
52
|
+
defaultLanguage: languageSchema,
|
|
51
53
|
languages: z.array(languageSchema),
|
|
52
54
|
llm: z.object({
|
|
53
55
|
choice: llmOptionsSchema,
|
|
@@ -104,9 +106,9 @@ async function loadUserConfig() {
|
|
|
104
106
|
var awaitedConfig = loadUserConfig();
|
|
105
107
|
function defaultPrePrompt(config, extraInstructions) {
|
|
106
108
|
return `
|
|
107
|
-
You are a translation generator.
|
|
109
|
+
You are a ultimate translation generator server api.
|
|
108
110
|
|
|
109
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
111
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
110
112
|
|
|
111
113
|
Follow these rules strictly:
|
|
112
114
|
|
|
@@ -116,7 +118,7 @@ Follow these rules strictly:
|
|
|
116
118
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
117
119
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
118
120
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
119
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
121
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
120
122
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
121
123
|
|
|
122
124
|
{
|
|
@@ -378,12 +380,17 @@ async function getCache() {
|
|
|
378
380
|
throw error;
|
|
379
381
|
}
|
|
380
382
|
}
|
|
383
|
+
var savingQueue = Promise.resolve();
|
|
381
384
|
async function saveCache(cache) {
|
|
382
385
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
386
|
+
savingQueue = savingQueue.then(async () => {
|
|
387
|
+
const config = await awaitedConfig;
|
|
388
|
+
await createCacheDir();
|
|
389
|
+
const contents = JSON.stringify(cache, null, 2);
|
|
390
|
+
await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
|
|
391
|
+
});
|
|
392
|
+
await savingQueue;
|
|
393
|
+
return cache;
|
|
387
394
|
} catch (error) {
|
|
388
395
|
throw error;
|
|
389
396
|
}
|
package/dist/data/get-cache.mjs
CHANGED
|
@@ -21,6 +21,7 @@ var defaultConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
keys: {},
|
|
23
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
24
25
|
languages: ["pt-BR", "fr-CA"],
|
|
25
26
|
llm: {
|
|
26
27
|
choice: "huggingface",
|
|
@@ -48,6 +49,7 @@ var configSchema = z.object({
|
|
|
48
49
|
geminiApiKey: z.string().optional()
|
|
49
50
|
}),
|
|
50
51
|
sourceLanguage: languageSchema,
|
|
52
|
+
defaultLanguage: languageSchema,
|
|
51
53
|
languages: z.array(languageSchema),
|
|
52
54
|
llm: z.object({
|
|
53
55
|
choice: llmOptionsSchema,
|
|
@@ -104,9 +106,9 @@ async function loadUserConfig() {
|
|
|
104
106
|
var awaitedConfig = loadUserConfig();
|
|
105
107
|
function defaultPrePrompt(config, extraInstructions) {
|
|
106
108
|
return `
|
|
107
|
-
You are a translation generator.
|
|
109
|
+
You are a ultimate translation generator server api.
|
|
108
110
|
|
|
109
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
111
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
110
112
|
|
|
111
113
|
Follow these rules strictly:
|
|
112
114
|
|
|
@@ -116,7 +118,7 @@ Follow these rules strictly:
|
|
|
116
118
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
117
119
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
118
120
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
119
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
121
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
120
122
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
121
123
|
|
|
122
124
|
{
|
|
@@ -3,7 +3,7 @@ import '../config.mjs';
|
|
|
3
3
|
import '../constants/default-config.mjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../schemas/config.shcema.mjs';
|
|
6
|
+
import '../create-cache-id.mjs';
|
|
6
7
|
import './clear-cache.mjs';
|
|
7
|
-
import './create-cache-id.mjs';
|
|
8
8
|
import './get-cache.mjs';
|
|
9
9
|
import '../flat-template-string.mjs';
|
|
@@ -21,6 +21,7 @@ var defaultConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
keys: {},
|
|
23
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
24
25
|
languages: ["pt-BR", "fr-CA"],
|
|
25
26
|
llm: {
|
|
26
27
|
choice: "huggingface",
|
|
@@ -48,6 +49,7 @@ var configSchema = z.object({
|
|
|
48
49
|
geminiApiKey: z.string().optional()
|
|
49
50
|
}),
|
|
50
51
|
sourceLanguage: languageSchema,
|
|
52
|
+
defaultLanguage: languageSchema,
|
|
51
53
|
languages: z.array(languageSchema),
|
|
52
54
|
llm: z.object({
|
|
53
55
|
choice: llmOptionsSchema,
|
|
@@ -104,9 +106,9 @@ async function loadUserConfig() {
|
|
|
104
106
|
var awaitedConfig = loadUserConfig();
|
|
105
107
|
function defaultPrePrompt(config, extraInstructions) {
|
|
106
108
|
return `
|
|
107
|
-
You are a translation generator.
|
|
109
|
+
You are a ultimate translation generator server api.
|
|
108
110
|
|
|
109
|
-
Your task is to output **only one valid JSON object**, with **no text, explanations, or formatting
|
|
111
|
+
Your task is to translate a given text and output **only one valid JSON object**, with **no text, explanations, or formatting than the JSON**.
|
|
110
112
|
|
|
111
113
|
Follow these rules strictly:
|
|
112
114
|
|
|
@@ -116,7 +118,7 @@ Follow these rules strictly:
|
|
|
116
118
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
117
119
|
3. Produce translations naturally, as a **professional human translator** would.
|
|
118
120
|
4. Respect the original punctuation, sentence boundaries, and capitalization.
|
|
119
|
-
5. Consider only the following target languages: ${(config?.languages ? config.languages : []).join(", ")}.
|
|
121
|
+
5. Consider only the following target languages: ${(config?.languages ? Array.from(/* @__PURE__ */ new Set(["es-ES", ...config.languages, config.sourceLanguage])) : []).join(", ")}.
|
|
120
122
|
6. The final output must be a **valid JSON** following this exact schema:
|
|
121
123
|
|
|
122
124
|
{
|
|
@@ -378,12 +380,17 @@ async function getCache() {
|
|
|
378
380
|
throw error;
|
|
379
381
|
}
|
|
380
382
|
}
|
|
383
|
+
var savingQueue = Promise.resolve();
|
|
381
384
|
async function saveCache(cache) {
|
|
382
385
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
386
|
+
savingQueue = savingQueue.then(async () => {
|
|
387
|
+
const config = await awaitedConfig;
|
|
388
|
+
await createCacheDir();
|
|
389
|
+
const contents = JSON.stringify(cache, null, 2);
|
|
390
|
+
await fs.writeFile(`${config.cache.dir}/${config.cache.file}`, contents);
|
|
391
|
+
});
|
|
392
|
+
await savingQueue;
|
|
393
|
+
return cache;
|
|
387
394
|
} catch (error) {
|
|
388
395
|
throw error;
|
|
389
396
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a deterministic 128-bit hexadecimal signature for the provided input.
|
|
3
|
+
*
|
|
4
|
+
* The implementation deliberately skips cryptographic guarantees, focusing instead
|
|
5
|
+
* on stability and speed so that identical strings always return the same 32-char
|
|
6
|
+
* lowercase hex output (without prefixes or separators).
|
|
7
|
+
*
|
|
8
|
+
* @param input - Text to hash
|
|
9
|
+
* @returns 32-character lowercase hexadecimal digest
|
|
10
|
+
*/
|
|
11
|
+
declare function md5(input: string): string;
|
|
12
|
+
|
|
13
|
+
export { md5 };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/data/md5.ts
|
|
2
|
+
var INITIAL_STATE = [1831565813, 461845907, 2246822507, 3266489909];
|
|
3
|
+
var MULTIPLIERS = [668265261, 374761393, 2654435769, 2496678331];
|
|
4
|
+
var AVA_MULT1 = 2146121005;
|
|
5
|
+
var AVA_MULT2 = 2221713035;
|
|
6
|
+
function seedState(input) {
|
|
7
|
+
const state = [...INITIAL_STATE];
|
|
8
|
+
for (const char of input) {
|
|
9
|
+
const codePoint = char.codePointAt(0) ?? 0;
|
|
10
|
+
for (let i = 0; i < state.length; i++) {
|
|
11
|
+
state[i] = Math.imul(state[i] ^ codePoint, MULTIPLIERS[i]);
|
|
12
|
+
state[i] = rotateLeft(state[i], (i + 1) * 3);
|
|
13
|
+
}
|
|
14
|
+
state[0] ^= state[3] >>> 11;
|
|
15
|
+
state[1] ^= state[0] << 7;
|
|
16
|
+
state[2] ^= state[1] >>> 13;
|
|
17
|
+
state[3] ^= state[2] << 5;
|
|
18
|
+
}
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
function rotateLeft(value, shift) {
|
|
22
|
+
return value << shift | value >>> 32 - shift;
|
|
23
|
+
}
|
|
24
|
+
function avalanche(value) {
|
|
25
|
+
value ^= value >>> 16;
|
|
26
|
+
value = Math.imul(value, AVA_MULT1);
|
|
27
|
+
value ^= value >>> 15;
|
|
28
|
+
value = Math.imul(value, AVA_MULT2);
|
|
29
|
+
value ^= value >>> 16;
|
|
30
|
+
return value >>> 0;
|
|
31
|
+
}
|
|
32
|
+
function toHex(value) {
|
|
33
|
+
return (value >>> 0).toString(16).padStart(8, "0");
|
|
34
|
+
}
|
|
35
|
+
function mixState([h1, h2, h3, h4]) {
|
|
36
|
+
h1 = avalanche(h1 ^ h3);
|
|
37
|
+
h2 = avalanche(h2 ^ h4);
|
|
38
|
+
h3 = avalanche(h3 ^ h1);
|
|
39
|
+
h4 = avalanche(h4 ^ h2);
|
|
40
|
+
return [h1, h2, h3, h4];
|
|
41
|
+
}
|
|
42
|
+
function md5(input) {
|
|
43
|
+
const state = mixState(seedState(input));
|
|
44
|
+
return state.map(toHex).join("");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { md5 };
|