@kopynator/cli 1.6.4 ā 1.6.6
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/dist/index.js +47 -0
- package/package.json +1 -1
- package/src/commands/init.ts +69 -1
package/dist/index.js
CHANGED
|
@@ -32,6 +32,41 @@ var import_inquirer = __toESM(require("inquirer"));
|
|
|
32
32
|
var import_chalk = __toESM(require("chalk"));
|
|
33
33
|
var import_fs = __toESM(require("fs"));
|
|
34
34
|
var import_path = __toESM(require("path"));
|
|
35
|
+
function findIndexHtml() {
|
|
36
|
+
const candidates = ["src/index.html", "index.html", "public/index.html"];
|
|
37
|
+
for (const rel of candidates) {
|
|
38
|
+
const p = import_path.default.join(process.cwd(), rel);
|
|
39
|
+
if (import_fs.default.existsSync(p)) return p;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
function ensureNoTranslate(indexPath, locale) {
|
|
44
|
+
const original = import_fs.default.readFileSync(indexPath, "utf-8");
|
|
45
|
+
let html = original;
|
|
46
|
+
const htmlTagMatch = html.match(/<html\b[^>]*>/i);
|
|
47
|
+
if (htmlTagMatch) {
|
|
48
|
+
let tag = htmlTagMatch[0];
|
|
49
|
+
let newTag = tag;
|
|
50
|
+
if (!/\btranslate\s*=/i.test(newTag)) {
|
|
51
|
+
newTag = newTag.replace(/^<html/i, '<html translate="no"');
|
|
52
|
+
}
|
|
53
|
+
if (!/\blang\s*=/i.test(newTag)) {
|
|
54
|
+
newTag = newTag.replace(/^<html/i, `<html lang="${locale}"`);
|
|
55
|
+
}
|
|
56
|
+
if (newTag !== tag) {
|
|
57
|
+
html = html.replace(tag, newTag);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!/<meta\s+name=["']google["']\s+content=["']notranslate["']/i.test(html)) {
|
|
61
|
+
html = html.replace(/<head(\s[^>]*)?>/i, (m) => `${m}
|
|
62
|
+
<meta name="google" content="notranslate">`);
|
|
63
|
+
}
|
|
64
|
+
if (html !== original) {
|
|
65
|
+
import_fs.default.writeFileSync(indexPath, html);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
35
70
|
async function initCommand() {
|
|
36
71
|
console.log(import_chalk.default.bold.blue("\n\u{1F680} Initializing Kopynator...\n"));
|
|
37
72
|
let detectedFramework = null;
|
|
@@ -138,6 +173,18 @@ async function initCommand() {
|
|
|
138
173
|
]);
|
|
139
174
|
console.log(import_chalk.default.green(`
|
|
140
175
|
\u2705 Setting up for ${answers.framework}...`));
|
|
176
|
+
if (!isReactNative) {
|
|
177
|
+
const indexHtmlPath = findIndexHtml();
|
|
178
|
+
if (indexHtmlPath) {
|
|
179
|
+
const changed = ensureNoTranslate(indexHtmlPath, answers.defaultLocale);
|
|
180
|
+
const relPath = import_path.default.relative(process.cwd(), indexHtmlPath);
|
|
181
|
+
console.log(
|
|
182
|
+
changed ? import_chalk.default.green(`\u2705 Added translate="no" + notranslate meta to ${relPath}`) : import_chalk.default.blue(`\u2139\uFE0F ${relPath} already has translate="no" / notranslate \u2014 skipping`)
|
|
183
|
+
);
|
|
184
|
+
} else {
|
|
185
|
+
console.log(import_chalk.default.yellow("\u26A0\uFE0F Could not find an index.html to patch against the browser translate prompt."));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
141
188
|
if (answers.framework === "Angular") {
|
|
142
189
|
const appConfigPath = import_path.default.join(process.cwd(), "src/app/app.config.ts");
|
|
143
190
|
const appModulePath = import_path.default.join(process.cwd(), "src/app/app.module.ts");
|
package/package.json
CHANGED
package/src/commands/init.ts
CHANGED
|
@@ -3,6 +3,55 @@ import chalk from 'chalk';
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Locate the project's HTML entry point across common framework layouts.
|
|
8
|
+
*/
|
|
9
|
+
function findIndexHtml(): string | null {
|
|
10
|
+
const candidates = ['src/index.html', 'index.html', 'public/index.html'];
|
|
11
|
+
for (const rel of candidates) {
|
|
12
|
+
const p = path.join(process.cwd(), rel);
|
|
13
|
+
if (fs.existsSync(p)) return p;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ensure the HTML entry point carries the two signals Chrome/Edge actually
|
|
20
|
+
* respect to suppress the "translate this page?" prompt: the translate="no"
|
|
21
|
+
* attribute (WHATWG standard) and the legacy google notranslate meta tag.
|
|
22
|
+
* Firefox/Safari have no reliable equivalent today, so this is best-effort.
|
|
23
|
+
* Idempotent: safe to run on a project that already has these.
|
|
24
|
+
*/
|
|
25
|
+
function ensureNoTranslate(indexPath: string, locale: string): boolean {
|
|
26
|
+
const original = fs.readFileSync(indexPath, 'utf-8');
|
|
27
|
+
let html = original;
|
|
28
|
+
|
|
29
|
+
const htmlTagMatch = html.match(/<html\b[^>]*>/i);
|
|
30
|
+
if (htmlTagMatch) {
|
|
31
|
+
let tag = htmlTagMatch[0];
|
|
32
|
+
let newTag = tag;
|
|
33
|
+
if (!/\btranslate\s*=/i.test(newTag)) {
|
|
34
|
+
newTag = newTag.replace(/^<html/i, '<html translate="no"');
|
|
35
|
+
}
|
|
36
|
+
if (!/\blang\s*=/i.test(newTag)) {
|
|
37
|
+
newTag = newTag.replace(/^<html/i, `<html lang="${locale}"`);
|
|
38
|
+
}
|
|
39
|
+
if (newTag !== tag) {
|
|
40
|
+
html = html.replace(tag, newTag);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!/<meta\s+name=["']google["']\s+content=["']notranslate["']/i.test(html)) {
|
|
45
|
+
html = html.replace(/<head(\s[^>]*)?>/i, (m) => `${m}\n <meta name="google" content="notranslate">`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (html !== original) {
|
|
49
|
+
fs.writeFileSync(indexPath, html);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
6
55
|
export async function initCommand() {
|
|
7
56
|
console.log(chalk.bold.blue('\nš Initializing Kopynator...\n'));
|
|
8
57
|
|
|
@@ -123,7 +172,26 @@ export async function initCommand() {
|
|
|
123
172
|
]);
|
|
124
173
|
|
|
125
174
|
console.log(chalk.green(`\nā
Setting up for ${answers.framework}...`));
|
|
126
|
-
|
|
175
|
+
|
|
176
|
+
// Best-effort, cross-framework: stop the browser's own "translate this
|
|
177
|
+
// page?" popup from firing on load. Runs regardless of whether the
|
|
178
|
+
// provider config below was already present, so re-running init on an
|
|
179
|
+
// existing Kopynator project also picks this up.
|
|
180
|
+
if (!isReactNative) {
|
|
181
|
+
const indexHtmlPath = findIndexHtml();
|
|
182
|
+
if (indexHtmlPath) {
|
|
183
|
+
const changed = ensureNoTranslate(indexHtmlPath, answers.defaultLocale);
|
|
184
|
+
const relPath = path.relative(process.cwd(), indexHtmlPath);
|
|
185
|
+
console.log(
|
|
186
|
+
changed
|
|
187
|
+
? chalk.green(`ā
Added translate="no" + notranslate meta to ${relPath}`)
|
|
188
|
+
: chalk.blue(`ā¹ļø ${relPath} already has translate="no" / notranslate ā skipping`)
|
|
189
|
+
);
|
|
190
|
+
} else {
|
|
191
|
+
console.log(chalk.yellow('ā ļø Could not find an index.html to patch against the browser translate prompt.'));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
127
195
|
if (answers.framework === 'Angular') {
|
|
128
196
|
// Try app.config.ts first (Angular 17+ standalone)
|
|
129
197
|
const appConfigPath = path.join(process.cwd(), 'src/app/app.config.ts');
|