@geolonia/yuuhitsu 0.1.0 → 0.1.2

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 (73) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +114 -0
  3. package/dist/cli/commands/glossary.d.ts +3 -0
  4. package/dist/cli/commands/glossary.d.ts.map +1 -0
  5. package/dist/cli/commands/glossary.js +110 -0
  6. package/dist/cli/commands/glossary.js.map +1 -0
  7. package/dist/cli/commands/init.d.ts +3 -0
  8. package/dist/cli/commands/init.d.ts.map +1 -0
  9. package/dist/cli/commands/init.js +82 -0
  10. package/dist/cli/commands/init.js.map +1 -0
  11. package/dist/cli/commands/translate.d.ts +0 -0
  12. package/dist/cli/commands/translate.d.ts.map +1 -1
  13. package/dist/cli/commands/translate.js +53 -26
  14. package/dist/cli/commands/translate.js.map +1 -1
  15. package/dist/cli/index.d.ts +0 -0
  16. package/dist/cli/index.d.ts.map +1 -1
  17. package/dist/cli/index.js +4 -0
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/config.d.ts +1 -0
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +6 -0
  22. package/dist/config.js.map +1 -1
  23. package/dist/errors.d.ts +0 -0
  24. package/dist/errors.d.ts.map +0 -0
  25. package/dist/errors.js +0 -0
  26. package/dist/errors.js.map +0 -0
  27. package/dist/logger.d.ts +0 -0
  28. package/dist/logger.d.ts.map +0 -0
  29. package/dist/logger.js +0 -0
  30. package/dist/logger.js.map +0 -0
  31. package/dist/provider/claude.d.ts +0 -0
  32. package/dist/provider/claude.d.ts.map +0 -0
  33. package/dist/provider/claude.js +0 -0
  34. package/dist/provider/claude.js.map +0 -0
  35. package/dist/provider/gemini.d.ts +0 -0
  36. package/dist/provider/gemini.d.ts.map +0 -0
  37. package/dist/provider/gemini.js +0 -0
  38. package/dist/provider/gemini.js.map +0 -0
  39. package/dist/provider/index.d.ts +0 -0
  40. package/dist/provider/index.d.ts.map +0 -0
  41. package/dist/provider/index.js +0 -0
  42. package/dist/provider/index.js.map +0 -0
  43. package/dist/provider/interface.d.ts +0 -0
  44. package/dist/provider/interface.d.ts.map +0 -0
  45. package/dist/provider/interface.js +0 -0
  46. package/dist/provider/interface.js.map +0 -0
  47. package/dist/provider/ollama.d.ts +0 -0
  48. package/dist/provider/ollama.d.ts.map +0 -0
  49. package/dist/provider/ollama.js +0 -0
  50. package/dist/provider/ollama.js.map +0 -0
  51. package/dist/tasks/batch-translate.d.ts +46 -0
  52. package/dist/tasks/batch-translate.d.ts.map +1 -0
  53. package/dist/tasks/batch-translate.js +174 -0
  54. package/dist/tasks/batch-translate.js.map +1 -0
  55. package/dist/tasks/glossary.d.ts +41 -0
  56. package/dist/tasks/glossary.d.ts.map +1 -0
  57. package/dist/tasks/glossary.js +273 -0
  58. package/dist/tasks/glossary.js.map +1 -0
  59. package/dist/tasks/stream.d.ts +0 -0
  60. package/dist/tasks/stream.d.ts.map +0 -0
  61. package/dist/tasks/stream.js +0 -0
  62. package/dist/tasks/stream.js.map +0 -0
  63. package/dist/tasks/translate.d.ts +27 -0
  64. package/dist/tasks/translate.d.ts.map +1 -1
  65. package/dist/tasks/translate.js +101 -7
  66. package/dist/tasks/translate.js.map +1 -1
  67. package/package.json +14 -8
  68. package/src/templates/fix-links.md +0 -0
  69. package/src/templates/generate-docs.md +0 -0
  70. package/src/templates/generate-tests.md +0 -0
  71. package/src/templates/research.md +0 -0
  72. package/src/templates/sync-docs.md +0 -0
  73. package/src/templates/translate.md +8 -0
@@ -1,6 +1,68 @@
1
1
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
2
2
  import { dirname, basename, extname, join } from "path";
3
+ import { buildGlossaryPrompt } from "./glossary.js";
3
4
  const CHUNK_SIZE = 50 * 1024; // 50KB
5
+ /**
6
+ * Separate frontmatter from Markdown content
7
+ * Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
8
+ * @param content - Full Markdown content
9
+ * @returns Object with separated frontmatter and body
10
+ */
11
+ export function separateFrontmatter(content) {
12
+ // Normalize CRLF to LF for regex matching
13
+ const normalized = content.replace(/\r\n/g, "\n");
14
+ // Match frontmatter (two alternations to keep closing --- on its own line):
15
+ // Case 1: non-empty body: ^---\n ... \n---[ \t]*(\n|$)
16
+ // Case 2: empty body: ^---\n---[ \t]*(\n|$)
17
+ // Using alternation avoids the \n? ambiguity that allows --- to match mid-line.
18
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---[ \t]*(\n|$)|^---\n---[ \t]*(\n|$)/;
19
+ const match = normalized.match(frontmatterRegex);
20
+ if (match) {
21
+ const matchedLength = match[0].length;
22
+ const frontmatter = normalized.slice(0, matchedLength);
23
+ const body = normalized.slice(matchedLength);
24
+ return { frontmatter, body };
25
+ }
26
+ return { frontmatter: null, body: normalized };
27
+ }
28
+ /**
29
+ * Replace fenced code blocks and inline code with placeholders.
30
+ * Fenced blocks (``` or ````+) take priority over inline code.
31
+ */
32
+ export function protectCodeBlocks(content) {
33
+ const map = new Map();
34
+ let blockIndex = 0;
35
+ let inlineIndex = 0;
36
+ // Step 1: Replace fenced code blocks (4+ backticks before 3-backtick blocks)
37
+ // Matches ````+ ... ```` or ``` ... ``` (non-greedy, multiline)
38
+ // Preserve the original line count by repeating newlines so subsequent line numbers stay correct.
39
+ let result = content.replace(/(`{3,})[^\n]*\n[\s\S]*?\1[ \t]*(\n|$)/g, (match) => {
40
+ const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
41
+ map.set(placeholder, match);
42
+ const newlineCount = (match.match(/\n/g) ?? []).length;
43
+ return placeholder + "\n".repeat(newlineCount);
44
+ });
45
+ // Step 2: Replace inline code (single backtick, not within code blocks)
46
+ result = result.replace(/`([^`\n]+)`/g, (match) => {
47
+ const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
48
+ map.set(placeholder, match);
49
+ return placeholder;
50
+ });
51
+ return { text: result, map };
52
+ }
53
+ /**
54
+ * Restore placeholders back to original code blocks/inline code.
55
+ */
56
+ export function restoreCodeBlocks(content, map) {
57
+ let result = content;
58
+ // Restore fenced code blocks (may have trailing newline added by protect)
59
+ for (const [placeholder, original] of map.entries()) {
60
+ // The placeholder may appear with or without trailing newline
61
+ result = result.split(placeholder + "\n").join(original);
62
+ result = result.split(placeholder).join(original);
63
+ }
64
+ return result;
65
+ }
4
66
  const DEFAULT_TEMPLATE = `You are a professional translator. Translate the following Markdown document to {{targetLanguage}}.
5
67
 
6
68
  Rules:
@@ -10,16 +72,37 @@ Rules:
10
72
  - Maintain the same document structure
11
73
  - Produce natural, fluent text in the target language
12
74
 
75
+ CRITICAL - Link and URL preservation:
76
+ - NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
77
+ - NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
78
+ - NEVER convert external URLs to different language versions.
79
+ - If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
80
+ - Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
81
+ - Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
82
+
13
83
  Additional rules for Japanese translation:
14
84
  - Use full-width punctuation: 。、?! (not .,?!)
15
85
  - Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
16
86
  - Use natural Japanese terms for technical words where appropriate (e.g., "registration" → "登録", "subscription" → "サブスクリプション")
17
87
  - Keep product names, proper nouns, and abbreviations unchanged (e.g., Vela, FIWARE, NGSIv2, NGSI-LD, MCP)`;
18
- function buildPrompt(content, targetLang, templateContent) {
88
+ function buildPrompt(content, targetLang, hasPlaceholders, templateContent, glossaryConfig) {
19
89
  const template = templateContent || DEFAULT_TEMPLATE;
20
- const systemPrompt = template
90
+ let systemPrompt = template
21
91
  .replace(/\{\{targetLanguage\}\}/g, targetLang)
22
92
  .replace(/\{\{content\}\}/g, "");
93
+ if (glossaryConfig) {
94
+ const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
95
+ if (glossarySection) {
96
+ systemPrompt += glossarySection;
97
+ }
98
+ }
99
+ if (hasPlaceholders) {
100
+ systemPrompt +=
101
+ "\n\nIMPORTANT - Placeholder preservation:\n" +
102
+ "- Tokens matching __CODE_BLOCK_N__ or __INLINE_CODE_N__ are placeholders for code blocks/inline code.\n" +
103
+ "- Output them VERBATIM and UNCHANGED. Do NOT translate, modify, or remove them.\n" +
104
+ "- Example: if input has __CODE_BLOCK_0__, output must contain __CODE_BLOCK_0__ exactly.";
105
+ }
23
106
  return [
24
107
  { role: "system", content: systemPrompt },
25
108
  { role: "user", content },
@@ -55,7 +138,7 @@ function splitIntoChunks(content) {
55
138
  return chunks;
56
139
  }
57
140
  export async function translateFile(options) {
58
- const { provider, inputPath, targetLang, templateContent } = options;
141
+ const { provider, inputPath, targetLang, templateContent, glossaryConfig } = options;
59
142
  // Read input file
60
143
  let content;
61
144
  try {
@@ -74,12 +157,17 @@ export async function translateFile(options) {
74
157
  const resolvedOutput = resolveOutputPath(inputPath, targetLang, options.outputPath);
75
158
  // Ensure output directory exists
76
159
  mkdirSync(dirname(resolvedOutput), { recursive: true });
77
- // Split into chunks if needed
78
- const chunks = splitIntoChunks(content);
160
+ // Separate frontmatter from body
161
+ const { frontmatter, body } = separateFrontmatter(content);
162
+ // Protect code blocks: replace with placeholders before sending to LLM
163
+ const { text: protectedBody, map: codeMap } = protectCodeBlocks(body);
164
+ const hasPlaceholders = codeMap.size > 0;
165
+ // Split body into chunks if needed (frontmatter is never sent to LLM)
166
+ const chunks = splitIntoChunks(protectedBody);
79
167
  const translatedParts = [];
80
168
  let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
81
169
  for (const chunk of chunks) {
82
- const messages = buildPrompt(chunk, targetLang, templateContent);
170
+ const messages = buildPrompt(chunk, targetLang, hasPlaceholders, templateContent, glossaryConfig);
83
171
  const response = await provider.chat({
84
172
  model: "",
85
173
  messages,
@@ -89,7 +177,13 @@ export async function translateFile(options) {
89
177
  totalUsage.completionTokens += response.usage.completionTokens;
90
178
  totalUsage.totalTokens += response.usage.totalTokens;
91
179
  }
92
- const translatedContent = translatedParts.join("");
180
+ // Restore code blocks from placeholders
181
+ const translatedBodyWithPlaceholders = translatedParts.join("");
182
+ const translatedBody = restoreCodeBlocks(translatedBodyWithPlaceholders, codeMap);
183
+ // Recombine frontmatter with translated body
184
+ const translatedContent = frontmatter
185
+ ? frontmatter + translatedBody
186
+ : translatedBody;
93
187
  // Write output
94
188
  writeFileSync(resolvedOutput, translatedContent, "utf-8");
95
189
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGxD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO;AAoBrC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;2GAakF,CAAC;AAE5G,SAAS,WAAW,CAClB,OAAe,EACf,UAAkB,EAClB,eAAwB;IAExB,MAAM,QAAQ,GAAG,eAAe,IAAI,gBAAgB,CAAC;IACrD,MAAM,YAAY,GAAG,QAAQ;SAC1B,OAAO,CAAC,yBAAyB,EAAE,UAAU,CAAC;SAC9C,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAEnC,OAAO;QACL,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;QACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,SAAiB,EACjB,UAAkB,EAClB,UAAmB;IAEnB,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QACjC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,YAAY,GAAG,EAAE,CAAC;IAEtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,YAAY,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,UAAU,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1B,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAyB;IAEzB,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAErE,kBAAkB;IAClB,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAK,GAAW,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,cAAc,GAAG,iBAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAEpF,iCAAiC;IACjC,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExD,8BAA8B;IAC9B,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,IAAI,UAAU,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAE1E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,EAAE;YACT,QAAQ;SACT,CAAC,CAAC;QAEH,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,UAAU,CAAC,YAAY,IAAI,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;QACvD,UAAU,CAAC,gBAAgB,IAAI,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC;QAC/D,UAAU,CAAC,WAAW,IAAI,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC;IACvD,CAAC;IAED,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEnD,eAAe;IACf,aAAa,CAAC,cAAc,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAE1D,OAAO;QACL,UAAU,EAAE,cAAc;QAC1B,KAAK,EAAE,UAAU;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geolonia/yuuhitsu",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "右筆 (Yuuhitsu) - AI-powered document operations CLI. Translate, generate, and sync documents using Claude, Gemini, or Ollama.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,12 @@
14
14
  "test:watch": "vitest",
15
15
  "lint": "tsc --noEmit"
16
16
  },
17
- "keywords": ["ai", "cli", "translation", "documentation"],
17
+ "keywords": [
18
+ "ai",
19
+ "cli",
20
+ "translation",
21
+ "documentation"
22
+ ],
18
23
  "license": "MIT",
19
24
  "files": [
20
25
  "dist",
@@ -25,16 +30,17 @@
25
30
  "dependencies": {
26
31
  "@anthropic-ai/sdk": "^0.39.0",
27
32
  "@google/genai": "^0.7.0",
28
- "openai": "^4.77.0",
33
+ "chalk": "^5.4.0",
29
34
  "commander": "^13.0.0",
30
- "yaml": "^2.7.0",
31
35
  "dotenv": "^16.4.0",
32
- "chalk": "^5.4.0"
36
+ "fast-glob": "^3.3.3",
37
+ "openai": "^4.77.0",
38
+ "yaml": "^2.7.0"
33
39
  },
34
40
  "devDependencies": {
35
- "vitest": "^3.0.0",
36
- "typescript": "^5.7.0",
41
+ "@types/node": "^22.0.0",
37
42
  "tsx": "^4.19.0",
38
- "@types/node": "^22.0.0"
43
+ "typescript": "^5.7.0",
44
+ "vitest": "^3.0.0"
39
45
  }
40
46
  }
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -7,6 +7,14 @@ Rules:
7
7
  - Maintain the same document structure
8
8
  - Produce natural, fluent text in the target language
9
9
 
10
+ CRITICAL - Link and URL preservation:
11
+ - NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
12
+ - NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
13
+ - NEVER convert external URLs to different language versions.
14
+ - If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
15
+ - Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
16
+ - Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
17
+
10
18
  Additional rules for Japanese translation:
11
19
  - Use full-width punctuation: 。、?! (not .,?!)
12
20
  - Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")