diff --git a/frontend/manifest.json b/frontend/manifest.json index daf9b1c..9d4ae3f 100644 --- a/frontend/manifest.json +++ b/frontend/manifest.json @@ -35,7 +35,7 @@ }, "web_accessible_resources": [ { - "resources": ["packages/prism.css"], + "resources": ["packages/prism.css","packages/prism-light.css"], "matches": [""] } ], diff --git a/frontend/packages/prism-light.css b/frontend/packages/prism-light.css new file mode 100644 index 0000000..cd20098 --- /dev/null +++ b/frontend/packages/prism-light.css @@ -0,0 +1,116 @@ +/* PrismJS 1.30.0 - Light Mode Theme +https://prismjs.com/download#themes=prism-tomorrow&languages=markup+css+clike+javascript+c+csharp+cpp+go+java+kotlin+markup-templating+php+python+ruby+rust+swift+typescript */ + +code[class*=language-], +pre[class*=language-] { + color: #333; + background: 0 0; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*=language-] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*=language-], +pre[class*=language-] { + background: #f8f8f8; + border: 1px solid #e8e8e8; +} + +:not(pre) > code[class*=language-] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.block-comment, +.token.cdata, +.token.comment, +.token.doctype, +.token.prolog { + color: #708090; +} + +.token.punctuation { + color: #999; +} + +.token.attr-name, +.token.deleted, +.token.namespace, +.token.tag { + color: #d73a49; +} + +.token.function-name { + color: #005cc5; +} + +.token.boolean, +.token.function, +.token.number { + color: #e36209; +} + +.token.class-name, +.token.constant, +.token.property, +.token.symbol { + color: #b08800; +} + +.token.atrule, +.token.builtin, +.token.important, +.token.keyword, +.token.selector { + color: #d73a49; +} + +.token.attr-value, +.token.char, +.token.regex, +.token.string, +.token.variable { + color: #22863a; +} + +.token.entity, +.token.operator, +.token.url { + color: #005cc5; +} + +.token.bold, +.token.important { + font-weight: 700; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.token.inserted { + color: #28a745; +} \ No newline at end of file diff --git a/frontend/scripts/content.js b/frontend/scripts/content.js index 19c1dd2..7ba0c58 100644 --- a/frontend/scripts/content.js +++ b/frontend/scripts/content.js @@ -20,12 +20,12 @@ async function handleElementClick(e) { const cacheKey = `translation_${hashCode(selectedCode)}`; const originalWidth = clickedElement.getBoundingClientRect().width; - const { targetLanguage } = await chrome.storage.sync.get("targetLanguage"); + const { targetLanguage, theme } = await chrome.storage.sync.get(["targetLanguage", "theme"]); const lang = targetLanguage; const cachedData = await getFromCache(cacheKey); if (cachedData && cachedData[lang]) { - injectOrUpdateTranslations(cachedData, clickedElement, originalWidth); + injectOrUpdateTranslations(cachedData, clickedElement, originalWidth,theme); return; } @@ -58,7 +58,7 @@ async function handleElementClick(e) { const newData = cachedData || {}; newData[lang] = cleaned; await saveToCache(cacheKey, newData, 10); - injectOrUpdateTranslations(newData, clickedElement, originalWidth); + injectOrUpdateTranslations(newData, clickedElement, originalWidth,theme); } } ); diff --git a/frontend/scripts/ui.js b/frontend/scripts/ui.js index f310db5..387ca85 100644 --- a/frontend/scripts/ui.js +++ b/frontend/scripts/ui.js @@ -1,7 +1,8 @@ export function injectOrUpdateTranslations( translations, originalElement, - width + width, + currentTheme ) { const componentStyles = ` .tab-nav { @@ -42,33 +43,67 @@ export function injectOrUpdateTranslations( right: 8px; padding: 6px 12px; font-size: 14px; - background-color: rgba(255, 255, 255, 0.08); /* soft overlay */ - border: 1px solid rgba(255, 255, 255, 0.2); + background-color: rgba(0, 0, 0, 0.05); /* soft overlay */ + border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 4px; - color: #f0f0f0; + color: #333; cursor: pointer; transition: background-color 0.3s, border-color 0.3s, color 0.3s; z-index: 10; } .copy-button:hover { - background-color: rgba(255, 255, 255, 0.15); - border-color: rgba(255, 255, 255, 0.3); - color: #ffffff; + background-color: rgba(0, 0, 0, 0.1); + border-color: rgba(0, 0, 0, 0.2); + color: #000; } .copy-button:active { - background-color: rgba(255, 255, 255, 0.2); + background-color: rgba(0, 0, 0, 0.15); } pre { margin: 0; white-space: pre-wrap; word-wrap: break-word; + } code { font-family: monospace; font-size: 0.8em; } + .dark .tab-nav { + border-bottom: 1px solid #3e3e42; + background-color: #2d2d30; + } + .dark .tab-link { + color: #969696; + } + .dark .tab-link:hover { + background-color: #3e3e42; + } + .dark .tab-link.active { + color: #4a9eff; + border-bottom: 3px solid #4a9eff; + } + .dark .copy-button { + background-color: rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.2); + color: #f0f0f0; + } + .dark .copy-button:hover { + background-color: rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.3); + color: #ffffff; + } + .dark .copy-button:active { + background-color: rgba(255, 255, 255, 0.2); + } + .dark pre { + background-color: #1e1e1e; + color: #cccccc; + } + .dark code { + color: #cccccc; + } `; - let container = originalElement.nextElementSibling; if (!container || container.id !== "my-code-translator-container") { @@ -77,13 +112,19 @@ export function injectOrUpdateTranslations( const shadowRoot = container.attachShadow({ mode: "open" }); const prismTheme = document.createElement("link"); prismTheme.rel = "stylesheet"; - prismTheme.href = chrome.runtime.getURL("packages/prism.css"); + if(currentTheme==="dark"){ + prismTheme.href = chrome.runtime.getURL("packages/prism.css"); + }else{ + prismTheme.href = chrome.runtime.getURL("packages/prism-light.css"); + } + shadowRoot.appendChild(prismTheme); const styleElement = document.createElement("style"); styleElement.textContent = componentStyles; shadowRoot.appendChild(styleElement); const uiWrapper = document.createElement("div"); uiWrapper.className = "ui-wrapper"; + uiWrapper.classList.add(currentTheme === "dark" ? "dark" : "light"); shadowRoot.appendChild(uiWrapper); originalElement.parentNode.insertBefore( container,