1- export function injectOrUpdateTranslations ( translations , originalElement , width ) {
2- const componentStyles = `
1+ export function injectOrUpdateTranslations (
2+ translations ,
3+ originalElement ,
4+ width
5+ ) {
6+ const componentStyles = `
37 .tab-nav {
48 display: flex;
59 border-bottom: 1px solid #ccc;
@@ -29,6 +33,31 @@ export function injectOrUpdateTranslations(translations, originalElement, width)
2933 .tab-content.active {
3034 display: block;
3135 }
36+ .code-wrapper{
37+ position:relative
38+ }
39+ .copy-button {
40+ position: absolute;
41+ top: 8px;
42+ right: 8px;
43+ padding: 6px 12px;
44+ font-size: 14px;
45+ background-color: rgba(255, 255, 255, 0.08); /* soft overlay */
46+ border: 1px solid rgba(255, 255, 255, 0.2);
47+ border-radius: 4px;
48+ color: #f0f0f0;
49+ cursor: pointer;
50+ transition: background-color 0.3s, border-color 0.3s, color 0.3s;
51+ z-index: 10;
52+ }
53+ .copy-button:hover {
54+ background-color: rgba(255, 255, 255, 0.15);
55+ border-color: rgba(255, 255, 255, 0.3);
56+ color: #ffffff;
57+ }
58+ .copy-button:active {
59+ background-color: rgba(255, 255, 255, 0.2);
60+ }
3261 pre {
3362 margin: 0;
3463 white-space: pre-wrap;
@@ -40,71 +69,96 @@ export function injectOrUpdateTranslations(translations, originalElement, width)
4069 }
4170 ` ;
4271
43- let container = originalElement . nextElementSibling ;
72+ let container = originalElement . nextElementSibling ;
4473
45- if ( ! container || container . id !== 'my-code-translator-container' ) {
46- container = document . createElement ( 'div' ) ;
47- container . id = 'my-code-translator-container' ;
48- const shadowRoot = container . attachShadow ( { mode : 'open' } ) ;
49- const prismTheme = document . createElement ( 'link' ) ;
50- prismTheme . rel = 'stylesheet' ;
51- prismTheme . href = chrome . runtime . getURL ( 'packages/prism.css' ) ;
52- shadowRoot . appendChild ( prismTheme ) ;
53- const styleElement = document . createElement ( 'style' ) ;
54- styleElement . textContent = componentStyles ;
55- shadowRoot . appendChild ( styleElement ) ;
56- const uiWrapper = document . createElement ( 'div' ) ;
57- uiWrapper . className = 'ui-wrapper' ;
58- shadowRoot . appendChild ( uiWrapper ) ;
59- originalElement . parentNode . insertBefore ( container , originalElement . nextSibling ) ;
60- }
74+ if ( ! container || container . id !== "my-code-translator-container" ) {
75+ container = document . createElement ( "div" ) ;
76+ container . id = "my-code-translator-container" ;
77+ const shadowRoot = container . attachShadow ( { mode : "open" } ) ;
78+ const prismTheme = document . createElement ( "link" ) ;
79+ prismTheme . rel = "stylesheet" ;
80+ prismTheme . href = chrome . runtime . getURL ( "packages/prism.css" ) ;
81+ shadowRoot . appendChild ( prismTheme ) ;
82+ const styleElement = document . createElement ( "style" ) ;
83+ styleElement . textContent = componentStyles ;
84+ shadowRoot . appendChild ( styleElement ) ;
85+ const uiWrapper = document . createElement ( "div" ) ;
86+ uiWrapper . className = "ui-wrapper" ;
87+ shadowRoot . appendChild ( uiWrapper ) ;
88+ originalElement . parentNode . insertBefore (
89+ container ,
90+ originalElement . nextSibling
91+ ) ;
92+ }
6193
62- container . style . width = `${ width } px` ;
63- container . style . boxSizing = 'border-box' ;
64- const shadowRoot = container . shadowRoot ;
65- const uiWrapper = shadowRoot . querySelector ( '.ui-wrapper' ) ;
66- uiWrapper . innerHTML = '' ;
67- const tabNav = document . createElement ( 'div' ) ;
68- tabNav . className = 'tab-nav' ;
69- const contentArea = document . createElement ( 'div' ) ;
70- contentArea . className = 'tab-content-area' ;
71- uiWrapper . appendChild ( tabNav ) ;
72- uiWrapper . appendChild ( contentArea ) ;
73- Object . keys ( translations ) . forEach ( lang => {
74- const contentPanel = document . createElement ( 'div' ) ;
75- contentPanel . className = 'tab-content' ;
76- contentPanel . dataset . lang = lang ;
77- const langClass = `language-${ lang . toLowerCase ( ) } ` ;
78- const pre = document . createElement ( 'pre' ) ;
79- pre . className = langClass ;
80- const code = document . createElement ( 'code' ) ;
81- code . className = langClass ;
82- code . textContent = translations [ lang ] ;
83- pre . appendChild ( code ) ;
84- contentPanel . appendChild ( pre ) ;
85- contentArea . appendChild ( contentPanel ) ;
94+ container . style . width = `${ width } px` ;
95+ container . style . boxSizing = "border-box" ;
96+ const shadowRoot = container . shadowRoot ;
97+ const uiWrapper = shadowRoot . querySelector ( ".ui-wrapper" ) ;
98+ uiWrapper . innerHTML = "" ;
99+ const tabNav = document . createElement ( "div" ) ;
100+ tabNav . className = "tab-nav" ;
101+ const contentArea = document . createElement ( "div" ) ;
102+ contentArea . className = "tab-content-area" ;
103+ uiWrapper . appendChild ( tabNav ) ;
104+ uiWrapper . appendChild ( contentArea ) ;
105+ Object . keys ( translations ) . forEach ( ( lang ) => {
106+ const contentPanel = document . createElement ( "div" ) ;
107+ contentPanel . className = "tab-content" ;
108+ contentPanel . dataset . lang = lang ;
109+ const codeWrapper = document . createElement ( "div" ) ;
110+ codeWrapper . className = "code-wrapper" ;
111+ const copyButton = document . createElement ( "div" ) ;
112+ copyButton . className = "copy-button" ;
113+ copyButton . innerText = "copy" ;
114+ copyButton . addEventListener ( "click" , ( ) => {
115+ navigator . clipboard . writeText ( translations [ lang ] ) . then ( ( ) => {
116+ copyButton . innerText = "Copied!" ;
117+ setTimeout ( ( ) => ( copyButton . innerText = "Copy" ) , 2000 ) ;
118+ } ) ;
86119 } ) ;
120+ const langClass = `language-${ lang . toLowerCase ( ) } ` ;
121+ const pre = document . createElement ( "pre" ) ;
122+ pre . className = langClass ;
123+ const code = document . createElement ( "code" ) ;
124+ code . className = langClass ;
125+ code . textContent = translations [ lang ] ;
87126
88- Object . keys ( translations ) . forEach ( ( lang , index ) => {
89- const tabButton = document . createElement ( 'button' ) ;
90- tabButton . className = 'tab-link' ;
91- tabButton . textContent = lang ;
92- tabButton . addEventListener ( 'click' , ( ) => {
93- shadowRoot . querySelectorAll ( '.tab-link' ) . forEach ( btn => btn . classList . remove ( 'active' ) ) ;
94- shadowRoot . querySelectorAll ( '.tab-content' ) . forEach ( panel => panel . classList . remove ( 'active' ) ) ;
95- tabButton . classList . add ( 'active' ) ;
96- shadowRoot . querySelector ( `.tab-content[data-lang="${ lang } "]` ) . classList . add ( 'active' ) ;
97- } ) ;
98- tabNav . appendChild ( tabButton ) ;
99- if ( index === 0 ) {
100- tabButton . click ( ) ;
101- }
127+ pre . appendChild ( code ) ;
128+ codeWrapper . appendChild ( copyButton ) ;
129+ codeWrapper . appendChild ( pre ) ;
130+ contentPanel . appendChild ( codeWrapper ) ;
131+ contentArea . appendChild ( contentPanel ) ;
132+ } ) ;
133+
134+ Object . keys ( translations ) . forEach ( ( lang , index ) => {
135+ const tabButton = document . createElement ( "button" ) ;
136+ tabButton . className = "tab-link" ;
137+ tabButton . textContent = lang ;
138+ tabButton . addEventListener ( "click" , ( ) => {
139+ shadowRoot
140+ . querySelectorAll ( ".tab-link" )
141+ . forEach ( ( btn ) => btn . classList . remove ( "active" ) ) ;
142+ shadowRoot
143+ . querySelectorAll ( ".tab-content" )
144+ . forEach ( ( panel ) => panel . classList . remove ( "active" ) ) ;
145+ tabButton . classList . add ( "active" ) ;
146+ shadowRoot
147+ . querySelector ( `.tab-content[data-lang="${ lang } "]` )
148+ . classList . add ( "active" ) ;
102149 } ) ;
103- try {
104- if ( window . Prism ) {
105- contentArea . querySelectorAll ( `pre[class*="language-"]` ) . forEach ( element => window . Prism . highlightElement ( element ) ) ;
106- }
107- } catch ( e ) {
108- console . error ( 'CodeTranslateAI: Error highlighting syntax.' , e ) ;
150+ tabNav . appendChild ( tabButton ) ;
151+ if ( index === 0 ) {
152+ tabButton . click ( ) ;
153+ }
154+ } ) ;
155+ try {
156+ if ( window . Prism ) {
157+ contentArea
158+ . querySelectorAll ( `pre[class*="language-"]` )
159+ . forEach ( ( element ) => window . Prism . highlightElement ( element ) ) ;
109160 }
110- }
161+ } catch ( e ) {
162+ console . error ( "CodeTranslateAI: Error highlighting syntax." , e ) ;
163+ }
164+ }
0 commit comments