Merge pull request #18 from outis1one/claude/read-repo-wA3y1
Claude/read repo w a3y1
This commit is contained in:
Executable
+66
@@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Convert Silent Send for Safari using Apple's safari-web-extension-converter.
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - macOS with Xcode installed (free from Mac App Store)
|
||||||
|
# - Apple Developer account ($99/year) for App Store distribution
|
||||||
|
# - Xcode Command Line Tools: xcode-select --install
|
||||||
|
#
|
||||||
|
# This script:
|
||||||
|
# 1. Builds the Firefox variant (Safari uses browser.* API like Firefox)
|
||||||
|
# 2. Runs safari-web-extension-converter to generate an Xcode project
|
||||||
|
# 3. The Xcode project can then be built, tested, and submitted to App Store
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
OUT_DIR="$SCRIPT_DIR/safari-build"
|
||||||
|
|
||||||
|
# Check for Xcode
|
||||||
|
if ! command -v xcrun &> /dev/null; then
|
||||||
|
echo "Error: Xcode is required. Install from the Mac App Store."
|
||||||
|
echo "Then run: xcode-select --install"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! xcrun --find safari-web-extension-converter &> /dev/null; then
|
||||||
|
echo "Error: safari-web-extension-converter not found."
|
||||||
|
echo "Make sure Xcode is installed and up to date."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the Firefox variant (Safari uses browser.* API)
|
||||||
|
echo "Building extension..."
|
||||||
|
"$SCRIPT_DIR/build.sh" firefox
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Converting for Safari..."
|
||||||
|
|
||||||
|
# Remove previous build
|
||||||
|
rm -rf "$OUT_DIR"
|
||||||
|
|
||||||
|
# Convert — generates an Xcode project
|
||||||
|
xcrun safari-web-extension-converter \
|
||||||
|
"$SCRIPT_DIR/dist/firefox" \
|
||||||
|
--project-location "$OUT_DIR" \
|
||||||
|
--app-name "Silent Send" \
|
||||||
|
--bundle-identifier "com.silentsend.extension" \
|
||||||
|
--swift \
|
||||||
|
--macos-only \
|
||||||
|
--no-open
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Safari project created at: $OUT_DIR"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Open $OUT_DIR/Silent Send.xcodeproj in Xcode"
|
||||||
|
echo " 2. Select your Apple Developer Team in Signing & Capabilities"
|
||||||
|
echo " 3. Build and run (Cmd+R) to test in Safari"
|
||||||
|
echo " 4. To distribute: Product → Archive → Distribute App"
|
||||||
|
echo ""
|
||||||
|
echo "For App Store submission, you'll also need:"
|
||||||
|
echo " - App Store screenshots (1280x800 for Mac)"
|
||||||
|
echo " - Privacy policy URL"
|
||||||
|
echo " - App description and keywords"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Silent Send",
|
"name": "Silent Send",
|
||||||
"version": "2.0.3",
|
"version": "2.0.5",
|
||||||
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Silent Send",
|
"name": "Silent Send",
|
||||||
"version": "2.0.3",
|
"version": "2.0.5",
|
||||||
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "silent-send",
|
"name": "silent-send",
|
||||||
"version": "2.0.3",
|
"version": "2.0.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "BSL-1.1",
|
"license": "BSL-1.1",
|
||||||
"description": "Browser extension that substitutes personal data before sending to AI services",
|
"description": "Browser extension that substitutes personal data before sending to AI services",
|
||||||
|
|||||||
+137
-16
@@ -14,7 +14,8 @@
|
|||||||
function safeHTML(el, html) {
|
function safeHTML(el, html) {
|
||||||
const template = document.createElement('template');
|
const template = document.createElement('template');
|
||||||
template.innerHTML = html;
|
template.innerHTML = html;
|
||||||
el.replaceChildren(...template.content.childNodes);
|
// Convert to static array — childNodes is live and shrinks as nodes move
|
||||||
|
el.replaceChildren(...Array.from(template.content.childNodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -181,6 +182,32 @@
|
|||||||
replacements.push({ original: matched, replaced: sub, category: 'name', pattern: 'smart' });
|
replacements.push({ original: matched, replaced: sub, category: 'name', pattern: 'smart' });
|
||||||
return sub;
|
return sub;
|
||||||
});
|
});
|
||||||
|
// Concatenated forms: JohnSmith, johnsmith, john.smith, john_smith, john-smith
|
||||||
|
// Also reversed: SmithJohn, smithjohn, smith.john, etc.
|
||||||
|
const f = first.real, l = last.real;
|
||||||
|
const fs = first.substitute, ls = last.substitute;
|
||||||
|
const concatPatterns = [
|
||||||
|
// first+last
|
||||||
|
[f + l, fs + ls],
|
||||||
|
[f + '.' + l, fs + '.' + ls],
|
||||||
|
[f + '_' + l, fs + '_' + ls],
|
||||||
|
[f + '-' + l, fs + '-' + ls],
|
||||||
|
// last+first
|
||||||
|
[l + f, ls + fs],
|
||||||
|
[l + '.' + f, ls + '.' + fs],
|
||||||
|
[l + '_' + f, ls + '_' + fs],
|
||||||
|
[l + '-' + f, ls + '-' + fs],
|
||||||
|
];
|
||||||
|
for (const [real, sub] of concatPatterns) {
|
||||||
|
result = result.replace(new RegExp('\\b' + esc(real) + '\\b', 'gi'), (matched) => {
|
||||||
|
// Preserve case: all-lower→lower, ALL-UPPER→upper, else use sub as-is
|
||||||
|
let replacement = sub;
|
||||||
|
if (matched === matched.toLowerCase()) replacement = sub.toLowerCase();
|
||||||
|
else if (matched === matched.toUpperCase()) replacement = sub.toUpperCase();
|
||||||
|
replacements.push({ original: matched, replaced: replacement, category: 'name', pattern: 'smart-concat' });
|
||||||
|
return replacement;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,17 +382,26 @@
|
|||||||
|
|
||||||
// Common English words that are capitalized but aren't proper nouns.
|
// Common English words that are capitalized but aren't proper nouns.
|
||||||
// Used by the proper noun heuristic to reduce false positives.
|
// Used by the proper noun heuristic to reduce false positives.
|
||||||
|
// Includes common verbs, nouns, adjectives that appear in titles,
|
||||||
|
// headings, UI buttons, and instructions.
|
||||||
const COMMON_CAPITALIZED = new Set([
|
const COMMON_CAPITALIZED = new Set([
|
||||||
|
// Prepositions, conjunctions, articles, pronouns
|
||||||
'the', 'a', 'an', 'and', 'or', 'but', 'if', 'then', 'else', 'when',
|
'the', 'a', 'an', 'and', 'or', 'but', 'if', 'then', 'else', 'when',
|
||||||
'at', 'by', 'for', 'with', 'about', 'against', 'between', 'through',
|
'at', 'by', 'for', 'with', 'about', 'against', 'between', 'through',
|
||||||
'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up',
|
'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up',
|
||||||
'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further',
|
'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further',
|
||||||
'then', 'once', 'here', 'there', 'all', 'each', 'every', 'both',
|
'once', 'here', 'there', 'all', 'each', 'every', 'both',
|
||||||
'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not',
|
'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not',
|
||||||
'only', 'own', 'same', 'so', 'than', 'too', 'very', 'can', 'will',
|
'only', 'own', 'same', 'so', 'than', 'too', 'very', 'can', 'will',
|
||||||
'just', 'should', 'now', 'also', 'into', 'could', 'would', 'may',
|
'just', 'should', 'now', 'also', 'into', 'could', 'would', 'may',
|
||||||
'might', 'shall', 'must', 'need', 'have', 'has', 'had', 'do', 'does',
|
'might', 'shall', 'must', 'need', 'have', 'has', 'had', 'do', 'does',
|
||||||
'did', 'be', 'is', 'am', 'are', 'was', 'were', 'been', 'being',
|
'did', 'be', 'is', 'am', 'are', 'was', 'were', 'been', 'being',
|
||||||
|
'i', 'you', 'he', 'she', 'it', 'we', 'they', 'me', 'him', 'her',
|
||||||
|
'us', 'them', 'my', 'your', 'his', 'its', 'our', 'their',
|
||||||
|
'this', 'that', 'these', 'those', 'what', 'who', 'how', 'why',
|
||||||
|
'which', 'where', 'when', 'while', 'since', 'because', 'although',
|
||||||
|
'however', 'therefore', 'moreover', 'furthermore', 'nevertheless',
|
||||||
|
// Common verbs (appear in titles, headings, buttons, instructions)
|
||||||
'get', 'got', 'make', 'made', 'go', 'went', 'gone', 'take', 'took',
|
'get', 'got', 'make', 'made', 'go', 'went', 'gone', 'take', 'took',
|
||||||
'come', 'came', 'see', 'saw', 'know', 'knew', 'think', 'thought',
|
'come', 'came', 'see', 'saw', 'know', 'knew', 'think', 'thought',
|
||||||
'say', 'said', 'tell', 'told', 'give', 'gave', 'find', 'found',
|
'say', 'said', 'tell', 'told', 'give', 'gave', 'find', 'found',
|
||||||
@@ -378,25 +414,110 @@
|
|||||||
'buy', 'wait', 'serve', 'die', 'send', 'expect', 'build', 'stay',
|
'buy', 'wait', 'serve', 'die', 'send', 'expect', 'build', 'stay',
|
||||||
'fall', 'cut', 'reach', 'kill', 'remain', 'suggest', 'raise', 'pass',
|
'fall', 'cut', 'reach', 'kill', 'remain', 'suggest', 'raise', 'pass',
|
||||||
'sell', 'require', 'report', 'decide', 'pull', 'develop', 'note',
|
'sell', 'require', 'report', 'decide', 'pull', 'develop', 'note',
|
||||||
'however', 'because', 'although', 'since', 'while', 'where', 'which',
|
'generate', 'design', 'manage', 'process', 'handle', 'check', 'verify',
|
||||||
'what', 'who', 'how', 'why', 'this', 'that', 'these', 'those',
|
'submit', 'apply', 'accept', 'reject', 'approve', 'deny', 'confirm',
|
||||||
'i', 'you', 'he', 'she', 'it', 'we', 'they', 'me', 'him', 'her',
|
'cancel', 'delete', 'remove', 'edit', 'modify', 'view', 'display',
|
||||||
'us', 'them', 'my', 'your', 'his', 'its', 'our', 'their',
|
'search', 'filter', 'sort', 'select', 'choose', 'pick', 'enter',
|
||||||
'new', 'old', 'big', 'small', 'long', 'short', 'good', 'bad',
|
'input', 'output', 'upload', 'download', 'install', 'uninstall',
|
||||||
'great', 'little', 'right', 'left', 'first', 'last', 'next',
|
'enable', 'disable', 'activate', 'deactivate', 'toggle', 'switch',
|
||||||
'sure', 'like', 'well', 'back', 'still', 'even', 'much', 'many',
|
'connect', 'disconnect', 'sync', 'refresh', 'reload', 'reset',
|
||||||
// Programming/tech words that appear capitalized
|
'save', 'load', 'store', 'restore', 'backup', 'export', 'import',
|
||||||
|
'copy', 'paste', 'drag', 'drop', 'click', 'press', 'hold', 'release',
|
||||||
|
'scroll', 'zoom', 'resize', 'expand', 'collapse', 'hide', 'reveal',
|
||||||
|
'lock', 'unlock', 'encrypt', 'decrypt', 'sign', 'register', 'login',
|
||||||
|
'logout', 'subscribe', 'unsubscribe', 'share', 'publish', 'deploy',
|
||||||
|
'launch', 'test', 'debug', 'fix', 'patch', 'merge', 'split', 'join',
|
||||||
|
'link', 'attach', 'detach', 'insert', 'append', 'prepend', 'wrap',
|
||||||
|
'format', 'parse', 'convert', 'transform', 'translate', 'compile',
|
||||||
|
'execute', 'render', 'animate', 'validate', 'sanitize', 'escape',
|
||||||
|
// Common nouns (appear in titles, headings, labels)
|
||||||
|
'account', 'action', 'address', 'alert', 'analysis', 'answer',
|
||||||
|
'application', 'area', 'article', 'asset', 'background', 'badge',
|
||||||
|
'banner', 'board', 'body', 'border', 'bottom', 'box', 'brand',
|
||||||
|
'browser', 'buffer', 'button', 'cache', 'calendar', 'card', 'case',
|
||||||
|
'category', 'center', 'channel', 'chart', 'chat', 'child', 'choice',
|
||||||
|
'class', 'client', 'cloud', 'cluster', 'code', 'collection', 'color',
|
||||||
|
'column', 'command', 'comment', 'community', 'company', 'component',
|
||||||
|
'config', 'configuration', 'connection', 'console', 'contact',
|
||||||
|
'container', 'content', 'context', 'control', 'corner', 'count',
|
||||||
|
'country', 'cover', 'custom', 'dashboard', 'data', 'database',
|
||||||
|
'date', 'day', 'default', 'description', 'design', 'desktop',
|
||||||
|
'detail', 'device', 'dialog', 'directory', 'document', 'domain',
|
||||||
|
'draft', 'driver', 'edge', 'editor', 'element', 'email', 'end',
|
||||||
|
'engine', 'entry', 'environment', 'error', 'event', 'example',
|
||||||
|
'exception', 'extension', 'feature', 'feedback', 'field', 'file',
|
||||||
|
'filter', 'folder', 'font', 'footer', 'form', 'format', 'frame',
|
||||||
|
'function', 'gallery', 'general', 'global', 'grid', 'group',
|
||||||
|
'guide', 'handler', 'header', 'health', 'help', 'helper', 'history',
|
||||||
|
'home', 'host', 'icon', 'image', 'index', 'info', 'input', 'instance',
|
||||||
|
'interface', 'issue', 'item', 'job', 'key', 'label', 'language',
|
||||||
|
'layout', 'level', 'library', 'light', 'limit', 'line', 'link',
|
||||||
|
'list', 'local', 'location', 'log', 'logo', 'main', 'manager',
|
||||||
|
'manual', 'map', 'margin', 'master', 'match', 'media', 'member',
|
||||||
|
'memory', 'menu', 'message', 'method', 'middle', 'mobile', 'modal',
|
||||||
|
'mode', 'model', 'module', 'monitor', 'name', 'navigation', 'network',
|
||||||
|
'node', 'note', 'notification', 'number', 'object', 'option',
|
||||||
|
'order', 'origin', 'output', 'overlay', 'overview', 'owner', 'package',
|
||||||
|
'padding', 'page', 'panel', 'parent', 'parser', 'password', 'path',
|
||||||
|
'pattern', 'permission', 'photo', 'pipeline', 'placeholder', 'plan',
|
||||||
|
'platform', 'player', 'plugin', 'point', 'policy', 'pool', 'popup',
|
||||||
|
'port', 'position', 'post', 'power', 'preview', 'primary', 'print',
|
||||||
|
'priority', 'process', 'product', 'profile', 'program', 'progress',
|
||||||
|
'project', 'prompt', 'property', 'protocol', 'provider', 'proxy',
|
||||||
|
'public', 'query', 'queue', 'quick', 'radio', 'range', 'rate',
|
||||||
|
'reader', 'record', 'region', 'release', 'remote', 'render',
|
||||||
|
'report', 'request', 'resource', 'response', 'result', 'review',
|
||||||
|
'role', 'root', 'route', 'row', 'rule', 'runtime', 'sample',
|
||||||
|
'scanner', 'schema', 'scope', 'screen', 'script', 'search',
|
||||||
|
'section', 'security', 'select', 'sender', 'server', 'service',
|
||||||
|
'session', 'setting', 'settings', 'setup', 'share', 'shell',
|
||||||
|
'shortcut', 'sidebar', 'signal', 'simple', 'single', 'site', 'size',
|
||||||
|
'slider', 'slot', 'snapshot', 'socket', 'solution', 'source', 'space',
|
||||||
|
'stage', 'standard', 'start', 'state', 'status', 'step', 'stop',
|
||||||
|
'storage', 'store', 'stream', 'string', 'style', 'subject',
|
||||||
|
'success', 'summary', 'support', 'switch', 'symbol', 'syntax',
|
||||||
|
'system', 'table', 'target', 'task', 'team', 'template', 'terminal',
|
||||||
|
'test', 'text', 'theme', 'thread', 'time', 'timer', 'title', 'token',
|
||||||
|
'tool', 'toolbar', 'tooltip', 'top', 'total', 'track', 'traffic',
|
||||||
|
'tree', 'trigger', 'type', 'unit', 'update', 'upload', 'user',
|
||||||
|
'util', 'utility', 'value', 'variable', 'version', 'video', 'view',
|
||||||
|
'virtual', 'warning', 'watch', 'web', 'widget', 'width', 'window',
|
||||||
|
'wizard', 'word', 'worker', 'workspace', 'wrapper', 'zone',
|
||||||
|
// Common adjectives
|
||||||
|
'active', 'advanced', 'available', 'basic', 'best', 'better', 'blank',
|
||||||
|
'bold', 'clean', 'clear', 'close', 'closed', 'complete', 'complex',
|
||||||
|
'connected', 'correct', 'critical', 'current', 'dark', 'deep',
|
||||||
|
'detailed', 'different', 'direct', 'double', 'dynamic', 'early',
|
||||||
|
'easy', 'empty', 'entire', 'equal', 'essential', 'exact', 'extra',
|
||||||
|
'fast', 'final', 'fine', 'fixed', 'flat', 'free', 'fresh', 'front',
|
||||||
|
'full', 'generic', 'given', 'good', 'great', 'green', 'hard',
|
||||||
|
'hidden', 'high', 'hot', 'huge', 'human', 'initial', 'inner',
|
||||||
|
'internal', 'invalid', 'large', 'late', 'latest', 'left', 'light',
|
||||||
|
'live', 'long', 'low', 'major', 'maximum', 'middle', 'minimum',
|
||||||
|
'minor', 'mixed', 'modern', 'multiple', 'native', 'natural',
|
||||||
|
'nested', 'neutral', 'new', 'normal', 'null', 'old', 'online',
|
||||||
|
'open', 'optional', 'outer', 'overall', 'parallel', 'partial',
|
||||||
|
'pending', 'plain', 'popular', 'possible', 'previous', 'primary',
|
||||||
|
'private', 'proper', 'protected', 'quick', 'random', 'raw', 'ready',
|
||||||
|
'real', 'recent', 'red', 'related', 'relative', 'remote', 'required',
|
||||||
|
'responsive', 'rich', 'right', 'round', 'safe', 'secure', 'selected',
|
||||||
|
'sensitive', 'separate', 'serial', 'shared', 'short', 'silent',
|
||||||
|
'similar', 'simple', 'single', 'small', 'smart', 'smooth', 'soft',
|
||||||
|
'solid', 'special', 'specific', 'stable', 'standard', 'static',
|
||||||
|
'strict', 'strong', 'supported', 'sweet', 'thin', 'tight', 'tiny',
|
||||||
|
'total', 'true', 'unique', 'universal', 'unknown', 'upper', 'valid',
|
||||||
|
'various', 'virtual', 'visible', 'visual', 'warm', 'weak', 'white',
|
||||||
|
'whole', 'wide', 'wild',
|
||||||
|
// Programming/tech terms
|
||||||
'string', 'number', 'boolean', 'object', 'array', 'function', 'class',
|
'string', 'number', 'boolean', 'object', 'array', 'function', 'class',
|
||||||
'type', 'error', 'null', 'undefined', 'true', 'false', 'return',
|
'type', 'error', 'null', 'undefined', 'true', 'false', 'return',
|
||||||
'import', 'export', 'default', 'const', 'let', 'var', 'async', 'await',
|
'import', 'export', 'default', 'const', 'let', 'var', 'async', 'await',
|
||||||
'try', 'catch', 'throw', 'finally', 'switch', 'case', 'break',
|
'try', 'catch', 'throw', 'finally', 'switch', 'case', 'break',
|
||||||
'note', 'example', 'warning', 'important', 'todo', 'fixme', 'hack',
|
'example', 'warning', 'important', 'todo', 'fixme', 'hack',
|
||||||
'step', 'option', 'result', 'value', 'key', 'data', 'info',
|
// Common sentence starters
|
||||||
'file', 'code', 'test', 'debug', 'config', 'setup', 'update',
|
|
||||||
// Common sentence starters that aren't names
|
|
||||||
'please', 'thanks', 'hello', 'hi', 'hey', 'dear', 'sincerely',
|
'please', 'thanks', 'hello', 'hi', 'hey', 'dear', 'sincerely',
|
||||||
'regards', 'best', 'cheers', 'sorry', 'yes', 'no', 'ok', 'okay',
|
'regards', 'best', 'cheers', 'sorry', 'yes', 'ok', 'okay',
|
||||||
// Days and months (not PPI)
|
// Days and months
|
||||||
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
||||||
'january', 'february', 'march', 'april', 'may', 'june', 'july',
|
'january', 'february', 'march', 'april', 'may', 'june', 'july',
|
||||||
'august', 'september', 'october', 'november', 'december',
|
'august', 'september', 'october', 'november', 'december',
|
||||||
|
|||||||
@@ -257,6 +257,8 @@ const AutoDetect = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Common English words to exclude from proper noun detection
|
// Common English words to exclude from proper noun detection
|
||||||
|
// Comprehensive list including verbs, nouns, adjectives that appear
|
||||||
|
// in titles, headings, UI buttons, and instructions
|
||||||
const COMMON_WORDS = new Set([
|
const COMMON_WORDS = new Set([
|
||||||
'the', 'and', 'but', 'for', 'not', 'you', 'all', 'can', 'had', 'her',
|
'the', 'and', 'but', 'for', 'not', 'you', 'all', 'can', 'had', 'her',
|
||||||
'was', 'one', 'our', 'out', 'are', 'has', 'his', 'how', 'its', 'may',
|
'was', 'one', 'our', 'out', 'are', 'has', 'his', 'how', 'its', 'may',
|
||||||
@@ -276,6 +278,84 @@ const COMMON_WORDS = new Set([
|
|||||||
'number', 'other', 'point', 'right', 'small', 'state', 'thing',
|
'number', 'other', 'point', 'right', 'small', 'state', 'thing',
|
||||||
'think', 'those', 'three', 'through', 'under', 'until', 'water',
|
'think', 'those', 'three', 'through', 'under', 'until', 'water',
|
||||||
'world', 'write', 'might', 'should', 'because', 'although',
|
'world', 'write', 'might', 'should', 'because', 'although',
|
||||||
|
// Common verbs (titles, headings, buttons, instructions)
|
||||||
|
'generate', 'design', 'manage', 'process', 'handle', 'check', 'verify',
|
||||||
|
'submit', 'apply', 'accept', 'reject', 'approve', 'deny', 'confirm',
|
||||||
|
'cancel', 'delete', 'remove', 'edit', 'modify', 'view', 'display',
|
||||||
|
'search', 'filter', 'sort', 'select', 'choose', 'pick', 'enter',
|
||||||
|
'upload', 'download', 'install', 'enable', 'disable', 'activate',
|
||||||
|
'connect', 'disconnect', 'sync', 'refresh', 'reload', 'reset',
|
||||||
|
'save', 'load', 'store', 'restore', 'backup', 'copy', 'paste',
|
||||||
|
'lock', 'unlock', 'encrypt', 'decrypt', 'sign', 'register', 'login',
|
||||||
|
'logout', 'subscribe', 'share', 'publish', 'deploy', 'launch',
|
||||||
|
'merge', 'split', 'join', 'link', 'attach', 'insert', 'append',
|
||||||
|
'format', 'parse', 'convert', 'transform', 'translate', 'compile',
|
||||||
|
'execute', 'render', 'animate', 'validate', 'sanitize', 'escape',
|
||||||
|
'create', 'build', 'start', 'stop', 'open', 'close', 'run', 'send',
|
||||||
|
// Common nouns (titles, headings, labels)
|
||||||
|
'account', 'action', 'address', 'alert', 'analysis', 'application',
|
||||||
|
'area', 'article', 'asset', 'background', 'badge', 'banner', 'board',
|
||||||
|
'body', 'border', 'bottom', 'box', 'browser', 'buffer', 'button',
|
||||||
|
'cache', 'calendar', 'card', 'category', 'center', 'channel', 'chart',
|
||||||
|
'chat', 'child', 'choice', 'client', 'cloud', 'code', 'collection',
|
||||||
|
'color', 'column', 'command', 'comment', 'community', 'company',
|
||||||
|
'component', 'config', 'configuration', 'connection', 'console',
|
||||||
|
'contact', 'container', 'content', 'context', 'control', 'count',
|
||||||
|
'country', 'custom', 'dashboard', 'data', 'database', 'date', 'day',
|
||||||
|
'default', 'description', 'design', 'desktop', 'detail', 'device',
|
||||||
|
'dialog', 'directory', 'document', 'domain', 'draft', 'driver',
|
||||||
|
'edge', 'editor', 'element', 'email', 'engine', 'entry', 'environment',
|
||||||
|
'error', 'event', 'example', 'extension', 'feature', 'feedback',
|
||||||
|
'field', 'file', 'filter', 'folder', 'font', 'footer', 'form',
|
||||||
|
'frame', 'function', 'gallery', 'general', 'global', 'grid',
|
||||||
|
'guide', 'handler', 'header', 'health', 'help', 'history', 'home',
|
||||||
|
'host', 'icon', 'image', 'index', 'info', 'input', 'instance',
|
||||||
|
'interface', 'issue', 'item', 'job', 'key', 'label', 'language',
|
||||||
|
'layout', 'level', 'library', 'light', 'limit', 'line', 'link',
|
||||||
|
'list', 'local', 'location', 'log', 'logo', 'main', 'manager',
|
||||||
|
'manual', 'map', 'media', 'member', 'memory', 'menu', 'message',
|
||||||
|
'method', 'mobile', 'modal', 'mode', 'model', 'module', 'monitor',
|
||||||
|
'navigation', 'network', 'node', 'note', 'notification', 'object',
|
||||||
|
'option', 'order', 'origin', 'output', 'overlay', 'overview', 'owner',
|
||||||
|
'package', 'page', 'panel', 'parent', 'parser', 'password', 'path',
|
||||||
|
'pattern', 'permission', 'photo', 'pipeline', 'placeholder', 'plan',
|
||||||
|
'platform', 'player', 'plugin', 'point', 'policy', 'pool', 'popup',
|
||||||
|
'port', 'position', 'post', 'power', 'preview', 'primary', 'print',
|
||||||
|
'priority', 'process', 'product', 'profile', 'program', 'progress',
|
||||||
|
'project', 'prompt', 'property', 'protocol', 'provider', 'proxy',
|
||||||
|
'public', 'query', 'queue', 'quick', 'range', 'rate', 'reader',
|
||||||
|
'record', 'region', 'release', 'remote', 'report', 'request',
|
||||||
|
'resource', 'response', 'result', 'review', 'role', 'root', 'route',
|
||||||
|
'row', 'rule', 'runtime', 'sample', 'scanner', 'schema', 'scope',
|
||||||
|
'screen', 'script', 'search', 'section', 'security', 'select',
|
||||||
|
'sender', 'server', 'service', 'session', 'setting', 'settings',
|
||||||
|
'setup', 'share', 'shell', 'shortcut', 'sidebar', 'signal', 'simple',
|
||||||
|
'single', 'site', 'size', 'slider', 'snapshot', 'socket', 'solution',
|
||||||
|
'source', 'space', 'stage', 'standard', 'status', 'step', 'storage',
|
||||||
|
'stream', 'string', 'style', 'subject', 'success', 'summary',
|
||||||
|
'support', 'switch', 'symbol', 'syntax', 'system', 'table', 'target',
|
||||||
|
'task', 'team', 'template', 'terminal', 'test', 'text', 'theme',
|
||||||
|
'thread', 'title', 'token', 'tool', 'toolbar', 'tooltip', 'total',
|
||||||
|
'track', 'traffic', 'tree', 'trigger', 'type', 'unit', 'update',
|
||||||
|
'upload', 'user', 'utility', 'value', 'variable', 'version', 'video',
|
||||||
|
'view', 'virtual', 'warning', 'watch', 'web', 'widget', 'width',
|
||||||
|
'window', 'wizard', 'word', 'worker', 'workspace', 'wrapper', 'zone',
|
||||||
|
// Common adjectives
|
||||||
|
'active', 'advanced', 'available', 'basic', 'clean', 'clear', 'complete',
|
||||||
|
'connected', 'correct', 'critical', 'current', 'dark', 'deep',
|
||||||
|
'different', 'direct', 'double', 'dynamic', 'easy', 'empty', 'entire',
|
||||||
|
'exact', 'extra', 'fast', 'final', 'fixed', 'flat', 'free', 'fresh',
|
||||||
|
'full', 'generic', 'given', 'hidden', 'initial', 'inner', 'internal',
|
||||||
|
'invalid', 'latest', 'live', 'major', 'maximum', 'minimum', 'minor',
|
||||||
|
'mixed', 'modern', 'multiple', 'native', 'natural', 'nested', 'normal',
|
||||||
|
'online', 'optional', 'outer', 'overall', 'partial', 'pending', 'plain',
|
||||||
|
'popular', 'possible', 'previous', 'private', 'proper', 'protected',
|
||||||
|
'random', 'raw', 'ready', 'real', 'recent', 'related', 'relative',
|
||||||
|
'required', 'responsive', 'safe', 'secure', 'selected', 'sensitive',
|
||||||
|
'separate', 'shared', 'silent', 'similar', 'smart', 'smooth', 'solid',
|
||||||
|
'special', 'specific', 'stable', 'static', 'strict', 'strong',
|
||||||
|
'supported', 'unique', 'universal', 'unknown', 'upper', 'valid',
|
||||||
|
'various', 'visible', 'visual', 'whole', 'wide',
|
||||||
// Programming / tech terms
|
// Programming / tech terms
|
||||||
'string', 'number', 'boolean', 'object', 'array', 'function', 'class',
|
'string', 'number', 'boolean', 'object', 'array', 'function', 'class',
|
||||||
'type', 'error', 'null', 'undefined', 'true', 'false', 'return',
|
'type', 'error', 'null', 'undefined', 'true', 'false', 'return',
|
||||||
|
|||||||
@@ -589,7 +589,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>Silent Send v2.0.3</p>
|
<p>Silent Send v2.0.5</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const $ = (sel) => document.querySelector(sel);
|
|||||||
// --- Safe innerHTML replacement (AMO-compliant) ---
|
// --- Safe innerHTML replacement (AMO-compliant) ---
|
||||||
function safeHTML(el, html) {
|
function safeHTML(el, html) {
|
||||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||||
el.replaceChildren(...doc.body.childNodes);
|
el.replaceChildren(...Array.from(doc.body.childNodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|||||||
@@ -623,6 +623,35 @@ body {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Options tab */
|
||||||
|
.setting-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 0;
|
||||||
|
border-bottom: 1px solid #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item:last-of-type { border-bottom: none; }
|
||||||
|
|
||||||
|
.setting-label {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-label strong {
|
||||||
|
font-size: 12px;
|
||||||
|
display: block;
|
||||||
|
color: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-label .setting-desc {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #9ca3af;
|
||||||
|
display: block;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
.footer {
|
.footer {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<button class="tab" data-tab="mappings">Mappings</button>
|
<button class="tab" data-tab="mappings">Mappings</button>
|
||||||
<button class="tab" data-tab="activity">Activity</button>
|
<button class="tab" data-tab="activity">Activity</button>
|
||||||
<button class="tab" data-tab="test">Test</button>
|
<button class="tab" data-tab="test">Test</button>
|
||||||
|
<button class="tab" data-tab="options">Options</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- Locked State Overlay -->
|
<!-- Locked State Overlay -->
|
||||||
@@ -193,6 +194,54 @@
|
|||||||
<div class="test-identity-status" id="identityStatus"></div>
|
<div class="test-identity-status" id="identityStatus"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- Options Tab -->
|
||||||
|
<section class="tab-content" id="tab-options">
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-label">
|
||||||
|
<strong>Secret scanning</strong>
|
||||||
|
<span class="setting-desc">Auto-redact API keys, tokens, passwords, SSNs, credit cards</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle"><input type="checkbox" id="optSecretScanning" checked><span class="toggle-slider"></span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-label">
|
||||||
|
<strong>Auto-detect PPI</strong>
|
||||||
|
<span class="setting-desc">Warn about unconfigured personal data (IPs, addresses, paths)</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle"><input type="checkbox" id="optAutoDetect" checked><span class="toggle-slider"></span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-label">
|
||||||
|
<strong>Auto-redact detected PPI</strong>
|
||||||
|
<span class="setting-desc">Replace detected PPI with placeholders on send</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle"><input type="checkbox" id="optAutoRedact" checked><span class="toggle-slider"></span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-label">
|
||||||
|
<strong>Show highlights</strong>
|
||||||
|
<span class="setting-desc">Highlight substituted values in AI responses</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle"><input type="checkbox" id="optHighlights"><span class="toggle-slider"></span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-label">
|
||||||
|
<strong>Document scan preview</strong>
|
||||||
|
<span class="setting-desc">Show PPI findings before uploading documents</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle"><input type="checkbox" id="optDocPreview" checked><span class="toggle-slider"></span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top:12px;padding-top:10px;border-top:1px solid #e5e7eb">
|
||||||
|
<button class="btn" id="btnOpenFullOptions" style="width:100%;font-size:12px">Open Full Options Page</button>
|
||||||
|
<p class="help-text" style="margin-top:6px;text-align:center">Sync, encryption, org, version history, import/export, and more</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="privacy-note">
|
<div class="privacy-note">
|
||||||
|
|||||||
+30
-2
@@ -21,7 +21,7 @@ const $$ = (sel) => document.querySelectorAll(sel);
|
|||||||
// --- Safe innerHTML replacement (AMO-compliant) ---
|
// --- Safe innerHTML replacement (AMO-compliant) ---
|
||||||
function safeHTML(el, html) {
|
function safeHTML(el, html) {
|
||||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||||
el.replaceChildren(...doc.body.childNodes);
|
el.replaceChildren(...Array.from(doc.body.childNodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Init ---
|
// --- Init ---
|
||||||
@@ -208,12 +208,40 @@ async function initUnlockedUI() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Options link
|
// Options link (footer)
|
||||||
$('#btnOptions').addEventListener('click', (e) => {
|
$('#btnOptions').addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
api.runtime.openOptionsPage();
|
api.runtime.openOptionsPage();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Options tab
|
||||||
|
$('#btnOpenFullOptions').addEventListener('click', () => {
|
||||||
|
api.runtime.openOptionsPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load options tab settings
|
||||||
|
$('#optSecretScanning').checked = settings.secretScanning !== false;
|
||||||
|
$('#optAutoDetect').checked = settings.autoDetect !== false;
|
||||||
|
$('#optAutoRedact').checked = settings.autoRedactDetected !== false;
|
||||||
|
$('#optHighlights').checked = settings.showHighlights || false;
|
||||||
|
$('#optDocPreview').checked = settings.docScanPreview !== false;
|
||||||
|
|
||||||
|
// Options tab change handlers
|
||||||
|
const optHandlers = [
|
||||||
|
['optSecretScanning', 'secretScanning'],
|
||||||
|
['optAutoDetect', 'autoDetect'],
|
||||||
|
['optAutoRedact', 'autoRedactDetected'],
|
||||||
|
['optHighlights', 'showHighlights'],
|
||||||
|
['optDocPreview', 'docScanPreview'],
|
||||||
|
];
|
||||||
|
for (const [id, key] of optHandlers) {
|
||||||
|
$(`#${id}`).addEventListener('change', async (e) => {
|
||||||
|
settings[key] = e.target.checked;
|
||||||
|
await Storage.saveSettings({ [key]: e.target.checked });
|
||||||
|
api.runtime.sendMessage({ type: 'update:settings', settings });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Update privacy note based on encryption state
|
// Update privacy note based on encryption state
|
||||||
const encEnabled = await Storage._isAtRestEncryptionEnabled();
|
const encEnabled = await Storage._isAtRestEncryptionEnabled();
|
||||||
const encNote = $('#privacyEncNote');
|
const encNote = $('#privacyEncNote');
|
||||||
|
|||||||
Reference in New Issue
Block a user