feat(ai): add sandboxed HTML preview for AI rich content
This commit is contained in:
1 parent
11e0db5acb
commit
39b2d2a6ac
22 files changed
+1199
-13
No files matched your search
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import en from "../locales/en";
|
||||
import es from "../locales/es";
|
||||
import it_ from "../locales/it";
|
||||
import ja from "../locales/ja";
|
||||
import ko from "../locales/ko";
|
||||
import ptBR from "../locales/pt-BR";
|
||||
import tr from "../locales/tr";
|
||||
import zhCN from "../locales/zh-CN";
|
||||
import zhTW from "../locales/zh-TW";
|
||||
|
||||
const locales: Array<[string, Record<string, unknown>]> = [
|
||||
["en", en],
|
||||
["es", es],
|
||||
["it", it_],
|
||||
["ja", ja],
|
||||
["ko", ko],
|
||||
["pt-BR", ptBR],
|
||||
["tr", tr],
|
||||
["zh-CN", zhCN],
|
||||
["zh-TW", zhTW],
|
||||
];
|
||||
|
||||
// Keys the safe-HTML preview (PR2 of #6467) adds to the `ai` namespace. Every
|
||||
// locale must expose all of them — the preview UI renders in whatever locale
|
||||
// the user runs, and a missing key would leak raw keys into the toolbar.
|
||||
const AI_HTML_PREVIEW_KEYS = ["htmlPreviewLabel", "htmlExpandPreview", "htmlExpandPreviewHint", "htmlSaveSafe", "htmlSaveFailed", "htmlCopySource", "htmlCopyRiskBody", "htmlCopyRiskAccept", "htmlCopyRiskRemember", "htmlCopyRiskToast"] as const;
|
||||
|
||||
describe("AI rich content locale parity", () => {
|
||||
it.each(locales)("%s exposes the full ai.html* key set with non-empty copy", (_name, locale) => {
|
||||
const ai = (locale as { ai: Record<string, unknown> }).ai;
|
||||
for (const key of AI_HTML_PREVIEW_KEYS) {
|
||||
expect(ai[key], `${_name}: ai.${key}`).toBeTypeOf("string");
|
||||
expect(ai[key] as string, `${_name}: ai.${key}`).not.toHaveLength(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -3037,6 +3037,16 @@ export default {
|
||||
chartDownloadPng: "Download PNG",
|
||||
chartDownloadFailed: "Failed to download chart image",
|
||||
chartData: "Chart data",
|
||||
htmlPreviewLabel: "AI-generated HTML preview",
|
||||
htmlExpandPreview: "Open larger preview",
|
||||
htmlExpandPreviewHint: "This preview runs fully sandboxed — scripts and network access are blocked.",
|
||||
htmlSaveSafe: "Save Safe HTML",
|
||||
htmlSaveFailed: "Failed to save HTML file",
|
||||
htmlCopySource: "Copy source",
|
||||
htmlCopyRiskBody: "This HTML was AI-generated. Opening it outside DBX may execute scripts and access the network.",
|
||||
htmlCopyRiskAccept: "Copy anyway",
|
||||
htmlCopyRiskRemember: "Don't ask again this session",
|
||||
htmlCopyRiskToast: "Copied. This AI-generated HTML may execute scripts or access the network when opened outside DBX.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "Open Connection",
|
||||
|
||||
@@ -2824,6 +2824,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "Descargar PNG",
|
||||
chartDownloadFailed: "No se pudo descargar la imagen del gráfico",
|
||||
chartData: "Datos del gráfico",
|
||||
htmlPreviewLabel: "Vista previa de HTML generado por IA",
|
||||
htmlExpandPreview: "Abrir vista previa ampliada",
|
||||
htmlExpandPreviewHint: "Esta vista previa se ejecuta en un sandbox completo: los scripts y el acceso a la red están bloqueados.",
|
||||
htmlSaveSafe: "Guardar HTML seguro",
|
||||
htmlSaveFailed: "No se pudo guardar el archivo HTML",
|
||||
htmlCopySource: "Copiar código fuente",
|
||||
htmlCopyRiskBody: "Este HTML fue generado por IA. Abrirlo fuera de DBX puede ejecutar scripts y acceder a la red.",
|
||||
htmlCopyRiskAccept: "Copiar de todos modos",
|
||||
htmlCopyRiskRemember: "No volver a preguntar en esta sesión",
|
||||
htmlCopyRiskToast: "Copiado. Este HTML generado por IA puede ejecutar scripts o acceder a la red si se abre fuera de DBX.",
|
||||
agentSteps: {
|
||||
generated: "SQL generado",
|
||||
noSql: "No se encontró SQL",
|
||||
|
||||
@@ -2718,6 +2718,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "Scarica PNG",
|
||||
chartDownloadFailed: "Impossibile scaricare l'immagine del grafico",
|
||||
chartData: "Dati del grafico",
|
||||
htmlPreviewLabel: "Anteprima HTML generata dall'IA",
|
||||
htmlExpandPreview: "Apri anteprima ingrandita",
|
||||
htmlExpandPreviewHint: "Questa anteprima viene eseguita in una sandbox completa: script e accesso alla rete sono bloccati.",
|
||||
htmlSaveSafe: "Salva HTML sicuro",
|
||||
htmlSaveFailed: "Salvataggio del file HTML non riuscito",
|
||||
htmlCopySource: "Copia sorgente",
|
||||
htmlCopyRiskBody: "Questo HTML è stato generato dall'IA. Aprirlo fuori da DBX può eseguire script e accedere alla rete.",
|
||||
htmlCopyRiskAccept: "Copia comunque",
|
||||
htmlCopyRiskRemember: "Non chiedere più in questa sessione",
|
||||
htmlCopyRiskToast: "Copiato. Questo HTML generato dall'IA può eseguire script o accedere alla rete se aperto fuori da DBX.",
|
||||
agentSteps: {
|
||||
generated: "SQL generato",
|
||||
noSql: "Nessun SQL trovato",
|
||||
|
||||
@@ -2860,6 +2860,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "PNGをダウンロード",
|
||||
chartDownloadFailed: "グラフ画像をダウンロードできませんでした",
|
||||
chartData: "グラフのデータ",
|
||||
htmlPreviewLabel: "AI生成HTMLのプレビュー",
|
||||
htmlExpandPreview: "拡大プレビューを開く",
|
||||
htmlExpandPreviewHint: "このプレビューは完全なサンドボックスで実行され、スクリプトとネットワークアクセスはブロックされます。",
|
||||
htmlSaveSafe: "安全なHTMLを保存",
|
||||
htmlSaveFailed: "HTMLファイルの保存に失敗しました",
|
||||
htmlCopySource: "ソースをコピー",
|
||||
htmlCopyRiskBody: "このHTMLはAIによって生成されました。DBXの外部で開くとスクリプトが実行され、ネットワークへアクセスする可能性があります。",
|
||||
htmlCopyRiskAccept: "それでもコピー",
|
||||
htmlCopyRiskRemember: "このセッションでは今後確認しない",
|
||||
htmlCopyRiskToast: "コピーしました。このAI生成HTMLは、DBXの外部で開くとスクリプトを実行したりネットワークへアクセスしたりする可能性があります。",
|
||||
agentSteps: {
|
||||
generated: "SQL生成完了",
|
||||
noSql: "SQLが見つかりません",
|
||||
|
||||
@@ -2830,6 +2830,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "PNG 다운로드",
|
||||
chartDownloadFailed: "차트 이미지를 다운로드하지 못했습니다",
|
||||
chartData: "차트 데이터",
|
||||
htmlPreviewLabel: "AI 생성 HTML 미리보기",
|
||||
htmlExpandPreview: "큰 화면으로 미리보기",
|
||||
htmlExpandPreviewHint: "이 미리보기는 완전한 샌드박스에서 실행되며 스크립트와 네트워크 액세스가 차단됩니다.",
|
||||
htmlSaveSafe: "안전한 HTML 저장",
|
||||
htmlSaveFailed: "HTML 파일 저장에 실패했습니다",
|
||||
htmlCopySource: "소스 복사",
|
||||
htmlCopyRiskBody: "이 HTML은 AI가 생성했습니다. DBX 외부에서 열면 스크립트가 실행되고 네트워크에 접근할 수 있습니다.",
|
||||
htmlCopyRiskAccept: "그래도 복사",
|
||||
htmlCopyRiskRemember: "이 세션에서 다시 묻지 않기",
|
||||
htmlCopyRiskToast: "복사되었습니다. 이 AI 생성 HTML은 DBX 외부에서 열면 스크립트를 실행하거나 네트워크에 접근할 수 있습니다.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "연결 열기",
|
||||
|
||||
@@ -2826,6 +2826,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "Baixar PNG",
|
||||
chartDownloadFailed: "Falha ao baixar a imagem do gráfico",
|
||||
chartData: "Dados do gráfico",
|
||||
htmlPreviewLabel: "Pré-visualização de HTML gerado por IA",
|
||||
htmlExpandPreview: "Abrir visualização ampliada",
|
||||
htmlExpandPreviewHint: "Esta visualização é executada em sandbox completo — scripts e acesso à rede são bloqueados.",
|
||||
htmlSaveSafe: "Salvar HTML seguro",
|
||||
htmlSaveFailed: "Falha ao salvar o arquivo HTML",
|
||||
htmlCopySource: "Copiar código-fonte",
|
||||
htmlCopyRiskBody: "Este HTML foi gerado por IA. Abri-lo fora do DBX pode executar scripts e acessar a rede.",
|
||||
htmlCopyRiskAccept: "Copiar mesmo assim",
|
||||
htmlCopyRiskRemember: "Não perguntar novamente nesta sessão",
|
||||
htmlCopyRiskToast: "Copiado. Este HTML gerado por IA pode executar scripts ou acessar a rede quando aberto fora do DBX.",
|
||||
agentSteps: {
|
||||
generated: "SQL gerado",
|
||||
noSql: "Nenhum SQL encontrado",
|
||||
|
||||
@@ -3011,6 +3011,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "PNG İndir",
|
||||
chartDownloadFailed: "Grafik görüntüsü indirilemedi",
|
||||
chartData: "Grafik verileri",
|
||||
htmlPreviewLabel: "AI tarafından oluşturulan HTML önizlemesi",
|
||||
htmlExpandPreview: "Büyük önizleme aç",
|
||||
htmlExpandPreviewHint: "Bu önizleme tamamen korumalı alanda çalışır; betikler ve ağ erişimi engellenir.",
|
||||
htmlSaveSafe: "Güvenli HTML'i kaydet",
|
||||
htmlSaveFailed: "HTML dosyası kaydedilemedi",
|
||||
htmlCopySource: "Kaynağı kopyala",
|
||||
htmlCopyRiskBody: "Bu HTML yapay zeka tarafından oluşturuldu. DBX dışında açmak betik çalıştırabilir ve ağa erişebilir.",
|
||||
htmlCopyRiskAccept: "Yine de kopyala",
|
||||
htmlCopyRiskRemember: "Bu oturumda tekrar sorma",
|
||||
htmlCopyRiskToast: "Kopyalandı. Bu AI tarafından oluşturulan HTML, DBX dışında açıldığında betik çalıştırabilir veya ağa erişebilir.",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "Bağlantıyı Aç",
|
||||
|
||||
@@ -2960,6 +2960,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "下载 PNG",
|
||||
chartDownloadFailed: "图表图片下载失败",
|
||||
chartData: "图表数据",
|
||||
htmlPreviewLabel: "AI 生成的 HTML 预览",
|
||||
htmlExpandPreview: "在大窗口预览",
|
||||
htmlExpandPreviewHint: "预览在完全沙箱中运行,脚本与网络访问均被阻止。",
|
||||
htmlSaveSafe: "保存安全 HTML",
|
||||
htmlSaveFailed: "保存 HTML 文件失败",
|
||||
htmlCopySource: "复制源码",
|
||||
htmlCopyRiskBody: "此 HTML 由 AI 生成,在 DBX 外打开可能执行脚本并访问网络。",
|
||||
htmlCopyRiskAccept: "仍要复制",
|
||||
htmlCopyRiskRemember: "本会话不再询问",
|
||||
htmlCopyRiskToast: "已复制。此 AI 生成的 HTML 在 DBX 外打开可能执行脚本或访问网络。",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "打开连接",
|
||||
|
||||
@@ -2938,6 +2938,16 @@ export default withEnglishFallback({
|
||||
chartDownloadPng: "下載 PNG",
|
||||
chartDownloadFailed: "圖表圖片下載失敗",
|
||||
chartData: "圖表資料",
|
||||
htmlPreviewLabel: "AI 產生的 HTML 預覽",
|
||||
htmlExpandPreview: "在大視窗預覽",
|
||||
htmlExpandPreviewHint: "預覽在完全沙箱中執行,指令碼與網路存取均被封鎖。",
|
||||
htmlSaveSafe: "儲存安全 HTML",
|
||||
htmlSaveFailed: "儲存 HTML 檔案失敗",
|
||||
htmlCopySource: "複製原始碼",
|
||||
htmlCopyRiskBody: "此 HTML 由 AI 產生,在 DBX 外開啟可能執行指令碼並存取網路。",
|
||||
htmlCopyRiskAccept: "仍要複製",
|
||||
htmlCopyRiskRemember: "本次工作階段不再詢問",
|
||||
htmlCopyRiskToast: "已複製。此 AI 產生的 HTML 在 DBX 外開啟可能執行指令碼或存取網路。",
|
||||
},
|
||||
contextMenu: {
|
||||
openConnection: "開啟連線",
|
||||
|
||||
Reference in new issue
Block a user