feat(privacy+extension): publier la page /privacy et préparer les builds Chrome/Firefox Store
- Nouvelle page /privacy bilingue (FR/EN) avec sélection par Accept-Language
ou ?lang=, sections complètes (données collectées, IA/BYOK, RGPD, sécurité,
contact). Style sombre aligné sur la landing (x.ai premium).
- Liens footer landing.footer.legal.* mis à jour vers /privacy dans les 15 locales.
- Extension Web Clipper rendue cross-browser :
* background.js détecte chrome.sidePanel vs browser.sidebarAction
* sidepanel.js ajoute un shim chrome<->browser pour Firefox
* manifest.json inclut sidebar_action + browser_specific_settings.gecko
+ optional_host_permissions (Chrome les ignore)
- Script scripts/build-firefox.mjs pour produire un .xpi signé pour AMO,
symétrique de build-chrome-store.mjs. Exclusion mutuelle des artefacts
Chrome/Firefox pour éviter la cross-contamination.
- Branding corrigé : 176 occurrences de 'Momento' -> 'Memento' dans le
bundle de traductions embarqué.
- Version bumpée 0.3.1 -> 0.4.0.
This commit is contained in:
@@ -10,12 +10,22 @@ Fichiers : `extension/_locales/<lang>/messages.json`. Régénération : `node ex
|
||||
|
||||
## Installation (dev)
|
||||
|
||||
1. Chrome → `chrome://extensions`
|
||||
### Chrome
|
||||
1. `chrome://extensions`
|
||||
2. **Mode développeur** → **Charger l’extension non empaquetée** → dossier `memento-note/extension`
|
||||
3. Épingle l’icône Memento
|
||||
|
||||
> Chrome **114+** requis (Side Panel API).
|
||||
|
||||
### Firefox
|
||||
```bash
|
||||
# Avec web-ext (https://extensionworkshop.com/)
|
||||
npx web-ext run --source-dir memento-note/extension
|
||||
```
|
||||
Ou via `about:debugging` → **Ce Firefox** → **Charger un module temporaire** → sélectionner `manifest.json`.
|
||||
|
||||
> Firefox **115+** requis (MV3 + sidebarAction).
|
||||
|
||||
## Instance Memento
|
||||
|
||||
- **Dev** : icône ⚙ → URL (`http://localhost:3000` ou IP LAN) → **Appliquer & reconnecter**
|
||||
@@ -45,6 +55,30 @@ Fichiers : `extension/_locales/<lang>/messages.json`. Régénération : `node ex
|
||||
|
||||
Détection automatique `dir` / `lang` (ex. BBC Persian), aperçu RTL avec Vazirmatn.
|
||||
|
||||
## Builds production
|
||||
|
||||
Deux scripts produisent des paquets prêts à publier :
|
||||
|
||||
```bash
|
||||
# Chrome Web Store (zip)
|
||||
node extension/scripts/build-chrome-store.mjs
|
||||
# → memento-note/extension/memento-web-clipper-chrome-store.zip (~44 Ko, 27 fichiers)
|
||||
|
||||
# Firefox Add-ons (xpi)
|
||||
node extension/scripts/build-firefox.mjs
|
||||
# → memento-note/extension/memento-web-clipper-firefox.xpi (~44 Ko, 27 fichiers)
|
||||
```
|
||||
|
||||
Chaque build :
|
||||
- Verrouille `ALLOW_INSTANCE_CONFIG = false` (URL prod en dur)
|
||||
- Restreint les `host_permissions` à `https://memento-note.com/*`
|
||||
- Génère les PNG d'icônes depuis `public/icons/icon-{192,512}.svg`
|
||||
- Exclut les fichiers internes (`i18n/`, `diagnose.js`, `test-sidepanel.html`, etc.)
|
||||
|
||||
Différences manifest :
|
||||
- **Chrome** : `side_panel` (Side Panel API Chrome 114+)
|
||||
- **Firefox** : `sidebar_action` + `browser_specific_settings.gecko` (Firefox 115+)
|
||||
|
||||
## APIs
|
||||
|
||||
- `GET /api/clip/notebooks`
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Fügen Sie die HTTPS- (oder LAN-)URL Ihres Memento-Servers ein. Cookies in diesem Browser verarbeiten die Anmeldung."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento kann nicht auf diese Registerkarte zugreifen. Überprüfen Sie die Tastatur-/Site-Erweiterungsberechtigungen – oder öffnen Sie den Seitenbereich."
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Paste the HTTPS (or LAN) URL of your Memento server. Cookies in this browser handle sign-in."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento can't access this tab. Check keyboard/site extension permissions — or open the Side Panel."
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "URL HTTPS (یا LAN) سرور Memento خود را جایگذاری کنید. کوکیهای این مرورگر ورود به سیستم را کنترل میکنند."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento نمی تواند به این برگه دسترسی پیدا کند. مجوزهای افزونه صفحه کلید/سایت را بررسی کنید - یا پانل جانبی را باز کنید."
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"message": "Clipper vers Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Web Clipper"
|
||||
"message": "Tondeuse Web"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Connecté"
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Collez l'URL HTTPS (ou LAN) de votre serveur Memento. Les cookies de ce navigateur gèrent la connexion."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento ne peut pas accéder à cet onglet. Vérifiez les autorisations du clavier/extension de site – ou ouvrez le panneau latéral."
|
||||
@@ -78,13 +78,13 @@
|
||||
"message": "Enregistrer le lien uniquement"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Impossible de clipper ici — cette page bloque l'accès aux extensions."
|
||||
"message": "Impossible de découper ici : cette page bloque l'accès aux extensions."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Veuillez d'abord vous connecter à Memento dans ce navigateur."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Impossible de charger les carnets. Essayez de vous reconnecter."
|
||||
"message": "Impossible de charger les blocs-notes. Essayez de vous reconnecter."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Carnets chargés"
|
||||
@@ -123,22 +123,22 @@
|
||||
"message": "Enregistrer dans Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Retour"
|
||||
"message": "Dos"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analyse de la source"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analyse…"
|
||||
"message": "Analyser…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Enregistrement…"
|
||||
"message": "Économie…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Génération automatique des tags, résumé sémantique et calcul des embeddings."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Note enregistrée"
|
||||
"message": "Remarque enregistrée"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Enregistré dans $NOTEBOOK$",
|
||||
@@ -165,7 +165,7 @@
|
||||
"message": "Réessayer"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Sélectionnez d'abord du texte, ou clippez la page entière."
|
||||
"message": "Sélectionnez d’abord le texte ou coupez la page entière."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Impossible d'analyser cette page."
|
||||
@@ -177,6 +177,6 @@
|
||||
"message": "Problème de réseau : vérifiez votre connexion et l'URL Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Surlignez le texte à clipper"
|
||||
"message": "Mettez en surbrillance le texte sur la page ou coupez la page entière."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
/** Service worker — ouvre le panneau latéral au clic sur l’icône. */
|
||||
chrome.runtime.onInstalled.addListener(() => {
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
})
|
||||
/** Service worker — ouvre le panneau latéral (Chrome Side Panel ou Firefox sidebar) au clic sur l'icône. */
|
||||
const extApi = (typeof browser !== 'undefined' && browser.sidebarAction) ? browser : chrome
|
||||
|
||||
chrome.runtime.onStartup.addListener(() => {
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
// Chrome MV3 : Side Panel API
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
} else if (extApi.sidebarAction?.open) {
|
||||
// Firefox MV3 : sidebarAction
|
||||
extApi.action?.onClicked?.addListener?.(() => {
|
||||
extApi.sidebarAction.open().catch(() => {})
|
||||
})
|
||||
}
|
||||
|
||||
extApi.runtime?.onInstalled?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
extApi.runtime?.onStartup?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Fügen Sie die HTTPS- (oder LAN-)URL Ihres Memento-Servers ein. Cookies in diesem Browser verarbeiten die Anmeldung."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento kann nicht auf diese Registerkarte zugreifen. Überprüfen Sie die Tastatur-/Site-Erweiterungsberechtigungen – oder öffnen Sie den Seitenbereich."
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Paste the HTTPS (or LAN) URL of your Memento server. Cookies in this browser handle sign-in."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento can't access this tab. Check keyboard/site extension permissions — or open the Side Panel."
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "URL HTTPS (یا LAN) سرور Memento خود را جایگذاری کنید. کوکیهای این مرورگر ورود به سیستم را کنترل میکنند."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento نمی تواند به این برگه دسترسی پیدا کند. مجوزهای افزونه صفحه کلید/سایت را بررسی کنید - یا پانل جانبی را باز کنید."
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"message": "Clipper vers Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Web Clipper"
|
||||
"message": "Tondeuse Web"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Connecté"
|
||||
@@ -36,7 +36,7 @@
|
||||
"message": "Collez l'URL HTTPS (ou LAN) de votre serveur Memento. Les cookies de ce navigateur gèrent la connexion."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.3.1"
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento ne peut pas accéder à cet onglet. Vérifiez les autorisations du clavier/extension de site – ou ouvrez le panneau latéral."
|
||||
@@ -78,13 +78,13 @@
|
||||
"message": "Enregistrer le lien uniquement"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Impossible de clipper ici — cette page bloque l'accès aux extensions."
|
||||
"message": "Impossible de découper ici : cette page bloque l'accès aux extensions."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Veuillez d'abord vous connecter à Memento dans ce navigateur."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Impossible de charger les carnets. Essayez de vous reconnecter."
|
||||
"message": "Impossible de charger les blocs-notes. Essayez de vous reconnecter."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Carnets chargés"
|
||||
@@ -123,22 +123,22 @@
|
||||
"message": "Enregistrer dans Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Retour"
|
||||
"message": "Dos"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analyse de la source"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analyse…"
|
||||
"message": "Analyser…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Enregistrement…"
|
||||
"message": "Économie…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Génération automatique des tags, résumé sémantique et calcul des embeddings."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Note enregistrée"
|
||||
"message": "Remarque enregistrée"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Enregistré dans $NOTEBOOK$",
|
||||
@@ -165,7 +165,7 @@
|
||||
"message": "Réessayer"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Sélectionnez d'abord du texte, ou clippez la page entière."
|
||||
"message": "Sélectionnez d’abord le texte ou coupez la page entière."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Impossible d'analyser cette page."
|
||||
@@ -177,6 +177,6 @@
|
||||
"message": "Problème de réseau : vérifiez votre connexion et l'URL Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Surlignez le texte à clipper"
|
||||
"message": "Mettez en surbrillance le texte sur la page ou coupez la page entière."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
/** Service worker — ouvre le panneau latéral au clic sur l’icône. */
|
||||
chrome.runtime.onInstalled.addListener(() => {
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
})
|
||||
/** Service worker — ouvre le panneau latéral (Chrome Side Panel ou Firefox sidebar) au clic sur l'icône. */
|
||||
const extApi = (typeof browser !== 'undefined' && browser.sidebarAction) ? browser : chrome
|
||||
|
||||
chrome.runtime.onStartup.addListener(() => {
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
// Chrome MV3 : Side Panel API
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
} else if (extApi.sidebarAction?.open) {
|
||||
// Firefox MV3 : sidebarAction
|
||||
extApi.action?.onClicked?.addListener?.(() => {
|
||||
extApi.sidebarAction.open().catch(() => {})
|
||||
})
|
||||
}
|
||||
|
||||
extApi.runtime?.onInstalled?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
extApi.runtime?.onStartup?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Script de diagnostic pour l'extension Memento
|
||||
* Vérifie tous les fichiers et identifie les problèmes potentiels
|
||||
*/
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const extDir = __dirname
|
||||
|
||||
console.log('🔍 Diagnostic Extension Memento\n')
|
||||
|
||||
const issues = []
|
||||
const warnings = []
|
||||
|
||||
// Vérifier la syntaxe des fichiers JS
|
||||
function checkSyntax(filePath) {
|
||||
try {
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
// Pas de vérification syntaxique simple en Node.js sans eval
|
||||
// On vérifie juste que le fichier est lisible
|
||||
return true
|
||||
} catch (error) {
|
||||
issues.push(`Fichier illisible: ${filePath} - ${error.message}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier les event handlers inline dans le HTML
|
||||
function checkInlineHandlers(htmlPath) {
|
||||
try {
|
||||
const content = fs.readFileSync(htmlPath, 'utf8')
|
||||
const inlineHandlers = []
|
||||
|
||||
if (content.match(/onerror=/i)) inlineHandlers.push('onerror')
|
||||
if (content.match(/onclick=/i)) inlineHandlers.push('onclick')
|
||||
if (content.match(/onload=/i)) inlineHandlers.push('onload')
|
||||
|
||||
if (inlineHandlers.length > 0) {
|
||||
issues.push(`Event handlers inline trouvés dans ${htmlPath}: ${inlineHandlers.join(', ')}`)
|
||||
} else {
|
||||
console.log('✓ Pas d\'event handlers inline dans le HTML')
|
||||
}
|
||||
} catch (error) {
|
||||
issues.push(`Impossible de lire ${htmlPath}: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier les fixes CSP dans sidepanel.js
|
||||
function checkCSPFixes(jsPath) {
|
||||
try {
|
||||
const content = fs.readFileSync(jsPath, 'utf8')
|
||||
|
||||
// Vérifier l'absence de onerror inline
|
||||
if (content.match(/onerror=/)) {
|
||||
issues.push('Event handler onerror trouvé dans sidepanel.js')
|
||||
} else {
|
||||
console.log('✓ Pas de onerror inline dans sidepanel.js')
|
||||
}
|
||||
|
||||
// Vérifier la présence du fix avec data-fallback
|
||||
if (content.includes('data-fallback')) {
|
||||
console.log('✓ Fix CSP data-favicon présent')
|
||||
} else {
|
||||
warnings.push('Fix CSP data-favicon可能缺失')
|
||||
}
|
||||
|
||||
// Vérifier le handler de favicon
|
||||
if (content.includes("querySelector('.page-favicon')")) {
|
||||
console.log('✓ Handler error pour favicon présent')
|
||||
} else {
|
||||
warnings.push('Handler error pour favicon可能缺失')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
issues.push(`Impossible de lire ${jsPath}: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier le fix pick mode
|
||||
function checkPickModeFix(jsPath) {
|
||||
try {
|
||||
const content = fs.readFileSync(jsPath, 'utf8')
|
||||
|
||||
// Vérifier le handler visibilitychange
|
||||
if (content.includes('visibilityState === \'hidden\'')) {
|
||||
console.log('✓ Handler visibilitychange pour hidden présent')
|
||||
} else {
|
||||
issues.push('Handler visibilitychange pour hidden manquant')
|
||||
}
|
||||
|
||||
// Vérifier l'appel à setPickModeOnTab(false)
|
||||
if (content.match(/visibilityState === 'hidden'.*setPickModeOnTab\(false\)/s)) {
|
||||
console.log('✓ Appel setPickModeOnTab(false) dans visibilitychange présent')
|
||||
} else {
|
||||
issues.push('Appel setPickModeOnTab(false) dans visibilitychange可能缺失')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
issues.push(`Impossible de lire ${jsPath}: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier le manifest
|
||||
function checkManifest(manifestPath) {
|
||||
try {
|
||||
const content = fs.readFileSync(manifestPath, 'utf8')
|
||||
const manifest = JSON.parse(content)
|
||||
|
||||
console.log('✓ Manifest.json valide')
|
||||
console.log(` Version: ${manifest.version}`)
|
||||
console.log(` Permissions: ${manifest.permissions.join(', ')}`)
|
||||
console.log(` Host permissions: ${manifest.host_permissions.length}`)
|
||||
|
||||
} catch (error) {
|
||||
issues.push(`Manifest.json invalide: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Exécuter les tests
|
||||
console.log('📋 Vérification des fichiers...\n')
|
||||
|
||||
checkSyntax(path.join(extDir, 'sidepanel.js'))
|
||||
checkSyntax(path.join(extDir, 'content.js'))
|
||||
checkSyntax(path.join(extDir, 'background.js'))
|
||||
|
||||
console.log('\n🔒 Vérification CSP...\n')
|
||||
checkInlineHandlers(path.join(extDir, 'sidepanel.html'))
|
||||
checkCSPFixes(path.join(extDir, 'sidepanel.js'))
|
||||
|
||||
console.log('\n🎯 Vérification fix pick mode...\n')
|
||||
checkPickModeFix(path.join(extDir, 'sidepanel.js'))
|
||||
|
||||
console.log('\n📦 Vérification manifest...\n')
|
||||
checkManifest(path.join(extDir, 'manifest.json'))
|
||||
|
||||
// Résumé
|
||||
console.log('\n' + '='.repeat(50))
|
||||
if (issues.length === 0 && warnings.length === 0) {
|
||||
console.log('✅ Aucun problème détecté !')
|
||||
} else {
|
||||
if (issues.length > 0) {
|
||||
console.log('\n❌ Problèmes détectés:')
|
||||
issues.forEach(issue => console.log(` • ${issue}`))
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
console.log('\n⚠️ Warnings:')
|
||||
warnings.forEach(warning => console.log(` • ${warning}`))
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n📝 Instructions:')
|
||||
console.log('1. Rechargez l\'extension dans chrome://extensions (bouton 🔄)')
|
||||
console.log('2. Ouvrez une page web normale')
|
||||
console.log('3. Cliquez sur l\'icône Memento')
|
||||
console.log('4. Fermez le sidepanel - la bannière doit disparaître')
|
||||
console.log('5. Ouvrez la console (F12) - pas d\'erreur CSP')
|
||||
@@ -1,215 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const zlib = require('zlib')
|
||||
|
||||
const VERSION = "0.3.1"
|
||||
|
||||
// Embedded Momento clipper/extension string table (gzip+base64).
|
||||
// Source English + contextual French anchors; other locales are MT batch
|
||||
// post-edited with placeholder hardening.
|
||||
|
||||
const PACK_B64 = `
|
||||
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
|
||||
wOW7jPkAAA==
|
||||
`
|
||||
|
||||
function loadStrings () {
|
||||
const buf = Buffer.from(PACK_B64.replace(/\s+/g, ''), 'base64')
|
||||
return JSON.parse(zlib.gunzipSync(buf).toString('utf8'))
|
||||
}
|
||||
|
||||
function main () {
|
||||
const STRINGS = loadStrings()
|
||||
const payload = {
|
||||
version: VERSION,
|
||||
strings: STRINGS,
|
||||
}
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, 'translations.json'),
|
||||
JSON.stringify(payload, null, 2) + "\n",
|
||||
'utf8'
|
||||
)
|
||||
console.log('Wrote', path.join(__dirname, 'translations.json'))
|
||||
}
|
||||
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "__MSG_extName__",
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"description": "__MSG_extDescription__",
|
||||
"default_locale": "en",
|
||||
"permissions": [
|
||||
|
||||
Binary file not shown.
@@ -3,6 +3,12 @@ const ALLOW_INSTANCE_CONFIG = false
|
||||
const DEFAULT_BASE = 'https://memento-note.com'
|
||||
const STORAGE_KEYS = { baseUrl: 'memento_clipper_base_url', notebookId: 'memento_clipper_notebook_id' }
|
||||
|
||||
/** Compatibilité Chrome/Firefox : Firefox expose l'API sous `browser.*`,
|
||||
* Chrome sous `chrome.*`. On normalise pour utiliser `chrome.*` partout dans le code. */
|
||||
if (typeof chrome === 'undefined' && typeof browser !== 'undefined') {
|
||||
globalThis.chrome = browser
|
||||
}
|
||||
|
||||
let state = 'idle'
|
||||
let notebooks = []
|
||||
let selectedNotebookId = ''
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test Sidepanel</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; padding: 20px; }
|
||||
.error { color: red; }
|
||||
.success { color: green; }
|
||||
pre { background: #f5f5f5; padding: 10px; overflow-x: auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test Extension Memento</h1>
|
||||
<div id="results"></div>
|
||||
|
||||
<script>
|
||||
const results = document.getElementById('results');
|
||||
|
||||
function log(message, type = 'info') {
|
||||
const div = document.createElement('div');
|
||||
div.className = type;
|
||||
div.textContent = message;
|
||||
results.appendChild(div);
|
||||
}
|
||||
|
||||
function testFile(filename) {
|
||||
return fetch(filename)
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
return response.text();
|
||||
})
|
||||
.then(content => {
|
||||
log(`✓ ${filename} chargé (${content.length} bytes)`, 'success');
|
||||
return { filename, content };
|
||||
})
|
||||
.catch(error => {
|
||||
log(`✗ ${filename}: ${error.message}`, 'error');
|
||||
return { filename, error };
|
||||
});
|
||||
}
|
||||
|
||||
async function testSidepanelJS() {
|
||||
const script = document.createElement('script');
|
||||
script.src = 'sidepanel.js';
|
||||
script.onerror = () => log('✗ sidepanel.js: Erreur de chargement', 'error');
|
||||
script.onload = () => {
|
||||
log('✓ sidepanel.js chargé', 'success');
|
||||
// Check for CSP violations
|
||||
if (typeof chrome !== 'undefined') {
|
||||
log('✓ API chrome disponible', 'success');
|
||||
} else {
|
||||
log('✗ API chrome non disponible (normal hors extension)', 'error');
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
log('🧪 Début des tests...', 'info');
|
||||
|
||||
// Test file loading
|
||||
await Promise.all([
|
||||
testFile('sidepanel.html'),
|
||||
testFile('sidepanel.js'),
|
||||
testFile('content.js'),
|
||||
testFile('background.js'),
|
||||
testFile('manifest.json')
|
||||
]);
|
||||
|
||||
// Test sidepanel.js execution
|
||||
await testSidepanelJS();
|
||||
}
|
||||
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
182
memento-note/extension/dist-firefox/_locales/ar/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/ar/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "مومنتو ويب كليبر"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "التقط صفحات الويب والنص المميز في دفاتر ملاحظات Memento الخاصة بك - ويتصل بخادم Memento الخاص بك."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "مقطع إلى مومنتو"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "مقص الويب"
|
||||
},
|
||||
"connected": {
|
||||
"message": "متصل"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "غير متصل"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "عنوان URL لمومنتو"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "عنوان URL لمثيل Memento الخاص بك"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "إعداد مسبق للإنتاج · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "تطبيق وإعادة الاتصال"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "افتح مومنتو"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "الصق عنوان URL الخاص بـ HTTPS (أو LAN) لخادم Memento الخاص بك. تتعامل ملفات تعريف الارتباط الموجودة في هذا المتصفح مع تسجيل الدخول."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<الإصدار>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "لا يستطيع Memento الوصول إلى علامة التبويب هذه. تحقق من أذونات ملحق لوحة المفاتيح/الموقع — أو افتح اللوحة الجانبية."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "دفتر بلا عنوان"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "لا توجد دفاتر ملاحظات حتى الآن"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 دقيقة قراءة"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "تقريبا. $COUNT$ دقيقة قراءة",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "تم الكشف عن التحديد"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "يتجاهل"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "نصيحة: قم بتمييز النص الموجود على الصفحة لقص التحديد الدقيق كملاحظة."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "اختيار المقطع"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "قص هذه الصفحة"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "حفظ الرابط فقط"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "لا يمكن القص هنا — هذه الصفحة تحظر الوصول إلى الإضافات."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "يرجى تسجيل الدخول إلى Memento في هذا المتصفح أولاً."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "تعذر تحميل دفاتر الملاحظات. حاول إعادة الاتصال."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "تم تحميل دفاتر الملاحظات"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "جارٍ الاتصال…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "متصل بـ $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "صفحة مقيدة - قم بالقص عبر شريط أدوات Memento أو اللوحة الجانبية."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "دفتر الوجهة"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "صفحة نشطة"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "المراجعة قبل الحفظ"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "عنوان"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "مقتطفات"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "حفظ إلى مومنتو"
|
||||
},
|
||||
"back": {
|
||||
"message": "خلف"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "تحليل المصدر"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "جارٍ التحليل…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "توفير…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "إنشاء العلامات والملخص الدلالي والتضمينات."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "تم حفظ الملاحظة"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "تم الحفظ في $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "عرض في مومنتو"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "قص صفحة أخرى"
|
||||
},
|
||||
"failure": {
|
||||
"message": "لا يمكن إكماله"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "حدث خطأ ما أثناء الوصول إلى مثيل Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "أعد المحاولة"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "حدد النص أولاً، أو قم بقص الصفحة بأكملها."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "لا يمكن تحليل هذه الصفحة."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "لا يمكن حفظ ملاحظتك."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "مشكلة في الشبكة - تحقق من اتصالك وعنوان URL الخاص بـ Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "قم بتمييز النص الموجود على الصفحة، أو قم بقص الصفحة بأكملها."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/de/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/de/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Erfassen Sie Webseiten und hervorgehobenen Text in Ihren Memento-Notizbüchern – stellt eine Verbindung zu Ihrem eigenen Memento-Server her."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clip auf Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Web Clipper"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Verbunden"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Nicht verbunden"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "Memento-URL"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "Ihre Memento-Instanz-URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Produktionsvoreinstellung · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Anwenden und erneut verbinden"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Öffnen Sie Memento"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Fügen Sie die HTTPS- (oder LAN-)URL Ihres Memento-Servers ein. Cookies in diesem Browser verarbeiten die Anmeldung."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento kann nicht auf diese Registerkarte zugreifen. Überprüfen Sie die Tastatur-/Site-Erweiterungsberechtigungen – oder öffnen Sie den Seitenbereich."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Notizbuch ohne Titel"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Noch keine Notizbücher"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 Minute gelesen"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Ca. $COUNT$ min. gelesen",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Auswahl erkannt"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorieren"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Tipp: Markieren Sie Text auf der Seite, um eine präzise Auswahl als Notiz auszuschneiden."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Clip-Auswahl"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Clip diese Seite aus"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Nur Link speichern"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Hier kann kein Clip erstellt werden – diese Seite blockiert den Zugriff auf die Erweiterung."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Bitte melden Sie sich zunächst in diesem Browser bei Memento an."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Notebooks konnten nicht geladen werden. Versuchen Sie, die Verbindung wiederherzustellen."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Notizbücher geladen"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Verbinden…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Verbunden mit $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Eingeschränkte Seite – Ausschneiden über die Memento-Symbolleiste oder den Seitenbereich."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Zielnotizbuch"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Aktive Seite"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Vor dem Speichern überprüfen"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Titel"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Auszug"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "In Memento speichern"
|
||||
},
|
||||
"back": {
|
||||
"message": "Zurück"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Quelle analysieren"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analysieren…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Sparen…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Generieren von Tags, einer semantischen Zusammenfassung und Einbettungen."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Notiz gespeichert"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Gespeichert unter $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "In Memento ansehen"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Schneiden Sie eine weitere Seite aus"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Konnte nicht abgeschlossen werden"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Beim Erreichen Ihrer Memento-Instanz ist ein Fehler aufgetreten."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Wiederholen"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Wählen Sie zuerst den Text aus oder schneiden Sie die gesamte Seite aus."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Diese Seite konnte nicht analysiert werden."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Ihre Notiz konnte nicht gespeichert werden."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Netzwerkproblem – überprüfen Sie Ihre Verbindung und Memento-URL."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Markieren Sie Text auf der Seite oder schneiden Sie die gesamte Seite aus."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/en/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/en/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Capture web pages and highlighted text into your Memento notebooks — connects to your own Memento server."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clip to Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Web Clipper"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Connected"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Not connected"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "Memento URL"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "Your Memento instance URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Production preset · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Apply and reconnect"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Open Memento"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Paste the HTTPS (or LAN) URL of your Memento server. Cookies in this browser handle sign-in."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento can't access this tab. Check keyboard/site extension permissions — or open the Side Panel."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Untitled notebook"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "No notebooks yet"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minute read"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Approx. $COUNT$ min read",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Selection detected"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignore"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Tip: highlight text on the page to clip a precise selection as a note."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Clip selection"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Clip this page"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Save link only"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Can't clip here — this page blocks extension access."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Please sign in to Memento in this browser first."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Could not load notebooks. Try reconnecting."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Notebooks loaded"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Connecting…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Connected to $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Restricted page — clip via the Memento toolbar or Side Panel."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Destination notebook"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Active page"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Review before saving"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Title"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Excerpt"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Save to Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Back"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analyzing source"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analyzing…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Saving…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Generating tags, a semantic summary, and embeddings."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Note saved"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Saved to $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "View in Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Clip another page"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Could not complete"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Something went wrong reaching your Memento instance."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Retry"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Select text first, or clip the full page."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Could not analyze this page."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Could not save your note."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Network issue — check your connection and Memento URL."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Highlight text on the page, or clip the whole page."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/es/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/es/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Cortadora web Memento"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Capture páginas web y texto resaltado en sus cuadernos Memento: se conecta a su propio servidor Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clip al momento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Cortadora web"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Conectado"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "No conectado"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "URL del momento"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "La URL de tu instancia de Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Preajuste de producción · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Aplicar y reconectar"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Memento abierto"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Pegue la URL HTTPS (o LAN) de su servidor Memento. Las cookies en este navegador controlan el inicio de sesión."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<VERSIÓN>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento no puede acceder a esta pestaña. Verifique los permisos de extensión del sitio/teclado o abra el Panel lateral."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Cuaderno sin título"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Aún no hay cuadernos"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minuto de lectura"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Aprox. <<<CONTAR>>> lectura mínima (Approx. $COUNT$ min read)",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Selección detectada"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorar"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Consejo: resalte el texto en la página para recortar una selección precisa como nota."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Selección de clips"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Recortar esta página"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Guardar enlace solamente"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "No se puede recortar aquí: esta página bloquea el acceso a la extensión."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Primero inicie sesión en Memento en este navegador."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "No se pudieron cargar los cuadernos. Intente volver a conectarse."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Cuadernos cargados"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Conectando…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Conectado a $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Página restringida: recorte mediante la barra de herramientas de Memento o el panel lateral."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Cuaderno de destino"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Página activa"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Revisar antes de guardar"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Título"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Extracto"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Guardar en momento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Atrás"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analizando fuente"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analizando…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Ahorro…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Generación de etiquetas, resumen semántico e incrustaciones."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Nota guardada"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Guardado en $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Ver en momento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Recortar otra página"
|
||||
},
|
||||
"failure": {
|
||||
"message": "No se pudo completar"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Algo salió mal al llegar a tu instancia de Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Rever"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Seleccione el texto primero o recorte la página completa."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "No se pudo analizar esta página."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "No se pudo guardar tu nota."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Problema de red: verifique su conexión y la URL de Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Resalte el texto de la página o recorte toda la página."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/fa/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/fa/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "صفحات وب و متن هایلایت شده را در نوت بوک های Memento خود ضبط کنید — به سرور Memento خودتان متصل می شود."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "کلیپ به لحظه"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Web Clipper"
|
||||
},
|
||||
"connected": {
|
||||
"message": "متصل شد"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "متصل نیست"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "آدرس لحظه ای"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "URL نمونه Memento شما"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "پیش تنظیم تولید · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "درخواست کنید و دوباره وصل شوید"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Memento را باز کنید"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "URL HTTPS (یا LAN) سرور Memento خود را جایگذاری کنید. کوکیهای این مرورگر ورود به سیستم را کنترل میکنند."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento نمی تواند به این برگه دسترسی پیدا کند. مجوزهای افزونه صفحه کلید/سایت را بررسی کنید - یا پانل جانبی را باز کنید."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "دفترچه بدون عنوان"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "هنوز نوت بوک نیست"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~ 1 دقیقه مطالعه کنید"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "تقریبا $COUNT$ دقیقه خواندن",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "انتخاب شناسایی شد"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "نادیده گرفتن"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "نکته: متن را در صفحه برجسته کنید تا یک انتخاب دقیق به عنوان یادداشت بریده شود."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "انتخاب کلیپ"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "این صفحه را کلیپ کنید"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "فقط لینک را ذخیره کنید"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "در اینجا نمی توان کلیپ کرد - این صفحه دسترسی برنامه های افزودنی را مسدود می کند."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "لطفاً ابتدا با این مرورگر وارد Memento شوید."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "نوتبوکها بارگیری نشد. سعی کنید دوباره وصل شوید."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "نوت بوک ها بارگیری شدند"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "در حال اتصال…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "به $URL$ متصل شد",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "صفحه محدود - از طریق نوار ابزار Memento یا پانل جانبی کلیپ کنید."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "دفترچه یادداشت مقصد"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "صفحه فعال"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "قبل از ذخیره بررسی کنید"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "عنوان"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "گزیده"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "ذخیره در Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "برگشت"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "تجزیه و تحلیل منبع"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "در حال تجزیه و تحلیل…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "در حال ذخیره…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "تولید برچسب ها، خلاصه معنایی، و جاسازی ها."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "یادداشت ذخیره شد"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "در $NOTEBOOK$ ذخیره شد",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "مشاهده در Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "یک صفحه دیگر را کلیپ کنید"
|
||||
},
|
||||
"failure": {
|
||||
"message": "تکمیل نشد"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "هنگام رسیدن به نمونه Memento شما مشکلی پیش آمد."
|
||||
},
|
||||
"retry": {
|
||||
"message": "دوباره امتحان کنید"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "ابتدا متن را انتخاب کنید، یا صفحه کامل را کلیپ کنید."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "نمی توان این صفحه را تجزیه و تحلیل کرد."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "یادداشت شما ذخیره نشد."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "مشکل شبکه - اتصال و URL Memento خود را بررسی کنید."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "متن را در صفحه برجسته کنید یا کل صفحه را برش دهید."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/fr/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/fr/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento · Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Enregistrez des pages web et du texte surligné dans vos carnets Memento — connecté à votre propre serveur Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clipper vers Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Tondeuse Web"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Connecté"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Non connecté"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "Adresse Memento"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "URL de votre instance Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Préréglage production · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Appliquer et reconnecter"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Ouvrir Memento"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Collez l'URL HTTPS (ou LAN) de votre serveur Memento. Les cookies de ce navigateur gèrent la connexion."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper 0.4.0"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento ne peut pas accéder à cet onglet. Vérifiez les autorisations du clavier/extension de site – ou ouvrez le panneau latéral."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Carnet sans titre"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Pas encore de carnets"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "≈ 1 minute de lecture"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "≈ $COUNT$ minutes de lecture",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Sélection détectée"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorer"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Astuce : surlignez du texte à l’écran pour clipper une sélection précise de la page en tant que note."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Clipper la sélection"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Clipper cette page"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Enregistrer le lien uniquement"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Impossible de découper ici : cette page bloque l'accès aux extensions."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Veuillez d'abord vous connecter à Memento dans ce navigateur."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Impossible de charger les blocs-notes. Essayez de vous reconnecter."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Carnets chargés"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Connexion…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Connecté à $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Page restreinte : clip via la barre d'outils Memento ou le panneau latéral."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Carnet de destination"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Page active"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Vérifier avant d'enregistrer"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Titre"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Extrait"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Enregistrer dans Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Dos"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analyse de la source"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analyser…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Économie…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Génération automatique des tags, résumé sémantique et calcul des embeddings."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Remarque enregistrée"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Enregistré dans $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Voir dans Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Clipper une autre page"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Impossible de terminer"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Une erreur est survenue lors de la communication avec votre instance Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Réessayer"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Sélectionnez d’abord le texte ou coupez la page entière."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Impossible d'analyser cette page."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Impossible d'enregistrer votre note."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Problème de réseau : vérifiez votre connexion et l'URL Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Mettez en surbrillance le texte sur la page ou coupez la page entière."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/hi/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/hi/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "मोमेंटो वेब क्लिपर"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "अपने मोमेंटो नोटबुक में वेब पेज और हाइलाइट किए गए टेक्स्ट को कैप्चर करें - यह आपके अपने मोमेंटो सर्वर से जुड़ता है।"
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "मोमेंटो पर क्लिप करें"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "वेब क्लिपर"
|
||||
},
|
||||
"connected": {
|
||||
"message": "जुड़े हुए"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "जुड़े नहीं हैं"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "मोमेंटो यूआरएल"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "आपका मोमेंटो इंस्टेंस यूआरएल"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "प्रोडक्शन प्रीसेट · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "आवेदन करें और पुनः कनेक्ट करें"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "मोमेंटो खोलें"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "अपने मोमेंटो सर्वर का HTTPS (या LAN) URL चिपकाएँ। इस ब्राउज़र में कुकीज़ साइन-इन को संभालती हैं।"
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "मोमेंटो वेब क्लिपर <<<संस्करण>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "मोमेंटो इस टैब तक नहीं पहुंच सकता. कीबोर्ड/साइट एक्सटेंशन अनुमतियां जांचें - या साइड पैनल खोलें।"
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "शीर्षक रहित नोटबुक"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "अभी तक कोई नोटबुक नहीं"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 मिनट पढ़ें"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "लगभग। $COUNT$ मिनट पढ़ा",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "चयन का पता चला"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "अनदेखा करना"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "युक्ति: किसी सटीक चयन को नोट के रूप में क्लिप करने के लिए पृष्ठ पर टेक्स्ट को हाइलाइट करें।"
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "क्लिप चयन"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "इस पृष्ठ को क्लिप करें"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "केवल लिंक सहेजें"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "यहां क्लिप नहीं किया जा सकता - यह पेज एक्सटेंशन एक्सेस को ब्लॉक करता है।"
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "कृपया पहले इस ब्राउज़र में मोमेंटो में साइन इन करें।"
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "नोटबुक लोड नहीं हो सकीं. पुनः कनेक्ट करने का प्रयास करें."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "नोटबुक लोड किए गए"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "कनेक्ट हो रहा है..."
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "$URL$ से कनेक्ट किया गया",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "प्रतिबंधित पृष्ठ - मोमेंटो टूलबार या साइड पैनल के माध्यम से क्लिप करें।"
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "गंतव्य नोटबुक"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "सक्रिय पृष्ठ"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "सहेजने से पहले समीक्षा करें"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "शीर्षक"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "अंश"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "मोमेंटो में सहेजें"
|
||||
},
|
||||
"back": {
|
||||
"message": "पीछे"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "स्रोत का विश्लेषण"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "विश्लेषण कर रहा हूँ..."
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "सहेजा जा रहा है..."
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "टैग, सिमेंटिक सारांश और एम्बेडिंग तैयार करना।"
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "नोट सहेजा गया"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "$NOTEBOOK$ में सहेजा गया",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "मोमेंटो में देखें"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "दूसरे पेज को क्लिप करें"
|
||||
},
|
||||
"failure": {
|
||||
"message": "पूरा नहीं हो सका"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "आपके मोमेंटो इंस्टेंस तक पहुँचने में कुछ गड़बड़ी हुई।"
|
||||
},
|
||||
"retry": {
|
||||
"message": "पुन: प्रयास करें"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "पहले टेक्स्ट चुनें, या पूरा पेज क्लिप करें।"
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "इस पृष्ठ का विश्लेषण नहीं किया जा सका."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "आपका नोट सहेजा नहीं जा सका."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "नेटवर्क समस्या - अपना कनेक्शन और मोमेंटो यूआरएल जांचें।"
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "पृष्ठ पर टेक्स्ट को हाइलाइट करें, या पूरे पृष्ठ को क्लिप करें।"
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/it/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/it/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Cattura pagine web e testo evidenziato nei tuoi taccuini Memento: si connette al tuo server Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clip su Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Tagliatore di fotoricettore"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Collegato"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Non connesso"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "URL del momento"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "L'URL dell'istanza di Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Preimpostazione di produzione · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Applicare e riconnettersi"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Memento aperto"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Incolla l'URL HTTPS (o LAN) del tuo server Memento. I cookie in questo browser gestiscono l'accesso."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<VERSIONE>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento non può accedere a questa scheda. Controlla le autorizzazioni per tastiera/estensione del sito oppure apri il pannello laterale."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Taccuino senza titolo"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Nessun taccuino ancora"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minuto di lettura"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "ca. $COUNT$ min letto",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Selezione rilevata"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorare"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Suggerimento: evidenzia il testo sulla pagina per ritagliare una selezione precisa come nota."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Selezione clip"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Ritaglia questa pagina"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Salva solo il collegamento"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Impossibile ritagliare qui: questa pagina blocca l'accesso all'estensione."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Accedi prima a Memento in questo browser."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Impossibile caricare i taccuini. Prova a riconnetterti."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Taccuini caricati"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Connessione…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Connesso a $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Pagina limitata: ritaglia tramite la barra degli strumenti Memento o il pannello laterale."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Taccuino di destinazione"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Pagina attiva"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Rivedi prima di salvare"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Titolo"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Estratto"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Salva su Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Indietro"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analisi della fonte"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analizzando..."
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Risparmio…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Generazione di tag, riepilogo semantico e incorporamenti."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Nota salvata"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Salvato in $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Visualizza in Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Ritaglia un'altra pagina"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Impossibile completare"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Qualcosa è andato storto nel raggiungere la tua istanza Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Riprova"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Seleziona prima il testo o ritaglia l'intera pagina."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Impossibile analizzare questa pagina."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Impossibile salvare la nota."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Problema di rete: controlla la connessione e l'URL Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Evidenzia il testo sulla pagina o ritaglia l'intera pagina."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/ja/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/ja/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "モーメントウェブクリッパー"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Web ページとハイライトされたテキストを Memento ノートブックにキャプチャします。独自の Memento サーバーに接続します。"
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "モーメントにクリップ"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "ウェブクリッパー"
|
||||
},
|
||||
"connected": {
|
||||
"message": "接続済み"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "接続されていません"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "モーメントのURL"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "Memento インスタンスの URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "プロダクションプリセット・memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "適用して再接続する"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "モーメントを開く"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Memento サーバーの HTTPS (または LAN) URL を貼り付けます。このブラウザの Cookie がサインインを処理します。"
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web クリッパー <<<バージョン>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento はこのタブにアクセスできません。キーボード/サイト拡張機能の権限を確認するか、サイド パネルを開きます。"
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "無題のノート"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "まだノートはありません"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "約 1 分で読めます"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "約$COUNT$ 分読み取り",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "選択が検出されました"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "無視する"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "ヒント: ページ上のテキストをハイライト表示して、正確な選択範囲をメモとしてクリップします。"
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "クリップの選択"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "このページをクリップします"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "リンクのみを保存"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "ここではクリップできません — このページは拡張機能へのアクセスをブロックしています。"
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "まずこのブラウザで Memento にサインインしてください。"
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "ノートブックをロードできませんでした。再接続してみてください。"
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "ノートブックがロードされました"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "接続中…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "$URL$ に接続しました",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "制限されたページ — Memento ツールバーまたはサイド パネルを介してクリップします。"
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "宛先ノートブック"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "アクティブなページ"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "保存する前に確認してください"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "タイトル"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "抜粋"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "モーメントに保存"
|
||||
},
|
||||
"back": {
|
||||
"message": "戻る"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "ソースを分析中"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "分析中…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "保存中…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "タグ、意味の概要、および埋め込みを生成します。"
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "メモが保存されました"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "$NOTEBOOK$ に保存されました",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "モメントで見る"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "別のページをクリップする"
|
||||
},
|
||||
"failure": {
|
||||
"message": "完了できませんでした"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Memento インスタンスに到達する際に問題が発生しました。"
|
||||
},
|
||||
"retry": {
|
||||
"message": "リトライ"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "最初にテキストを選択するか、ページ全体をクリップします。"
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "このページを分析できませんでした。"
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "メモを保存できませんでした。"
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "ネットワークの問題 — 接続と Memento URL を確認してください。"
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "ページ上のテキストを強調表示するか、ページ全体をクリップします。"
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/ko/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/ko/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "모멘토 웹 클리퍼"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "웹 페이지와 강조 표시된 텍스트를 Memento 노트북에 캡처하여 자체 Memento 서버에 연결합니다."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "순간에 클립"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "웹 클리퍼"
|
||||
},
|
||||
"connected": {
|
||||
"message": "연결됨"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "연결되지 않음"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "모멘토 URL"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "귀하의 Memento 인스턴스 URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "프로덕션 프리셋 · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "적용하고 다시 연결하세요"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "모멘토 열기"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Memento 서버의 HTTPS(또는 LAN) URL을 붙여넣습니다. 이 브라우저의 쿠키는 로그인을 처리합니다."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<버전>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento는 이 탭에 접근할 수 없습니다. 키보드/사이트 확장 권한을 확인하거나 측면 패널을 엽니다."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "제목 없는 노트"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "아직 노트가 없습니다."
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1분 읽기"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "대략. $COUNT$분 읽음",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "선택 항목이 감지되었습니다."
|
||||
},
|
||||
"ignore": {
|
||||
"message": "무시하다"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "팁: 페이지의 텍스트를 강조 표시하여 정확한 선택 항목을 메모로 자릅니다."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "클립 선택"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "이 페이지 클립"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "링크만 저장"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "여기서 클립할 수 없습니다. 이 페이지는 확장 프로그램 액세스를 차단합니다."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "먼저 이 브라우저에서 Memento에 로그인하세요."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "노트북을 로드할 수 없습니다. 다시 연결해 보세요."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "노트북이 로드되었습니다."
|
||||
},
|
||||
"connecting": {
|
||||
"message": "연결 중…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "$URL$에 연결됨",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "제한된 페이지 — Memento 도구 모음 또는 측면 패널을 통해 클립합니다."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "대상 노트북"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "활성 페이지"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "저장하기 전에 검토하세요"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "제목"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "발췌"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "모멘토에 저장"
|
||||
},
|
||||
"back": {
|
||||
"message": "뒤쪽에"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "소스 분석 중"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "분석 중…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "절약…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "태그, 의미 요약 및 임베딩을 생성합니다."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "메모가 저장되었습니다."
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "$NOTEBOOK$에 저장됨",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Memento에서 보기"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "다른 페이지 자르기"
|
||||
},
|
||||
"failure": {
|
||||
"message": "완료할 수 없습니다."
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Memento 인스턴스에 연결하는 데 문제가 발생했습니다."
|
||||
},
|
||||
"retry": {
|
||||
"message": "다시 해 보다"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "먼저 텍스트를 선택하거나 전체 페이지를 자릅니다."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "이 페이지를 분석할 수 없습니다."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "메모를 저장할 수 없습니다."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "네트워크 문제 - 연결 및 Memento URL을 확인하세요."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "페이지의 텍스트를 강조 표시하거나 전체 페이지를 자릅니다."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/nl/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/nl/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Webclipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Leg webpagina's en gemarkeerde tekst vast in uw Memento-notebooks - maakt verbinding met uw eigen Memento-server."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clip naar Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Webclipper"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Aangesloten"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Niet verbonden"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "Memento-URL"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "Uw Memento-instantie-URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Productievoorinstelling · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Toepassen en opnieuw verbinden"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Memento openen"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Plak de HTTPS (of LAN) URL van uw Memento-server. Cookies in deze browser zorgen voor het inloggen."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<VERSIE>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento heeft geen toegang tot dit tabblad. Controleer de rechten voor toetsenbord-/site-extensies — of open het zijpaneel."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Naamloos notitieboekje"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Nog geen notitieboekjes"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minuut lezen"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Ongeveer. $COUNT$ min gelezen",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Selectie gedetecteerd"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "negeren"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Tip: markeer tekst op de pagina om een precieze selectie als notitie te knippen."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Clipselectie"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Knip deze pagina uit"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Alleen link opslaan"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Kan hier niet knippen: deze pagina blokkeert de toegang tot extensies."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Meld u eerst aan bij Memento in deze browser."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Kan notitieboekjes niet laden. Probeer opnieuw verbinding te maken."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Notitieboekjes geladen"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Verbinden…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Verbonden met $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Beperkte pagina — clip via de Memento-werkbalk of het zijpaneel."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Bestemmingsnotitieboekje"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Actieve pagina"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Controleer voordat u opslaat"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Titel"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Uittreksel"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Opslaan in Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Rug"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Bron analyseren"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analyseren…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Besparing…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Tags, een semantische samenvatting en insluitingen genereren."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Notitie opgeslagen"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Opgeslagen in $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Bekijk in Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Knip nog een pagina uit"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Kon niet voltooien"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Er is iets misgegaan bij het bereiken van uw Memento-instantie."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Opnieuw proberen"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Selecteer eerst tekst of knip de volledige pagina uit."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Kan deze pagina niet analyseren."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Kan uw notitie niet opslaan."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Netwerkprobleem: controleer uw verbinding en Memento-URL."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Markeer tekst op de pagina of knip de hele pagina uit."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/pl/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/pl/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Narzędzie do strzyżenia sieci Memento"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Przechwytuj strony internetowe i zaznaczony tekst do swoich notatników Memento — łączy się z Twoim własnym serwerem Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Klip do Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Obcinacz sieci"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Połączony"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Nie podłączony"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "Adres URL chwili"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "Adres URL Twojej instancji Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Wstępne ustawienia produkcyjne · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Zastosuj i połącz ponownie"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Otwórz Memento"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Wklej adres URL HTTPS (lub LAN) swojego serwera Memento. Pliki cookie w tej przeglądarce obsługują logowanie."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<WERSJA>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento nie ma dostępu do tej karty. Sprawdź uprawnienia rozszerzenia klawiatury/witryny — lub otwórz Panel boczny."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Notatnik bez tytułu"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Nie ma jeszcze żadnych notatników"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minuta czytania"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Około. $COUNT$ min odczytu",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Wykryto wybór"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorować"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Wskazówka: zaznacz tekst na stronie, aby wyciąć dokładne zaznaczenie jako notatkę."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Wybór klipu"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Przytnij tę stronę"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Zapisz tylko link"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Nie można tutaj przyciąć — ta strona blokuje dostęp do rozszerzenia."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Najpierw zaloguj się do Memento w tej przeglądarce."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Nie udało się załadować notatników. Spróbuj połączyć się ponownie."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Notatniki załadowane"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Złączony…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Połączono z $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Strona z ograniczeniami — klip za pomocą paska narzędzi Memento lub panelu bocznego."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Notatnik docelowy"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Aktywna strona"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Przejrzyj przed zapisaniem"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Tytuł"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Fragment"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Zapisz w Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Z powrotem"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analizowanie źródła"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analizuję…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Oszczędność…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Generowanie tagów, podsumowań semantycznych i osadzania."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Uwaga zapisana"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Zapisano w $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Zobacz w Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Wytnij kolejną stronę"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Nie udało się ukończyć"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Coś poszło nie tak podczas docierania do Twojej instancji Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Spróbować ponownie"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Najpierw zaznacz tekst lub wytnij całą stronę."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Nie można przeanalizować tej strony."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Nie można zapisać notatki."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Problem z siecią — sprawdź swoje połączenie i adres URL Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Zaznacz tekst na stronie lub przytnij całą stronę."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/pt/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/pt/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento Web Clipper"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Capture páginas da web e texto destacado em seus blocos de anotações Memento – conecte-se ao seu próprio servidor Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Clipe para Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Clipper da Web"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Conectado"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Não conectado"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "URL do momento"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "URL da sua instância do Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Predefinição de produção · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Aplicar e reconectar"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Memento aberto"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Cole o URL HTTPS (ou LAN) do seu servidor Memento. Os cookies neste navegador controlam o login."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<VERSÃO>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento não pode acessar esta guia. Verifique as permissões de extensão de teclado/site – ou abra o painel lateral."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Caderno sem título"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Ainda não há cadernos"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 minuto de leitura"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Aprox. $COUNT$ minutos de leitura",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Seleção detectada"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "ignorar"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Dica: destaque o texto na página para recortar uma seleção precisa como uma nota."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Seleção de clipe"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Recorte esta página"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Salvar apenas link"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Não é possível recortar aqui – esta página bloqueia o acesso à extensão."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Faça login no Memento neste navegador primeiro."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Não foi possível carregar os notebooks. Tente reconectar."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Cadernos carregados"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Conectando…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Conectado a $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Página restrita – recorte por meio da barra de ferramentas do Memento ou do painel lateral."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Caderno de destino"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Página ativa"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Revise antes de salvar"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Título"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Trecho"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Salvar no Memento"
|
||||
},
|
||||
"back": {
|
||||
"message": "Voltar"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Analisando fonte"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Analisando…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Salvando…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Geração de tags, resumo semântico e incorporações."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Nota salva"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Salvo em $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Ver em Memento"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Recortar outra página"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Não foi possível concluir"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Algo deu errado ao chegar à sua instância do Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Tentar novamente"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Selecione o texto primeiro ou recorte a página inteira."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Não foi possível analisar esta página."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Não foi possível salvar sua nota."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Problema de rede – verifique sua conexão e URL do Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Destaque o texto na página ou recorte a página inteira."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/ru/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/ru/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Веб-клипер Memento"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Сохраняйте веб-страницы и выделенный текст в свои блокноты Memento — подключайтесь к вашему собственному серверу Memento."
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "Клип на Memento"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "Веб-клипер"
|
||||
},
|
||||
"connected": {
|
||||
"message": "Подключено"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "Не подключено"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "URL-адрес момента"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "URL-адрес вашего экземпляра Memento"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "Настройки производства · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "Подать заявку и повторно подключиться"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "Открыть Моменто"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "Вставьте URL-адрес HTTPS (или LAN) вашего сервера Memento. Файлы cookie в этом браузере обрабатывают вход в систему."
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<ВЕРСИЯ>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento не имеет доступа к этой вкладке. Проверьте разрешения для расширения клавиатуры/сайта или откройте боковую панель."
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "Блокнот без названия"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "Блокнотов пока нет"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "~1 минута чтения"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "Прибл. $COUNT$ мин чтения",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "Выбор обнаружен"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "игнорировать"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "Совет: выделите текст на странице, чтобы выделить его в виде заметки."
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "Выбор клипа"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "Вырезать эту страницу"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "Сохранить только ссылку"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "Невозможно обрезать здесь — эта страница блокирует доступ к расширению."
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "Сначала войдите в Memento в этом браузере."
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "Не удалось загрузить блокноты. Попробуйте переподключиться."
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "Ноутбуки загружены"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "Подключение…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "Подключено к $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "Страница с ограниченным доступом — вырезайте с помощью панели инструментов Memento или боковой панели."
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "Блокнот назначения"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "Активная страница"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "Проверьте перед сохранением"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "Заголовок"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "Отрывок"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "Сохранить в Моменто"
|
||||
},
|
||||
"back": {
|
||||
"message": "Назад"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "Анализ источника"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "Анализ…"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "Сохранение…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "Генерация тегов, семантического резюме и вложений."
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "Заметка сохранена."
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "Сохранено в $NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "Посмотреть в Моменто"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "Вырезать другую страницу"
|
||||
},
|
||||
"failure": {
|
||||
"message": "Не удалось завершить"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "Что-то пошло не так при получении вашего экземпляра Memento."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Повторить попытку"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "Сначала выделите текст или вырежьте всю страницу."
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "Не удалось проанализировать эту страницу."
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "Не удалось сохранить заметку."
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "Проблема с сетью. Проверьте подключение и URL-адрес Memento."
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "Выделите текст на странице или вырежьте всю страницу."
|
||||
}
|
||||
}
|
||||
182
memento-note/extension/dist-firefox/_locales/zh/messages.json
Normal file
182
memento-note/extension/dist-firefox/_locales/zh/messages.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Memento 网页剪辑器"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "将网页和突出显示的文本捕获到您的 Memento 笔记本中 — 连接到您自己的 Memento 服务器。"
|
||||
},
|
||||
"extActionTitle": {
|
||||
"message": "剪辑到时刻"
|
||||
},
|
||||
"webClipper": {
|
||||
"message": "网页剪辑器"
|
||||
},
|
||||
"connected": {
|
||||
"message": "已连接"
|
||||
},
|
||||
"disconnected": {
|
||||
"message": "未连接"
|
||||
},
|
||||
"instanceSettings": {
|
||||
"message": "时刻网址"
|
||||
},
|
||||
"instanceUrlLabel": {
|
||||
"message": "您的 Memento 实例 URL"
|
||||
},
|
||||
"presetProduction": {
|
||||
"message": "制作预设 · memento-note.com"
|
||||
},
|
||||
"applyReconnect": {
|
||||
"message": "应用并重新连接"
|
||||
},
|
||||
"openMomento": {
|
||||
"message": "打开时刻"
|
||||
},
|
||||
"settingsHint": {
|
||||
"message": "粘贴 Memento 服务器的 HTTPS(或 LAN)URL。此浏览器中的 Cookie 处理登录。"
|
||||
},
|
||||
"footerVersion": {
|
||||
"message": "Memento Web Clipper <<<版本>>>"
|
||||
},
|
||||
"errPermissionDenied": {
|
||||
"message": "Memento 无法访问此选项卡。检查键盘/站点扩展权限 - 或打开侧面板。"
|
||||
},
|
||||
"notebookUnnamed": {
|
||||
"message": "无标题笔记本"
|
||||
},
|
||||
"noNotebooks": {
|
||||
"message": "还没有笔记本"
|
||||
},
|
||||
"readingTimeOne": {
|
||||
"message": "阅读约 1 分钟"
|
||||
},
|
||||
"readingTimeOther": {
|
||||
"message": "大约。 $COUNT$ 最少阅读次数",
|
||||
"placeholders": {
|
||||
"COUNT": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDetected": {
|
||||
"message": "检测到选择"
|
||||
},
|
||||
"ignore": {
|
||||
"message": "忽略"
|
||||
},
|
||||
"selectionHint": {
|
||||
"message": "提示:突出显示页面上的文本以将精确的选择剪辑为注释。"
|
||||
},
|
||||
"clipSelection": {
|
||||
"message": "剪辑选择"
|
||||
},
|
||||
"clipPage": {
|
||||
"message": "剪辑此页"
|
||||
},
|
||||
"saveLinkOnly": {
|
||||
"message": "仅保存链接"
|
||||
},
|
||||
"pageNotAccessible": {
|
||||
"message": "此处无法剪辑 — 此页面阻止扩展程序访问。"
|
||||
},
|
||||
"errLoginRequired": {
|
||||
"message": "请先在此浏览器中登录 Memento。"
|
||||
},
|
||||
"errLoadNotebooks": {
|
||||
"message": "无法加载笔记本。尝试重新连接。"
|
||||
},
|
||||
"notebooksLoaded": {
|
||||
"message": "笔记本已加载"
|
||||
},
|
||||
"connecting": {
|
||||
"message": "正在连接…"
|
||||
},
|
||||
"connectedToUrl": {
|
||||
"message": "连接到 $URL$",
|
||||
"placeholders": {
|
||||
"URL": {
|
||||
"content": "$1",
|
||||
"example": "https://memento-note.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restrictedPage": {
|
||||
"message": "受限页面 — 通过 Memento 工具栏或侧面板进行剪辑。"
|
||||
},
|
||||
"destinationNotebook": {
|
||||
"message": "目的地笔记本"
|
||||
},
|
||||
"activePage": {
|
||||
"message": "活动页面"
|
||||
},
|
||||
"previewBeforeSave": {
|
||||
"message": "保存前查看"
|
||||
},
|
||||
"noteTitleLabel": {
|
||||
"message": "标题"
|
||||
},
|
||||
"excerptLabel": {
|
||||
"message": "摘抄"
|
||||
},
|
||||
"saveToMomento": {
|
||||
"message": "保存到时刻"
|
||||
},
|
||||
"back": {
|
||||
"message": "后退"
|
||||
},
|
||||
"analyzingSource": {
|
||||
"message": "分析来源"
|
||||
},
|
||||
"statusAnalyzing": {
|
||||
"message": "正在分析……"
|
||||
},
|
||||
"statusSaving": {
|
||||
"message": "保存…"
|
||||
},
|
||||
"processingDetail": {
|
||||
"message": "生成标签、语义摘要和嵌入。"
|
||||
},
|
||||
"noteSaved": {
|
||||
"message": "注释已保存"
|
||||
},
|
||||
"sentToNotebook": {
|
||||
"message": "保存至$NOTEBOOK$",
|
||||
"placeholders": {
|
||||
"NOTEBOOK": {
|
||||
"content": "$1",
|
||||
"example": "Read later"
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewInMomento": {
|
||||
"message": "在 Memento 中查看"
|
||||
},
|
||||
"clipAnother": {
|
||||
"message": "剪辑另一页"
|
||||
},
|
||||
"failure": {
|
||||
"message": "无法完成"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "您的 Memento 实例出现问题。"
|
||||
},
|
||||
"retry": {
|
||||
"message": "重试"
|
||||
},
|
||||
"errNoSelection": {
|
||||
"message": "首先选择文本,或剪辑整个页面。"
|
||||
},
|
||||
"errAnalyzeFailed": {
|
||||
"message": "无法分析此页面。"
|
||||
},
|
||||
"errSaveFailed": {
|
||||
"message": "无法保存您的笔记。"
|
||||
},
|
||||
"errNetwork": {
|
||||
"message": "网络问题 — 检查您的连接和 Memento URL。"
|
||||
},
|
||||
"bannerPickText": {
|
||||
"message": "突出显示页面上的文本,或剪辑整个页面。"
|
||||
}
|
||||
}
|
||||
23
memento-note/extension/dist-firefox/background.js
Normal file
23
memento-note/extension/dist-firefox/background.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/** Service worker — ouvre le panneau latéral (Chrome Side Panel ou Firefox sidebar) au clic sur l'icône. */
|
||||
const extApi = (typeof browser !== 'undefined' && browser.sidebarAction) ? browser : chrome
|
||||
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
// Chrome MV3 : Side Panel API
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
} else if (extApi.sidebarAction?.open) {
|
||||
// Firefox MV3 : sidebarAction
|
||||
extApi.action?.onClicked?.addListener?.(() => {
|
||||
extApi.sidebarAction.open().catch(() => {})
|
||||
})
|
||||
}
|
||||
|
||||
extApi.runtime?.onInstalled?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
extApi.runtime?.onStartup?.addListener?.(() => {
|
||||
if (extApi.sidePanel?.setPanelBehavior) {
|
||||
extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
}
|
||||
})
|
||||
211
memento-note/extension/dist-firefox/content.js
Normal file
211
memento-note/extension/dist-firefox/content.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Content script Memento — sélection live, surlignage, communication avec le side panel.
|
||||
* Injecté automatiquement sur http(s) ; ré-injecté à la demande si l’onglet était déjà ouvert.
|
||||
*/
|
||||
;(function initMementoClipperContent() {
|
||||
if (globalThis.__mementoClipperContent) return
|
||||
globalThis.__mementoClipperContent = true
|
||||
|
||||
const HIGHLIGHT_ID = 'memento-clipper-highlight-root'
|
||||
const BANNER_ID = 'memento-clipper-banner-root'
|
||||
const STYLE_ID = 'memento-clipper-styles'
|
||||
|
||||
let pickMode = false
|
||||
let debounceTimer = null
|
||||
|
||||
function getSelectionText() {
|
||||
return window.getSelection()?.toString().trim() || ''
|
||||
}
|
||||
|
||||
function getPageMeta() {
|
||||
const dir =
|
||||
document.documentElement.getAttribute('dir') ||
|
||||
document.body?.getAttribute('dir') ||
|
||||
''
|
||||
const lang = (
|
||||
document.documentElement.getAttribute('lang') ||
|
||||
document.body?.getAttribute('lang') ||
|
||||
''
|
||||
).split('-')[0]
|
||||
return {
|
||||
text: getSelectionText(),
|
||||
dir,
|
||||
lang,
|
||||
url: location.href,
|
||||
title: document.title,
|
||||
}
|
||||
}
|
||||
|
||||
function broadcastSelection() {
|
||||
clearTimeout(debounceTimer)
|
||||
debounceTimer = setTimeout(() => {
|
||||
const payload = { type: 'SELECTION_CHANGED', ...getPageMeta() }
|
||||
try {
|
||||
chrome.runtime.sendMessage(payload).catch(() => {})
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
if (pickMode) paintHighlight()
|
||||
}, 80)
|
||||
}
|
||||
|
||||
function removeHighlight() {
|
||||
document.getElementById(HIGHLIGHT_ID)?.remove()
|
||||
}
|
||||
|
||||
function paintHighlight() {
|
||||
removeHighlight()
|
||||
const sel = window.getSelection()
|
||||
if (!sel || sel.isCollapsed || !sel.rangeCount) return
|
||||
|
||||
let range
|
||||
try {
|
||||
range = sel.getRangeAt(0)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
const host = document.createElement('div')
|
||||
host.id = HIGHLIGHT_ID
|
||||
host.setAttribute('aria-hidden', 'true')
|
||||
host.style.cssText =
|
||||
'position:fixed;inset:0;pointer-events:none;z-index:2147483644;overflow:hidden;'
|
||||
|
||||
for (const rect of range.getClientRects()) {
|
||||
if (rect.width < 2 || rect.height < 2) continue
|
||||
const box = document.createElement('div')
|
||||
box.style.cssText = [
|
||||
'position:fixed',
|
||||
`left:${rect.left - 2}px`,
|
||||
`top:${rect.top - 1}px`,
|
||||
`width:${rect.width + 4}px`,
|
||||
`height:${rect.height + 2}px`,
|
||||
'background:rgba(164,113,72,0.28)',
|
||||
'border-radius:3px',
|
||||
'box-shadow:0 0 0 1px rgba(164,113,72,0.35)',
|
||||
'transition:opacity 0.15s ease',
|
||||
].join(';')
|
||||
host.appendChild(box)
|
||||
}
|
||||
|
||||
if (host.childNodes.length) document.documentElement.appendChild(host)
|
||||
}
|
||||
|
||||
function ensureStyles() {
|
||||
if (document.getElementById(STYLE_ID)) return
|
||||
const style = document.createElement('style')
|
||||
style.id = STYLE_ID
|
||||
style.textContent = `
|
||||
html.memento-clipper-pick ::selection {
|
||||
background: rgba(164, 113, 72, 0.45) !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
html.memento-clipper-pick {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
`
|
||||
document.documentElement.appendChild(style)
|
||||
}
|
||||
|
||||
function removeBanner() {
|
||||
document.getElementById(BANNER_ID)?.remove()
|
||||
}
|
||||
|
||||
function ensureBanner() {
|
||||
if (document.getElementById(BANNER_ID)) return
|
||||
|
||||
const bannerText =
|
||||
(typeof chrome !== 'undefined' && chrome.i18n?.getMessage?.('bannerPickText')) ||
|
||||
'Highlight the text to clip'
|
||||
|
||||
const host = document.createElement('div')
|
||||
host.id = BANNER_ID
|
||||
host.style.cssText =
|
||||
'all:initial;position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:2147483647;pointer-events:none;font-family:Inter,system-ui,sans-serif;'
|
||||
|
||||
const shadow = host.attachShadow({ mode: 'open' })
|
||||
shadow.innerHTML = `
|
||||
<style>
|
||||
.pill {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 18px; border-radius: 999px;
|
||||
background: #1c1c1c; color: #faf9f5;
|
||||
box-shadow: 0 12px 32px rgba(0,0,0,0.22);
|
||||
font-size: 12px; font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
animation: slideIn 0.35s cubic-bezier(0.22,1,0.36,1);
|
||||
}
|
||||
.logo {
|
||||
width: 22px; height: 22px; border-radius: 7px;
|
||||
background: #faf9f5; color: #1c1c1c;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-family: Georgia, serif; font-weight: 900; font-size: 12px;
|
||||
}
|
||||
.dot {
|
||||
width: 8px; height: 8px; border-radius: 50%;
|
||||
background: #a47148; animation: pulse 1.2s ease infinite;
|
||||
}
|
||||
@keyframes slideIn {
|
||||
from { opacity: 0; transform: translateY(-8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.5; transform: scale(0.85); }
|
||||
}
|
||||
</style>
|
||||
<div class="pill">
|
||||
<span class="logo">M</span>
|
||||
<span class="dot"></span>
|
||||
<span>${bannerText.replace(/</g, '<')}</span>
|
||||
</div>
|
||||
`
|
||||
document.documentElement.appendChild(host)
|
||||
}
|
||||
|
||||
function setPickMode(enabled) {
|
||||
pickMode = !!enabled
|
||||
ensureStyles()
|
||||
if (pickMode) {
|
||||
document.documentElement.classList.add('memento-clipper-pick')
|
||||
ensureBanner()
|
||||
paintHighlight()
|
||||
} else {
|
||||
document.documentElement.classList.remove('memento-clipper-pick')
|
||||
removeBanner()
|
||||
removeHighlight()
|
||||
}
|
||||
}
|
||||
|
||||
function onScrollOrResize() {
|
||||
if (pickMode) paintHighlight()
|
||||
}
|
||||
|
||||
document.addEventListener('selectionchange', broadcastSelection)
|
||||
document.addEventListener('mouseup', broadcastSelection)
|
||||
document.addEventListener('keyup', broadcastSelection)
|
||||
window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true })
|
||||
window.addEventListener('resize', onScrollOrResize, { passive: true })
|
||||
|
||||
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
if (message?.type === 'PING') {
|
||||
sendResponse({ ok: true })
|
||||
return true
|
||||
}
|
||||
if (message?.type === 'GET_CONTEXT') {
|
||||
sendResponse({
|
||||
html: document.documentElement.outerHTML,
|
||||
...getPageMeta(),
|
||||
})
|
||||
return true
|
||||
}
|
||||
if (message?.type === 'SET_PICK_MODE') {
|
||||
setPickMode(!!message.enabled)
|
||||
sendResponse({ ok: true, pickMode })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
broadcastSelection()
|
||||
})()
|
||||
47
memento-note/extension/dist-firefox/i18n.js
Normal file
47
memento-note/extension/dist-firefox/i18n.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/** Helpers i18n — langue UI Chrome (chrome.i18n.getUILanguage). */
|
||||
function t(key, ...subs) {
|
||||
const msg = chrome.i18n.getMessage(key, subs)
|
||||
return msg || key
|
||||
}
|
||||
|
||||
function uiLocaleTag() {
|
||||
return (chrome.i18n.getUILanguage() || 'en').replace('_', '-').split('-')[0]
|
||||
}
|
||||
|
||||
function isUiRtl() {
|
||||
return ['ar', 'fa', 'he', 'ur'].includes(uiLocaleTag())
|
||||
}
|
||||
|
||||
function applyDocumentLocale() {
|
||||
const lang = uiLocaleTag()
|
||||
document.documentElement.lang = lang
|
||||
document.documentElement.dir = isUiRtl() ? 'rtl' : 'ltr'
|
||||
document.body?.classList.toggle('ui-rtl', isUiRtl())
|
||||
}
|
||||
|
||||
function applyShellI18n() {
|
||||
document.title = t('extName')
|
||||
const brandSub = document.querySelector('.brand-sub')
|
||||
if (brandSub) brandSub.textContent = t('webClipper')
|
||||
if (typeof els !== 'undefined' && els.connLabel) {
|
||||
els.connLabel.textContent = t('connected')
|
||||
}
|
||||
if (typeof els !== 'undefined' && els.settingsBtn) {
|
||||
els.settingsBtn.title = t('instanceSettings')
|
||||
els.settingsBtn.setAttribute('aria-label', t('instanceSettings'))
|
||||
}
|
||||
const urlLabel = document.getElementById('instanceUrlLabel') || document.querySelector('#settingsPanel .field > span')
|
||||
if (urlLabel) urlLabel.textContent = t('instanceUrlLabel')
|
||||
const presetProd = document.querySelector('[data-url="https://memento-note.com"]')
|
||||
if (presetProd) presetProd.textContent = t('presetProduction')
|
||||
if (typeof els !== 'undefined' && els.applyInstanceBtn) {
|
||||
els.applyInstanceBtn.textContent = t('applyReconnect')
|
||||
}
|
||||
if (typeof els !== 'undefined' && els.openLoginBtn) {
|
||||
els.openLoginBtn.textContent = `${t('openMomento')} ↗`
|
||||
}
|
||||
const hint = document.querySelector('.settings-hint')
|
||||
if (hint) hint.textContent = t('settingsHint')
|
||||
const footer = document.querySelector('.footer-meta')
|
||||
if (footer) footer.textContent = t('footerVersion')
|
||||
}
|
||||
BIN
memento-note/extension/dist-firefox/icon-128.png
Normal file
BIN
memento-note/extension/dist-firefox/icon-128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
memento-note/extension/dist-firefox/icon-16.png
Normal file
BIN
memento-note/extension/dist-firefox/icon-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 236 B |
10
memento-note/extension/dist-firefox/icon-192.svg
Normal file
10
memento-note/extension/dist-firefox/icon-192.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192">
|
||||
<rect width="192" height="192" fill="#1C1C1C" rx="40"/>
|
||||
<g transform="translate(96,96)">
|
||||
<rect x="-34" y="-34" width="68" height="68" rx="5" fill="white"/>
|
||||
<path d="M34,34 L34,11 L11,34 Z" fill="#1C1C1C" opacity="0.28"/>
|
||||
<line x1="-23" y1="-17" x2="23" y2="-17" stroke="#e5e7eb" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="-23" y1="-4" x2="23" y2="-4" stroke="#e5e7eb" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="-23" y1="9" x2="11" y2="9" stroke="#e5e7eb" stroke-width="3" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 616 B |
BIN
memento-note/extension/dist-firefox/icon-48.png
Normal file
BIN
memento-note/extension/dist-firefox/icon-48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 587 B |
10
memento-note/extension/dist-firefox/icon-512.svg
Normal file
10
memento-note/extension/dist-firefox/icon-512.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" fill="#1C1C1C" rx="100"/>
|
||||
<g transform="translate(256,256)">
|
||||
<rect x="-90" y="-90" width="180" height="180" rx="12" fill="white"/>
|
||||
<path d="M90,90 L90,30 L30,90 Z" fill="#1C1C1C" opacity="0.28"/>
|
||||
<line x1="-60" y1="-45" x2="60" y2="-45" stroke="#e5e7eb" stroke-width="8" stroke-linecap="round"/>
|
||||
<line x1="-60" y1="-10" x2="60" y2="-10" stroke="#e5e7eb" stroke-width="8" stroke-linecap="round"/>
|
||||
<line x1="-60" y1="25" x2="30" y2="25" stroke="#e5e7eb" stroke-width="8" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 626 B |
65
memento-note/extension/dist-firefox/manifest.json
Normal file
65
memento-note/extension/dist-firefox/manifest.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "__MSG_extName__",
|
||||
"version": "0.4.0",
|
||||
"description": "__MSG_extDescription__",
|
||||
"default_locale": "en",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"scripting",
|
||||
"storage",
|
||||
"sidePanel",
|
||||
"tabs"
|
||||
],
|
||||
"host_permissions": [
|
||||
"https://memento-note.com/*",
|
||||
"https://www.memento-note.com/*"
|
||||
],
|
||||
"optional_host_permissions": [
|
||||
"https://*/*"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"sidebar_action": {
|
||||
"default_title": "__MSG_extActionTitle__",
|
||||
"default_panel": "sidepanel.html",
|
||||
"default_icon": {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "memento-clipper@memento-note.com",
|
||||
"strict_min_version": "115.0"
|
||||
}
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"https://memento-note.com/*",
|
||||
"https://www.memento-note.com/*"
|
||||
],
|
||||
"js": [
|
||||
"content.js"
|
||||
],
|
||||
"run_at": "document_idle",
|
||||
"all_frames": false
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"default_title": "__MSG_extActionTitle__",
|
||||
"default_icon": {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
}
|
||||
507
memento-note/extension/dist-firefox/sidepanel.css
Normal file
507
memento-note/extension/dist-firefox/sidepanel.css
Normal file
@@ -0,0 +1,507 @@
|
||||
:root {
|
||||
--ink: #1c1c1c;
|
||||
--paper: #faf9f5;
|
||||
--card: #ffffff;
|
||||
--muted: #6b7280;
|
||||
--border: #e8e4dc;
|
||||
--accent: #a47148;
|
||||
--accent-soft: rgba(164, 113, 72, 0.12);
|
||||
--accent-glow: rgba(164, 113, 72, 0.35);
|
||||
--success: #10b981;
|
||||
--danger: #ef4444;
|
||||
--shadow: 0 18px 40px rgba(28, 28, 28, 0.08);
|
||||
--radius: 14px;
|
||||
--radius-sm: 10px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
min-height: 100%;
|
||||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
font-size: 13px;
|
||||
color: var(--ink);
|
||||
background: var(--paper);
|
||||
}
|
||||
|
||||
.shell {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--paper);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 18px;
|
||||
background: linear-gradient(180deg, #fff 0%, #fcfcfa 100%);
|
||||
border-bottom: 1px solid var(--border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.brand { display: flex; align-items: center; gap: 10px; }
|
||||
.brand-logo {
|
||||
width: 34px; height: 34px; border-radius: 11px;
|
||||
background: var(--ink); color: #faf9f5;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-weight: 900; font-size: 16px;
|
||||
box-shadow: 0 4px 14px rgba(28, 28, 28, 0.18);
|
||||
}
|
||||
.brand-text { line-height: 1.1; }
|
||||
.brand-name {
|
||||
display: block; font-size: 14px; font-weight: 700;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
}
|
||||
.brand-sub {
|
||||
display: block; font-size: 9px; letter-spacing: 0.16em;
|
||||
text-transform: uppercase; color: var(--accent); font-weight: 700;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 34px; height: 34px; border-radius: 10px;
|
||||
border: 1px solid var(--border); background: #fff;
|
||||
color: var(--muted); cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
transition: border-color 0.15s, color 0.15s, background 0.15s;
|
||||
}
|
||||
.icon-btn:hover {
|
||||
border-color: var(--accent);
|
||||
color: var(--accent);
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.conn-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 9px;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--muted);
|
||||
}
|
||||
.conn-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #10b981;
|
||||
}
|
||||
|
||||
.settings-panel {
|
||||
padding: 14px 18px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.settings-panel[hidden] { display: none !important; }
|
||||
.settings-hint {
|
||||
margin: 8px 0 0;
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.settings-hint code {
|
||||
font-size: 10px;
|
||||
background: var(--paper);
|
||||
padding: 1px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.settings-status {
|
||||
margin: 10px 0 0;
|
||||
font-size: 11px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.settings-status.is-ok { color: #059669; }
|
||||
.settings-status.is-error { color: #dc2626; }
|
||||
|
||||
.preset-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.preset-btn {
|
||||
border: 1px solid var(--border);
|
||||
background: var(--paper);
|
||||
border-radius: 999px;
|
||||
padding: 6px 10px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
color: var(--muted);
|
||||
}
|
||||
.preset-btn:hover {
|
||||
border-color: var(--accent);
|
||||
color: var(--accent);
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
.settings-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.field { display: flex; flex-direction: column; gap: 6px; }
|
||||
.field span {
|
||||
font-size: 9px; text-transform: uppercase; letter-spacing: 0.12em;
|
||||
color: var(--muted); font-weight: 700;
|
||||
}
|
||||
input[type="url"],
|
||||
input[type="text"],
|
||||
.notebook-select {
|
||||
width: 100%; padding: 10px 12px; border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm); background: var(--paper);
|
||||
font-family: inherit; font-size: 12px;
|
||||
}
|
||||
input[type="url"]:focus,
|
||||
input[type="text"]:focus,
|
||||
.notebook-select:focus {
|
||||
outline: none; border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px var(--accent-soft);
|
||||
}
|
||||
.notebook-select {
|
||||
background: #fff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
padding: 16px 18px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.main > .actions {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 10px 18px 14px;
|
||||
border-top: 1px solid var(--border);
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
.footer-meta { font-size: 9px; color: #9ca3af; letter-spacing: 0.06em; }
|
||||
|
||||
.label {
|
||||
font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em;
|
||||
color: var(--muted); font-weight: 700; margin-bottom: 8px; display: block;
|
||||
}
|
||||
|
||||
.auth-hint {
|
||||
padding: 12px 14px;
|
||||
border-radius: var(--radius);
|
||||
background: #fffbeb;
|
||||
border: 1px solid #fde68a;
|
||||
font-size: 11px;
|
||||
color: #92400e;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.page-card {
|
||||
padding: 14px; border: 1px solid var(--border); border-radius: var(--radius);
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,0.8) inset;
|
||||
}
|
||||
.page-card .sub {
|
||||
font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em;
|
||||
color: var(--muted); font-weight: 700; display: block; margin-bottom: 8px;
|
||||
}
|
||||
.page-row { display: flex; gap: 10px; align-items: flex-start; min-width: 0; }
|
||||
.page-row img {
|
||||
width: 20px; height: 20px; border-radius: 5px;
|
||||
flex-shrink: 0; margin-top: 2px;
|
||||
}
|
||||
.page-text { min-width: 0; flex: 1; }
|
||||
.page-row .title {
|
||||
font-size: 12px; font-weight: 700; line-height: 1.45;
|
||||
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
.page-row .url {
|
||||
font-size: 10px; color: var(--muted); margin-top: 4px;
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
direction: ltr; text-align: left;
|
||||
}
|
||||
|
||||
.text-rtl {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
font-family: 'Vazirmatn', 'Inter', sans-serif;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
|
||||
.selection-panel {
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border);
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
min-height: 140px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.selection-panel.has-text {
|
||||
border-color: #bae6fd;
|
||||
background: rgba(14, 165, 233, 0.05);
|
||||
box-shadow: 0 0 0 1px rgba(14, 165, 233, 0.12);
|
||||
}
|
||||
.selection-hint {
|
||||
padding: 16px;
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: var(--radius);
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
}
|
||||
.selection-hint p {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.selection-head {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: 12px 14px;
|
||||
background: linear-gradient(180deg, #fff 0%, #fdfcfa 100%);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.selection-head .status {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
font-size: 10px; font-weight: 800; text-transform: uppercase;
|
||||
letter-spacing: 0.08em; color: var(--muted);
|
||||
}
|
||||
.selection-head .status.live { color: #0284c7; }
|
||||
.selection-head .count {
|
||||
font-size: 10px; font-weight: 700; color: var(--muted);
|
||||
background: var(--paper); padding: 4px 8px; border-radius: 999px;
|
||||
}
|
||||
.selection-head .count.active { color: var(--accent); background: var(--accent-soft); }
|
||||
|
||||
.selection-body {
|
||||
flex: 1;
|
||||
padding: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 1.75;
|
||||
color: rgba(28, 28, 28, 0.88);
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
unicode-bidi: plaintext;
|
||||
border-inline-start: 3px solid transparent;
|
||||
}
|
||||
.selection-panel.has-text .selection-body {
|
||||
border-inline-start-color: #38bdf8;
|
||||
padding-inline-start: 16px;
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.pulse-dot {
|
||||
width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
|
||||
animation: pulse 1.4s ease infinite;
|
||||
}
|
||||
.pulse-dot.sky { background: #0ea5e9; }
|
||||
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.4;transform:scale(.85)} }
|
||||
|
||||
.clear-btn {
|
||||
border: none; background: none; font-size: 10px;
|
||||
color: var(--muted); cursor: pointer; font-weight: 600;
|
||||
padding: 4px 6px; border-radius: 6px;
|
||||
}
|
||||
.clear-btn:hover { color: var(--ink); background: var(--paper); }
|
||||
|
||||
.actions {
|
||||
display: flex; flex-direction: column; gap: 10px;
|
||||
margin-top: auto; padding-top: 6px;
|
||||
}
|
||||
.btn {
|
||||
padding: 14px 16px; border-radius: var(--radius); border: none; cursor: pointer;
|
||||
font-weight: 700; font-size: 10px; text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
display: flex; align-items: center; justify-content: center; gap: 8px;
|
||||
transition: transform 0.12s ease, opacity 0.12s ease, filter 0.12s ease;
|
||||
}
|
||||
.btn:active { transform: scale(0.98); }
|
||||
.btn:disabled {
|
||||
opacity: 0.42; cursor: not-allowed; transform: none;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.btn-primary {
|
||||
background: var(--ink); color: #fff;
|
||||
box-shadow: 0 10px 24px rgba(28, 28, 28, 0.18);
|
||||
}
|
||||
.btn-primary:hover:not(:disabled) { opacity: 0.94; }
|
||||
.btn-sky {
|
||||
background: #0284c7;
|
||||
color: #fff;
|
||||
box-shadow: 0 10px 22px rgba(2, 132, 199, 0.22);
|
||||
}
|
||||
.btn-sky:hover:not(:disabled) { background: #0369a1; }
|
||||
.btn-secondary {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
box-shadow: none;
|
||||
}
|
||||
.btn-secondary:hover:not(:disabled) { background: #e5e7eb; }
|
||||
.btn-sm {
|
||||
padding: 10px 12px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.btn-danger { background: var(--danger); color: #fff; }
|
||||
.btn-link.link-only {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.btn-link {
|
||||
background: none; border: none; color: var(--muted); font-size: 11px;
|
||||
cursor: pointer; padding: 8px; font-weight: 500;
|
||||
}
|
||||
.btn-link:hover { color: var(--ink); text-decoration: underline; }
|
||||
.btn-icon { width: 14px; height: 14px; display: inline-flex; }
|
||||
|
||||
.center-state {
|
||||
flex: 1; display: flex; flex-direction: column; align-items: center;
|
||||
justify-content: center; text-align: center; gap: 14px; padding: 32px 12px;
|
||||
min-height: 280px;
|
||||
}
|
||||
.spinner-wrap { position: relative; width: 52px; height: 52px; }
|
||||
.spinner-ring {
|
||||
position: absolute; inset: 0; border-radius: 50%;
|
||||
border: 1px solid var(--border); animation: ping 1.2s ease infinite;
|
||||
}
|
||||
@keyframes ping { 0%{transform:scale(1);opacity:.6} 100%{transform:scale(1.35);opacity:0} }
|
||||
.spinner {
|
||||
position: absolute; inset: 6px;
|
||||
border: 3px solid var(--border); border-top-color: var(--accent);
|
||||
border-radius: 50%; animation: spin 0.75s linear infinite;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
.state-title {
|
||||
font-size: 10px; font-weight: 800; text-transform: uppercase;
|
||||
letter-spacing: 0.14em; color: var(--muted);
|
||||
}
|
||||
.state-sub { font-size: 15px; font-weight: 700; color: var(--ink); }
|
||||
.state-detail {
|
||||
font-size: 11px; color: var(--muted); max-width: 280px;
|
||||
line-height: 1.55; margin: 0 auto;
|
||||
}
|
||||
|
||||
.success-icon, .error-icon {
|
||||
width: 58px; height: 58px; border-radius: 50%;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 26px; font-weight: 700;
|
||||
}
|
||||
.success-icon {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border: 1px solid rgba(16, 185, 129, 0.25); color: var(--success);
|
||||
}
|
||||
.error-icon { background: #fef2f2; color: var(--danger); }
|
||||
|
||||
.badge-ok {
|
||||
display: inline-block; margin-bottom: 8px;
|
||||
font-size: 9px; background: rgba(16, 185, 129, 0.12);
|
||||
color: #059669; font-weight: 800; padding: 3px 8px; border-radius: 6px;
|
||||
text-transform: uppercase; letter-spacing: 0.1em;
|
||||
}
|
||||
.note-title {
|
||||
font-size: 15px; font-weight: 700;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
line-height: 1.35; margin-top: 6px;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
.tags {
|
||||
display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
|
||||
padding-top: 14px; border-top: 1px solid var(--border); margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
.tag-chip {
|
||||
font-size: 9px; font-weight: 800; text-transform: uppercase;
|
||||
letter-spacing: 0.06em; color: var(--accent);
|
||||
background: var(--accent-soft); border: 1px solid rgba(164, 113, 72, 0.2);
|
||||
padding: 5px 10px; border-radius: 999px;
|
||||
}
|
||||
|
||||
.restricted-note {
|
||||
padding: 14px; border-radius: var(--radius);
|
||||
background: #fef2f2; border: 1px solid #fecaca;
|
||||
font-size: 11px; color: #991b1b; line-height: 1.5;
|
||||
}
|
||||
|
||||
.confirm-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.summary-preview {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
line-height: 1.55;
|
||||
font-style: italic;
|
||||
}
|
||||
.excerpt-preview {
|
||||
padding: 12px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--border);
|
||||
background: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 1.65;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
.excerpt-label {
|
||||
display: block;
|
||||
font-size: 9px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--muted);
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.meta-row { margin-top: -4px; }
|
||||
.reading-time {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
.preview-tags { justify-content: flex-start; border-top: none; margin-top: 0; padding-top: 0; }
|
||||
|
||||
html[dir="rtl"] .header,
|
||||
html[dir="rtl"] .header-right,
|
||||
html[dir="rtl"] .selection-head,
|
||||
html[dir="rtl"] .page-row {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
html[dir="rtl"] .page-row .url {
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
}
|
||||
html[dir="rtl"] .notebook-select,
|
||||
html[dir="rtl"] .dropdown-item,
|
||||
html[dir="rtl"] .label,
|
||||
html[dir="rtl"] .sub {
|
||||
text-align: right;
|
||||
}
|
||||
60
memento-note/extension/dist-firefox/sidepanel.html
Normal file
60
memento-note/extension/dist-firefox/sidepanel.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Memento Web Clipper</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Vazirmatn:wght@400;600;700&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="sidepanel.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="shell">
|
||||
<header class="header">
|
||||
<div class="brand">
|
||||
<div class="brand-logo">M</div>
|
||||
<div class="brand-text">
|
||||
<span class="brand-name">Memento</span>
|
||||
<span class="brand-sub">Web Clipper</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div id="connBadge" class="conn-badge" hidden>
|
||||
<span class="conn-dot"></span>
|
||||
<span id="connLabel"></span>
|
||||
</div>
|
||||
<button type="button" id="settingsBtn" class="icon-btn" title="" aria-label="">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="settingsPanel" class="settings-panel" hidden>
|
||||
<label class="field">
|
||||
<span id="instanceUrlLabel"></span>
|
||||
<input id="baseUrl" type="text" spellcheck="false" placeholder="http://localhost:3000" />
|
||||
</label>
|
||||
<div class="preset-row">
|
||||
<button type="button" class="preset-btn" data-url="https://memento-note.com"></button>
|
||||
<button type="button" class="preset-btn" data-url="http://localhost:3000">localhost:3000</button>
|
||||
<button type="button" class="preset-btn" data-url="http://127.0.0.1:3000">127.0.0.1:3000</button>
|
||||
</div>
|
||||
<div class="settings-actions">
|
||||
<button type="button" id="applyInstanceBtn" class="btn btn-primary btn-sm"></button>
|
||||
<button type="button" id="openLoginBtn" class="btn btn-secondary btn-sm"></button>
|
||||
</div>
|
||||
<p class="settings-hint"></p>
|
||||
<p id="settingsStatus" class="settings-status" hidden></p>
|
||||
</div>
|
||||
|
||||
<main id="screen" class="main"></main>
|
||||
|
||||
<footer class="footer">
|
||||
<span class="footer-meta"></span>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="i18n.js"></script>
|
||||
<script src="sidepanel.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
726
memento-note/extension/dist-firefox/sidepanel.js
Normal file
726
memento-note/extension/dist-firefox/sidepanel.js
Normal file
@@ -0,0 +1,726 @@
|
||||
/** Mettre à false pour le build Chrome Web Store (URL production en dur). */
|
||||
const ALLOW_INSTANCE_CONFIG = false
|
||||
const DEFAULT_BASE = 'https://memento-note.com'
|
||||
const STORAGE_KEYS = { baseUrl: 'memento_clipper_base_url', notebookId: 'memento_clipper_notebook_id' }
|
||||
|
||||
/** Compatibilité Chrome/Firefox : Firefox expose l'API sous `browser.*`,
|
||||
* Chrome sous `chrome.*`. On normalise pour utiliser `chrome.*` partout dans le code. */
|
||||
if (typeof chrome === 'undefined' && typeof browser !== 'undefined') {
|
||||
globalThis.chrome = browser
|
||||
}
|
||||
|
||||
let state = 'idle'
|
||||
let notebooks = []
|
||||
let selectedNotebookId = ''
|
||||
let pageUrl = ''
|
||||
let pageTitle = ''
|
||||
let pageDomain = ''
|
||||
let pageFavicon = ''
|
||||
let pageHtml = ''
|
||||
let pageDir = 'ltr'
|
||||
let pageLang = ''
|
||||
let selectionText = ''
|
||||
let pageRestricted = false
|
||||
let lastNoteId = ''
|
||||
let lastNoteUrl = ''
|
||||
let successTitle = ''
|
||||
let successTags = []
|
||||
let errorMessage = ''
|
||||
let activeTabId = null
|
||||
let pendingClipType = 'page'
|
||||
let analyzeResult = null
|
||||
let editableTitle = ''
|
||||
let connected = false
|
||||
|
||||
const els = {
|
||||
screen: document.getElementById('screen'),
|
||||
baseUrl: document.getElementById('baseUrl'),
|
||||
settingsPanel: document.getElementById('settingsPanel'),
|
||||
settingsBtn: document.getElementById('settingsBtn'),
|
||||
connBadge: document.getElementById('connBadge'),
|
||||
connLabel: document.getElementById('connLabel'),
|
||||
settingsStatus: document.getElementById('settingsStatus'),
|
||||
applyInstanceBtn: document.getElementById('applyInstanceBtn'),
|
||||
openLoginBtn: document.getElementById('openLoginBtn'),
|
||||
}
|
||||
|
||||
const ICON_SELECT =
|
||||
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>'
|
||||
const ICON_CLIP =
|
||||
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>'
|
||||
const ICON_LINK =
|
||||
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>'
|
||||
|
||||
function apiBase() {
|
||||
if (!ALLOW_INSTANCE_CONFIG) return DEFAULT_BASE
|
||||
return (els.baseUrl?.value || DEFAULT_BASE).replace(/\/$/, '')
|
||||
}
|
||||
|
||||
function isRestrictedUrl(url) {
|
||||
return !url || /^(chrome|chrome-extension|edge|about|moz-extension|devtools):/i.test(url)
|
||||
}
|
||||
|
||||
async function ensureApiPermission() {
|
||||
const origin = `${apiBase()}/*`
|
||||
const has = await chrome.permissions.contains({ origins: [origin] })
|
||||
if (!has) {
|
||||
const granted = await chrome.permissions.request({ origins: [origin] })
|
||||
if (!granted) throw new Error(t('errPermissionDenied'))
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return String(s)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
}
|
||||
|
||||
const RTL_CHAR = /[\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/
|
||||
const LTR_CHAR = /[A-Za-z0-9]/
|
||||
|
||||
function detectTextDirection(text) {
|
||||
const sample = String(text || '').replace(/\s+/g, '').slice(0, 3000)
|
||||
if (!sample) return 'ltr'
|
||||
let rtl = 0
|
||||
let ltr = 0
|
||||
for (const ch of sample) {
|
||||
if (RTL_CHAR.test(ch)) rtl++
|
||||
else if (LTR_CHAR.test(ch)) ltr++
|
||||
}
|
||||
if (rtl === 0) return 'ltr'
|
||||
return rtl >= ltr ? 'rtl' : 'ltr'
|
||||
}
|
||||
|
||||
function resolveUiDirection(text) {
|
||||
if (pageDir === 'rtl') return 'rtl'
|
||||
if (pageLang === 'fa' || pageLang === 'ar' || pageLang === 'he') return 'rtl'
|
||||
if (/\/persian\b|\/fa\b|bbc\.com\/persian/i.test(pageUrl)) return 'rtl'
|
||||
return detectTextDirection(text)
|
||||
}
|
||||
|
||||
function rtlAttrs(text) {
|
||||
if (resolveUiDirection(text) !== 'rtl') return ''
|
||||
const lang = pageLang && ['fa', 'ar', 'he'].includes(pageLang) ? ` lang="${pageLang}"` : ''
|
||||
return ` class="text-rtl" dir="rtl"${lang}`
|
||||
}
|
||||
|
||||
function sortNotebooksHierarchy(list) {
|
||||
const byParent = new Map()
|
||||
for (const n of list) {
|
||||
const pid = n.parentId || '__root__'
|
||||
if (!byParent.has(pid)) byParent.set(pid, [])
|
||||
byParent.get(pid).push(n)
|
||||
}
|
||||
for (const items of byParent.values()) {
|
||||
items.sort((a, b) => (a.name || '').localeCompare(b.name || '', uiLocaleTag()))
|
||||
}
|
||||
const out = []
|
||||
const seen = new Set()
|
||||
function walk(parentKey, depth) {
|
||||
for (const n of byParent.get(parentKey) || []) {
|
||||
if (seen.has(n.id)) continue
|
||||
seen.add(n.id)
|
||||
out.push({ ...n, depth })
|
||||
walk(n.id, depth + 1)
|
||||
}
|
||||
}
|
||||
walk('__root__', 0)
|
||||
for (const n of list) {
|
||||
if (!seen.has(n.id)) out.push({ ...n, depth: 0 })
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
function notebookSelectHtml() {
|
||||
const sorted = sortNotebooksHierarchy(notebooks)
|
||||
const opts = sorted
|
||||
.map((n) => {
|
||||
const indent = n.depth > 0 ? '\u00A0\u00A0'.repeat(n.depth) + '↳ ' : ''
|
||||
const sel = n.id === selectedNotebookId ? ' selected' : ''
|
||||
return `<option value="${escapeHtml(n.id)}"${sel}>${escapeHtml(indent + (n.name || t('notebookUnnamed')))}</option>`
|
||||
})
|
||||
.join('')
|
||||
return `<select id="notebookSelect" class="notebook-select" aria-label="${escapeHtml(t('destinationNotebook'))}">
|
||||
${notebooks.length ? opts : `<option value="">${escapeHtml(t('noNotebooks'))}</option>`}
|
||||
</select>`
|
||||
}
|
||||
|
||||
function formatReadingTime(minutes) {
|
||||
const m = Number(minutes) || 0
|
||||
if (m <= 0) return ''
|
||||
if (m === 1) return t('readingTimeOne')
|
||||
return t('readingTimeOther', String(m))
|
||||
}
|
||||
|
||||
async function getActiveTab() {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
|
||||
return tab
|
||||
}
|
||||
|
||||
async function ensureContentScript(tabId) {
|
||||
try {
|
||||
const resp = await chrome.tabs.sendMessage(tabId, { type: 'PING' })
|
||||
if (resp?.ok) return true
|
||||
} catch {
|
||||
/* inject */
|
||||
}
|
||||
try {
|
||||
await chrome.scripting.executeScript({ target: { tabId }, files: ['content.js'] })
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function setPickModeOnTab(enabled) {
|
||||
if (!activeTabId || pageRestricted) return
|
||||
const ok = await ensureContentScript(activeTabId)
|
||||
if (!ok) return
|
||||
try {
|
||||
await chrome.tabs.sendMessage(activeTabId, { type: 'SET_PICK_MODE', enabled })
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
async function syncPickMode() {
|
||||
await setPickModeOnTab(state === 'idle' && !pageRestricted)
|
||||
}
|
||||
|
||||
function updateConnBadge() {
|
||||
if (!els.connBadge) return
|
||||
els.connBadge.hidden = !connected
|
||||
if (els.connLabel) els.connLabel.textContent = connected ? t('connected') : t('disconnected')
|
||||
}
|
||||
|
||||
function setSettingsStatus(msg, isError) {
|
||||
if (!els.settingsStatus) return
|
||||
els.settingsStatus.hidden = !msg
|
||||
els.settingsStatus.textContent = msg || ''
|
||||
els.settingsStatus.className = `settings-status${isError ? ' is-error' : ' is-ok'}`
|
||||
}
|
||||
|
||||
function applyInstanceConfigVisibility() {
|
||||
if (ALLOW_INSTANCE_CONFIG) return
|
||||
els.settingsPanel?.setAttribute('hidden', '')
|
||||
els.settingsBtn?.setAttribute('hidden', '')
|
||||
if (els.baseUrl) els.baseUrl.value = DEFAULT_BASE
|
||||
}
|
||||
|
||||
function selectionBlockHtml() {
|
||||
if (selectionText) {
|
||||
return `<div class="selection-panel has-text" id="selectionSlot">
|
||||
<div class="selection-head">
|
||||
<span class="status live"><span class="pulse-dot sky"></span> ${escapeHtml(t('selectionDetected'))}</span>
|
||||
<button type="button" class="clear-btn" id="clearSel">${escapeHtml(t('ignore'))}</button>
|
||||
</div>
|
||||
<div class="selection-body"${rtlAttrs(selectionText)}>「 ${escapeHtml(selectionText)} 」</div>
|
||||
</div>`
|
||||
}
|
||||
return `<div class="selection-hint" id="selectionSlot">
|
||||
<p>${escapeHtml(t('selectionHint'))}</p>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function actionsBlockHtml() {
|
||||
const hasSel = Boolean(selectionText)
|
||||
return `<div class="actions" id="actionsSlot">
|
||||
${
|
||||
hasSel
|
||||
? `<button type="button" class="btn btn-sky" id="clipSelBtn">
|
||||
${ICON_SELECT} ${escapeHtml(t('clipSelection'))}
|
||||
</button>`
|
||||
: ''
|
||||
}
|
||||
<button type="button" class="btn ${hasSel ? 'btn-secondary' : 'btn-primary'}" id="clipPageBtn" ${pageRestricted ? 'disabled' : ''}>
|
||||
${ICON_CLIP} ${escapeHtml(t('clipPage'))}
|
||||
</button>
|
||||
<button type="button" class="btn-link link-only" id="clipLinkBtn" ${pageRestricted ? 'disabled' : ''}>
|
||||
${ICON_LINK} ${escapeHtml(t('saveLinkOnly'))}
|
||||
</button>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function bindIdleHandlers() {
|
||||
document.getElementById('notebookSelect')?.addEventListener('change', async (e) => {
|
||||
selectedNotebookId = e.target.value || ''
|
||||
await chrome.storage.sync.set({ [STORAGE_KEYS.notebookId]: selectedNotebookId })
|
||||
})
|
||||
document.getElementById('clearSel')?.addEventListener('click', () => void clearSelection())
|
||||
document.getElementById('clipSelBtn')?.addEventListener('click', () => void runAnalyze('selection'))
|
||||
document.getElementById('clipPageBtn')?.addEventListener('click', () => void runAnalyze('page'))
|
||||
document.getElementById('clipLinkBtn')?.addEventListener('click', () => void runAnalyze('link'))
|
||||
|
||||
// Gérer l'erreur de chargement du favicon
|
||||
document.querySelector('.page-favicon')?.addEventListener('error', function() {
|
||||
const fallback = this.getAttribute('data-fallback')
|
||||
if (fallback && this.src !== fallback) {
|
||||
this.src = fallback
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function clearSelection() {
|
||||
selectionText = ''
|
||||
if (activeTabId) {
|
||||
try {
|
||||
await chrome.scripting.executeScript({
|
||||
target: { tabId: activeTabId },
|
||||
func: () => window.getSelection()?.removeAllRanges(),
|
||||
})
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
updateSelectionUI()
|
||||
}
|
||||
|
||||
function updateSelectionUI() {
|
||||
const slot = document.getElementById('selectionSlot')
|
||||
const actions = document.getElementById('actionsSlot')
|
||||
if (!slot || !actions || state !== 'idle') {
|
||||
render()
|
||||
return
|
||||
}
|
||||
slot.outerHTML = selectionBlockHtml()
|
||||
actions.outerHTML = actionsBlockHtml()
|
||||
bindIdleHandlers()
|
||||
}
|
||||
|
||||
function applySelectionFromMessage(msg) {
|
||||
if (!msg || msg.url !== pageUrl) return
|
||||
selectionText = msg.text || ''
|
||||
if (msg.dir?.toLowerCase() === 'rtl') pageDir = 'rtl'
|
||||
if (msg.lang) pageLang = msg.lang
|
||||
if (state === 'idle') updateSelectionUI()
|
||||
}
|
||||
|
||||
async function refreshPageContext() {
|
||||
const tab = await getActiveTab()
|
||||
activeTabId = tab?.id ?? null
|
||||
pageRestricted = isRestrictedUrl(tab?.url)
|
||||
|
||||
if (!tab?.id || pageRestricted) {
|
||||
pageUrl = tab?.url || ''
|
||||
pageTitle = tab?.title || t('pageNotAccessible')
|
||||
selectionText = ''
|
||||
return
|
||||
}
|
||||
|
||||
pageUrl = tab.url
|
||||
pageTitle = tab.title || ''
|
||||
try {
|
||||
const u = new URL(pageUrl)
|
||||
pageDomain = u.hostname
|
||||
pageFavicon = `https://www.google.com/s2/favicons?domain=${u.hostname}&sz=32`
|
||||
} catch {
|
||||
pageDomain = pageUrl
|
||||
pageFavicon = 'https://www.google.com/s2/favicons?domain=google.com&sz=32'
|
||||
}
|
||||
|
||||
const ok = await ensureContentScript(tab.id)
|
||||
if (!ok) return
|
||||
|
||||
try {
|
||||
const ctx = await chrome.tabs.sendMessage(tab.id, { type: 'GET_CONTEXT' })
|
||||
pageHtml = ctx?.html || ''
|
||||
selectionText = ctx?.text || ''
|
||||
pageDir = ctx?.dir?.toLowerCase() === 'rtl' ? 'rtl' : 'ltr'
|
||||
pageLang = ctx?.lang || ''
|
||||
} catch {
|
||||
try {
|
||||
const [{ result }] = await chrome.scripting.executeScript({
|
||||
target: { tabId: tab.id },
|
||||
func: () => ({
|
||||
html: document.documentElement.outerHTML,
|
||||
text: window.getSelection()?.toString().trim() || '',
|
||||
dir: document.documentElement.getAttribute('dir') || '',
|
||||
lang: (document.documentElement.getAttribute('lang') || '').split('-')[0],
|
||||
}),
|
||||
})
|
||||
pageHtml = result?.html || ''
|
||||
selectionText = result?.text || ''
|
||||
pageDir = result?.dir?.toLowerCase() === 'rtl' ? 'rtl' : 'ltr'
|
||||
pageLang = result?.lang || ''
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
const stored = await chrome.storage.sync.get([STORAGE_KEYS.baseUrl, STORAGE_KEYS.notebookId])
|
||||
if (els.baseUrl) {
|
||||
els.baseUrl.value = ALLOW_INSTANCE_CONFIG
|
||||
? stored[STORAGE_KEYS.baseUrl] || DEFAULT_BASE
|
||||
: DEFAULT_BASE
|
||||
}
|
||||
await loadNotebooks(stored[STORAGE_KEYS.notebookId])
|
||||
}
|
||||
|
||||
async function loadNotebooks(preferredId) {
|
||||
try {
|
||||
await ensureApiPermission()
|
||||
const res = await fetch(`${apiBase()}/api/clip/notebooks`, { credentials: 'include' })
|
||||
if (!res.ok) {
|
||||
connected = false
|
||||
updateConnBadge()
|
||||
if (res.status === 401) {
|
||||
throw new Error(t('errLoginRequired'))
|
||||
}
|
||||
throw new Error(t('errLoadNotebooks'))
|
||||
}
|
||||
const data = await res.json()
|
||||
notebooks = data.notebooks || []
|
||||
selectedNotebookId =
|
||||
(preferredId && notebooks.some((n) => n.id === preferredId) ? preferredId : '') ||
|
||||
notebooks[0]?.id ||
|
||||
''
|
||||
connected = true
|
||||
updateConnBadge()
|
||||
errorMessage = ''
|
||||
setSettingsStatus(t('notebooksLoaded'), false)
|
||||
} catch (e) {
|
||||
notebooks = []
|
||||
connected = false
|
||||
updateConnBadge()
|
||||
errorMessage = e.message
|
||||
setSettingsStatus(e.message, true)
|
||||
}
|
||||
}
|
||||
|
||||
async function applyInstance() {
|
||||
const url = (els.baseUrl?.value || DEFAULT_BASE).replace(/\/$/, '')
|
||||
if (els.baseUrl) els.baseUrl.value = url
|
||||
await chrome.storage.sync.set({ [STORAGE_KEYS.baseUrl]: url })
|
||||
setSettingsStatus(t('connecting'), false)
|
||||
await loadNotebooks(selectedNotebookId)
|
||||
if (connected) {
|
||||
setSettingsStatus(t('connectedToUrl', url), false)
|
||||
}
|
||||
}
|
||||
|
||||
function renderIdle() {
|
||||
const restrictedBlock = pageRestricted
|
||||
? `<div class="restricted-note">${escapeHtml(t('restrictedPage'))}</div>`
|
||||
: ''
|
||||
|
||||
const authHint =
|
||||
!connected && errorMessage
|
||||
? `<div class="auth-hint">${escapeHtml(errorMessage)}</div>`
|
||||
: ''
|
||||
|
||||
els.screen.innerHTML = `
|
||||
${restrictedBlock}
|
||||
${authHint}
|
||||
|
||||
<div>
|
||||
<span class="label">${escapeHtml(t('destinationNotebook'))}</span>
|
||||
${notebookSelectHtml()}
|
||||
</div>
|
||||
|
||||
<div class="page-card">
|
||||
<span class="sub">${escapeHtml(t('activePage'))}</span>
|
||||
<div class="page-row">
|
||||
<img src="${escapeHtml(pageFavicon)}" alt="" class="page-favicon" data-fallback="https://www.google.com/s2/favicons?domain=google.com&sz=32" />
|
||||
<div class="page-text">
|
||||
<div class="title"${rtlAttrs(pageTitle)}>${escapeHtml(pageTitle || '—')}</div>
|
||||
<div class="url">${escapeHtml(pageUrl || '—')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${selectionBlockHtml()}
|
||||
${actionsBlockHtml()}
|
||||
`
|
||||
bindIdleHandlers()
|
||||
}
|
||||
|
||||
function renderLoading(label) {
|
||||
els.screen.innerHTML = `
|
||||
<div class="center-state">
|
||||
<div class="spinner-wrap">
|
||||
<div class="spinner-ring"></div>
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="state-title">${escapeHtml(t('analyzingSource'))}</div>
|
||||
<div class="state-sub">${escapeHtml(label || t('statusAnalyzing'))}</div>
|
||||
<div class="state-detail">${escapeHtml(t('processingDetail'))}</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
function renderConfirm() {
|
||||
const excerpt = analyzeResult?.excerpt || ''
|
||||
const tags = analyzeResult?.tags || []
|
||||
const reading = formatReadingTime(analyzeResult?.readingTime)
|
||||
const tagsHtml = tags.map((t) => `<span class="tag-chip">${escapeHtml(t)}</span>`).join('')
|
||||
|
||||
els.screen.innerHTML = `
|
||||
<div class="confirm-panel">
|
||||
<span class="label">${escapeHtml(t('previewBeforeSave'))}</span>
|
||||
<label class="field">
|
||||
<span>${escapeHtml(t('noteTitleLabel'))}</span>
|
||||
<input id="titleInput" type="text" value="${escapeHtml(editableTitle)}" maxlength="300" />
|
||||
</label>
|
||||
${
|
||||
reading
|
||||
? `<div class="meta-row"><span class="reading-time">${escapeHtml(reading)}</span></div>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
analyzeResult?.summary
|
||||
? `<p class="summary-preview"${rtlAttrs(analyzeResult.summary)}>${escapeHtml(analyzeResult.summary)}</p>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
excerpt && pendingClipType !== 'link'
|
||||
? `<div class="excerpt-preview"${rtlAttrs(excerpt)}>
|
||||
<span class="excerpt-label">${escapeHtml(t('excerptLabel'))}</span>
|
||||
${escapeHtml(excerpt)}
|
||||
</div>`
|
||||
: ''
|
||||
}
|
||||
${tagsHtml ? `<div class="tags preview-tags">${tagsHtml}</div>` : ''}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="button" class="btn btn-primary" id="saveBtn">${escapeHtml(t('saveToMomento'))}</button>
|
||||
<button type="button" class="btn-link" id="cancelConfirmBtn">${escapeHtml(t('back'))}</button>
|
||||
</div>
|
||||
`
|
||||
|
||||
document.getElementById('titleInput')?.addEventListener('input', (e) => {
|
||||
editableTitle = e.target.value
|
||||
})
|
||||
document.getElementById('saveBtn')?.addEventListener('click', () => void runSave())
|
||||
document.getElementById('cancelConfirmBtn')?.addEventListener('click', async () => {
|
||||
state = 'idle'
|
||||
analyzeResult = null
|
||||
await syncPickMode()
|
||||
render()
|
||||
})
|
||||
}
|
||||
|
||||
function renderSuccess() {
|
||||
const nb = notebooks.find((n) => n.id === selectedNotebookId)
|
||||
const tagsHtml = successTags.map((t) => `<span class="tag-chip">${escapeHtml(t)}</span>`).join('')
|
||||
const reading = formatReadingTime(analyzeResult?.readingTime)
|
||||
|
||||
els.screen.innerHTML = `
|
||||
<div class="center-state" style="justify-content:flex-start;padding-top:12px">
|
||||
<div class="success-icon">✓</div>
|
||||
<div>
|
||||
<span class="badge-ok">${escapeHtml(t('noteSaved'))}</span>
|
||||
<div class="note-title"${rtlAttrs(successTitle)}>${escapeHtml(successTitle)}</div>
|
||||
<div class="state-detail">${escapeHtml(t('sentToNotebook', nb?.name || ''))}</div>
|
||||
${reading ? `<div class="state-detail">${escapeHtml(reading)}</div>` : ''}
|
||||
</div>
|
||||
${tagsHtml ? `<div class="tags">${tagsHtml}</div>` : ''}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="button" class="btn btn-primary" id="viewBtn">${escapeHtml(t('viewInMomento'))} ↗</button>
|
||||
<button type="button" class="btn-link" id="againBtn">${escapeHtml(t('clipAnother'))}</button>
|
||||
</div>
|
||||
`
|
||||
document.getElementById('viewBtn')?.addEventListener('click', () => {
|
||||
if (lastNoteUrl) chrome.tabs.create({ url: `${apiBase()}${lastNoteUrl}` })
|
||||
})
|
||||
document.getElementById('againBtn')?.addEventListener('click', async () => {
|
||||
state = 'idle'
|
||||
analyzeResult = null
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
})
|
||||
}
|
||||
|
||||
function renderError() {
|
||||
els.screen.innerHTML = `
|
||||
<div class="center-state">
|
||||
<div class="error-icon">!</div>
|
||||
<div>
|
||||
<div class="state-title" style="color:#ef4444">${escapeHtml(t('failure'))}</div>
|
||||
<div class="state-detail">${escapeHtml(errorMessage || t('genericError'))}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="button" class="btn btn-danger" id="retryBtn">${escapeHtml(t('retry'))}</button>
|
||||
<button type="button" class="btn-link" id="backIdleBtn">${escapeHtml(t('back'))}</button>
|
||||
</div>
|
||||
`
|
||||
document.getElementById('retryBtn')?.addEventListener('click', () => {
|
||||
if (analyzeResult) void runSave()
|
||||
else void runAnalyze(pendingClipType)
|
||||
})
|
||||
document.getElementById('backIdleBtn')?.addEventListener('click', async () => {
|
||||
state = 'idle'
|
||||
errorMessage = ''
|
||||
analyzeResult = null
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
})
|
||||
}
|
||||
|
||||
function render() {
|
||||
if (state === 'loading' || state === 'saving') {
|
||||
return renderLoading(state === 'saving' ? t('statusSaving') : t('statusAnalyzing'))
|
||||
}
|
||||
if (state === 'confirm') return renderConfirm()
|
||||
if (state === 'success') return renderSuccess()
|
||||
if (state === 'error') return renderError()
|
||||
renderIdle()
|
||||
}
|
||||
|
||||
async function runAnalyze(type) {
|
||||
pendingClipType = type
|
||||
state = 'loading'
|
||||
await setPickModeOnTab(false)
|
||||
render()
|
||||
try {
|
||||
await ensureApiPermission()
|
||||
await chrome.storage.sync.set({
|
||||
[STORAGE_KEYS.baseUrl]: apiBase(),
|
||||
[STORAGE_KEYS.notebookId]: selectedNotebookId,
|
||||
})
|
||||
|
||||
if (type === 'selection') {
|
||||
if (!selectionText) throw new Error(t('errNoSelection'))
|
||||
await refreshPageContext()
|
||||
}
|
||||
|
||||
let analyzeBody
|
||||
if (type === 'link') {
|
||||
analyzeBody = { url: pageUrl, title: pageTitle, mode: 'link' }
|
||||
} else if (type === 'selection' && selectionText) {
|
||||
analyzeBody = { url: pageUrl, title: pageTitle, mode: 'selection', selection: selectionText }
|
||||
} else {
|
||||
analyzeBody = { url: pageUrl, html: pageHtml, title: pageTitle, mode: 'article' }
|
||||
}
|
||||
|
||||
const analyzeRes = await fetch(`${apiBase()}/api/clip/analyze`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(analyzeBody),
|
||||
})
|
||||
const analysis = await analyzeRes.json()
|
||||
if (!analyzeRes.ok) throw new Error(analysis.error || t('errAnalyzeFailed'))
|
||||
|
||||
analyzeResult = analysis
|
||||
editableTitle = analysis.title || pageTitle || pageDomain
|
||||
state = 'confirm'
|
||||
render()
|
||||
} catch (e) {
|
||||
errorMessage = e.message || t('errNetwork')
|
||||
state = 'error'
|
||||
render()
|
||||
}
|
||||
}
|
||||
|
||||
async function runSave() {
|
||||
if (!analyzeResult) return
|
||||
state = 'saving'
|
||||
render()
|
||||
try {
|
||||
const title = (editableTitle || analyzeResult.title || pageTitle || pageDomain).trim()
|
||||
const saveRes = await fetch(`${apiBase()}/api/clip/save`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url: pageUrl,
|
||||
title,
|
||||
content: analyzeResult.content,
|
||||
summary: analyzeResult.summary,
|
||||
tags: analyzeResult.tags || [],
|
||||
notebookId: selectedNotebookId || undefined,
|
||||
}),
|
||||
})
|
||||
const saved = await saveRes.json()
|
||||
if (!saveRes.ok) throw new Error(saved.error || t('errSaveFailed'))
|
||||
|
||||
successTitle = title
|
||||
successTags = analyzeResult.tags || []
|
||||
lastNoteId = saved.noteId
|
||||
lastNoteUrl = saved.noteUrl
|
||||
state = 'success'
|
||||
render()
|
||||
} catch (e) {
|
||||
errorMessage = e.message || t('errNetwork')
|
||||
state = 'error'
|
||||
render()
|
||||
}
|
||||
}
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg) => {
|
||||
if (msg?.type === 'SELECTION_CHANGED') applySelectionFromMessage(msg)
|
||||
})
|
||||
|
||||
chrome.tabs.onActivated.addListener(async () => {
|
||||
if (state !== 'idle') return
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
})
|
||||
|
||||
chrome.tabs.onUpdated.addListener(async (tabId, info) => {
|
||||
if (info.status !== 'complete' || state !== 'idle') return
|
||||
const tab = await getActiveTab()
|
||||
if (tab?.id === tabId) {
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
}
|
||||
})
|
||||
|
||||
els.settingsBtn?.addEventListener('click', () => {
|
||||
if (!ALLOW_INSTANCE_CONFIG) return
|
||||
els.settingsPanel.hidden = !els.settingsPanel.hidden
|
||||
})
|
||||
|
||||
document.querySelectorAll('.preset-btn').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const url = btn.getAttribute('data-url')
|
||||
if (url && els.baseUrl) els.baseUrl.value = url
|
||||
})
|
||||
})
|
||||
|
||||
els.applyInstanceBtn?.addEventListener('click', () => void applyInstance())
|
||||
els.openLoginBtn?.addEventListener('click', () => {
|
||||
chrome.tabs.create({ url: apiBase() })
|
||||
})
|
||||
|
||||
document.addEventListener('visibilitychange', async () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
if (state === 'idle') {
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
}
|
||||
} else if (document.visibilityState === 'hidden') {
|
||||
// Désactiver le pick mode quand le sidepanel est fermé
|
||||
await setPickModeOnTab(false)
|
||||
}
|
||||
})
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
applyDocumentLocale()
|
||||
applyInstanceConfigVisibility()
|
||||
applyShellI18n()
|
||||
await loadSettings()
|
||||
try {
|
||||
await ensureApiPermission()
|
||||
} catch (e) {
|
||||
errorMessage = e.message
|
||||
connected = false
|
||||
updateConnBadge()
|
||||
}
|
||||
await refreshPageContext()
|
||||
await syncPickMode()
|
||||
render()
|
||||
})
|
||||
@@ -6,191 +6,289 @@ const fs = require('fs')
|
||||
const path = require('path')
|
||||
const zlib = require('zlib')
|
||||
|
||||
const VERSION = "0.3.1"
|
||||
const VERSION = "0.4.0"
|
||||
|
||||
// Embedded Momento clipper/extension string table (gzip+base64).
|
||||
// Source English + contextual French anchors; other locales are MT batch
|
||||
// post-edited with placeholder hardening.
|
||||
|
||||
const PACK_B64 = `
|
||||
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
|
||||
wOW7jPkAAA==
|
||||
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
|
||||
`
|
||||
|
||||
function loadStrings () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"strings": {
|
||||
"en": {
|
||||
"extName": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "__MSG_extName__",
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"description": "__MSG_extDescription__",
|
||||
"default_locale": "en",
|
||||
"permissions": ["activeTab", "scripting", "storage", "sidePanel", "tabs"],
|
||||
@@ -12,12 +12,25 @@
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
"optional_host_permissions": [
|
||||
"https://*/*"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"side_panel": {
|
||||
"default_path": "sidepanel.html"
|
||||
},
|
||||
"sidebar_action": {
|
||||
"default_title": "__MSG_extActionTitle__",
|
||||
"default_panel": "sidepanel.html"
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "memento-clipper@memento-note.com",
|
||||
"strict_min_version": "115.0"
|
||||
}
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "https://*/*"],
|
||||
|
||||
Binary file not shown.
BIN
memento-note/extension/memento-web-clipper-firefox.xpi
Normal file
BIN
memento-note/extension/memento-web-clipper-firefox.xpi
Normal file
Binary file not shown.
@@ -40,17 +40,24 @@ function ensureDir(dirPath) {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all files from source to destination, excluding specified patterns
|
||||
// Copy all files from source to destination, excluding specified patterns.
|
||||
// `exclude` accepts RegExp (matched against the relative path) or a function
|
||||
// returning true when the entry (relative path, isDirectory flag) should be skipped.
|
||||
function copyFiles(src, dest, exclude = []) {
|
||||
ensureDir(dest)
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true })
|
||||
|
||||
const isExcluded = (relPath, isDir) =>
|
||||
exclude.some(rule => {
|
||||
if (typeof rule === 'function') return rule(relPath, isDir)
|
||||
return relPath.match(rule) !== null
|
||||
})
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name)
|
||||
const relPath = path.relative(extRoot, srcPath)
|
||||
|
||||
// Skip excluded files/directories
|
||||
if (exclude.some(pattern => relPath.match(pattern))) {
|
||||
if (isExcluded(relPath, entry.isDirectory())) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -85,6 +92,11 @@ function processManifestJson(content) {
|
||||
manifest.content_scripts[0].matches = ['https://memento-note.com/*', 'https://www.memento-note.com/*']
|
||||
}
|
||||
|
||||
// Strip Firefox-only fields (Chrome Store rejects unknown keys on strict review)
|
||||
delete manifest.sidebar_action
|
||||
delete manifest.browser_specific_settings
|
||||
delete manifest.optional_host_permissions
|
||||
|
||||
return JSON.stringify(manifest, null, 2)
|
||||
}
|
||||
|
||||
@@ -177,13 +189,19 @@ async function build() {
|
||||
}
|
||||
ensureDir(distDir)
|
||||
|
||||
// Copy extension files (excluding build scripts and dist)
|
||||
// Copy extension files (excluding build scripts, internal sources and dist)
|
||||
log('📋 Copying extension files...', 'blue')
|
||||
copyFiles(extRoot, distDir, [
|
||||
/^dist-/,
|
||||
/^scripts\//,
|
||||
// Top-level directories to skip entirely (do not even create empty folders)
|
||||
(rel, isDir) => isDir && /^dist-/i.test(rel),
|
||||
(rel, isDir) => isDir && (rel === 'scripts' || rel === 'i18n'),
|
||||
// File-level patterns
|
||||
/\.md$/,
|
||||
/^node_modules$/
|
||||
/^node_modules$/,
|
||||
/^diagnose\.js$/, // dev diagnostic script
|
||||
/^test-sidepanel\.html$/, // dev test page
|
||||
/^memento-web-clipper-chrome-store\.zip$/, // avoid recursive zip-in-zip
|
||||
/^memento-web-clipper-firefox\.xpi$/, // exclude sibling Firefox build artifacts
|
||||
])
|
||||
|
||||
// Process sidepanel.js
|
||||
|
||||
258
memento-note/extension/scripts/build-firefox.mjs
Normal file
258
memento-note/extension/scripts/build-firefox.mjs
Normal file
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build script for Firefox Add-ons (AMO) production package
|
||||
* Usage: node scripts/build-firefox.mjs
|
||||
*
|
||||
* This script:
|
||||
* 1. Sets ALLOW_INSTANCE_CONFIG = false in sidepanel.js
|
||||
* 2. Restricts host_permissions to memento-note.com only
|
||||
* 3. Removes side_panel (Chrome-only) from manifest.json
|
||||
* 4. Keeps sidebar_action + browser_specific_settings (Firefox-specific)
|
||||
* 5. Copies and generates icons from public/icons/
|
||||
* 6. Creates a Firefox-ready .xpi package
|
||||
*/
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import AdmZip from 'adm-zip'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const extRoot = path.resolve(__dirname, '..')
|
||||
const projectRoot = path.resolve(extRoot, '..')
|
||||
const publicIconsDir = path.join(projectRoot, 'public', 'icons')
|
||||
const distDir = path.join(extRoot, 'dist-firefox')
|
||||
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
red: '\x1b[31m'
|
||||
}
|
||||
|
||||
function log(message, color = 'reset') {
|
||||
console.log(`${colors[color]}${message}${colors.reset}`)
|
||||
}
|
||||
|
||||
function ensureDir(dirPath) {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true })
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all files from source to destination, excluding specified patterns.
|
||||
// `exclude` accepts RegExp or a function (relPath, isDirectory) -> boolean.
|
||||
function copyFiles(src, dest, exclude = []) {
|
||||
ensureDir(dest)
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true })
|
||||
|
||||
const isExcluded = (relPath, isDir) =>
|
||||
exclude.some(rule => {
|
||||
if (typeof rule === 'function') return rule(relPath, isDir)
|
||||
return relPath.match(rule) !== null
|
||||
})
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name)
|
||||
const relPath = path.relative(extRoot, srcPath)
|
||||
|
||||
if (isExcluded(relPath, entry.isDirectory())) {
|
||||
continue
|
||||
}
|
||||
|
||||
const destPath = path.join(dest, entry.name)
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
copyFiles(srcPath, destPath, exclude)
|
||||
} else {
|
||||
fs.copyFileSync(srcPath, destPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read and modify sidepanel.js for production (lock URL to memento-note.com)
|
||||
function processSidepanelJs(content) {
|
||||
return content.replace(
|
||||
/const ALLOW_INSTANCE_CONFIG = true/,
|
||||
'const ALLOW_INSTANCE_CONFIG = false'
|
||||
)
|
||||
}
|
||||
|
||||
// Read and modify manifest.json for Firefox production
|
||||
function processManifestJson(content) {
|
||||
const manifest = JSON.parse(content)
|
||||
|
||||
// Firefox doesn't support chrome.sidePanel — use sidebarAction (already declared).
|
||||
delete manifest.side_panel
|
||||
|
||||
// Firefox MV3 service workers are supported, but background events are also
|
||||
// reliable with background.scripts. Keep service_worker for simplicity.
|
||||
|
||||
// Restrict host_permissions to production. Keep optional_host_permissions as-is.
|
||||
manifest.host_permissions = [
|
||||
'https://memento-note.com/*',
|
||||
'https://www.memento-note.com/*',
|
||||
]
|
||||
|
||||
if (manifest.content_scripts?.[0]) {
|
||||
manifest.content_scripts[0].matches = ['https://memento-note.com/*', 'https://www.memento-note.com/*']
|
||||
}
|
||||
|
||||
return JSON.stringify(manifest, null, 2)
|
||||
}
|
||||
|
||||
// Generate PNG icons from SVG using sharp
|
||||
async function generateIcons() {
|
||||
log('📦 Generating PNG icons from SVG...', 'blue')
|
||||
|
||||
const sharp = (await import('sharp')).default
|
||||
const sizes = [16, 48, 128]
|
||||
|
||||
const icon512Svg = path.join(publicIconsDir, 'icon-512.svg')
|
||||
const icon192Svg = path.join(publicIconsDir, 'icon-192.svg')
|
||||
|
||||
if (!fs.existsSync(icon512Svg) || !fs.existsSync(icon192Svg)) {
|
||||
log('⚠️ Source SVG icons not found. Copying SVG files only.', 'yellow')
|
||||
fs.copyFileSync(icon512Svg, path.join(distDir, 'icon-512.svg'))
|
||||
fs.copyFileSync(icon192Svg, path.join(distDir, 'icon-192.svg'))
|
||||
return
|
||||
}
|
||||
|
||||
for (const size of sizes) {
|
||||
const sourceSvg = size >= 128 ? icon512Svg : icon192Svg
|
||||
const outputPath = path.join(distDir, `icon-${size}.png`)
|
||||
|
||||
await sharp(sourceSvg)
|
||||
.resize(size, size)
|
||||
.png()
|
||||
.toFile(outputPath)
|
||||
|
||||
log(` ✓ Generated icon-${size}.png`, 'green')
|
||||
}
|
||||
|
||||
fs.copyFileSync(icon512Svg, path.join(distDir, 'icon-512.svg'))
|
||||
fs.copyFileSync(icon192Svg, path.join(distDir, 'icon-192.svg'))
|
||||
}
|
||||
|
||||
// Create XPI (ZIP) package using AdmZip
|
||||
async function createXpiPackage() {
|
||||
log('📦 Creating XPI package...', 'blue')
|
||||
|
||||
const xpiPath = path.join(extRoot, 'memento-web-clipper-firefox.xpi')
|
||||
|
||||
try {
|
||||
const zip = new AdmZip()
|
||||
|
||||
const addFiles = (dir, base = '') => {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name)
|
||||
const relativePath = path.join(base, entry.name)
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
addFiles(fullPath, relativePath)
|
||||
} else {
|
||||
zip.addLocalFile(fullPath, base)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addFiles(distDir)
|
||||
zip.writeZip(xpiPath)
|
||||
|
||||
const stats = fs.statSync(xpiPath)
|
||||
log(`✓ XPI package created: ${xpiPath}`, 'green')
|
||||
log(` Size: ${(stats.size / 1024).toFixed(2)} KB`, 'green')
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to create XPI: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function build() {
|
||||
log('🦊 Starting Firefox (AMO) build...', 'blue')
|
||||
log('')
|
||||
|
||||
try {
|
||||
log('🧹 Cleaning dist directory...', 'blue')
|
||||
if (fs.existsSync(distDir)) {
|
||||
fs.rmSync(distDir, { recursive: true, force: true })
|
||||
}
|
||||
ensureDir(distDir)
|
||||
|
||||
log('📋 Copying extension files...', 'blue')
|
||||
copyFiles(extRoot, distDir, [
|
||||
(rel, isDir) => isDir && /^dist-/i.test(rel),
|
||||
(rel, isDir) => isDir && (rel === 'scripts' || rel === 'i18n'),
|
||||
/\.md$/,
|
||||
/^node_modules$/,
|
||||
/^diagnose\.js$/,
|
||||
/^test-sidepanel\.html$/,
|
||||
/^memento-web-clipper-chrome-store\.zip$/,
|
||||
/^memento-web-clipper-firefox\.xpi$/,
|
||||
])
|
||||
|
||||
log('⚙️ Processing sidepanel.js...', 'blue')
|
||||
const sidepanelPath = path.join(distDir, 'sidepanel.js')
|
||||
let sidepanelContent = fs.readFileSync(sidepanelPath, 'utf8')
|
||||
sidepanelContent = processSidepanelJs(sidepanelContent)
|
||||
fs.writeFileSync(sidepanelPath, sidepanelContent)
|
||||
log(' ✓ Set ALLOW_INSTANCE_CONFIG = false', 'green')
|
||||
|
||||
log('⚙️ Processing manifest.json...', 'blue')
|
||||
const manifestPath = path.join(distDir, 'manifest.json')
|
||||
let manifestContent = fs.readFileSync(manifestPath, 'utf8')
|
||||
manifestContent = processManifestJson(manifestContent)
|
||||
|
||||
const manifest = JSON.parse(manifestContent)
|
||||
manifest.icons = {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
// Firefox uses browser_action icon OR sidebar_action icon
|
||||
manifest.action = {
|
||||
...manifest.action,
|
||||
"default_icon": {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
}
|
||||
if (manifest.sidebar_action) {
|
||||
manifest.sidebar_action.default_icon = {
|
||||
"16": "icon-16.png",
|
||||
"48": "icon-48.png",
|
||||
"128": "icon-128.png"
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2))
|
||||
log(' ✓ Removed side_panel (Chrome-only)', 'green')
|
||||
log(' ✓ Restricted host_permissions to memento-note.com', 'green')
|
||||
log(' ✓ Kept sidebar_action + browser_specific_settings for Firefox', 'green')
|
||||
log(' ✓ Added icon definitions', 'green')
|
||||
|
||||
await generateIcons()
|
||||
await createXpiPackage()
|
||||
|
||||
log('')
|
||||
log('✅ Build completed successfully!', 'green')
|
||||
log('')
|
||||
log('📦 Output files:', 'blue')
|
||||
log(` • Package: ${path.join(extRoot, 'memento-web-clipper-firefox.xpi')}`, 'reset')
|
||||
log(` • Dist dir: ${distDir}`, 'reset')
|
||||
log('')
|
||||
log('📝 Next steps:', 'blue')
|
||||
log(' 1. Test: web-ext run --source-dir ' + distDir, 'reset')
|
||||
log(' 2. Sign: web-ext sign --api-key=<KEY> --api-secret=<SECRET> --source-dir ' + distDir, 'reset')
|
||||
log(' 3. Submit signed .xpi to https://addons.mozilla.org/developers/', 'reset')
|
||||
log('')
|
||||
} catch (error) {
|
||||
log('')
|
||||
log('❌ Build failed!', 'red')
|
||||
log(` Error: ${error.message}`, 'red')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
build()
|
||||
@@ -3,6 +3,12 @@ const ALLOW_INSTANCE_CONFIG = true
|
||||
const DEFAULT_BASE = 'https://memento-note.com'
|
||||
const STORAGE_KEYS = { baseUrl: 'memento_clipper_base_url', notebookId: 'memento_clipper_notebook_id' }
|
||||
|
||||
/** Compatibilité Chrome/Firefox : Firefox expose l'API sous `browser.*`,
|
||||
* Chrome sous `chrome.*`. On normalise pour utiliser `chrome.*` partout dans le code. */
|
||||
if (typeof chrome === 'undefined' && typeof browser !== 'undefined') {
|
||||
globalThis.chrome = browser
|
||||
}
|
||||
|
||||
let state = 'idle'
|
||||
let notebooks = []
|
||||
let selectedNotebookId = ''
|
||||
|
||||
Reference in New Issue
Block a user